The "method references Self" object-safety rule is overly restrictive

2ffb1a4
Opened by Michael Hewson at 2024-12-21 05:01:44

Is there any reason why the following trait method can't be object safe?

trait Trait {
    fn take_and_return_box(self: Box<Self>) -> Box<Self>;
}

Intuitively, it would return Box<T> when called on a Box<T> where T: Trait, and Box<Trait> when called on a Box<Trait>. The compiler would do an unsize coercion on the Box<T> returned by the vtable method, combining it with the vtable of the Box<Trait> that was passed in.

If I'm not mistaken, the object safety rule could be relaxed to allow methods that reference the Self type in the return value, as long as it's a type that meets certain CoerceUnsized requirements:

  • Let ReturnType<Self> be the return type of the method, e.g. Box<Self>
  • For a given type T, let ReturnType<T> be ReturnType<Self> with every occurrence of Self replaced with T
  • The trait method is object safe if the following conditions are met:
    • ReturnType<Trait>: Sized
    • for every type T: Unsize<Trait>, ReturnType<T>: CoerceUnsized<Trait>.

Note: this is very similar to what I think the object-safety rules for arbitrary_self_types (#44874) will look like