about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0801.md51
-rw-r--r--compiler/rustc_error_codes/src/lib.rs1
-rw-r--r--compiler/rustc_hir_analysis/messages.ftl6
-rw-r--r--compiler/rustc_hir_analysis/src/check/wfcheck.rs86
-rw-r--r--compiler/rustc_hir_analysis/src/errors.rs10
-rw-r--r--compiler/rustc_hir_typeck/src/method/confirm.rs3
-rw-r--r--src/tools/tidy/src/issues.txt1
-rw-r--r--tests/ui/self/arbitrary-self-from-method-substs-ice.rs2
-rw-r--r--tests/ui/self/arbitrary-self-from-method-substs-ice.stderr10
-rw-r--r--tests/ui/self/arbitrary-self-from-method-substs.default.stderr162
-rw-r--r--tests/ui/self/arbitrary-self-from-method-substs.feature.stderr176
-rw-r--r--tests/ui/self/arbitrary-self-from-method-substs.rs94
-rw-r--r--tests/ui/type-alias-impl-trait/issue-57700.rs21
-rw-r--r--tests/ui/type-alias-impl-trait/issue-57700.stderr8
14 files changed, 570 insertions, 61 deletions
diff --git a/compiler/rustc_error_codes/src/error_codes/E0801.md b/compiler/rustc_error_codes/src/error_codes/E0801.md
new file mode 100644
index 00000000000..c89feb9b308
--- /dev/null
+++ b/compiler/rustc_error_codes/src/error_codes/E0801.md
@@ -0,0 +1,51 @@
+The `self` parameter in a method has an invalid generic "receiver type".
+
+Erroneous code example:
+
+```compile_fail,E0801
+struct Foo;
+
+impl Foo {
+    fn foo<R: std::ops::Deref<Target=Self>>(self: R) {}
+}
+```
+
+or alternatively,
+
+```compile_fail,E0801
+struct Foo;
+
+impl Foo {
+    fn foo(self: impl std::ops::Deref<Target=Self>) {}
+}
+```
+
+Methods take a special first parameter, termed `self`. It's normal to
+use `self`, `&self` or `&mut self`, which are syntactic sugar for
+`self: Self`, `self: &Self`, and `self: &mut Self` respectively.
+But it's also possible to use more sophisticated types of `self`
+parameter, for instance `std::rc::Rc<Self>`. The set of allowable
+`Self` types is extensible using the nightly feature
+[Arbitrary self types][AST].
+This will extend the valid set of `Self` types to anything which implements
+`std::ops::Deref<Target=Self>`, for example `Rc<Self>`, `Box<Self>`, or
+your own smart pointers that do the same.
+
+However, even with that feature, the `self` type must be concrete.
+Generic `self` types are not permitted. Specifically, a `self` type will
+be rejected if it is a type parameter defined on the method.
+
+These are OK:
+
+```
+struct Foo;
+
+impl Foo {
+    fn foo(self) {}
+    fn foo2(self: std::rc::Rc<Self>) {} // or some other similar
+        // smart pointer if you enable arbitrary self types and
+        // the pointer implements Deref<Target=Self>
+}
+```
+
+[AST]: https://doc.rust-lang.org/unstable-book/language-features/arbitrary-self-types.html
diff --git a/compiler/rustc_error_codes/src/lib.rs b/compiler/rustc_error_codes/src/lib.rs
index 27a34d6003d..29f3277d399 100644
--- a/compiler/rustc_error_codes/src/lib.rs
+++ b/compiler/rustc_error_codes/src/lib.rs
@@ -540,6 +540,7 @@ E0797: 0797,
 E0798: 0798,
 E0799: 0799,
 E0800: 0800,
+E0801: 0801,
         );
     )
 }
diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl
index 7191c724061..38b11aa4017 100644
--- a/compiler/rustc_hir_analysis/messages.ftl
+++ b/compiler/rustc_hir_analysis/messages.ftl
@@ -234,6 +234,12 @@ hir_analysis_inherent_ty_outside_relevant = cannot define inherent `impl` for a
     .help = consider moving this inherent impl into the crate defining the type if possible
     .span_help = alternatively add `#[rustc_allow_incoherent_impl]` to the relevant impl items
 
+hir_analysis_invalid_generic_receiver_ty = invalid generic `self` parameter type: `{$receiver_ty}`
+    .note = type of `self` must not be a method generic parameter type
+
+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
 
diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
index 12ed7b89f68..5bc320b12b0 100644
--- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs
+++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
@@ -2,13 +2,14 @@ use std::cell::LazyCell;
 use std::ops::{ControlFlow, Deref};
 
 use hir::intravisit::{self, Visitor};
+use itertools::Itertools;
 use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
 use rustc_errors::codes::*;
 use rustc_errors::{Applicability, ErrorGuaranteed, pluralize, struct_span_code_err};
-use rustc_hir::ItemKind;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::{DefId, LocalDefId, LocalModDefId};
 use rustc_hir::lang_items::LangItem;
+use rustc_hir::{GenericParamKind, ItemKind};
 use rustc_infer::infer::outlives::env::OutlivesEnvironment;
 use rustc_infer::infer::{self, InferCtxt, TyCtxtInferExt};
 use rustc_macros::LintDiagnostic;
@@ -378,7 +379,7 @@ fn check_trait_item<'tcx>(
         _ => (None, trait_item.span),
     };
     check_dyn_incompatible_self_trait_by_name(tcx, trait_item);
-    let mut res = check_associated_item(tcx, def_id, span, method_sig);
+    let mut res = check_associated_item(tcx, def_id, span, method_sig, None);
 
     if matches!(trait_item.kind, hir::TraitItemKind::Fn(..)) {
         for &assoc_ty_def_id in tcx.associated_types_for_impl_traits_in_associated_fn(def_id) {
@@ -387,6 +388,7 @@ fn check_trait_item<'tcx>(
                 assoc_ty_def_id.expect_local(),
                 tcx.def_span(assoc_ty_def_id),
                 None,
+                None,
             ));
         }
     }
@@ -904,8 +906,13 @@ fn check_impl_item<'tcx>(
         hir::ImplItemKind::Type(ty) if ty.span != DUMMY_SP => (None, ty.span),
         _ => (None, impl_item.span),
     };
-
-    check_associated_item(tcx, impl_item.owner_id.def_id, span, method_sig)
+    check_associated_item(
+        tcx,
+        impl_item.owner_id.def_id,
+        span,
+        method_sig,
+        Some(impl_item.generics),
+    )
 }
 
 fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) -> Result<(), ErrorGuaranteed> {
@@ -1038,6 +1045,7 @@ fn check_associated_item(
     item_id: LocalDefId,
     span: Span,
     sig_if_method: Option<&hir::FnSig<'_>>,
+    generics: Option<&hir::Generics<'_>>,
 ) -> Result<(), ErrorGuaranteed> {
     let loc = Some(WellFormedLoc::Ty(item_id));
     enter_wf_checking_ctxt(tcx, span, item_id, |wfcx| {
@@ -1070,7 +1078,7 @@ fn check_associated_item(
                     hir_sig.decl,
                     item.def_id.expect_local(),
                 );
-                check_method_receiver(wfcx, hir_sig, item, self_ty)
+                check_method_receiver(wfcx, hir_sig, item, self_ty, generics)
             }
             ty::AssocKind::Type => {
                 if let ty::AssocItemContainer::TraitContainer = item.container {
@@ -1692,6 +1700,7 @@ fn check_method_receiver<'tcx>(
     fn_sig: &hir::FnSig<'_>,
     method: ty::AssocItem,
     self_ty: Ty<'tcx>,
+    generics: Option<&hir::Generics<'_>>,
 ) -> Result<(), ErrorGuaranteed> {
     let tcx = wfcx.tcx();
 
@@ -1726,7 +1735,9 @@ fn check_method_receiver<'tcx>(
         None
     };
 
-    if !receiver_is_valid(wfcx, span, receiver_ty, self_ty, arbitrary_self_types_level) {
+    let receiver_validity =
+        receiver_is_valid(wfcx, span, receiver_ty, self_ty, arbitrary_self_types_level, generics);
+    if let Err(receiver_validity_err) = receiver_validity {
         return Err(match arbitrary_self_types_level {
             // Wherever possible, emit a message advising folks that the features
             // `arbitrary_self_types` or `arbitrary_self_types_pointers` might
@@ -1737,7 +1748,9 @@ fn check_method_receiver<'tcx>(
                 receiver_ty,
                 self_ty,
                 Some(ArbitrarySelfTypesLevel::Basic),
-            ) =>
+                generics,
+            )
+            .is_ok() =>
             {
                 // Report error; would have worked with `arbitrary_self_types`.
                 feature_err(
@@ -1759,7 +1772,9 @@ fn check_method_receiver<'tcx>(
                     receiver_ty,
                     self_ty,
                     Some(ArbitrarySelfTypesLevel::WithPointers),
-                ) =>
+                    generics,
+                )
+                .is_ok() =>
             {
                 // Report error; would have worked with `arbitrary_self_types_pointers`.
                 feature_err(
@@ -1777,13 +1792,53 @@ fn check_method_receiver<'tcx>(
             _ =>
             // Report error; would not have worked with `arbitrary_self_types[_pointers]`.
             {
-                tcx.dcx().emit_err(errors::InvalidReceiverTy { span, receiver_ty })
+                match receiver_validity_err {
+                    ReceiverValidityError::DoesNotDeref => {
+                        tcx.dcx().emit_err(errors::InvalidReceiverTy { span, receiver_ty })
+                    }
+                    ReceiverValidityError::MethodGenericParamUsed => {
+                        tcx.dcx().emit_err(errors::InvalidGenericReceiverTy { span, receiver_ty })
+                    }
+                }
             }
         });
     }
     Ok(())
 }
 
+/// Error cases which may be returned from `receiver_is_valid`. These error
+/// cases are generated in this function as they may be unearthed as we explore
+/// the `autoderef` chain, but they're converted to diagnostics in the caller.
+enum ReceiverValidityError {
+    /// The self type does not get to the receiver type by following the
+    /// autoderef chain.
+    DoesNotDeref,
+    /// A type was found which is a method type parameter, and that's not allowed.
+    MethodGenericParamUsed,
+}
+
+/// Confirms that a type is not a type parameter referring to one of the
+/// method's type params.
+fn confirm_type_is_not_a_method_generic_param(
+    ty: Ty<'_>,
+    method_generics: Option<&hir::Generics<'_>>,
+) -> Result<(), ReceiverValidityError> {
+    if let ty::Param(param) = ty.kind() {
+        if let Some(generics) = method_generics {
+            if generics
+                .params
+                .iter()
+                .filter(|g| matches!(g.kind, GenericParamKind::Type { .. }))
+                .map(|g| g.name.ident().name)
+                .contains(&param.name)
+            {
+                return Err(ReceiverValidityError::MethodGenericParamUsed);
+            }
+        }
+    }
+    Ok(())
+}
+
 /// Returns whether `receiver_ty` would be considered a valid receiver type for `self_ty`. If
 /// `arbitrary_self_types` is enabled, `receiver_ty` must transitively deref to `self_ty`, possibly
 /// through a `*const/mut T` raw pointer if  `arbitrary_self_types_pointers` is also enabled.
@@ -1799,7 +1854,8 @@ fn receiver_is_valid<'tcx>(
     receiver_ty: Ty<'tcx>,
     self_ty: Ty<'tcx>,
     arbitrary_self_types_enabled: Option<ArbitrarySelfTypesLevel>,
-) -> bool {
+    generics: Option<&hir::Generics<'_>>,
+) -> Result<(), ReceiverValidityError> {
     let infcx = wfcx.infcx;
     let tcx = wfcx.tcx();
     let cause =
@@ -1811,9 +1867,11 @@ fn receiver_is_valid<'tcx>(
         ocx.eq(&cause, wfcx.param_env, self_ty, receiver_ty)?;
         if ocx.select_all_or_error().is_empty() { Ok(()) } else { Err(NoSolution) }
     }) {
-        return true;
+        return Ok(());
     }
 
+    confirm_type_is_not_a_method_generic_param(receiver_ty, generics)?;
+
     let mut autoderef = Autoderef::new(infcx, wfcx.param_env, wfcx.body_def_id, span, receiver_ty);
 
     // The `arbitrary_self_types_pointers` feature allows raw pointer receivers like `self: *const Self`.
@@ -1830,6 +1888,8 @@ fn receiver_is_valid<'tcx>(
             potential_self_ty, self_ty
         );
 
+        confirm_type_is_not_a_method_generic_param(potential_self_ty, generics)?;
+
         // Check if the self type unifies. If it does, then commit the result
         // since it may have region side-effects.
         if let Ok(()) = wfcx.infcx.commit_if_ok(|_| {
@@ -1838,7 +1898,7 @@ fn receiver_is_valid<'tcx>(
             if ocx.select_all_or_error().is_empty() { Ok(()) } else { Err(NoSolution) }
         }) {
             wfcx.register_obligations(autoderef.into_obligations());
-            return true;
+            return Ok(());
         }
 
         // Without `feature(arbitrary_self_types)`, we require that each step in the
@@ -1865,7 +1925,7 @@ fn receiver_is_valid<'tcx>(
     }
 
     debug!("receiver_is_valid: type `{:?}` does not deref to `{:?}`", receiver_ty, self_ty);
-    false
+    Err(ReceiverValidityError::DoesNotDeref)
 }
 
 fn receiver_is_implemented<'tcx>(
diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs
index 7fa9dfe346d..a92a5e4278c 100644
--- a/compiler/rustc_hir_analysis/src/errors.rs
+++ b/compiler/rustc_hir_analysis/src/errors.rs
@@ -1624,6 +1624,16 @@ pub(crate) struct InvalidReceiverTy<'tcx> {
 }
 
 #[derive(Diagnostic)]
+#[diag(hir_analysis_invalid_generic_receiver_ty, code = E0801)]
+#[note]
+#[help(hir_analysis_invalid_generic_receiver_ty_help)]
+pub(crate) struct InvalidGenericReceiverTy<'tcx> {
+    #[primary_span]
+    pub span: Span,
+    pub receiver_ty: Ty<'tcx>,
+}
+
+#[derive(Diagnostic)]
 #[diag(hir_analysis_cmse_inputs_stack_spill, code = E0798)]
 #[note]
 pub(crate) struct CmseInputsStackSpill {
diff --git a/compiler/rustc_hir_typeck/src/method/confirm.rs b/compiler/rustc_hir_typeck/src/method/confirm.rs
index f2b55d3aa4e..92b504d10bc 100644
--- a/compiler/rustc_hir_typeck/src/method/confirm.rs
+++ b/compiler/rustc_hir_typeck/src/method/confirm.rs
@@ -533,9 +533,6 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
                 self.register_predicates(obligations);
             }
             Err(terr) => {
-                // FIXME(arbitrary_self_types): We probably should limit the
-                // situations where this can occur by adding additional restrictions
-                // to the feature, like the self type can't reference method args.
                 if self.tcx.features().arbitrary_self_types() {
                     self.err_ctxt()
                         .report_mismatched_types(
diff --git a/src/tools/tidy/src/issues.txt b/src/tools/tidy/src/issues.txt
index 94f8d23c158..932a58788e0 100644
--- a/src/tools/tidy/src/issues.txt
+++ b/src/tools/tidy/src/issues.txt
@@ -4102,7 +4102,6 @@ ui/type-alias-impl-trait/issue-53678-coroutine-and-const-fn.rs
 ui/type-alias-impl-trait/issue-55099-lifetime-inference.rs
 ui/type-alias-impl-trait/issue-57188-associate-impl-capture.rs
 ui/type-alias-impl-trait/issue-57611-trait-alias.rs
-ui/type-alias-impl-trait/issue-57700.rs
 ui/type-alias-impl-trait/issue-57807-associated-type.rs
 ui/type-alias-impl-trait/issue-57961.rs
 ui/type-alias-impl-trait/issue-58662-coroutine-with-lifetime.rs
diff --git a/tests/ui/self/arbitrary-self-from-method-substs-ice.rs b/tests/ui/self/arbitrary-self-from-method-substs-ice.rs
index a544c8ea0d1..d121a194be6 100644
--- a/tests/ui/self/arbitrary-self-from-method-substs-ice.rs
+++ b/tests/ui/self/arbitrary-self-from-method-substs-ice.rs
@@ -8,7 +8,7 @@ use std::ops::Deref;
 struct Foo(u32);
 impl Foo {
     const fn get<R: Deref<Target = Self>>(self: R) -> u32 {
-        //~^ ERROR: `R` cannot be used as the type of `self`
+        //~^ ERROR invalid generic `self` parameter type
         //~| ERROR destructor of `R` cannot be evaluated at compile-time
         self.0
         //~^ ERROR cannot call non-const fn `<R as Deref>::deref` in constant function
diff --git a/tests/ui/self/arbitrary-self-from-method-substs-ice.stderr b/tests/ui/self/arbitrary-self-from-method-substs-ice.stderr
index 6ae60e7af47..7252b5890fd 100644
--- a/tests/ui/self/arbitrary-self-from-method-substs-ice.stderr
+++ b/tests/ui/self/arbitrary-self-from-method-substs-ice.stderr
@@ -15,18 +15,16 @@ LL |     const fn get<R: Deref<Target = Self>>(self: R) -> u32 {
 LL |     }
    |     - value is dropped here
 
-error[E0658]: `R` cannot be used as the type of `self` without the `arbitrary_self_types` feature
+error[E0801]: invalid generic `self` parameter type: `R`
   --> $DIR/arbitrary-self-from-method-substs-ice.rs:10:49
    |
 LL |     const fn get<R: Deref<Target = Self>>(self: R) -> 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`)
+   = 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: aborting due to 3 previous errors
 
-Some errors have detailed explanations: E0015, E0493, E0658.
+Some errors have detailed explanations: E0015, E0493, E0801.
 For more information about an error, try `rustc --explain E0015`.
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 4cc69666b88..5dc3a0b0234 100644
--- a/tests/ui/self/arbitrary-self-from-method-substs.default.stderr
+++ b/tests/ui/self/arbitrary-self-from-method-substs.default.stderr
@@ -1,14 +1,168 @@
-error[E0658]: `R` cannot be used as the type of `self` without the `arbitrary_self_types` feature
-  --> $DIR/arbitrary-self-from-method-substs.rs:8:43
+error[E0801]: invalid generic `self` parameter type: `R`
+  --> $DIR/arbitrary-self-from-method-substs.rs:9:43
    |
 LL |     fn get<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: `&R`
+  --> $DIR/arbitrary-self-from-method-substs.rs:13:44
+   |
+LL |     fn get1<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: `&mut R`
+  --> $DIR/arbitrary-self-from-method-substs.rs:17:44
+   |
+LL |     fn get2<R: Deref<Target = Self>>(self: &mut 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: `Rc<R>`
+  --> $DIR/arbitrary-self-from-method-substs.rs:21:44
+   |
+LL |     fn get3<R: Deref<Target = Self>>(self: std::rc::Rc<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: `&Rc<R>`
+  --> $DIR/arbitrary-self-from-method-substs.rs:25:44
+   |
+LL |     fn get4<R: Deref<Target = Self>>(self: &std::rc::Rc<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: `Rc<&R>`
+  --> $DIR/arbitrary-self-from-method-substs.rs:29:44
+   |
+LL |     fn get5<R: Deref<Target = Self>>(self: std::rc::Rc<&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[E0658]: `<FR as FindReceiver>::Receiver` cannot be used as the type of `self` without the `arbitrary_self_types` feature
+  --> $DIR/arbitrary-self-from-method-substs.rs:33:37
+   |
+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`)
 
-error: aborting due to 1 previous error
+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
+   |
+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`)
+
+error[E0271]: type mismatch resolving `<Silly as FindReceiver>::Receiver == Foo`
+  --> $DIR/arbitrary-self-from-method-substs.rs:92:9
+   |
+LL |     foo.get6(Silly);
+   |         ^^^^ type mismatch resolving `<Silly as FindReceiver>::Receiver == Foo`
+   |
+note: expected this to be `Foo`
+  --> $DIR/arbitrary-self-from-method-substs.rs:71:21
+   |
+LL |     type Receiver = std::rc::Rc<Foo>;
+   |                     ^^^^^^^^^^^^^^^^
+   = note: expected struct `Foo`
+              found struct `Rc<Foo>`
+
+error[E0271]: type mismatch resolving `<Silly as FindReceiver>::Receiver == &Foo`
+  --> $DIR/arbitrary-self-from-method-substs.rs:96:9
+   |
+LL |     foo.get6(Silly);
+   |         ^^^^ type mismatch resolving `<Silly as FindReceiver>::Receiver == &Foo`
+   |
+note: expected this to be `&Foo`
+  --> $DIR/arbitrary-self-from-method-substs.rs:71:21
+   |
+LL |     type Receiver = std::rc::Rc<Foo>;
+   |                     ^^^^^^^^^^^^^^^^
+   = note: expected reference `&Foo`
+                 found struct `Rc<Foo>`
+
+error[E0599]: the method `get` exists for struct `Rc<Bar<_>>`, but its trait bounds were not satisfied
+  --> $DIR/arbitrary-self-from-method-substs.rs:100:7
+   |
+LL | struct Bar<R>(std::marker::PhantomData<R>);
+   | ------------- doesn't satisfy `Bar<_>: Deref`
+...
+LL |     t.get();
+   |       ^^^ method cannot be called on `Rc<Bar<_>>` due to unsatisfied trait bounds
+   |
+note: the following trait bounds were not satisfied:
+      `<&Bar<_> as Deref>::Target = Bar<&Bar<_>>`
+      `<&Rc<Bar<_>> as Deref>::Target = Bar<&Rc<Bar<_>>>`
+      `<&mut Bar<_> as Deref>::Target = Bar<&mut Bar<_>>`
+      `<&mut Rc<Bar<_>> as Deref>::Target = Bar<&mut Rc<Bar<_>>>`
+      `<Rc<Bar<_>> as Deref>::Target = Bar<Rc<Bar<_>>>`
+      `Bar<_>: Deref`
+  --> $DIR/arbitrary-self-from-method-substs.rs:60:9
+   |
+LL | impl<R: std::ops::Deref<Target = Self>> Bar<R> {
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^  ------
+   |         |               |
+   |         |               unsatisfied trait bound introduced here
+   |         unsatisfied trait bound introduced here
+note: the trait `Deref` must be implemented
+  --> $SRC_DIR/core/src/ops/deref.rs:LL:COL
+   = help: items from traits can only be used if the trait is implemented and in scope
+   = note: the following trait defines an item `get`, perhaps you need to implement it:
+           candidate #1: `SliceIndex`
+
+error[E0599]: the method `get` exists for reference `&Rc<Bar<_>>`, but its trait bounds were not satisfied
+  --> $DIR/arbitrary-self-from-method-substs.rs:108:7
+   |
+LL | struct Bar<R>(std::marker::PhantomData<R>);
+   | ------------- doesn't satisfy `Bar<_>: Deref`
+...
+LL |     t.get();
+   |       ^^^ method cannot be called on `&Rc<Bar<_>>` due to unsatisfied trait bounds
+   |
+note: the following trait bounds were not satisfied:
+      `<&&Rc<Bar<_>> as Deref>::Target = Bar<&&Rc<Bar<_>>>`
+      `<&Bar<_> as Deref>::Target = Bar<&Bar<_>>`
+      `<&Rc<Bar<_>> as Deref>::Target = Bar<&Rc<Bar<_>>>`
+      `<&mut &Rc<Bar<_>> as Deref>::Target = Bar<&mut &Rc<Bar<_>>>`
+      `<&mut Bar<_> as Deref>::Target = Bar<&mut Bar<_>>`
+      `<&mut Rc<Bar<_>> as Deref>::Target = Bar<&mut Rc<Bar<_>>>`
+      `<Rc<Bar<_>> as Deref>::Target = Bar<Rc<Bar<_>>>`
+      `Bar<_>: Deref`
+  --> $DIR/arbitrary-self-from-method-substs.rs:60:9
+   |
+LL | impl<R: std::ops::Deref<Target = Self>> Bar<R> {
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^  ------
+   |         |               |
+   |         |               unsatisfied trait bound introduced here
+   |         unsatisfied trait bound introduced here
+note: the trait `Deref` must be implemented
+  --> $SRC_DIR/core/src/ops/deref.rs:LL:COL
+   = help: items from traits can only be used if the trait is implemented and in scope
+   = note: the following trait defines an item `get`, perhaps you need to implement it:
+           candidate #1: `SliceIndex`
+
+error: aborting due to 12 previous errors
 
-For more information about this error, try `rustc --explain E0658`.
+Some errors have detailed explanations: E0271, E0599, E0658, E0801.
+For more information about an error, try `rustc --explain E0271`.
diff --git a/tests/ui/self/arbitrary-self-from-method-substs.feature.stderr b/tests/ui/self/arbitrary-self-from-method-substs.feature.stderr
index 44e553f1a06..6e864f44aa3 100644
--- a/tests/ui/self/arbitrary-self-from-method-substs.feature.stderr
+++ b/tests/ui/self/arbitrary-self-from-method-substs.feature.stderr
@@ -1,9 +1,179 @@
+error[E0801]: invalid generic `self` parameter type: `R`
+  --> $DIR/arbitrary-self-from-method-substs.rs:9:43
+   |
+LL |     fn get<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: `&R`
+  --> $DIR/arbitrary-self-from-method-substs.rs:13:44
+   |
+LL |     fn get1<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: `&mut R`
+  --> $DIR/arbitrary-self-from-method-substs.rs:17:44
+   |
+LL |     fn get2<R: Deref<Target = Self>>(self: &mut 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: `Rc<R>`
+  --> $DIR/arbitrary-self-from-method-substs.rs:21:44
+   |
+LL |     fn get3<R: Deref<Target = Self>>(self: std::rc::Rc<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: `&Rc<R>`
+  --> $DIR/arbitrary-self-from-method-substs.rs:25:44
+   |
+LL |     fn get4<R: Deref<Target = Self>>(self: &std::rc::Rc<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: `Rc<&R>`
+  --> $DIR/arbitrary-self-from-method-substs.rs:29:44
+   |
+LL |     fn get5<R: Deref<Target = Self>>(self: std::rc::Rc<&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[E0308]: mismatched types
-  --> $DIR/arbitrary-self-from-method-substs.rs:16:5
+  --> $DIR/arbitrary-self-from-method-substs.rs:76:5
    |
 LL |     foo.get::<&Foo>();
    |     ^^^ expected `&Foo`, found `Foo`
 
-error: aborting due to 1 previous error
+error[E0308]: mismatched types
+  --> $DIR/arbitrary-self-from-method-substs.rs:78:5
+   |
+LL |     foo.get::<std::rc::Rc<Foo>>();
+   |     ^^^ expected `Rc<Foo>`, found `Foo`
+   |
+   = note: expected struct `Rc<Foo>`
+              found struct `Foo`
+
+error[E0308]: mismatched types
+  --> $DIR/arbitrary-self-from-method-substs.rs:84:5
+   |
+LL |     smart_ptr.get::<SmartPtr2<Foo>>();
+   |     ^^^^^^^^^ expected `SmartPtr2<'_, Foo>`, found `SmartPtr<'_, Foo>`
+   |
+   = note: expected struct `SmartPtr2<'_, Foo>`
+              found struct `SmartPtr<'_, Foo>`
+
+error[E0308]: mismatched types
+  --> $DIR/arbitrary-self-from-method-substs.rs:86:5
+   |
+LL |     smart_ptr.get::<&Foo>();
+   |     ^^^^^^^^^ expected `&Foo`, found `SmartPtr<'_, Foo>`
+   |
+   = note: expected reference `&Foo`
+                 found struct `SmartPtr<'_, Foo, >`
+
+error[E0271]: type mismatch resolving `<Silly as FindReceiver>::Receiver == Foo`
+  --> $DIR/arbitrary-self-from-method-substs.rs:92:9
+   |
+LL |     foo.get6(Silly);
+   |         ^^^^ type mismatch resolving `<Silly as FindReceiver>::Receiver == Foo`
+   |
+note: expected this to be `Foo`
+  --> $DIR/arbitrary-self-from-method-substs.rs:71:21
+   |
+LL |     type Receiver = std::rc::Rc<Foo>;
+   |                     ^^^^^^^^^^^^^^^^
+   = note: expected struct `Foo`
+              found struct `Rc<Foo>`
+
+error[E0271]: type mismatch resolving `<Silly as FindReceiver>::Receiver == &Foo`
+  --> $DIR/arbitrary-self-from-method-substs.rs:96:9
+   |
+LL |     foo.get6(Silly);
+   |         ^^^^ type mismatch resolving `<Silly as FindReceiver>::Receiver == &Foo`
+   |
+note: expected this to be `&Foo`
+  --> $DIR/arbitrary-self-from-method-substs.rs:71:21
+   |
+LL |     type Receiver = std::rc::Rc<Foo>;
+   |                     ^^^^^^^^^^^^^^^^
+   = note: expected reference `&Foo`
+                 found struct `Rc<Foo>`
+
+error[E0599]: the method `get` exists for struct `Rc<Bar<_>>`, but its trait bounds were not satisfied
+  --> $DIR/arbitrary-self-from-method-substs.rs:100:7
+   |
+LL | struct Bar<R>(std::marker::PhantomData<R>);
+   | ------------- doesn't satisfy `Bar<_>: Deref`
+...
+LL |     t.get();
+   |       ^^^ method cannot be called on `Rc<Bar<_>>` due to unsatisfied trait bounds
+   |
+note: the following trait bounds were not satisfied:
+      `<&Bar<_> as Deref>::Target = Bar<&Bar<_>>`
+      `<&Rc<Bar<_>> as Deref>::Target = Bar<&Rc<Bar<_>>>`
+      `<&mut Bar<_> as Deref>::Target = Bar<&mut Bar<_>>`
+      `<&mut Rc<Bar<_>> as Deref>::Target = Bar<&mut Rc<Bar<_>>>`
+      `<Rc<Bar<_>> as Deref>::Target = Bar<Rc<Bar<_>>>`
+      `Bar<_>: Deref`
+  --> $DIR/arbitrary-self-from-method-substs.rs:60:9
+   |
+LL | impl<R: std::ops::Deref<Target = Self>> Bar<R> {
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^  ------
+   |         |               |
+   |         |               unsatisfied trait bound introduced here
+   |         unsatisfied trait bound introduced here
+note: the trait `Deref` must be implemented
+  --> $SRC_DIR/core/src/ops/deref.rs:LL:COL
+   = help: items from traits can only be used if the trait is implemented and in scope
+   = note: the following trait defines an item `get`, perhaps you need to implement it:
+           candidate #1: `SliceIndex`
+
+error[E0599]: the method `get` exists for reference `&Rc<Bar<_>>`, but its trait bounds were not satisfied
+  --> $DIR/arbitrary-self-from-method-substs.rs:108:7
+   |
+LL | struct Bar<R>(std::marker::PhantomData<R>);
+   | ------------- doesn't satisfy `Bar<_>: Deref`
+...
+LL |     t.get();
+   |       ^^^ method cannot be called on `&Rc<Bar<_>>` due to unsatisfied trait bounds
+   |
+note: the following trait bounds were not satisfied:
+      `<&&Rc<Bar<_>> as Deref>::Target = Bar<&&Rc<Bar<_>>>`
+      `<&Bar<_> as Deref>::Target = Bar<&Bar<_>>`
+      `<&Rc<Bar<_>> as Deref>::Target = Bar<&Rc<Bar<_>>>`
+      `<&mut &Rc<Bar<_>> as Deref>::Target = Bar<&mut &Rc<Bar<_>>>`
+      `<&mut Bar<_> as Deref>::Target = Bar<&mut Bar<_>>`
+      `<&mut Rc<Bar<_>> as Deref>::Target = Bar<&mut Rc<Bar<_>>>`
+      `<Rc<Bar<_>> as Deref>::Target = Bar<Rc<Bar<_>>>`
+      `Bar<_>: Deref`
+  --> $DIR/arbitrary-self-from-method-substs.rs:60:9
+   |
+LL | impl<R: std::ops::Deref<Target = Self>> Bar<R> {
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^  ------
+   |         |               |
+   |         |               unsatisfied trait bound introduced here
+   |         unsatisfied trait bound introduced here
+note: the trait `Deref` must be implemented
+  --> $SRC_DIR/core/src/ops/deref.rs:LL:COL
+   = help: items from traits can only be used if the trait is implemented and in scope
+   = note: the following trait defines an item `get`, perhaps you need to implement it:
+           candidate #1: `SliceIndex`
+
+error: aborting due to 14 previous errors
 
-For more information about this error, try `rustc --explain E0308`.
+Some errors have detailed explanations: E0271, E0308, E0599, E0801.
+For more information about an error, try `rustc --explain E0271`.
diff --git a/tests/ui/self/arbitrary-self-from-method-substs.rs b/tests/ui/self/arbitrary-self-from-method-substs.rs
index 99977ed9b8c..f2d65859615 100644
--- a/tests/ui/self/arbitrary-self-from-method-substs.rs
+++ b/tests/ui/self/arbitrary-self-from-method-substs.rs
@@ -2,17 +2,109 @@
 #![cfg_attr(feature, feature(arbitrary_self_types))]
 
 use std::ops::Deref;
+use std::marker::PhantomData;
 
 struct Foo(u32);
 impl Foo {
     fn get<R: Deref<Target = Self>>(self: R) -> u32 {
-        //[default]~^ ERROR: `R` cannot be used as the type of `self`
+        //~^ ERROR: invalid generic `self` parameter type
         self.0
     }
+    fn get1<R: Deref<Target = Self>>(self: &R) -> u32 {
+        //~^ ERROR: invalid generic `self` parameter type
+        self.0
+    }
+    fn get2<R: Deref<Target = Self>>(self: &mut R) -> u32 {
+        //~^ ERROR: invalid generic `self` parameter type
+        self.0
+    }
+    fn get3<R: Deref<Target = Self>>(self: std::rc::Rc<R>) -> u32 {
+        //~^ ERROR: invalid generic `self` parameter type
+        self.0
+    }
+    fn get4<R: Deref<Target = Self>>(self: &std::rc::Rc<R>) -> u32 {
+        //~^ ERROR: invalid generic `self` parameter type
+        self.0
+    }
+    fn get5<R: Deref<Target = Self>>(self: std::rc::Rc<&R>) -> u32 {
+        //~^ ERROR: invalid generic `self` parameter type
+        self.0
+    }
+    fn get6<FR: FindReceiver>(self: FR::Receiver, other: FR) -> u32 {
+        //[default]~^ ERROR: `<FR as FindReceiver>::Receiver` cannot be used as the type of `self`
+        42
+    }
+}
+
+
+struct SmartPtr<'a, T: ?Sized>(&'a T);
+
+impl<'a, T: ?Sized> Deref for SmartPtr<'a, T> {
+    type Target = T;
+    fn deref(&self) -> &Self::Target {
+        unimplemented!()
+    }
+}
+
+struct SmartPtr2<'a, T: ?Sized>(&'a T);
+
+impl<'a, T: ?Sized> Deref for SmartPtr2<'a, T> {
+    type Target = T;
+    fn deref(&self) -> &Self::Target {
+        unimplemented!()
+    }
+}
+
+struct Bar<R>(std::marker::PhantomData<R>);
+
+impl<R: std::ops::Deref<Target = Self>> Bar<R> {
+    fn get(self: R) {}
+    //[default]~^ ERROR: `R` cannot be used as the type of `self`
+}
+
+trait FindReceiver {
+    type Receiver: Deref<Target = Foo>;
+}
+
+struct Silly;
+impl FindReceiver for Silly {
+    type Receiver = std::rc::Rc<Foo>;
 }
 
 fn main() {
     let mut foo = Foo(1);
     foo.get::<&Foo>();
     //[feature]~^ ERROR mismatched types
+    foo.get::<std::rc::Rc<Foo>>();
+    //[feature]~^ ERROR mismatched types
+
+    let smart_ptr = SmartPtr(&foo);
+    let smart_ptr2 = SmartPtr2(&foo);
+    smart_ptr.get(); // this compiles
+    smart_ptr.get::<SmartPtr2<Foo>>();
+    //[feature]~^ ERROR mismatched types
+    smart_ptr.get::<&Foo>();
+    //[feature]~^ ERROR mismatched types
+
+    let mut foo = Foo(1);
+    // This test is slightly contrived in an attempt to generate a mismatched types
+    // error for the self type below, without using the turbofish.
+    foo.get6(Silly);
+    //~^ ERROR type mismatch
+    let mut foo = Foo(1);
+    let foo = &foo;
+    foo.get6(Silly);
+    //~^ ERROR type mismatch
+
+    let t = std::rc::Rc::new(Bar(std::marker::PhantomData));
+    t.get();
+    //~^ ERROR its trait bounds were not satisfied
+    let t = &t;
+    // This is a further attempt at triggering 'type mismatch' errors
+    // from arbitrary self types without resorting to the turbofish.
+    // Ideally, here, t is Thing<Rc<Target=Self>> while we're going to call
+    // it with a &t method receiver. However, this doesn't work since that
+    // type of t becomes recursive and trait bounds can't be satisfied.
+    t.get();
+    //~^ ERROR its trait bounds were not satisfied
 }
diff --git a/tests/ui/type-alias-impl-trait/issue-57700.rs b/tests/ui/type-alias-impl-trait/issue-57700.rs
deleted file mode 100644
index 8746545ecc9..00000000000
--- a/tests/ui/type-alias-impl-trait/issue-57700.rs
+++ /dev/null
@@ -1,21 +0,0 @@
-#![feature(arbitrary_self_types)]
-#![feature(impl_trait_in_assoc_type)]
-
-use std::ops::Deref;
-
-trait Foo {
-    type Bar: Foo;
-
-    fn foo(self: impl Deref<Target = Self>) -> Self::Bar;
-}
-
-impl<C> Foo for C {
-    type Bar = impl Foo;
-
-    fn foo(self: impl Deref<Target = Self>) -> Self::Bar {
-        self
-        //~^ Error type parameter `impl Deref<Target = Self>` is part of concrete type but not used in parameter list for the `impl Trait` type alias
-    }
-}
-
-fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/issue-57700.stderr b/tests/ui/type-alias-impl-trait/issue-57700.stderr
deleted file mode 100644
index 7efb05f40b0..00000000000
--- a/tests/ui/type-alias-impl-trait/issue-57700.stderr
+++ /dev/null
@@ -1,8 +0,0 @@
-error: type parameter `impl Deref<Target = Self>` is part of concrete type but not used in parameter list for the `impl Trait` type alias
-  --> $DIR/issue-57700.rs:16:9
-   |
-LL |         self
-   |         ^^^^
-
-error: aborting due to 1 previous error
-