receiver_is_dispatchable in rustc_trait_selection::traits::dyn_compatibility - Rust
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:

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>>>`