diff --git a/compiler/rustc_hir_typeck/src/method/confirm.rs b/compiler/rustc_hir_typeck/src/method/confirm.rs index 0c93c9817b467..ea06518a6d3d0 100644 --- a/compiler/rustc_hir_typeck/src/method/confirm.rs +++ b/compiler/rustc_hir_typeck/src/method/confirm.rs @@ -347,9 +347,17 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { // yield an object-type (e.g., `&Object` or `Box` // etc). - // FIXME: this feels, like, super dubious - self.fcx - .autoderef(self.span, self_ty) + let mut autoderef = self.fcx.autoderef(self.span, self_ty); + + // We don't need to gate this behind arbitrary self types + // per se, but it does make things a bit more gated. + if self.tcx.features().arbitrary_self_types() + || self.tcx.features().arbitrary_self_types_pointers() + { + autoderef = autoderef.use_receiver_trait(); + } + + autoderef .include_raw_pointers() .find_map(|(ty, _)| match ty.kind() { ty::Dynamic(data, ..) => Some(closure( diff --git a/tests/ui/self/arbitrary_self_types_dispatch_to_vtable.rs b/tests/ui/self/arbitrary_self_types_dispatch_to_vtable.rs new file mode 100644 index 0000000000000..f9e346ea11e21 --- /dev/null +++ b/tests/ui/self/arbitrary_self_types_dispatch_to_vtable.rs @@ -0,0 +1,33 @@ +//@ check-pass + +#![feature(derive_coerce_pointee)] +#![feature(arbitrary_self_types)] + +use std::marker::CoercePointee; +use std::ops::Receiver; + +// `CoercePointee` isn't needed here, it's just a simpler +// (and more conceptual) way of deriving `DispatchFromDyn`. +// You could think of `MyDispatcher` as a smart pointer +// that just doesn't deref to its target type. +#[derive(CoercePointee)] +#[repr(transparent)] +struct MyDispatcher(*const T); + +impl Receiver for MyDispatcher { + type Target = T; +} +struct Test; + +trait Trait { + fn test(self: MyDispatcher); +} + +impl Trait for Test { + fn test(self: MyDispatcher) { + todo!() + } +} +fn main() { + MyDispatcher::(core::ptr::null_mut::()).test(); +}