Skip to content

Keep dyn-compatible final methods in the vtable#153696

Open
mu001999 wants to merge 1 commit intorust-lang:mainfrom
mu001999-contrib:fix/final
Open

Keep dyn-compatible final methods in the vtable#153696
mu001999 wants to merge 1 commit intorust-lang:mainfrom
mu001999-contrib:fix/final

Conversation

@mu001999
Copy link
Contributor

@mu001999 mu001999 commented Mar 11, 2026

Fixes #153649

Current implementation will exclude final methods from the trait's vtable, this PR will keep those dyn-compatible ones in the trait's vtable.

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Mar 11, 2026
@rustbot
Copy link
Collaborator

rustbot commented Mar 11, 2026

r? @dingxiangfei2009

rustbot has assigned @dingxiangfei2009.
They will have a look at your PR within the next two weeks and either review your PR or reassign to another reviewer.

Use r? to explicitly pick a reviewer

Why was this reviewer chosen?

The reviewer was selected based on:

  • Owners of files modified in this PR: compiler
  • compiler expanded to 69 candidates
  • Random selection from 16 candidates

@eggyal
Copy link
Contributor

eggyal commented Mar 11, 2026

I don't think this is sound. If the final method is not dyn compatible, then surely it should definitely NOT appear in the vtable and should also not be available on dyn Trait (if the trait can itself be dyn compatible at all)?

@mu001999
Copy link
Contributor Author

RFC has the statement says:

A final fn never prevents a trait from having dyn-compatibility; the trait can remain dyn-compatible as long as all non-final methods support dyn-compatibility. This also means that a final fn can always be called on a dyn Trait, even if the same method as a non-final fn would not have been dyn-compatible.

And with allowing final methods not dyn compatible to be available on dyn Trait can allow the following usage:

#![feature(final_associated_functions)]

trait Trait {
    fn foo(&self);

    final fn bar<T>(&self, x: T) -> T {
        self.foo(); // Call dyn-compatible methods
        x
    }
}

struct Foo;
impl Trait for Foo {
    fn foo(&self) {
        println!("Foo");
    }
}

struct Bar;
impl Trait for Bar {
    fn foo(&self) {
        println!("Bar");
    }
}

fn foo(t: &dyn Trait) {
    let _ = t.bar(0i32);
}

fn main() {
    foo(&Foo);
    foo(&Bar);
}

@QuineDot
Copy link

Repeating a comment from IRLO:

[The cited issue] is related to #57893; namely, always preferring the user defined method in cases of overlap breaks invocations of .type_id() on dyn Any (preferring the built-in implementation in that case is load bearing). Which is considered unfortunate as preferring the user implementation is the best fix from a soundness perspective, as I understand it. (See this example of preferring the built-in implementation causing unsoundness.)

[...]

If final fn is always not in the vtable, it would basically act like preferring the user implementation. Corollary: Any::type_id could not be a final fn.


The cited issue shows that this applies to custom downcasting impls, not just dyn Any. An alternative to this PR is to just not make the method final. There is probably a larger lang/types decision to be made here wrt. final methods and vtables.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

final methods should work the same as without it (if it works without it)

5 participants