Idea: trait methods with un-overridable implementations

That's a great example, but I don't think it proves what you claim it's proving. "The .baz() method prints () because it's being monomorphized for ()" --- this isn't true. The .baz() methods follows the usual rules of method resolution: it calls <dyn Foo>::baz(t), which calls the compiler-provided method implementation:

impl Foo for dyn Foo {
    fn baz(&self) {
        unsafe { (*vtable_ptr(self)).baz(data_ptr(self)); }
    }
}

The function pointer in the vtable, in turn, corresponds to <() as Foo>::baz.

This shows that dynamic dispatch crucially depends on the ability to override default trait implementations.

If the final feature is self-consistent, this implies that final methods cannot be allowed to work with dynamic dispatch on trait objects. Arguably, this makes them even less useful.

If we allow dynamic dispatch for final methods, it would be a weird exception from the rules specifically for the compiler, and would lead to surprising resolution ambiguities, like in the example above.

2 Likes

Monomorphisation is a process of turning generic a foo<T> into a number of foo_sometype for each type it is instantiated with. There is no longer a singleton foo you can call, hence you need vtable if your object has been type-erased.

The type_name example 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.[1]

Whatever ends up happening to fix that bug will probably involve weird exceptions no matter what. The new trait solver already prefers the user implementation in more cases.

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.


  1. See this example of preferring the built-in implementation causing unsoundness. â†Šī¸Ž

1 Like

Fwiw, I had written a helper attribute to achieve this very thing:

1 Like