fn receiver_is_dispatchable<'tcx>(
tcx: TyCtxt<'tcx>,
method: AssocItem,
receiver_ty: Ty<'tcx>
) -> boolExpand description
Checks the method’s receiver (the self argument) can be dispatched on when Self is a
trait object. We require that DispatchableFromDyn be implemented for the receiver type
in the following way:
-
let
Receiverbe the type of theselfargument, i.eSelf,&Self,Rc<Self>, -
require the following bound:
ⓘReceiver[Self => T]: DispatchFromDyn<Receiver[Self => dyn Trait]>where
Foo[X => Y]means “the same type asFoo, but withXreplaced withY” (instantiation notation).
Some examples of receiver types and their required obligation:
&'a mut selfrequires&'a mut Self: DispatchFromDyn<&'a mut dyn Trait>,self: Rc<Self>requiresRc<Self>: DispatchFromDyn<Rc<dyn Trait>>,self: Pin<Box<Self>>requiresPin<Box<Self>>: DispatchFromDyn<Pin<Box<dyn Trait>>>.
The only case where the receiver is not dispatchable, but is still a valid receiver
type (just not object-safe), is when there is more than one level of pointer indirection.
E.g., self: &&Self, self: &Rc<Self>, self: Box<Box<Self>>. In these cases, there
is no way, or at least no inexpensive way, to coerce the receiver from the version where
Self = dyn Trait to the version where Self = T, where T is the unknown erased type
contained by the trait object, because the object that needs to be coerced is behind
a pointer.
In practice, we cannot use dyn Trait explicitly in the obligation because it would result
in a new check that Trait is object safe, creating a cycle (until object_safe_for_dispatch
is stabilized, see tracking issue https://github.com/rust-lang/rust/issues/43561).
Instead, we fudge a little by introducing a new type parameter U such that
Self: Unsize<U> and U: Trait + ?Sized, and use U in place of dyn Trait.
Written as a chalk-style query:
forall (U: Trait + ?Sized) {
if (Self: Unsize<U>) {
Receiver: DispatchFromDyn<Receiver[Self => U]>
}
}for self: &'a mut Self, this means &'a mut Self: DispatchFromDyn<&'a mut U>
for self: Rc<Self>, this means Rc<Self>: DispatchFromDyn<Rc<U>>
for self: Pin<Box<Self>>, this means Pin<Box<Self>>: DispatchFromDyn<Pin<Box<U>>>