about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0307.md6
-rw-r--r--compiler/rustc_hir_analysis/messages.ftl4
-rw-r--r--compiler/rustc_hir_analysis/src/autoderef.rs37
-rw-r--r--compiler/rustc_hir_analysis/src/check/wfcheck.rs27
-rw-r--r--compiler/rustc_hir_typeck/src/method/probe.rs97
-rw-r--r--compiler/rustc_middle/src/traits/query.rs12
-rw-r--r--tests/ui/async-await/inference_var_self_argument.stderr4
-rw-r--r--tests/ui/async-await/issue-66312.stderr4
-rw-r--r--tests/ui/feature-gates/feature-gate-arbitrary-self-types-pointers.stderr6
-rw-r--r--tests/ui/feature-gates/feature-gate-arbitrary-self-types.stderr6
-rw-r--r--tests/ui/feature-gates/feature-gate-arbitrary_self_types-raw-pointer.stderr6
-rw-r--r--tests/ui/feature-gates/feature-gate-dispatch-from-dyn-cell.stderr4
-rw-r--r--tests/ui/issues/issue-56806.stderr4
-rw-r--r--tests/ui/lifetimes/could-not-resolve-issue-121503.stderr2
-rw-r--r--tests/ui/methods/call_method_unknown_referent.rs48
-rw-r--r--tests/ui/methods/call_method_unknown_referent.stderr29
-rw-r--r--tests/ui/methods/call_method_unknown_referent2.rs24
-rw-r--r--tests/ui/self/arbitrary-self-from-method-substs-with-receiver.rs64
-rw-r--r--tests/ui/self/arbitrary-self-from-method-substs-with-receiver.stderr70
-rw-r--r--tests/ui/self/arbitrary-self-from-method-substs.default.stderr4
-rw-r--r--tests/ui/self/arbitrary-self-opaque.stderr4
-rw-r--r--tests/ui/self/arbitrary_self_types_generic_over_receiver.rs23
-rw-r--r--tests/ui/self/arbitrary_self_types_generic_over_receiver.stderr59
-rw-r--r--tests/ui/self/arbitrary_self_types_lifetime_elision.rs27
-rw-r--r--tests/ui/self/arbitrary_self_types_no_generics.rs32
-rw-r--r--tests/ui/self/arbitrary_self_types_not_allow_call_with_no_deref.rs38
-rw-r--r--tests/ui/self/arbitrary_self_types_not_allow_call_with_no_deref.stderr39
-rw-r--r--tests/ui/self/arbitrary_self_types_recursive_receiver.rs32
-rw-r--r--tests/ui/self/arbitrary_self_types_struct_receiver_trait.rs31
-rw-r--r--tests/ui/self/arbitrary_self_types_trait_receiver_trait.rs25
-rw-r--r--tests/ui/span/issue-27522.stderr4
-rw-r--r--tests/ui/suggestions/dyn-incompatible-trait-should-use-where-sized.stderr4
-rw-r--r--tests/ui/traits/const-traits/effects/auxiliary/minicore.rs10
-rw-r--r--tests/ui/traits/issue-78372.stderr4
-rw-r--r--tests/ui/type-alias-impl-trait/method_resolution3.current.stderr8
-rw-r--r--tests/ui/type-alias-impl-trait/method_resolution3.next.stderr8
-rw-r--r--tests/ui/type-alias-impl-trait/method_resolution4.current.stderr8
-rw-r--r--tests/ui/type-alias-impl-trait/method_resolution4.next.stderr8
-rw-r--r--tests/ui/ufcs/ufcs-explicit-self-bad.stderr12
39 files changed, 737 insertions, 97 deletions
diff --git a/compiler/rustc_error_codes/src/error_codes/E0307.md b/compiler/rustc_error_codes/src/error_codes/E0307.md
index 0d29d56ea1a..b9c0493e8d6 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0307.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0307.md
@@ -65,8 +65,10 @@ impl Trait for Foo {
 ```
 
 The nightly feature [Arbitrary self types][AST] extends the accepted
-set of receiver types to also include any type that can dereference to
-`Self`:
+set of receiver types to also include any type that implements the
+`Receiver` trait and can follow its chain of `Target` types to `Self`.
+There's a blanket implementation of `Receiver` for `T: Deref`, so any
+type which dereferences to `Self` can be used.
 
 ```
 #![feature(arbitrary_self_types)]
diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl
index 32498d9c5ab..25feb95d5df 100644
--- a/compiler/rustc_hir_analysis/messages.ftl
+++ b/compiler/rustc_hir_analysis/messages.ftl
@@ -241,10 +241,10 @@ hir_analysis_invalid_generic_receiver_ty_help =
     use a concrete type such as `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
 
 hir_analysis_invalid_receiver_ty = invalid `self` parameter type: `{$receiver_ty}`
-    .note = type of `self` must be `Self` or a type that dereferences to it
+    .note = type of `self` must be `Self` or some type implementing `Receiver`
 
 hir_analysis_invalid_receiver_ty_help =
-    consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
+    consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>`
 
 hir_analysis_invalid_union_field =
     field must implement `Copy` or be wrapped in `ManuallyDrop<...>` to be used in a union
diff --git a/compiler/rustc_hir_analysis/src/autoderef.rs b/compiler/rustc_hir_analysis/src/autoderef.rs
index 5a66c31a0cc..d8e9227a87c 100644
--- a/compiler/rustc_hir_analysis/src/autoderef.rs
+++ b/compiler/rustc_hir_analysis/src/autoderef.rs
@@ -18,7 +18,6 @@ pub enum AutoderefKind {
     /// A type which must dispatch to a `Deref` implementation.
     Overloaded,
 }
-
 struct AutoderefSnapshot<'tcx> {
     at_start: bool,
     reached_recursion_limit: bool,
@@ -27,6 +26,10 @@ struct AutoderefSnapshot<'tcx> {
     obligations: PredicateObligations<'tcx>,
 }
 
+/// Recursively dereference a type, considering both built-in
+/// dereferences (`*`) and the `Deref` trait.
+/// Although called `Autoderef` it can be configured to use the
+/// `Receiver` trait instead of the `Deref` trait.
 pub struct Autoderef<'a, 'tcx> {
     // Meta infos:
     infcx: &'a InferCtxt<'tcx>,
@@ -39,6 +42,7 @@ pub struct Autoderef<'a, 'tcx> {
 
     // Configurations:
     include_raw_pointers: bool,
+    use_receiver_trait: bool,
     silence_errors: bool,
 }
 
@@ -69,6 +73,10 @@ impl<'a, 'tcx> Iterator for Autoderef<'a, 'tcx> {
         }
 
         // Otherwise, deref if type is derefable:
+        // NOTE: in the case of self.use_receiver_trait = true, you might think it would
+        // be better to skip this clause and use the Overloaded case only, since &T
+        // and &mut T implement Receiver. But built-in derefs apply equally to Receiver
+        // and Deref, and this has benefits for const and the emitted MIR.
         let (kind, new_ty) =
             if let Some(ty) = self.state.cur_ty.builtin_deref(self.include_raw_pointers) {
                 debug_assert_eq!(ty, self.infcx.resolve_vars_if_possible(ty));
@@ -111,7 +119,7 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> {
         body_def_id: LocalDefId,
         span: Span,
         base_ty: Ty<'tcx>,
-    ) -> Autoderef<'a, 'tcx> {
+    ) -> Self {
         Autoderef {
             infcx,
             span,
@@ -125,6 +133,7 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> {
                 reached_recursion_limit: false,
             },
             include_raw_pointers: false,
+            use_receiver_trait: false,
             silence_errors: false,
         }
     }
@@ -137,8 +146,13 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> {
             return None;
         }
 
-        // <ty as Deref>
-        let trait_ref = ty::TraitRef::new(tcx, tcx.lang_items().deref_trait()?, [ty]);
+        // <ty as Deref>, or whatever the equivalent trait is that we've been asked to walk.
+        let (trait_def_id, trait_target_def_id) = if self.use_receiver_trait {
+            (tcx.lang_items().receiver_trait()?, tcx.lang_items().receiver_target()?)
+        } else {
+            (tcx.lang_items().deref_trait()?, tcx.lang_items().deref_target()?)
+        };
+        let trait_ref = ty::TraitRef::new(tcx, trait_def_id, [ty]);
         let cause = traits::ObligationCause::misc(self.span, self.body_id);
         let obligation = traits::Obligation::new(
             tcx,
@@ -151,11 +165,8 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> {
             return None;
         }
 
-        let (normalized_ty, obligations) = self.structurally_normalize(Ty::new_projection(
-            tcx,
-            tcx.lang_items().deref_target()?,
-            [ty],
-        ))?;
+        let (normalized_ty, obligations) =
+            self.structurally_normalize(Ty::new_projection(tcx, trait_target_def_id, [ty]))?;
         debug!("overloaded_deref_ty({:?}) = ({:?}, {:?})", ty, normalized_ty, obligations);
         self.state.obligations.extend(obligations);
 
@@ -234,6 +245,14 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> {
         self
     }
 
+    /// Use `core::ops::Receiver` and `core::ops::Receiver::Target` as
+    /// the trait and associated type to iterate, instead of
+    /// `core::ops::Deref` and `core::ops::Deref::Target`
+    pub fn use_receiver_trait(mut self) -> Self {
+        self.use_receiver_trait = true;
+        self
+    }
+
     pub fn silence_errors(mut self) -> Self {
         self.silence_errors = true;
         self
diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
index c9773972d9a..57264d0bd2a 100644
--- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs
+++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
@@ -1821,13 +1821,18 @@ fn receiver_is_valid<'tcx>(
 
     let mut autoderef = Autoderef::new(infcx, wfcx.param_env, wfcx.body_def_id, span, receiver_ty);
 
+    // The `arbitrary_self_types` feature allows custom smart pointer
+    // types to be method receivers, as identified by following the Receiver<Target=T>
+    // chain.
+    if arbitrary_self_types_enabled.is_some() {
+        autoderef = autoderef.use_receiver_trait();
+    }
+
     // The `arbitrary_self_types_pointers` feature allows raw pointer receivers like `self: *const Self`.
     if arbitrary_self_types_enabled == Some(ArbitrarySelfTypesLevel::WithPointers) {
         autoderef = autoderef.include_raw_pointers();
     }
 
-    let receiver_trait_def_id = tcx.require_lang_item(LangItem::LegacyReceiver, Some(span));
-
     // Keep dereferencing `receiver_ty` until we get to `self_ty`.
     while let Some((potential_self_ty, _)) = autoderef.next() {
         debug!(
@@ -1849,11 +1854,13 @@ fn receiver_is_valid<'tcx>(
         }
 
         // Without `feature(arbitrary_self_types)`, we require that each step in the
-        // deref chain implement `receiver`.
+        // deref chain implement `LegacyReceiver`.
         if arbitrary_self_types_enabled.is_none() {
-            if !receiver_is_implemented(
+            let legacy_receiver_trait_def_id =
+                tcx.require_lang_item(LangItem::LegacyReceiver, Some(span));
+            if !legacy_receiver_is_implemented(
                 wfcx,
-                receiver_trait_def_id,
+                legacy_receiver_trait_def_id,
                 cause.clone(),
                 potential_self_ty,
             ) {
@@ -1866,7 +1873,7 @@ fn receiver_is_valid<'tcx>(
                 cause.clone(),
                 wfcx.param_env,
                 potential_self_ty,
-                receiver_trait_def_id,
+                legacy_receiver_trait_def_id,
             );
         }
     }
@@ -1875,14 +1882,14 @@ fn receiver_is_valid<'tcx>(
     Err(ReceiverValidityError::DoesNotDeref)
 }
 
-fn receiver_is_implemented<'tcx>(
+fn legacy_receiver_is_implemented<'tcx>(
     wfcx: &WfCheckingCtxt<'_, 'tcx>,
-    receiver_trait_def_id: DefId,
+    legacy_receiver_trait_def_id: DefId,
     cause: ObligationCause<'tcx>,
     receiver_ty: Ty<'tcx>,
 ) -> bool {
     let tcx = wfcx.tcx();
-    let trait_ref = ty::TraitRef::new(tcx, receiver_trait_def_id, [receiver_ty]);
+    let trait_ref = ty::TraitRef::new(tcx, legacy_receiver_trait_def_id, [receiver_ty]);
 
     let obligation = Obligation::new(tcx, cause, wfcx.param_env, trait_ref);
 
@@ -1890,7 +1897,7 @@ fn receiver_is_implemented<'tcx>(
         true
     } else {
         debug!(
-            "receiver_is_implemented: type `{:?}` does not implement `Receiver` trait",
+            "receiver_is_implemented: type `{:?}` does not implement `LegacyReceiver` trait",
             receiver_ty
         );
         false
diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs
index 039c117c099..91e65af8df9 100644
--- a/compiler/rustc_hir_typeck/src/method/probe.rs
+++ b/compiler/rustc_hir_typeck/src/method/probe.rs
@@ -366,6 +366,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         autoderefs: 0,
                         from_unsafe_deref: false,
                         unsize: false,
+                        reachable_via_deref: true,
                     }]),
                     opt_bad_ty: None,
                     reached_recursion_limit: false,
@@ -516,47 +517,93 @@ fn method_autoderef_steps<'tcx>(
     let (ref infcx, goal, inference_vars) = tcx.infer_ctxt().build_with_canonical(DUMMY_SP, &goal);
     let ParamEnvAnd { param_env, value: self_ty } = goal;
 
-    let mut autoderef =
+    // If arbitrary self types is not enabled, we follow the chain of
+    // `Deref<Target=T>`. If arbitrary self types is enabled, we instead
+    // follow the chain of `Receiver<Target=T>`, but we also record whether
+    // such types are reachable by following the (potentially shorter)
+    // chain of `Deref<Target=T>`. We will use the first list when finding
+    // potentially relevant function implementations (e.g. relevant impl blocks)
+    // but the second list when determining types that the receiver may be
+    // converted to, in order to find out which of those methods might actually
+    // be callable.
+    let mut autoderef_via_deref =
         Autoderef::new(infcx, param_env, hir::def_id::CRATE_DEF_ID, DUMMY_SP, self_ty)
             .include_raw_pointers()
             .silence_errors();
-    let mut reached_raw_pointer = false;
-    let mut steps: Vec<_> = autoderef
-        .by_ref()
-        .map(|(ty, d)| {
-            let step = CandidateStep {
-                self_ty: infcx.make_query_response_ignoring_pending_obligations(inference_vars, ty),
-                autoderefs: d,
-                from_unsafe_deref: reached_raw_pointer,
-                unsize: false,
-            };
-            if let ty::RawPtr(_, _) = ty.kind() {
-                // all the subsequent steps will be from_unsafe_deref
-                reached_raw_pointer = true;
-            }
-            step
-        })
-        .collect();
 
-    let final_ty = autoderef.final_ty(true);
+    let mut reached_raw_pointer = false;
+    let arbitrary_self_types_enabled =
+        tcx.features().arbitrary_self_types() || tcx.features().arbitrary_self_types_pointers();
+    let (mut steps, reached_recursion_limit): (Vec<_>, bool) = if arbitrary_self_types_enabled {
+        let reachable_via_deref =
+            autoderef_via_deref.by_ref().map(|_| true).chain(std::iter::repeat(false));
+
+        let mut autoderef_via_receiver =
+            Autoderef::new(infcx, param_env, hir::def_id::CRATE_DEF_ID, DUMMY_SP, self_ty)
+                .include_raw_pointers()
+                .use_receiver_trait()
+                .silence_errors();
+        let steps = autoderef_via_receiver
+            .by_ref()
+            .zip(reachable_via_deref)
+            .map(|((ty, d), reachable_via_deref)| {
+                let step = CandidateStep {
+                    self_ty: infcx
+                        .make_query_response_ignoring_pending_obligations(inference_vars, ty),
+                    autoderefs: d,
+                    from_unsafe_deref: reached_raw_pointer,
+                    unsize: false,
+                    reachable_via_deref,
+                };
+                if ty.is_unsafe_ptr() {
+                    // all the subsequent steps will be from_unsafe_deref
+                    reached_raw_pointer = true;
+                }
+                step
+            })
+            .collect();
+        (steps, autoderef_via_receiver.reached_recursion_limit())
+    } else {
+        let steps = autoderef_via_deref
+            .by_ref()
+            .map(|(ty, d)| {
+                let step = CandidateStep {
+                    self_ty: infcx
+                        .make_query_response_ignoring_pending_obligations(inference_vars, ty),
+                    autoderefs: d,
+                    from_unsafe_deref: reached_raw_pointer,
+                    unsize: false,
+                    reachable_via_deref: true,
+                };
+                if ty.is_unsafe_ptr() {
+                    // all the subsequent steps will be from_unsafe_deref
+                    reached_raw_pointer = true;
+                }
+                step
+            })
+            .collect();
+        (steps, autoderef_via_deref.reached_recursion_limit())
+    };
+    let final_ty = autoderef_via_deref.final_ty(true);
     let opt_bad_ty = match final_ty.kind() {
         ty::Infer(ty::TyVar(_)) | ty::Error(_) => Some(MethodAutoderefBadTy {
             reached_raw_pointer,
             ty: infcx.make_query_response_ignoring_pending_obligations(inference_vars, final_ty),
         }),
         ty::Array(elem_ty, _) => {
-            let dereferences = steps.len() - 1;
-
+            let autoderefs = steps.iter().filter(|s| s.reachable_via_deref).count() - 1;
             steps.push(CandidateStep {
                 self_ty: infcx.make_query_response_ignoring_pending_obligations(
                     inference_vars,
                     Ty::new_slice(infcx.tcx, *elem_ty),
                 ),
-                autoderefs: dereferences,
+                autoderefs,
                 // this could be from an unsafe deref if we had
                 // a *mut/const [T; N]
                 from_unsafe_deref: reached_raw_pointer,
                 unsize: true,
+                reachable_via_deref: true, // this is always the final type from
+                                           // autoderef_via_deref
             });
 
             None
@@ -569,7 +616,7 @@ fn method_autoderef_steps<'tcx>(
     MethodAutoderefStepsResult {
         steps: tcx.arena.alloc_from_iter(steps),
         opt_bad_ty: opt_bad_ty.map(|ty| &*tcx.arena.alloc(ty)),
-        reached_recursion_limit: autoderef.reached_recursion_limit(),
+        reached_recursion_limit,
     }
 }
 
@@ -1065,6 +1112,10 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
     ) -> Option<PickResult<'tcx>> {
         self.steps
             .iter()
+            // At this point we're considering the types to which the receiver can be converted,
+            // so we want to follow the `Deref` chain not the `Receiver` chain. Filter out
+            // steps which can only be reached by following the (longer) `Receiver` chain.
+            .filter(|step| step.reachable_via_deref)
             .filter(|step| {
                 debug!("pick_all_method: step={:?}", step);
                 // skip types that are from a type error or that would require dereferencing
diff --git a/compiler/rustc_middle/src/traits/query.rs b/compiler/rustc_middle/src/traits/query.rs
index eeed5118592..f049da95f29 100644
--- a/compiler/rustc_middle/src/traits/query.rs
+++ b/compiler/rustc_middle/src/traits/query.rs
@@ -149,11 +149,21 @@ pub struct CandidateStep<'tcx> {
     /// `foo.by_raw_ptr()` will work and `foo.by_ref()` won't.
     pub from_unsafe_deref: bool,
     pub unsize: bool,
+    /// We will generate CandidateSteps which are reachable via a chain
+    /// of following `Receiver`. The first 'n' of those will be reachable
+    /// by following a chain of 'Deref' instead (since there's a blanket
+    /// implementation of Receiver for Deref).
+    /// We use the entire set of steps when identifying method candidates
+    /// (e.g. identifying relevant `impl` blocks) but only those that are
+    /// reachable via Deref when examining what the receiver type can
+    /// be converted into by autodereffing.
+    pub reachable_via_deref: bool,
 }
 
 #[derive(Copy, Clone, Debug, HashStable)]
 pub struct MethodAutoderefStepsResult<'tcx> {
-    /// The valid autoderef steps that could be found.
+    /// The valid autoderef steps that could be found by following a chain
+    /// of `Receiver<Target=T>` or `Deref<Target=T>` trait implementations.
     pub steps: &'tcx [CandidateStep<'tcx>],
     /// If Some(T), a type autoderef reported an error on.
     pub opt_bad_ty: Option<&'tcx MethodAutoderefBadTy<'tcx>>,
diff --git a/tests/ui/async-await/inference_var_self_argument.stderr b/tests/ui/async-await/inference_var_self_argument.stderr
index 7b7b3dbc757..a33c5f7b07d 100644
--- a/tests/ui/async-await/inference_var_self_argument.stderr
+++ b/tests/ui/async-await/inference_var_self_argument.stderr
@@ -4,8 +4,8 @@ error[E0307]: invalid `self` parameter type: `&dyn Foo`
 LL |     async fn foo(self: &dyn Foo) {
    |                        ^^^^^^^^
    |
-   = note: type of `self` must be `Self` or a type that dereferences to it
-   = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
+   = note: type of `self` must be `Self` or some type implementing `Receiver`
+   = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>`
 
 error[E0038]: the trait `Foo` cannot be made into an object
   --> $DIR/inference_var_self_argument.rs:5:5
diff --git a/tests/ui/async-await/issue-66312.stderr b/tests/ui/async-await/issue-66312.stderr
index c95ae1147df..f4db949a5f4 100644
--- a/tests/ui/async-await/issue-66312.stderr
+++ b/tests/ui/async-await/issue-66312.stderr
@@ -4,8 +4,8 @@ error[E0307]: invalid `self` parameter type: `T`
 LL |     fn is_some(self: T);
    |                      ^
    |
-   = note: type of `self` must be `Self` or a type that dereferences to it
-   = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
+   = note: type of `self` must be `Self` or some type implementing `Receiver`
+   = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>`
 
 error[E0308]: mismatched types
   --> $DIR/issue-66312.rs:9:8
diff --git a/tests/ui/feature-gates/feature-gate-arbitrary-self-types-pointers.stderr b/tests/ui/feature-gates/feature-gate-arbitrary-self-types-pointers.stderr
index 3bb93cf2ea0..0c5b8a4d3b6 100644
--- a/tests/ui/feature-gates/feature-gate-arbitrary-self-types-pointers.stderr
+++ b/tests/ui/feature-gates/feature-gate-arbitrary-self-types-pointers.stderr
@@ -7,7 +7,7 @@ LL |     fn foo(self: *const Self) {}
    = note: see issue #44874 <https://github.com/rust-lang/rust/issues/44874> for more information
    = help: add `#![feature(arbitrary_self_types_pointers)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-   = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
+   = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>`
 
 error[E0658]: `*mut Bar` cannot be used as the type of `self` without the `arbitrary_self_types_pointers` feature
   --> $DIR/feature-gate-arbitrary-self-types-pointers.rs:12:18
@@ -18,7 +18,7 @@ LL |     fn bar(self: *mut Self) {}
    = note: see issue #44874 <https://github.com/rust-lang/rust/issues/44874> for more information
    = help: add `#![feature(arbitrary_self_types_pointers)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-   = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
+   = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>`
 
 error[E0658]: `*const Self` cannot be used as the type of `self` without the `arbitrary_self_types_pointers` feature
   --> $DIR/feature-gate-arbitrary-self-types-pointers.rs:2:18
@@ -29,7 +29,7 @@ LL |     fn foo(self: *const Self);
    = note: see issue #44874 <https://github.com/rust-lang/rust/issues/44874> for more information
    = help: add `#![feature(arbitrary_self_types_pointers)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-   = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
+   = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>`
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/feature-gates/feature-gate-arbitrary-self-types.stderr b/tests/ui/feature-gates/feature-gate-arbitrary-self-types.stderr
index 7f0e02c91f8..3ffba533d63 100644
--- a/tests/ui/feature-gates/feature-gate-arbitrary-self-types.stderr
+++ b/tests/ui/feature-gates/feature-gate-arbitrary-self-types.stderr
@@ -7,7 +7,7 @@ LL |     fn foo(self: Ptr<Self>) {}
    = note: see issue #44874 <https://github.com/rust-lang/rust/issues/44874> for more information
    = help: add `#![feature(arbitrary_self_types)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-   = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
+   = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>`
 
 error[E0658]: `Box<Ptr<Bar>>` cannot be used as the type of `self` without the `arbitrary_self_types` feature
   --> $DIR/feature-gate-arbitrary-self-types.rs:26:18
@@ -18,7 +18,7 @@ LL |     fn bar(self: Box<Ptr<Self>>) {}
    = note: see issue #44874 <https://github.com/rust-lang/rust/issues/44874> for more information
    = help: add `#![feature(arbitrary_self_types)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-   = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
+   = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>`
 
 error[E0658]: `Ptr<Self>` cannot be used as the type of `self` without the `arbitrary_self_types` feature
   --> $DIR/feature-gate-arbitrary-self-types.rs:16:18
@@ -29,7 +29,7 @@ LL |     fn foo(self: Ptr<Self>);
    = note: see issue #44874 <https://github.com/rust-lang/rust/issues/44874> for more information
    = help: add `#![feature(arbitrary_self_types)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-   = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
+   = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>`
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/feature-gates/feature-gate-arbitrary_self_types-raw-pointer.stderr b/tests/ui/feature-gates/feature-gate-arbitrary_self_types-raw-pointer.stderr
index 856e0595331..3eb87adb33a 100644
--- a/tests/ui/feature-gates/feature-gate-arbitrary_self_types-raw-pointer.stderr
+++ b/tests/ui/feature-gates/feature-gate-arbitrary_self_types-raw-pointer.stderr
@@ -7,7 +7,7 @@ LL |     fn foo(self: *const Self) {}
    = note: see issue #44874 <https://github.com/rust-lang/rust/issues/44874> for more information
    = help: add `#![feature(arbitrary_self_types_pointers)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-   = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
+   = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>`
 
 error[E0658]: `*const ()` cannot be used as the type of `self` without the `arbitrary_self_types_pointers` feature
   --> $DIR/feature-gate-arbitrary_self_types-raw-pointer.rs:14:18
@@ -18,7 +18,7 @@ LL |     fn bar(self: *const Self) {}
    = note: see issue #44874 <https://github.com/rust-lang/rust/issues/44874> for more information
    = help: add `#![feature(arbitrary_self_types_pointers)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-   = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
+   = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>`
 
 error[E0658]: `*const Self` cannot be used as the type of `self` without the `arbitrary_self_types_pointers` feature
   --> $DIR/feature-gate-arbitrary_self_types-raw-pointer.rs:9:18
@@ -29,7 +29,7 @@ LL |     fn bar(self: *const Self);
    = note: see issue #44874 <https://github.com/rust-lang/rust/issues/44874> for more information
    = help: add `#![feature(arbitrary_self_types_pointers)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-   = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
+   = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>`
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-cell.stderr b/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-cell.stderr
index 2150effc3b7..eb9e51a04c3 100644
--- a/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-cell.stderr
+++ b/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-cell.stderr
@@ -4,8 +4,8 @@ error[E0307]: invalid `self` parameter type: `Cell<&Self>`
 LL |     fn cell(self: Cell<&Self>);
    |                   ^^^^^^^^^^^
    |
-   = note: type of `self` must be `Self` or a type that dereferences to it
-   = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
+   = note: type of `self` must be `Self` or some type implementing `Receiver`
+   = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>`
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/issues/issue-56806.stderr b/tests/ui/issues/issue-56806.stderr
index ec50d863758..4b0a59fe12d 100644
--- a/tests/ui/issues/issue-56806.stderr
+++ b/tests/ui/issues/issue-56806.stderr
@@ -4,8 +4,8 @@ error[E0307]: invalid `self` parameter type: `Box<(dyn Trait + 'static)>`
 LL |     fn dyn_instead_of_self(self: Box<dyn Trait>);
    |                                  ^^^^^^^^^^^^^^
    |
-   = note: type of `self` must be `Self` or a type that dereferences to it
-   = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
+   = note: type of `self` must be `Self` or some type implementing `Receiver`
+   = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>`
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/lifetimes/could-not-resolve-issue-121503.stderr b/tests/ui/lifetimes/could-not-resolve-issue-121503.stderr
index 3babf63347c..46804642af8 100644
--- a/tests/ui/lifetimes/could-not-resolve-issue-121503.stderr
+++ b/tests/ui/lifetimes/could-not-resolve-issue-121503.stderr
@@ -7,7 +7,7 @@ LL |     async fn box_ref_Struct(self: Box<Self, impl FnMut(&mut Self)>) -> &u32
    = note: see issue #44874 <https://github.com/rust-lang/rust/issues/44874> for more information
    = help: add `#![feature(arbitrary_self_types)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-   = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
+   = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>`
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/methods/call_method_unknown_referent.rs b/tests/ui/methods/call_method_unknown_referent.rs
new file mode 100644
index 00000000000..b01e2d80f7f
--- /dev/null
+++ b/tests/ui/methods/call_method_unknown_referent.rs
@@ -0,0 +1,48 @@
+//@ edition: 2018
+
+#![feature(arbitrary_self_types)]
+
+// tests that the referent type of a reference must be known to call methods on it
+
+struct SmartPtr<T>(T);
+
+impl<T> core::ops::Receiver for SmartPtr<T> {
+    type Target = T;
+}
+
+impl<T> SmartPtr<T> {
+    fn foo(&self) {}
+}
+
+fn main() {
+    let val = 1_u32;
+    let ptr = &val;
+    let _a: i32 = (ptr as &_).read();
+    //~^ ERROR type annotations needed
+
+    // Same again, but with a smart pointer type
+    let val2 = 1_u32;
+    let rc = std::rc::Rc::new(val2);
+    let _b = (rc as std::rc::Rc<_>).read();
+    //~^ ERROR type annotations needed
+
+    // Same again, but with a smart pointer type
+    let ptr = SmartPtr(val);
+
+    // We can call unambiguous outer-type methods on this
+    (ptr as SmartPtr<_>).foo();
+    // ... but we can't follow the Receiver chain to the inner type
+    // because we end up with _.
+
+    // Because SmartPtr implements Receiver, it's arguable which of the
+    // following two diagnostics we'd want in this case:
+    // (a) "type annotations needed" (because the inner type is _)
+    // (b) "no method named `read` found for struct `SmartPtr`"
+    //     (ignoring the fact that there might have been methods on the
+    //      inner type, had it not been _)
+    // At present we produce error type (b), which is necessary because
+    // our resolution logic needs to be able to call methods such as foo()
+    // on the outer type even if the inner type is ambiguous.
+    let _c = (ptr as SmartPtr<_>).read();
+    //~^ ERROR no method named `read` found for struct `SmartPtr`
+}
diff --git a/tests/ui/methods/call_method_unknown_referent.stderr b/tests/ui/methods/call_method_unknown_referent.stderr
new file mode 100644
index 00000000000..748b02b52b5
--- /dev/null
+++ b/tests/ui/methods/call_method_unknown_referent.stderr
@@ -0,0 +1,29 @@
+error[E0282]: type annotations needed
+  --> $DIR/call_method_unknown_referent.rs:20:31
+   |
+LL |     let _a: i32 = (ptr as &_).read();
+   |                               ^^^^ cannot infer type
+
+error[E0282]: type annotations needed
+  --> $DIR/call_method_unknown_referent.rs:26:37
+   |
+LL |     let _b = (rc as std::rc::Rc<_>).read();
+   |                                     ^^^^ cannot infer type
+
+error[E0599]: no method named `read` found for struct `SmartPtr` in the current scope
+  --> $DIR/call_method_unknown_referent.rs:46:35
+   |
+LL | struct SmartPtr<T>(T);
+   | ------------------ method `read` not found for this struct
+...
+LL |     let _c = (ptr as SmartPtr<_>).read();
+   |                                   ^^^^ method not found in `SmartPtr<_>`
+   |
+   = help: items from traits can only be used if the trait is implemented and in scope
+   = note: the following trait defines an item `read`, perhaps you need to implement it:
+           candidate #1: `std::io::Read`
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0282, E0599.
+For more information about an error, try `rustc --explain E0282`.
diff --git a/tests/ui/methods/call_method_unknown_referent2.rs b/tests/ui/methods/call_method_unknown_referent2.rs
new file mode 100644
index 00000000000..b1615bd8d44
--- /dev/null
+++ b/tests/ui/methods/call_method_unknown_referent2.rs
@@ -0,0 +1,24 @@
+//@ edition: 2018
+//@ run-pass
+
+#![feature(arbitrary_self_types)]
+
+// tests that the referent type of a reference must be known to call methods on it
+
+struct SmartPtr<T>(T);
+
+impl<T> core::ops::Receiver for SmartPtr<T> {
+    type Target = T;
+}
+
+impl<T> SmartPtr<T> {
+    fn foo(&self) -> usize { 3 }
+}
+
+fn main() {
+    let val = 1_u32;
+    let ptr = SmartPtr(val);
+    // Ensure calls to outer methods work even if inner methods can't be
+    // resolved due to the type variable
+    assert_eq!((ptr as SmartPtr<_>).foo(), 3);
+}
diff --git a/tests/ui/self/arbitrary-self-from-method-substs-with-receiver.rs b/tests/ui/self/arbitrary-self-from-method-substs-with-receiver.rs
new file mode 100644
index 00000000000..495d261c549
--- /dev/null
+++ b/tests/ui/self/arbitrary-self-from-method-substs-with-receiver.rs
@@ -0,0 +1,64 @@
+#![feature(arbitrary_self_types)]
+
+use std::ops::{Receiver, Deref};
+
+struct SmartPtr<'a, T: ?Sized>(&'a T);
+
+impl<'a, T: ?Sized> Deref for SmartPtr<'a, T> {
+    type Target = T;
+    fn deref(&self) -> &Self::Target {
+        self.0
+    }
+}
+
+impl<'a, T: ?Sized> Clone for SmartPtr<'a, T> {
+    fn clone(&self) -> Self {
+        Self(self.0)
+    }
+}
+
+impl<'a, T: ?Sized> Copy for SmartPtr<'a, T> {
+}
+
+struct Foo(u32);
+impl Foo {
+    fn a<R: Receiver<Target=Self>>(self: R) -> u32 {
+        //~^ ERROR invalid generic `self` parameter type: `R`
+        2
+    }
+    fn b<R: Deref<Target=Self>>(self: R) -> u32 {
+        //~^ ERROR invalid generic `self` parameter type: `R`
+        self.0
+    }
+    fn c(self: impl Receiver<Target=Self>) -> u32 {
+        //~^ ERROR invalid generic `self` parameter type: `impl Receiver<Target = Self>`
+        3
+    }
+    fn d(self: impl Deref<Target=Self>) -> u32 {
+        //~^ ERROR invalid generic `self` parameter type: `impl Deref<Target = Self>`
+        self.0
+    }
+}
+
+fn main() {
+    let foo = Foo(1);
+    assert_eq!((&foo).a::<&Foo>(), 2);
+    assert_eq!((&foo).b::<&Foo>(), 1);
+    assert_eq!((&foo).a(), 2);
+    assert_eq!((&foo).b(), 1);
+    assert_eq!((&foo).c(), 3);
+    assert_eq!((&foo).d(), 1);
+    assert_eq!(foo.a::<&Foo>(), 2);
+    //~^ ERROR mismatched types
+    assert_eq!(foo.b::<&Foo>(), 1);
+    //~^ ERROR mismatched types
+    let smart_ptr = SmartPtr(&foo);
+    assert_eq!(smart_ptr.a(), 2);
+    assert_eq!(smart_ptr.b(), 1);
+    assert_eq!(smart_ptr.c(), 3);
+    assert_eq!(smart_ptr.d(), 1);
+    assert_eq!(smart_ptr.a::<&Foo>(), 2);
+    //~^ ERROR mismatched types
+    assert_eq!(smart_ptr.b::<&Foo>(), 1);
+    //~^ ERROR mismatched types
+}
diff --git a/tests/ui/self/arbitrary-self-from-method-substs-with-receiver.stderr b/tests/ui/self/arbitrary-self-from-method-substs-with-receiver.stderr
new file mode 100644
index 00000000000..9af2a08f371
--- /dev/null
+++ b/tests/ui/self/arbitrary-self-from-method-substs-with-receiver.stderr
@@ -0,0 +1,70 @@
+error[E0801]: invalid generic `self` parameter type: `R`
+  --> $DIR/arbitrary-self-from-method-substs-with-receiver.rs:25:42
+   |
+LL |     fn a<R: Receiver<Target=Self>>(self: R) -> u32 {
+   |                                          ^
+   |
+   = note: type of `self` must not be a method generic parameter type
+   = help: use a concrete type such as `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
+
+error[E0801]: invalid generic `self` parameter type: `R`
+  --> $DIR/arbitrary-self-from-method-substs-with-receiver.rs:29:39
+   |
+LL |     fn b<R: Deref<Target=Self>>(self: R) -> u32 {
+   |                                       ^
+   |
+   = note: type of `self` must not be a method generic parameter type
+   = help: use a concrete type such as `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
+
+error[E0801]: invalid generic `self` parameter type: `impl Receiver<Target = Self>`
+  --> $DIR/arbitrary-self-from-method-substs-with-receiver.rs:33:16
+   |
+LL |     fn c(self: impl Receiver<Target=Self>) -> u32 {
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: type of `self` must not be a method generic parameter type
+   = help: use a concrete type such as `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
+
+error[E0801]: invalid generic `self` parameter type: `impl Deref<Target = Self>`
+  --> $DIR/arbitrary-self-from-method-substs-with-receiver.rs:37:16
+   |
+LL |     fn d(self: impl Deref<Target=Self>) -> u32 {
+   |                ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: type of `self` must not be a method generic parameter type
+   = help: use a concrete type such as `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
+
+error[E0308]: mismatched types
+  --> $DIR/arbitrary-self-from-method-substs-with-receiver.rs:51:16
+   |
+LL |     assert_eq!(foo.a::<&Foo>(), 2);
+   |                ^^^ expected `&Foo`, found `Foo`
+
+error[E0308]: mismatched types
+  --> $DIR/arbitrary-self-from-method-substs-with-receiver.rs:53:16
+   |
+LL |     assert_eq!(foo.b::<&Foo>(), 1);
+   |                ^^^ expected `&Foo`, found `Foo`
+
+error[E0308]: mismatched types
+  --> $DIR/arbitrary-self-from-method-substs-with-receiver.rs:60:16
+   |
+LL |     assert_eq!(smart_ptr.a::<&Foo>(), 2);
+   |                ^^^^^^^^^ expected `&Foo`, found `SmartPtr<'_, Foo>`
+   |
+   = note: expected reference `&Foo`
+                 found struct `SmartPtr<'_, Foo, >`
+
+error[E0308]: mismatched types
+  --> $DIR/arbitrary-self-from-method-substs-with-receiver.rs:62:16
+   |
+LL |     assert_eq!(smart_ptr.b::<&Foo>(), 1);
+   |                ^^^^^^^^^ expected `&Foo`, found `SmartPtr<'_, Foo>`
+   |
+   = note: expected reference `&Foo`
+                 found struct `SmartPtr<'_, Foo, >`
+
+error: aborting due to 8 previous errors
+
+Some errors have detailed explanations: E0308, E0801.
+For more information about an error, try `rustc --explain E0308`.
diff --git a/tests/ui/self/arbitrary-self-from-method-substs.default.stderr b/tests/ui/self/arbitrary-self-from-method-substs.default.stderr
index 5dc3a0b0234..7cf9c9a3afd 100644
--- a/tests/ui/self/arbitrary-self-from-method-substs.default.stderr
+++ b/tests/ui/self/arbitrary-self-from-method-substs.default.stderr
@@ -61,7 +61,7 @@ LL |     fn get6<FR: FindReceiver>(self: FR::Receiver, other: FR) -> u32 {
    = note: see issue #44874 <https://github.com/rust-lang/rust/issues/44874> for more information
    = help: add `#![feature(arbitrary_self_types)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-   = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
+   = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>`
 
 error[E0658]: `R` cannot be used as the type of `self` without the `arbitrary_self_types` feature
   --> $DIR/arbitrary-self-from-method-substs.rs:61:18
@@ -72,7 +72,7 @@ LL |     fn get(self: R) {}
    = note: see issue #44874 <https://github.com/rust-lang/rust/issues/44874> for more information
    = help: add `#![feature(arbitrary_self_types)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-   = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
+   = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>`
 
 error[E0271]: type mismatch resolving `<Silly as FindReceiver>::Receiver == Foo`
   --> $DIR/arbitrary-self-from-method-substs.rs:92:9
diff --git a/tests/ui/self/arbitrary-self-opaque.stderr b/tests/ui/self/arbitrary-self-opaque.stderr
index c75165d9f8e..0469aca27dc 100644
--- a/tests/ui/self/arbitrary-self-opaque.stderr
+++ b/tests/ui/self/arbitrary-self-opaque.stderr
@@ -4,8 +4,8 @@ error[E0307]: invalid `self` parameter type: `Bar`
 LL |     fn foo(self: Bar) {}
    |                  ^^^
    |
-   = note: type of `self` must be `Self` or a type that dereferences to it
-   = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
+   = note: type of `self` must be `Self` or some type implementing `Receiver`
+   = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>`
 
 error: item does not constrain `Bar::{opaque#0}`, but has it in its signature
   --> $DIR/arbitrary-self-opaque.rs:7:8
diff --git a/tests/ui/self/arbitrary_self_types_generic_over_receiver.rs b/tests/ui/self/arbitrary_self_types_generic_over_receiver.rs
new file mode 100644
index 00000000000..8ccda9368ad
--- /dev/null
+++ b/tests/ui/self/arbitrary_self_types_generic_over_receiver.rs
@@ -0,0 +1,23 @@
+#![feature(arbitrary_self_types)]
+
+use std::ops::{Receiver, Deref};
+
+struct Foo(u32);
+impl Foo {
+    fn a(self: impl Receiver<Target=Self>) -> u32 {
+        //~^ ERROR invalid generic `self` parameter type: `impl Receiver<Target = Self>`
+        3
+    }
+    fn b(self: impl Deref<Target=Self>) -> u32 {
+        //~^ ERROR invalid generic `self` parameter type: `impl Deref<Target = Self>`
+        self.0
+    }
+}
+
+fn main() {
+    let foo = Foo(1);
+    foo.a();
+    //~^ ERROR the trait bound
+    foo.b();
+    //~^ ERROR the trait bound
+}
diff --git a/tests/ui/self/arbitrary_self_types_generic_over_receiver.stderr b/tests/ui/self/arbitrary_self_types_generic_over_receiver.stderr
new file mode 100644
index 00000000000..2da3925341e
--- /dev/null
+++ b/tests/ui/self/arbitrary_self_types_generic_over_receiver.stderr
@@ -0,0 +1,59 @@
+error[E0801]: invalid generic `self` parameter type: `impl Receiver<Target = Self>`
+  --> $DIR/arbitrary_self_types_generic_over_receiver.rs:7:16
+   |
+LL |     fn a(self: impl Receiver<Target=Self>) -> u32 {
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: type of `self` must not be a method generic parameter type
+   = help: use a concrete type such as `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
+
+error[E0801]: invalid generic `self` parameter type: `impl Deref<Target = Self>`
+  --> $DIR/arbitrary_self_types_generic_over_receiver.rs:11:16
+   |
+LL |     fn b(self: impl Deref<Target=Self>) -> u32 {
+   |                ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: type of `self` must not be a method generic parameter type
+   = help: use a concrete type such as `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
+
+error[E0277]: the trait bound `Foo: std::ops::Receiver` is not satisfied
+  --> $DIR/arbitrary_self_types_generic_over_receiver.rs:19:9
+   |
+LL |     foo.a();
+   |         ^ the trait `std::ops::Receiver` is not implemented for `Foo`
+   |
+   = note: required for `Foo` to implement `std::ops::Receiver`
+note: required by a bound in `Foo::a`
+  --> $DIR/arbitrary_self_types_generic_over_receiver.rs:7:21
+   |
+LL |     fn a(self: impl Receiver<Target=Self>) -> u32 {
+   |                     ^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Foo::a`
+help: consider borrowing here
+   |
+LL |     &foo.a();
+   |     +
+LL |     &mut foo.a();
+   |     ++++
+
+error[E0277]: the trait bound `Foo: Deref` is not satisfied
+  --> $DIR/arbitrary_self_types_generic_over_receiver.rs:21:9
+   |
+LL |     foo.b();
+   |         ^ the trait `Deref` is not implemented for `Foo`
+   |
+note: required by a bound in `Foo::b`
+  --> $DIR/arbitrary_self_types_generic_over_receiver.rs:11:21
+   |
+LL |     fn b(self: impl Deref<Target=Self>) -> u32 {
+   |                     ^^^^^^^^^^^^^^^^^^ required by this bound in `Foo::b`
+help: consider borrowing here
+   |
+LL |     &foo.b();
+   |     +
+LL |     &mut foo.b();
+   |     ++++
+
+error: aborting due to 4 previous errors
+
+Some errors have detailed explanations: E0277, E0801.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/tests/ui/self/arbitrary_self_types_lifetime_elision.rs b/tests/ui/self/arbitrary_self_types_lifetime_elision.rs
new file mode 100644
index 00000000000..fd645c1013b
--- /dev/null
+++ b/tests/ui/self/arbitrary_self_types_lifetime_elision.rs
@@ -0,0 +1,27 @@
+//@ run-pass
+
+#![feature(arbitrary_self_types)]
+
+#[derive(Clone)]
+struct SmartPtr<'a, T: ?Sized>(&'a T);
+
+impl<'a, T: ?Sized> std::ops::Receiver for SmartPtr<'a, T> {
+    type Target = T;
+}
+
+#[derive(Clone)]
+struct MyType;
+
+impl MyType {
+    fn m(self: SmartPtr<Self>) {}
+    fn n(self: SmartPtr<'_, Self>) {}
+    fn o<'a>(self: SmartPtr<'a, Self>) {}
+}
+
+fn main() {
+    let a = MyType;
+    let ptr = SmartPtr(&a);
+    ptr.clone().m();
+    ptr.clone().n();
+    ptr.o();
+}
diff --git a/tests/ui/self/arbitrary_self_types_no_generics.rs b/tests/ui/self/arbitrary_self_types_no_generics.rs
new file mode 100644
index 00000000000..8a6f5741882
--- /dev/null
+++ b/tests/ui/self/arbitrary_self_types_no_generics.rs
@@ -0,0 +1,32 @@
+//@ run-pass
+
+#![feature(arbitrary_self_types)]
+
+pub struct A;
+
+impl A {
+    pub fn f(self: B) -> i32 { 1 }
+}
+
+pub struct B(A);
+
+impl core::ops::Receiver for B {
+    type Target = A;
+}
+
+struct C;
+
+struct D;
+
+impl C {
+    fn weird(self: D) -> i32 { 3 }
+}
+
+impl core::ops::Receiver for D {
+    type Target = C;
+}
+
+fn main() {
+    assert_eq!(B(A).f(), 1);
+    assert_eq!(D.weird(), 3);
+}
diff --git a/tests/ui/self/arbitrary_self_types_not_allow_call_with_no_deref.rs b/tests/ui/self/arbitrary_self_types_not_allow_call_with_no_deref.rs
new file mode 100644
index 00000000000..26e48f69d23
--- /dev/null
+++ b/tests/ui/self/arbitrary_self_types_not_allow_call_with_no_deref.rs
@@ -0,0 +1,38 @@
+#![feature(arbitrary_self_types)]
+
+use std::rc::Rc;
+
+struct Foo;
+
+struct CppRef<T>(T);
+
+impl<T> std::ops::Receiver for CppRef<T> {
+    type Target = T;
+}
+
+impl Foo{
+    fn frobnicate_self(self) {}
+    fn frobnicate_ref(&self) {}
+    fn frobnicate_cpp_ref(self: CppRef<Self>) {}
+}
+
+fn main() {
+    let foo_rc = Rc::new(Foo);
+
+    // this compiles fine, and desugars to `Foo::frobnicate_ref(&*foo_rc)`
+    foo_rc.frobnicate_ref();
+
+    let foo_cpp_ref = CppRef(Foo);
+
+    // should not compile because it would desugar to `Foo::frobnicate_ref(&*foo_cpp_ref)`
+    // and you can't deref a CppRef
+    foo_cpp_ref.frobnicate_ref();
+    //~^ ERROR no method named
+
+    foo_cpp_ref.frobnicate_self(); // would desugar to `Foo::frobnicate_self(*foo_cpp_ref)`
+    //~^ ERROR no method named
+
+    // should compile, because we're not dereffing the CppRef
+    // desugars to `Foo::frobnicate_cpp_ref(foo_cpp_ref)`
+    foo_cpp_ref.frobnicate_cpp_ref();
+}
diff --git a/tests/ui/self/arbitrary_self_types_not_allow_call_with_no_deref.stderr b/tests/ui/self/arbitrary_self_types_not_allow_call_with_no_deref.stderr
new file mode 100644
index 00000000000..4c0ab88493e
--- /dev/null
+++ b/tests/ui/self/arbitrary_self_types_not_allow_call_with_no_deref.stderr
@@ -0,0 +1,39 @@
+error[E0599]: no method named `frobnicate_ref` found for struct `CppRef` in the current scope
+  --> $DIR/arbitrary_self_types_not_allow_call_with_no_deref.rs:29:17
+   |
+LL | struct CppRef<T>(T);
+   | ---------------- method `frobnicate_ref` not found for this struct
+...
+LL |     foo_cpp_ref.frobnicate_ref();
+   |                 ^^^^^^^^^^^^^^
+   |
+help: one of the expressions' fields has a method of the same name
+   |
+LL |     foo_cpp_ref.0.frobnicate_ref();
+   |                 ++
+help: there is a method `frobnicate_cpp_ref` with a similar name
+   |
+LL |     foo_cpp_ref.frobnicate_cpp_ref();
+   |                 ~~~~~~~~~~~~~~~~~~
+
+error[E0599]: no method named `frobnicate_self` found for struct `CppRef` in the current scope
+  --> $DIR/arbitrary_self_types_not_allow_call_with_no_deref.rs:32:17
+   |
+LL | struct CppRef<T>(T);
+   | ---------------- method `frobnicate_self` not found for this struct
+...
+LL |     foo_cpp_ref.frobnicate_self(); // would desugar to `Foo::frobnicate_self(*foo_cpp_ref)`
+   |                 ^^^^^^^^^^^^^^^
+   |
+help: one of the expressions' fields has a method of the same name
+   |
+LL |     foo_cpp_ref.0.frobnicate_self(); // would desugar to `Foo::frobnicate_self(*foo_cpp_ref)`
+   |                 ++
+help: there is a method `frobnicate_cpp_ref` with a similar name
+   |
+LL |     foo_cpp_ref.frobnicate_cpp_ref(); // would desugar to `Foo::frobnicate_self(*foo_cpp_ref)`
+   |                 ~~~~~~~~~~~~~~~~~~
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/tests/ui/self/arbitrary_self_types_recursive_receiver.rs b/tests/ui/self/arbitrary_self_types_recursive_receiver.rs
new file mode 100644
index 00000000000..f3e7f96d7c4
--- /dev/null
+++ b/tests/ui/self/arbitrary_self_types_recursive_receiver.rs
@@ -0,0 +1,32 @@
+//@ run-pass
+#![feature(arbitrary_self_types)]
+
+struct MyNonNull<T>(*const T);
+
+impl<T> std::ops::Receiver for MyNonNull<T> {
+    type Target = T;
+}
+
+#[allow(dead_code)]
+impl<T> MyNonNull<T> {
+    fn foo<U>(&self) -> *const U {
+        self.cast::<U>().bar()
+    }
+    fn cast<U>(&self) -> MyNonNull<U> {
+        MyNonNull(self.0 as *const U)
+    }
+    fn bar(&self) -> *const T {
+        self.0
+    }
+}
+
+#[repr(transparent)]
+struct Foo(usize);
+#[repr(transparent)]
+struct Bar(usize);
+
+fn main() {
+    let a = Foo(3);
+    let ptr = MyNonNull(&a);
+    let _bar_ptr: *const Bar = ptr.foo();
+}
diff --git a/tests/ui/self/arbitrary_self_types_struct_receiver_trait.rs b/tests/ui/self/arbitrary_self_types_struct_receiver_trait.rs
new file mode 100644
index 00000000000..cebf0ea7cba
--- /dev/null
+++ b/tests/ui/self/arbitrary_self_types_struct_receiver_trait.rs
@@ -0,0 +1,31 @@
+//@ run-pass
+#![feature(arbitrary_self_types)]
+
+use std::ops::Receiver;
+
+struct SmartPtr<T>(T);
+
+impl<T> Receiver for SmartPtr<T> {
+    type Target = T;
+}
+
+struct Foo {
+    x: i32,
+    y: i32,
+}
+
+impl Foo {
+    fn x(self: &SmartPtr<Self>) -> i32 {
+        self.0.x
+    }
+
+    fn y(self: SmartPtr<Self>) -> i32 {
+        self.0.y
+    }
+}
+
+fn main() {
+    let foo = SmartPtr(Foo {x: 3, y: 4});
+    assert_eq!(3, foo.x());
+    assert_eq!(4, foo.y());
+}
diff --git a/tests/ui/self/arbitrary_self_types_trait_receiver_trait.rs b/tests/ui/self/arbitrary_self_types_trait_receiver_trait.rs
new file mode 100644
index 00000000000..9c0402da0be
--- /dev/null
+++ b/tests/ui/self/arbitrary_self_types_trait_receiver_trait.rs
@@ -0,0 +1,25 @@
+//@ run-pass
+#![feature(arbitrary_self_types)]
+#![allow(unused_allocation)]
+
+struct SmartPtr<T: ?Sized>(T);
+
+impl<T: ?Sized> std::ops::Receiver for SmartPtr<T> {
+    type Target = T;
+}
+
+trait Trait {
+    fn trait_method<'a>(self: &'a Box<SmartPtr<Self>>) -> &'a [i32];
+}
+
+impl Trait for Vec<i32> {
+    fn trait_method<'a>(self: &'a Box<SmartPtr<Self>>) -> &'a [i32] {
+        &(**self).0
+    }
+}
+
+fn main() {
+    let v = vec![1, 2, 3];
+
+    assert_eq!(&[1, 2, 3], Box::new(SmartPtr(v)).trait_method());
+}
diff --git a/tests/ui/span/issue-27522.stderr b/tests/ui/span/issue-27522.stderr
index c57a100bbe2..04904b0ddc1 100644
--- a/tests/ui/span/issue-27522.stderr
+++ b/tests/ui/span/issue-27522.stderr
@@ -4,8 +4,8 @@ error[E0307]: invalid `self` parameter type: `&SomeType`
 LL |     fn handler(self: &SomeType);
    |                      ^^^^^^^^^
    |
-   = note: type of `self` must be `Self` or a type that dereferences to it
-   = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
+   = note: type of `self` must be `Self` or some type implementing `Receiver`
+   = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>`
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/suggestions/dyn-incompatible-trait-should-use-where-sized.stderr b/tests/ui/suggestions/dyn-incompatible-trait-should-use-where-sized.stderr
index beafd7c2ab0..eb9f9196a72 100644
--- a/tests/ui/suggestions/dyn-incompatible-trait-should-use-where-sized.stderr
+++ b/tests/ui/suggestions/dyn-incompatible-trait-should-use-where-sized.stderr
@@ -32,8 +32,8 @@ error[E0307]: invalid `self` parameter type: `()`
 LL |     fn bar(self: ()) {}
    |                  ^^
    |
-   = note: type of `self` must be `Self` or a type that dereferences to it
-   = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
+   = note: type of `self` must be `Self` or some type implementing `Receiver`
+   = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>`
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/traits/const-traits/effects/auxiliary/minicore.rs b/tests/ui/traits/const-traits/effects/auxiliary/minicore.rs
index aaa61e21155..e606d896e93 100644
--- a/tests/ui/traits/const-traits/effects/auxiliary/minicore.rs
+++ b/tests/ui/traits/const-traits/effects/auxiliary/minicore.rs
@@ -110,6 +110,16 @@ impl<T: ?Sized> LegacyReceiver for &T {}
 
 impl<T: ?Sized> LegacyReceiver for &mut T {}
 
+#[lang = "receiver"]
+pub trait Receiver {
+    #[lang = "receiver_target"]
+    type Target: ?Sized;
+}
+
+impl<T: Deref + ?Sized> Receiver for T {
+    type Target = <T as Deref>::Target;
+}
+
 #[lang = "destruct"]
 #[const_trait]
 pub trait Destruct {}
diff --git a/tests/ui/traits/issue-78372.stderr b/tests/ui/traits/issue-78372.stderr
index 86234d15a5d..1c58915111f 100644
--- a/tests/ui/traits/issue-78372.stderr
+++ b/tests/ui/traits/issue-78372.stderr
@@ -61,8 +61,8 @@ error[E0307]: invalid `self` parameter type: `Smaht<Self, T>`
 LL |     fn foo(self: Smaht<Self, T>);
    |                  ^^^^^^^^^^^^^^
    |
-   = note: type of `self` must be `Self` or a type that dereferences to it
-   = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
+   = note: type of `self` must be `Self` or some type implementing `Receiver`
+   = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>`
 
 error[E0378]: the trait `DispatchFromDyn` may only be implemented for a coercion between structures
   --> $DIR/issue-78372.rs:3:1
diff --git a/tests/ui/type-alias-impl-trait/method_resolution3.current.stderr b/tests/ui/type-alias-impl-trait/method_resolution3.current.stderr
index 09efd7a9e7e..c6aa0e811f3 100644
--- a/tests/ui/type-alias-impl-trait/method_resolution3.current.stderr
+++ b/tests/ui/type-alias-impl-trait/method_resolution3.current.stderr
@@ -4,8 +4,8 @@ error[E0307]: invalid `self` parameter type: `Bar<u32>`
 LL |     fn bar(self: Bar<u32>) {
    |                  ^^^^^^^^
    |
-   = note: type of `self` must be `Self` or a type that dereferences to it
-   = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
+   = note: type of `self` must be `Self` or some type implementing `Receiver`
+   = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>`
 
 error[E0307]: invalid `self` parameter type: `&Bar<u32>`
   --> $DIR/method_resolution3.rs:20:18
@@ -13,8 +13,8 @@ error[E0307]: invalid `self` parameter type: `&Bar<u32>`
 LL |     fn baz(self: &Bar<u32>) {
    |                  ^^^^^^^^^
    |
-   = note: type of `self` must be `Self` or a type that dereferences to it
-   = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
+   = note: type of `self` must be `Self` or some type implementing `Receiver`
+   = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>`
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/type-alias-impl-trait/method_resolution3.next.stderr b/tests/ui/type-alias-impl-trait/method_resolution3.next.stderr
index 09efd7a9e7e..c6aa0e811f3 100644
--- a/tests/ui/type-alias-impl-trait/method_resolution3.next.stderr
+++ b/tests/ui/type-alias-impl-trait/method_resolution3.next.stderr
@@ -4,8 +4,8 @@ error[E0307]: invalid `self` parameter type: `Bar<u32>`
 LL |     fn bar(self: Bar<u32>) {
    |                  ^^^^^^^^
    |
-   = note: type of `self` must be `Self` or a type that dereferences to it
-   = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
+   = note: type of `self` must be `Self` or some type implementing `Receiver`
+   = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>`
 
 error[E0307]: invalid `self` parameter type: `&Bar<u32>`
   --> $DIR/method_resolution3.rs:20:18
@@ -13,8 +13,8 @@ error[E0307]: invalid `self` parameter type: `&Bar<u32>`
 LL |     fn baz(self: &Bar<u32>) {
    |                  ^^^^^^^^^
    |
-   = note: type of `self` must be `Self` or a type that dereferences to it
-   = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
+   = note: type of `self` must be `Self` or some type implementing `Receiver`
+   = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>`
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/type-alias-impl-trait/method_resolution4.current.stderr b/tests/ui/type-alias-impl-trait/method_resolution4.current.stderr
index 8ffdb21f251..e4c4d121733 100644
--- a/tests/ui/type-alias-impl-trait/method_resolution4.current.stderr
+++ b/tests/ui/type-alias-impl-trait/method_resolution4.current.stderr
@@ -4,8 +4,8 @@ error[E0307]: invalid `self` parameter type: `Bar<Foo>`
 LL |     fn foo(self: Bar<Foo>) {
    |                  ^^^^^^^^
    |
-   = note: type of `self` must be `Self` or a type that dereferences to it
-   = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
+   = note: type of `self` must be `Self` or some type implementing `Receiver`
+   = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>`
 
 error[E0307]: invalid `self` parameter type: `&Bar<Foo>`
   --> $DIR/method_resolution4.rs:31:20
@@ -13,8 +13,8 @@ error[E0307]: invalid `self` parameter type: `&Bar<Foo>`
 LL |     fn foomp(self: &Bar<Foo>) {
    |                    ^^^^^^^^^
    |
-   = note: type of `self` must be `Self` or a type that dereferences to it
-   = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
+   = note: type of `self` must be `Self` or some type implementing `Receiver`
+   = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>`
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/type-alias-impl-trait/method_resolution4.next.stderr b/tests/ui/type-alias-impl-trait/method_resolution4.next.stderr
index 8ffdb21f251..e4c4d121733 100644
--- a/tests/ui/type-alias-impl-trait/method_resolution4.next.stderr
+++ b/tests/ui/type-alias-impl-trait/method_resolution4.next.stderr
@@ -4,8 +4,8 @@ error[E0307]: invalid `self` parameter type: `Bar<Foo>`
 LL |     fn foo(self: Bar<Foo>) {
    |                  ^^^^^^^^
    |
-   = note: type of `self` must be `Self` or a type that dereferences to it
-   = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
+   = note: type of `self` must be `Self` or some type implementing `Receiver`
+   = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>`
 
 error[E0307]: invalid `self` parameter type: `&Bar<Foo>`
   --> $DIR/method_resolution4.rs:31:20
@@ -13,8 +13,8 @@ error[E0307]: invalid `self` parameter type: `&Bar<Foo>`
 LL |     fn foomp(self: &Bar<Foo>) {
    |                    ^^^^^^^^^
    |
-   = note: type of `self` must be `Self` or a type that dereferences to it
-   = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
+   = note: type of `self` must be `Self` or some type implementing `Receiver`
+   = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>`
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/ufcs/ufcs-explicit-self-bad.stderr b/tests/ui/ufcs/ufcs-explicit-self-bad.stderr
index 2a8c4edbdb5..36bdc714e05 100644
--- a/tests/ui/ufcs/ufcs-explicit-self-bad.stderr
+++ b/tests/ui/ufcs/ufcs-explicit-self-bad.stderr
@@ -22,8 +22,8 @@ error[E0307]: invalid `self` parameter type: `isize`
 LL |     fn foo(self: isize, x: isize) -> isize {
    |                  ^^^^^
    |
-   = note: type of `self` must be `Self` or a type that dereferences to it
-   = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
+   = note: type of `self` must be `Self` or some type implementing `Receiver`
+   = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>`
 
 error[E0307]: invalid `self` parameter type: `Bar<isize>`
   --> $DIR/ufcs-explicit-self-bad.rs:19:18
@@ -31,8 +31,8 @@ error[E0307]: invalid `self` parameter type: `Bar<isize>`
 LL |     fn foo(self: Bar<isize>, x: isize) -> isize {
    |                  ^^^^^^^^^^
    |
-   = note: type of `self` must be `Self` or a type that dereferences to it
-   = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
+   = note: type of `self` must be `Self` or some type implementing `Receiver`
+   = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>`
 
 error[E0307]: invalid `self` parameter type: `&Bar<usize>`
   --> $DIR/ufcs-explicit-self-bad.rs:23:18
@@ -40,8 +40,8 @@ error[E0307]: invalid `self` parameter type: `&Bar<usize>`
 LL |     fn bar(self: &Bar<usize>, x: isize) -> isize {
    |                  ^^^^^^^^^^^
    |
-   = note: type of `self` must be `Self` or a type that dereferences to it
-   = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
+   = note: type of `self` must be `Self` or some type implementing `Receiver`
+   = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>`
 
 error[E0308]: mismatched `self` parameter type
   --> $DIR/ufcs-explicit-self-bad.rs:37:21