Skip to main content

receiver_is_dispatchable

Function receiver_is_dispatchable 

Source
fn receiver_is_dispatchable<'tcx>(
    tcx: TyCtxt<'tcx>,
    method: AssocItem,
    receiver_ty: Ty<'tcx>,
) -> bool
Expand 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 Receiver be the type of the self argument, i.e Self, &Self, Rc<Self>,

  • require the following bound:

    Receiver[Self => T]: DispatchFromDyn<Receiver[Self => dyn Trait]>

    where Foo[X => Y] means “the same type as Foo, but with X replaced with Y” (instantiation notation).

Some examples of receiver types and their required obligation:

  • &'a mut self requires &'a mut Self: DispatchFromDyn<&'a mut dyn Trait>,
  • self: Rc<Self> requires Rc<Self>: DispatchFromDyn<Rc<dyn Trait>>,
  • self: Pin<Box<Self>> requires Pin<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 dyn compatible), 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.

If lowering already produced an error in the receiver type, we conservatively treat it as undispatchable instead of asking the solver.

In practice, we cannot use dyn Trait explicitly in the obligation because it would result in a new check that Trait is dyn-compatible, creating a cycle. Instead, we emulate a placeholder by introducing a new type parameter U such that Self: Unsize<U> and U: Trait + MetaSized, and use U in place of dyn Trait.

Written as a chalk-style query:

forall (U: Trait + MetaSized) {
    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>>>