# RFC 3678: Why should final rule out downstream use cases that library authors never anticipated?

**URL:** <https://internals.rust-lang.org/t/rfc-3678-why-should-final-rule-out-downstream-use-cases-that-library-authors-never-anticipated/24701>\
**Category:** language design\
**Created:** [October 24, 2026, 7:10am UTC](https://internals.rust-lang.org/t/rfc-3678-why-should-final-rule-out-downstream-use-cases-that-library-authors-never-anticipated/24701 "2026-10-24T07:10:44Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![cyan-river](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/cyan-river/32/14669_2.png) [@cyan-river](https://internals.rust-lang.org/u/cyan-river)\
**Post date:** [October 24, 2026, 7:10am UTC](https://internals.rust-lang.org/t/rfc-3678-why-should-final-rule-out-downstream-use-cases-that-library-authors-never-anticipated/24701/1 "2026-10-24T07:10:44Z")

</div>

# RFC 3678: Why should `final` rule out downstream use cases that library authors never anticipated?

I'd like to raise a concern about [RFC 3678 — Final Trait Methods](https://github.com/rust-lang/rfcs/pull/3678).

My concern is simple:

**Why should a library author's inability to anticipate a future use case become a hard compiler restriction for everyone else?**

This is an everyday reality of open-source development.

Many libraries start as small projects built for their authors' own needs. Some eventually become widely adopted, while others remain small but still have users with requirements the authors never considered.

Library authors cannot predict every future use case. Nor should we expect them to.

A method that seems to have no reason to be overridden today may have a perfectly legitimate reason to be overridden tomorrow.

Yet `final` turns the author's current assumption into an absolute restriction.

When an unforeseen requirement appears, the downstream user cannot simply override the method, even if they fully understand the consequences and are willing to take responsibility for their implementation.

Instead, they may have to fork the dependency, maintain patches, and deal with potential compatibility issues across updates. In complex workspaces, this can be an enormous amount of work just to change one method.

**Why should we force downstream users to pay such a high price for requirements that the original author simply couldn't foresee?**

I understand that some methods must not be overridden because soundness or other essential guarantees depend on their exact implementation. I'm not arguing against enforcing those guarantees.

But not every reason for marking a method `final` is a soundness requirement.

For cases where no hard guarantee depends on prohibiting overrides, I think a warning-based approach would be more appropriate.

## My proposal: Warn by default, allow explicit overrides with a reason

Instead of always rejecting an override, the compiler could emit a warning:

```rust
impl SomeTrait for MyType {
    fn method(&self) {
        // Custom implementation
    }
}

```

If the user intentionally overrides the method, they could explicitly acknowledge the warning and explain why:

```rust
impl SomeTrait for MyType {
    #[expect(
        final_method_override,
        reason = "Required for compatibility with a legacy protocol"
    )]
    fn method(&self) {
        // Custom implementation
    }
}

```

Here, `final_method_override` is a hypothetical lint. Ideally, suppressing this warning would require an explicit reason.

This would mean:

- The library author's intention is still clearly communicated.
- Accidental overrides produce compiler warnings.
- Intentional overrides require an explicit, reviewable acknowledgement.
- Downstream users retain the ability to handle requirements the library author never anticipated.

For cases where overriding would violate soundness or other necessary guarantees, a separate strict mechanism could still prohibit it.

This approach feels much closer to the Rust philosophy I appreciate: make risks and responsibilities explicit, without unnecessarily removing the developer's ability to make informed decisions.

## The question

I understand that absolute prohibition is a familiar and straightforward way to prevent unwanted overrides.

But being straightforward doesn't necessarily make it the right solution for every situation.

I worry that we are choosing an absolute restriction without giving enough weight to the long-term consequences for downstream extensibility.

**A library author can know what their implementation needs today. They cannot know everything their users will need tomorrow.**

Why should the language enforce the former at the expense of the latter, when a warning and explicit acknowledgement could offer a more flexible alternative?

I would really like to see this trade-off discussed before `final` is stabilized.

---

<div class="post-metadata">

**Author:** ![SkiFire13](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/skifire13/32/7579_2.png) [@SkiFire13](https://internals.rust-lang.org/u/SkiFire13)\
**Post date:** [October 24, 2026, 8:33am UTC](https://internals.rust-lang.org/t/rfc-3678-why-should-final-rule-out-downstream-use-cases-that-library-authors-never-anticipated/24701/2 "2026-10-24T08:33:14Z")

</div>

> [@cyan-river](#):
>
> Yet `final` turns the author's current assumption into an absolute restriction.
> 
> When an unforeseen requirement appears, the downstream user cannot simply override the method, even if they fully understand the consequences and are willing to take responsibility for their implementation.

Note that right now we have worse alternatives like making the trait completely unimplementable, or making the trait method uncallable by downstream. If anything `final` allows giving _more_ freedom to downstream compared to what we have to do right now.

> [@cyan-river](#):
>
> For cases where overriding would violate soundness or other necessary guarantees, a separate strict mechanism could still prohibit it.

What would this separate strict mechanism if not `final`?

---

<div class="post-metadata">

**Author:** ![cyan-river](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/cyan-river/32/14669_2.png) [@cyan-river](https://internals.rust-lang.org/u/cyan-river)\
**Post date:** [October 24, 2026, 10:32am UTC](https://internals.rust-lang.org/t/rfc-3678-why-should-final-rule-out-downstream-use-cases-that-library-authors-never-anticipated/24701/3 "2026-10-24T10:32:11Z")

</div>

I'd like to add some personal context and clarify one important distinction behind my concern.

When I first saw `final` being introduced in Rust, my immediate reaction was that it felt uncomfortably familiar from Java.

I've personally encountered frustrating situations involving `final` methods in Java. Sometimes I knew exactly what needed to be changed, but an absolute restriction turned what should have been a relatively small customization into a much larger problem.

That experience made me question whether we really want to introduce the same kind of restriction into Rust.

But I think the broader issue is much more common than my personal experience.

### Library authors cannot predict their users' futures

Many open-source libraries begin as small projects written primarily for their authors' own use. Some authors may not even expect other people to depend on their code.

Yet these projects can eventually become widely adopted, sometimes growing far beyond their original purpose.

Even libraries that remain small can attract users with requirements their authors never anticipated.

This is not a failure on the author's part. It's simply how software evolves.

**The author is the author. The user is the user. They have different requirements, and neither can fully predict the other's future needs.**

A library author might mark a method as `final` because they believe its implementation should never need to change.

But what happens when a downstream user has a legitimate reason to change it?

Perhaps the user needs deep customization of one particular behavior, while still wanting to use and maintain compatibility with the rest of the library.

That is a very different situation from wanting to fork and maintain an entire project.

Why should a relatively narrow customization require taking responsibility for maintaining a whole dependency?

### A small decision with potentially enormous consequences

There's another practical concern, especially for developers familiar with multiple programming languages.

`final` looks like an ordinary, familiar API design tool.

I don't think it's realistic to expect developers to approach every use of `final` with the same level of scrutiny they would give an `unsafe` contract.

Yet a single `final` keyword can impose substantial, long-lasting restrictions on downstream users.

**A decision that costs the library author almost nothing can impose enormous maintenance costs on users who had no say in that decision.**

And those users may not even exist yet when the decision is made.

### "I don't want this overridden" and "overriding this requires a safety contract" are two different problems

This is the distinction I most want to emphasize.

**A library author's desire to prevent overrides is not the same thing as a safety requirement that overrides must satisfy.**

I don't think these two fundamentally different concerns should automatically lead to the same absolute prohibition.

If the author simply wants to discourage overriding a method, I would prefer a compiler warning, with an explicit acknowledgement and documented reason for intentional overrides.

If overriding a method involves safety invariants, then the responsibility should be expressed as a safety contract.

For example, the RFC itself mentions the possibility of `impl(unsafe)`: a method that remains safe to call but requires an explicit unsafe obligation to override.

I find that direction much more compelling than an unconditional ban.

Of course, `unsafe` must not mean that anything is permitted. An override would still be required to uphold the documented safety invariants. If an alternative implementation cannot satisfy those invariants, it cannot be considered sound.

But that is a question of whether the implementation satisfies a contract, not simply whether the original author wanted to permit it.

**I would rather Rust provide an explicit path for responsible overrides than make methods categorically impossible to override.**

The user who deliberately chooses an alternative implementation should take responsibility for satisfying its contracts and maintaining their customization.

The original library author should not be expected to support every possible customization.

But neither should the author's inability to foresee a particular use case automatically prevent users from addressing it themselves.

### Why this matters to me

What concerns me is not merely that Rust is adopting something resembling Java's `final`.

It's that we may be repeating a familiar approach without sufficiently considering how differently it affects library authors and downstream users.

I appreciate Rust's emphasis on explicit responsibilities and well-defined safety boundaries.

To me, a warning with an explicit reason for ordinary overrides, and an unsafe contract for safety-critical overrides, would better reflect that philosophy than a blanket prohibition.

**Not wanting something to be overridden is not the same as proving that nobody should ever be allowed to override it.**

And I don't think an author's inability to anticipate future requirements should, by itself, become a permanent limitation on everyone else's ability to solve their own problems.

---

<div class="post-metadata">

**Author:** ![pitaj](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/pitaj/32/11262_2.png) [@pitaj](https://internals.rust-lang.org/u/pitaj)\
**Post date:** [October 24, 2026, 3:17pm UTC](https://internals.rust-lang.org/t/rfc-3678-why-should-final-rule-out-downstream-use-cases-that-library-authors-never-anticipated/24701/4 "2026-10-24T15:17:51Z")

</div>

Final should be used sparingly and typically only when necessary for soundness guarantees.

---

<div class="post-metadata">

**Author:** ![chrefr](https://avatars.discourse-cdn.com/v4/letter/c/e480ec/32.png) [@chrefr](https://internals.rust-lang.org/u/chrefr)\
**Post date:** [October 24, 2026, 5:13pm UTC](https://internals.rust-lang.org/t/rfc-3678-why-should-final-rule-out-downstream-use-cases-that-library-authors-never-anticipated/24701/5 "2026-10-24T17:13:28Z")

</div>

(post deleted by author)

---

<div class="post-metadata">

**Author:** ![matt1985](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/matt1985/32/4772_2.png) [@matt1985](https://internals.rust-lang.org/u/matt1985)\
**Post date:** [October 24, 2026, 7:09pm UTC](https://internals.rust-lang.org/t/rfc-3678-why-should-final-rule-out-downstream-use-cases-that-library-authors-never-anticipated/24701/6 "2026-10-24T19:09:05Z")

</div>

Among other things, `final` is an alternative for module-scoped items that are related to the trait. Since module-scoped items can't be overriden, `final` associated items is a fine way to express that.

---

<div class="post-metadata">

**Author:** ![josh](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/josh/32/5934_2.png) [@josh](https://internals.rust-lang.org/u/josh)\
**Post date:** [October 24, 2026, 7:19pm UTC](https://internals.rust-lang.org/t/rfc-3678-why-should-final-rule-out-downstream-use-cases-that-library-authors-never-anticipated/24701/7 "2026-10-24T19:19:46Z")

</div>

Exactly. The crate author didn't _have_ to provide the method at all. They chose to provide it in a way you can call but not implement.

If you run into a library that provides a `final` method and you want to do something that would be easier if it weren't `final`, then report it to them upstream, and you always have the option of forking it to build your own demonstration of why it's useful, and using the result yourself.

---

<div class="post-metadata">

**Author:** ![ais523](https://avatars.discourse-cdn.com/v4/letter/a/a183cd/32.png) [@ais523](https://internals.rust-lang.org/u/ais523)\
**Post date:** [October 24, 2026, 7:43pm UTC](https://internals.rust-lang.org/t/rfc-3678-why-should-final-rule-out-downstream-use-cases-that-library-authors-never-anticipated/24701/8 "2026-10-24T19:43:22Z")

</div>

Another good reason not to allow the overriding of a `final` associated item is that future versions of the library might assume that their downstream hasn't done that. For example, suppose a trait defined in a library has associated functions `x` and `y`, with `x` being `final`. A downstream crate might override `x`, defining it in terms of `y`; but a future version of the library might change the implementation of `y`, defining it in terms of `x`. If the downstream crate updates to the new version of the library, the resulting program will now crash with a stack overflow at runtime because the two functions are defined in terms of each other.

As such, you have to prevent downstream use cases that would override a `final` associated item in order to give the upstream library the flexibility to change their code in the future (in much the same way that `#[non_exhaustive]` prevents the downstream assuming that a `struct` won't get new fields or an `enum` won't get new variants).
