about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock1
-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.rs61
-rw-r--r--compiler/rustc_hir_analysis/src/errors.rs10
-rw-r--r--compiler/rustc_hir_typeck/src/method/confirm.rs3
-rw-r--r--compiler/rustc_mir_dataflow/src/framework/graphviz.rs111
-rw-r--r--compiler/rustc_session/src/filesearch.rs2
-rw-r--r--src/librustdoc/doctest/runner.rs4
-rw-r--r--src/tools/compiletest/Cargo.toml1
-rw-r--r--src/tools/compiletest/src/common.rs3
-rw-r--r--src/tools/compiletest/src/header.rs112
-rw-r--r--src/tools/compiletest/src/header/tests.rs78
-rw-r--r--src/tools/compiletest/src/lib.rs2
-rw-r--r--src/tools/compiletest/src/tests.rs13
-rw-r--r--src/tools/tidy/src/issues.txt1
-rw-r--r--tests/rustdoc-ui/doctest/dead-code-2024.rs15
-rw-r--r--tests/rustdoc-ui/doctest/dead-code-2024.stdout29
-rw-r--r--tests/rustdoc-ui/doctest/dead-code.rs15
-rw-r--r--tests/rustdoc-ui/doctest/dead-code.stdout29
-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
-rw-r--r--triagebot.toml1
29 files changed, 836 insertions, 186 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 22b3e8280d6..fc16ccf0a67 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -720,6 +720,7 @@ dependencies = [
  "miropt-test-tools",
  "regex",
  "rustfix",
+ "semver",
  "serde",
  "serde_json",
  "tracing",
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..b20fa49eadb 100644
--- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs
+++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
@@ -904,7 +904,6 @@ 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)
 }
 
@@ -1725,8 +1724,11 @@ fn check_method_receiver<'tcx>(
     } else {
         None
     };
+    let generics = tcx.generics_of(method.def_id);
 
-    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 +1739,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 +1763,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 +1783,45 @@ 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: &ty::Generics,
+) -> Result<(), ReceiverValidityError> {
+    if let ty::Param(param) = ty.kind() {
+        if (param.index as usize) >= method_generics.parent_count {
+            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 +1837,8 @@ fn receiver_is_valid<'tcx>(
     receiver_ty: Ty<'tcx>,
     self_ty: Ty<'tcx>,
     arbitrary_self_types_enabled: Option<ArbitrarySelfTypesLevel>,
-) -> bool {
+    method_generics: &ty::Generics,
+) -> Result<(), ReceiverValidityError> {
     let infcx = wfcx.infcx;
     let tcx = wfcx.tcx();
     let cause =
@@ -1811,9 +1850,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, method_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 +1871,8 @@ fn receiver_is_valid<'tcx>(
             potential_self_ty, self_ty
         );
 
+        confirm_type_is_not_a_method_generic_param(potential_self_ty, method_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 +1881,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 +1908,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/compiler/rustc_mir_dataflow/src/framework/graphviz.rs b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs
index 96a70f4fa5b..bac75b972f9 100644
--- a/compiler/rustc_mir_dataflow/src/framework/graphviz.rs
+++ b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs
@@ -32,8 +32,11 @@ pub(crate) struct Formatter<'mir, 'tcx, A>
 where
     A: Analysis<'tcx>,
 {
-    body: &'mir Body<'tcx>,
-    results: RefCell<Option<Results<'tcx, A>>>,
+    // The `RefCell` is used because `<Formatter as Labeller>::node_label`
+    // takes `&self`, but it needs to modify the cursor. This is also the
+    // reason for the `Formatter`/`BlockFormatter` split; `BlockFormatter` has
+    // the operations that involve the mutation, i.e. within the `borrow_mut`.
+    cursor: RefCell<ResultsCursor<'mir, 'tcx, A>>,
     style: OutputStyle,
     reachable: BitSet<BasicBlock>,
 }
@@ -48,11 +51,15 @@ where
         style: OutputStyle,
     ) -> Self {
         let reachable = mir::traversal::reachable_as_bitset(body);
-        Formatter { body, results: Some(results).into(), style, reachable }
+        Formatter { cursor: results.into_results_cursor(body).into(), style, reachable }
+    }
+
+    fn body(&self) -> &'mir Body<'tcx> {
+        self.cursor.borrow().body()
     }
 
     pub(crate) fn into_results(self) -> Results<'tcx, A> {
-        self.results.into_inner().unwrap()
+        self.cursor.into_inner().into_results()
     }
 }
 
@@ -81,7 +88,7 @@ where
     type Edge = CfgEdge;
 
     fn graph_id(&self) -> dot::Id<'_> {
-        let name = graphviz_safe_def_name(self.body.source.def_id());
+        let name = graphviz_safe_def_name(self.body().source.def_id());
         dot::Id::new(format!("graph_for_def_id_{name}")).unwrap()
     }
 
@@ -90,20 +97,11 @@ where
     }
 
     fn node_label(&self, block: &Self::Node) -> dot::LabelText<'_> {
-        let mut label = Vec::new();
-        self.results.replace_with(|results| {
-            // `Formatter::result` is a `RefCell<Option<_>>` so we can replace
-            // the value with `None`, move it into the results cursor, move it
-            // back out, and return it to the refcell wrapped in `Some`.
-            let mut fmt = BlockFormatter {
-                results: results.take().unwrap().into_results_cursor(self.body),
-                style: self.style,
-                bg: Background::Light,
-            };
+        let mut cursor = self.cursor.borrow_mut();
+        let mut fmt =
+            BlockFormatter { cursor: &mut cursor, style: self.style, bg: Background::Light };
+        let label = fmt.write_node_label(*block).unwrap();
 
-            fmt.write_node_label(&mut label, *block).unwrap();
-            Some(fmt.results.into_results())
-        });
         dot::LabelText::html(String::from_utf8(label).unwrap())
     }
 
@@ -112,12 +110,12 @@ where
     }
 
     fn edge_label(&self, e: &Self::Edge) -> dot::LabelText<'_> {
-        let label = &self.body[e.source].terminator().kind.fmt_successor_labels()[e.index];
+        let label = &self.body()[e.source].terminator().kind.fmt_successor_labels()[e.index];
         dot::LabelText::label(label.clone())
     }
 }
 
-impl<'mir, 'tcx, A> dot::GraphWalk<'mir> for Formatter<'mir, 'tcx, A>
+impl<'tcx, A> dot::GraphWalk<'_> for Formatter<'_, 'tcx, A>
 where
     A: Analysis<'tcx>,
 {
@@ -125,7 +123,7 @@ where
     type Edge = CfgEdge;
 
     fn nodes(&self) -> dot::Nodes<'_, Self::Node> {
-        self.body
+        self.body()
             .basic_blocks
             .indices()
             .filter(|&idx| self.reachable.contains(idx))
@@ -134,10 +132,10 @@ where
     }
 
     fn edges(&self) -> dot::Edges<'_, Self::Edge> {
-        self.body
-            .basic_blocks
+        let body = self.body();
+        body.basic_blocks
             .indices()
-            .flat_map(|bb| dataflow_successors(self.body, bb))
+            .flat_map(|bb| dataflow_successors(body, bb))
             .collect::<Vec<_>>()
             .into()
     }
@@ -147,20 +145,20 @@ where
     }
 
     fn target(&self, edge: &Self::Edge) -> Self::Node {
-        self.body[edge.source].terminator().successors().nth(edge.index).unwrap()
+        self.body()[edge.source].terminator().successors().nth(edge.index).unwrap()
     }
 }
 
-struct BlockFormatter<'mir, 'tcx, A>
+struct BlockFormatter<'a, 'mir, 'tcx, A>
 where
     A: Analysis<'tcx>,
 {
-    results: ResultsCursor<'mir, 'tcx, A>,
+    cursor: &'a mut ResultsCursor<'mir, 'tcx, A>,
     bg: Background,
     style: OutputStyle,
 }
 
-impl<'mir, 'tcx, A> BlockFormatter<'mir, 'tcx, A>
+impl<'tcx, A> BlockFormatter<'_, '_, 'tcx, A>
 where
     A: Analysis<'tcx>,
     A::Domain: DebugWithContext<A>,
@@ -173,7 +171,9 @@ where
         bg
     }
 
-    fn write_node_label(&mut self, w: &mut impl io::Write, block: BasicBlock) -> io::Result<()> {
+    fn write_node_label(&mut self, block: BasicBlock) -> io::Result<Vec<u8>> {
+        use std::io::Write;
+
         //   Sample output:
         //   +-+-----------------------------------------------+
         // A |                      bb4                        |
@@ -200,6 +200,9 @@ where
         // attributes. Make sure to test the output before trying to remove the redundancy.
         // Notably, `align` was found to have no effect when applied only to <table>.
 
+        let mut v = vec![];
+        let w = &mut v;
+
         let table_fmt = concat!(
             " border=\"1\"",
             " cellborder=\"1\"",
@@ -219,8 +222,8 @@ where
 
         // C: State at start of block
         self.bg = Background::Light;
-        self.results.seek_to_block_start(block);
-        let block_start_state = self.results.get().clone();
+        self.cursor.seek_to_block_start(block);
+        let block_start_state = self.cursor.get().clone();
         self.write_row_with_full_state(w, "", "(on start)")?;
 
         // D + E: Statement and terminator transfer functions
@@ -228,12 +231,12 @@ where
 
         // F: State at end of block
 
-        let terminator = self.results.body()[block].terminator();
+        let terminator = self.cursor.body()[block].terminator();
 
         // Write the full dataflow state immediately after the terminator if it differs from the
         // state at block entry.
-        self.results.seek_to_block_end(block);
-        if self.results.get() != &block_start_state || A::Direction::IS_BACKWARD {
+        self.cursor.seek_to_block_end(block);
+        if self.cursor.get() != &block_start_state || A::Direction::IS_BACKWARD {
             let after_terminator_name = match terminator.kind {
                 mir::TerminatorKind::Call { target: Some(_), .. } => "(on unwind)",
                 _ => "(on end)",
@@ -250,8 +253,8 @@ where
         match terminator.kind {
             mir::TerminatorKind::Call { destination, .. } => {
                 self.write_row(w, "", "(on successful return)", |this, w, fmt| {
-                    let state_on_unwind = this.results.get().clone();
-                    this.results.apply_custom_effect(|analysis, state| {
+                    let state_on_unwind = this.cursor.get().clone();
+                    this.cursor.apply_custom_effect(|analysis, state| {
                         analysis.apply_call_return_effect(
                             state,
                             block,
@@ -265,9 +268,9 @@ where
                         colspan = this.style.num_state_columns(),
                         fmt = fmt,
                         diff = diff_pretty(
-                            this.results.get(),
+                            this.cursor.get(),
                             &state_on_unwind,
-                            this.results.analysis()
+                            this.cursor.analysis()
                         ),
                     )
                 })?;
@@ -275,8 +278,8 @@ where
 
             mir::TerminatorKind::Yield { resume, resume_arg, .. } => {
                 self.write_row(w, "", "(on yield resume)", |this, w, fmt| {
-                    let state_on_coroutine_drop = this.results.get().clone();
-                    this.results.apply_custom_effect(|analysis, state| {
+                    let state_on_coroutine_drop = this.cursor.get().clone();
+                    this.cursor.apply_custom_effect(|analysis, state| {
                         analysis.apply_call_return_effect(
                             state,
                             resume,
@@ -290,9 +293,9 @@ where
                         colspan = this.style.num_state_columns(),
                         fmt = fmt,
                         diff = diff_pretty(
-                            this.results.get(),
+                            this.cursor.get(),
                             &state_on_coroutine_drop,
-                            this.results.analysis()
+                            this.cursor.analysis()
                         ),
                     )
                 })?;
@@ -302,8 +305,8 @@ where
                 if !targets.is_empty() =>
             {
                 self.write_row(w, "", "(on successful return)", |this, w, fmt| {
-                    let state_on_unwind = this.results.get().clone();
-                    this.results.apply_custom_effect(|analysis, state| {
+                    let state_on_unwind = this.cursor.get().clone();
+                    this.cursor.apply_custom_effect(|analysis, state| {
                         analysis.apply_call_return_effect(
                             state,
                             block,
@@ -317,9 +320,9 @@ where
                         colspan = this.style.num_state_columns(),
                         fmt = fmt,
                         diff = diff_pretty(
-                            this.results.get(),
+                            this.cursor.get(),
                             &state_on_unwind,
-                            this.results.analysis()
+                            this.cursor.analysis()
                         ),
                     )
                 })?;
@@ -328,7 +331,9 @@ where
             _ => {}
         };
 
-        write!(w, "</table>")
+        write!(w, "</table>")?;
+
+        Ok(v)
     }
 
     fn write_block_header_simple(
@@ -407,9 +412,9 @@ where
         block: BasicBlock,
     ) -> io::Result<()> {
         let diffs = StateDiffCollector::run(
-            self.results.body(),
+            self.cursor.body(),
             block,
-            self.results.mut_results(),
+            self.cursor.mut_results(),
             self.style,
         );
 
@@ -420,7 +425,7 @@ where
             if A::Direction::IS_FORWARD { it.next().unwrap() } else { it.next_back().unwrap() }
         };
 
-        for (i, statement) in self.results.body()[block].statements.iter().enumerate() {
+        for (i, statement) in self.cursor.body()[block].statements.iter().enumerate() {
             let statement_str = format!("{statement:?}");
             let index_str = format!("{i}");
 
@@ -442,7 +447,7 @@ where
         assert!(diffs_after.is_empty());
         assert!(diffs_before.as_ref().map_or(true, ExactSizeIterator::is_empty));
 
-        let terminator = self.results.body()[block].terminator();
+        let terminator = self.cursor.body()[block].terminator();
         let mut terminator_str = String::new();
         terminator.kind.fmt_head(&mut terminator_str).unwrap();
 
@@ -492,8 +497,8 @@ where
         mir: &str,
     ) -> io::Result<()> {
         self.write_row(w, i, mir, |this, w, fmt| {
-            let state = this.results.get();
-            let analysis = this.results.analysis();
+            let state = this.cursor.get();
+            let analysis = this.cursor.analysis();
 
             // FIXME: The full state vector can be quite long. It would be nice to split on commas
             // and use some text wrapping algorithm.
diff --git a/compiler/rustc_session/src/filesearch.rs b/compiler/rustc_session/src/filesearch.rs
index 4aae2649843..b3e3381d986 100644
--- a/compiler/rustc_session/src/filesearch.rs
+++ b/compiler/rustc_session/src/filesearch.rs
@@ -84,7 +84,7 @@ fn current_dll_path() -> Result<PathBuf, String> {
         loop {
             if libc::loadquery(
                 libc::L_GETINFO,
-                buffer.as_mut_ptr() as *mut i8,
+                buffer.as_mut_ptr() as *mut u8,
                 (std::mem::size_of::<libc::ld_info>() * buffer.len()) as u32,
             ) >= 0
             {
diff --git a/src/librustdoc/doctest/runner.rs b/src/librustdoc/doctest/runner.rs
index 093755103f3..234f40c6c1a 100644
--- a/src/librustdoc/doctest/runner.rs
+++ b/src/librustdoc/doctest/runner.rs
@@ -198,10 +198,6 @@ fn generate_mergeable_doctest(
     } else {
         writeln!(output, "mod {test_id} {{\n{}{}", doctest.crates, doctest.maybe_crate_attrs)
             .unwrap();
-        if scraped_test.langstr.no_run {
-            // To prevent having warnings about unused items since they're not called.
-            writeln!(output, "#![allow(unused)]").unwrap();
-        }
         if doctest.has_main_fn {
             output.push_str(&doctest.everything_else);
         } else {
diff --git a/src/tools/compiletest/Cargo.toml b/src/tools/compiletest/Cargo.toml
index b6a89dd49e6..cef6b525a7b 100644
--- a/src/tools/compiletest/Cargo.toml
+++ b/src/tools/compiletest/Cargo.toml
@@ -18,6 +18,7 @@ build_helper = { path = "../build_helper" }
 tracing = "0.1"
 tracing-subscriber = { version = "0.3.3", default-features = false, features = ["fmt", "env-filter", "smallvec", "parking_lot", "ansi"] }
 regex = "1.0"
+semver = { version = "1.0.23", features = ["serde"] }
 serde = { version = "1.0", features = ["derive"] }
 serde_json = "1.0"
 rustfix = "0.8.1"
diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs
index 69ac4644941..e82b88eef79 100644
--- a/src/tools/compiletest/src/common.rs
+++ b/src/tools/compiletest/src/common.rs
@@ -7,6 +7,7 @@ use std::sync::OnceLock;
 use std::{fmt, iter};
 
 use build_helper::git::GitConfig;
+use semver::Version;
 use serde::de::{Deserialize, Deserializer, Error as _};
 use test::{ColorConfig, OutputFormat};
 
@@ -298,7 +299,7 @@ pub struct Config {
     pub lldb_version: Option<u32>,
 
     /// Version of LLVM
-    pub llvm_version: Option<u32>,
+    pub llvm_version: Option<Version>,
 
     /// Is LLVM a system LLVM
     pub system_llvm: bool,
diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs
index a3bf36c0e90..bfcdd747eb4 100644
--- a/src/tools/compiletest/src/header.rs
+++ b/src/tools/compiletest/src/header.rs
@@ -6,6 +6,7 @@ use std::io::prelude::*;
 use std::path::{Path, PathBuf};
 use std::process::Command;
 
+use semver::Version;
 use tracing::*;
 
 use crate::common::{Config, Debugger, FailMode, Mode, PassMode};
@@ -1113,26 +1114,39 @@ fn parse_normalize_rule(header: &str) -> Option<(String, String)> {
     Some((regex, replacement))
 }
 
-pub fn extract_llvm_version(version: &str) -> Option<u32> {
-    let pat = |c: char| !c.is_ascii_digit() && c != '.';
-    let version_without_suffix = match version.find(pat) {
-        Some(pos) => &version[..pos],
+/// Given an llvm version string that looks like `1.2.3-rc1`, extract as semver. Note that this
+/// accepts more than just strict `semver` syntax (as in `major.minor.patch`); this permits omitting
+/// minor and patch version components so users can write e.g. `//@ min-llvm-version: 19` instead of
+/// having to write `//@ min-llvm-version: 19.0.0`.
+///
+/// Currently panics if the input string is malformed, though we really should not use panic as an
+/// error handling strategy.
+///
+/// FIXME(jieyouxu): improve error handling
+pub fn extract_llvm_version(version: &str) -> Version {
+    // The version substring we're interested in usually looks like the `1.2.3`, without any of the
+    // fancy suffix like `-rc1` or `meow`.
+    let version = version.trim();
+    let uninterested = |c: char| !c.is_ascii_digit() && c != '.';
+    let version_without_suffix = match version.split_once(uninterested) {
+        Some((prefix, _suffix)) => prefix,
         None => version,
     };
-    let components: Vec<u32> = version_without_suffix
+
+    let components: Vec<u64> = version_without_suffix
         .split('.')
-        .map(|s| s.parse().expect("Malformed version component"))
+        .map(|s| s.parse().expect("llvm version component should consist of only digits"))
         .collect();
-    let version = match *components {
-        [a] => a * 10_000,
-        [a, b] => a * 10_000 + b * 100,
-        [a, b, c] => a * 10_000 + b * 100 + c,
-        _ => panic!("Malformed version"),
-    };
-    Some(version)
+
+    match &components[..] {
+        [major] => Version::new(*major, 0, 0),
+        [major, minor] => Version::new(*major, *minor, 0),
+        [major, minor, patch] => Version::new(*major, *minor, *patch),
+        _ => panic!("malformed llvm version string, expected only 1-3 components: {version}"),
+    }
 }
 
-pub fn extract_llvm_version_from_binary(binary_path: &str) -> Option<u32> {
+pub fn extract_llvm_version_from_binary(binary_path: &str) -> Option<Version> {
     let output = Command::new(binary_path).arg("--version").output().ok()?;
     if !output.status.success() {
         return None;
@@ -1140,7 +1154,7 @@ pub fn extract_llvm_version_from_binary(binary_path: &str) -> Option<u32> {
     let version = String::from_utf8(output.stdout).ok()?;
     for line in version.lines() {
         if let Some(version) = line.split("LLVM version ").nth(1) {
-            return extract_llvm_version(version);
+            return Some(extract_llvm_version(version));
         }
     }
     None
@@ -1247,15 +1261,17 @@ pub fn llvm_has_libzstd(config: &Config) -> bool {
     false
 }
 
-/// Takes a directive of the form `"<version1> [- <version2>]"`,
-/// returns the numeric representation of `<version1>` and `<version2>` as
-/// tuple: `(<version1> as u32, <version2> as u32)`.
+/// Takes a directive of the form `"<version1> [- <version2>]"`, returns the numeric representation
+/// of `<version1>` and `<version2>` as tuple: `(<version1>, <version2>)`.
 ///
-/// If the `<version2>` part is omitted, the second component of the tuple
-/// is the same as `<version1>`.
-fn extract_version_range<F>(line: &str, parse: F) -> Option<(u32, u32)>
+/// If the `<version2>` part is omitted, the second component of the tuple is the same as
+/// `<version1>`.
+fn extract_version_range<'a, F, VersionTy: Clone>(
+    line: &'a str,
+    parse: F,
+) -> Option<(VersionTy, VersionTy)>
 where
-    F: Fn(&str) -> Option<u32>,
+    F: Fn(&'a str) -> Option<VersionTy>,
 {
     let mut splits = line.splitn(2, "- ").map(str::trim);
     let min = splits.next().unwrap();
@@ -1273,7 +1289,7 @@ where
     let max = match max {
         Some("") => return None,
         Some(max) => parse(max)?,
-        _ => min,
+        _ => min.clone(),
     };
 
     Some((min, max))
@@ -1489,43 +1505,55 @@ fn ignore_llvm(config: &Config, line: &str) -> IgnoreDecision {
             };
         }
     }
-    if let Some(actual_version) = config.llvm_version {
-        if let Some(rest) = line.strip_prefix("min-llvm-version:").map(str::trim) {
-            let min_version = extract_llvm_version(rest).unwrap();
-            // Ignore if actual version is smaller the minimum required
-            // version
-            if actual_version < min_version {
+    if let Some(actual_version) = &config.llvm_version {
+        // Note that these `min` versions will check for not just major versions.
+
+        if let Some(version_string) = config.parse_name_value_directive(line, "min-llvm-version") {
+            let min_version = extract_llvm_version(&version_string);
+            // Ignore if actual version is smaller than the minimum required version.
+            if *actual_version < min_version {
                 return IgnoreDecision::Ignore {
-                    reason: format!("ignored when the LLVM version is older than {rest}"),
+                    reason: format!(
+                        "ignored when the LLVM version {actual_version} is older than {min_version}"
+                    ),
                 };
             }
-        } else if let Some(rest) = line.strip_prefix("min-system-llvm-version:").map(str::trim) {
-            let min_version = extract_llvm_version(rest).unwrap();
+        } else if let Some(version_string) =
+            config.parse_name_value_directive(line, "min-system-llvm-version")
+        {
+            let min_version = extract_llvm_version(&version_string);
             // Ignore if using system LLVM and actual version
             // is smaller the minimum required version
-            if config.system_llvm && actual_version < min_version {
+            if config.system_llvm && *actual_version < min_version {
                 return IgnoreDecision::Ignore {
-                    reason: format!("ignored when the system LLVM version is older than {rest}"),
+                    reason: format!(
+                        "ignored when the system LLVM version {actual_version} is older than {min_version}"
+                    ),
                 };
             }
-        } else if let Some(rest) = line.strip_prefix("ignore-llvm-version:").map(str::trim) {
+        } else if let Some(version_range) =
+            config.parse_name_value_directive(line, "ignore-llvm-version")
+        {
             // Syntax is: "ignore-llvm-version: <version1> [- <version2>]"
             let (v_min, v_max) =
-                extract_version_range(rest, extract_llvm_version).unwrap_or_else(|| {
-                    panic!("couldn't parse version range: {:?}", rest);
-                });
+                extract_version_range(&version_range, |s| Some(extract_llvm_version(s)))
+                    .unwrap_or_else(|| {
+                        panic!("couldn't parse version range: \"{version_range}\"");
+                    });
             if v_max < v_min {
-                panic!("Malformed LLVM version range: max < min")
+                panic!("malformed LLVM version range where {v_max} < {v_min}")
             }
             // Ignore if version lies inside of range.
-            if actual_version >= v_min && actual_version <= v_max {
+            if *actual_version >= v_min && *actual_version <= v_max {
                 if v_min == v_max {
                     return IgnoreDecision::Ignore {
-                        reason: format!("ignored when the LLVM version is {rest}"),
+                        reason: format!("ignored when the LLVM version is {actual_version}"),
                     };
                 } else {
                     return IgnoreDecision::Ignore {
-                        reason: format!("ignored when the LLVM version is between {rest}"),
+                        reason: format!(
+                            "ignored when the LLVM version is between {v_min} and {v_max}"
+                        ),
                     };
                 }
             }
diff --git a/src/tools/compiletest/src/header/tests.rs b/src/tools/compiletest/src/header/tests.rs
index c3c9496c4d2..2e6effcab98 100644
--- a/src/tools/compiletest/src/header/tests.rs
+++ b/src/tools/compiletest/src/header/tests.rs
@@ -1,9 +1,13 @@
 use std::io::Read;
 use std::path::Path;
 
-use super::iter_header;
+use semver::Version;
+
+use super::{
+    EarlyProps, HeadersCache, extract_llvm_version, extract_version_range, iter_header,
+    parse_normalize_rule,
+};
 use crate::common::{Config, Debugger, Mode};
-use crate::header::{EarlyProps, HeadersCache, parse_normalize_rule};
 
 fn make_test_description<R: Read>(
     config: &Config,
@@ -408,18 +412,66 @@ fn channel() {
 }
 
 #[test]
+fn test_extract_llvm_version() {
+    // Note: officially, semver *requires* that versions at the minimum have all three
+    // `major.minor.patch` numbers, though for test-writer's convenience we allow omitting the minor
+    // and patch numbers (which will be stubbed out as 0).
+    assert_eq!(extract_llvm_version("0"), Version::new(0, 0, 0));
+    assert_eq!(extract_llvm_version("0.0"), Version::new(0, 0, 0));
+    assert_eq!(extract_llvm_version("0.0.0"), Version::new(0, 0, 0));
+    assert_eq!(extract_llvm_version("1"), Version::new(1, 0, 0));
+    assert_eq!(extract_llvm_version("1.2"), Version::new(1, 2, 0));
+    assert_eq!(extract_llvm_version("1.2.3"), Version::new(1, 2, 3));
+    assert_eq!(extract_llvm_version("4.5.6git"), Version::new(4, 5, 6));
+    assert_eq!(extract_llvm_version("4.5.6-rc1"), Version::new(4, 5, 6));
+    assert_eq!(extract_llvm_version("123.456.789-rc1"), Version::new(123, 456, 789));
+    assert_eq!(extract_llvm_version("8.1.2-rust"), Version::new(8, 1, 2));
+    assert_eq!(extract_llvm_version("9.0.1-rust-1.43.0-dev"), Version::new(9, 0, 1));
+    assert_eq!(extract_llvm_version("9.3.1-rust-1.43.0-dev"), Version::new(9, 3, 1));
+    assert_eq!(extract_llvm_version("10.0.0-rust"), Version::new(10, 0, 0));
+    assert_eq!(extract_llvm_version("11.1.0"), Version::new(11, 1, 0));
+    assert_eq!(extract_llvm_version("12.0.0libcxx"), Version::new(12, 0, 0));
+    assert_eq!(extract_llvm_version("12.0.0-rc3"), Version::new(12, 0, 0));
+    assert_eq!(extract_llvm_version("13.0.0git"), Version::new(13, 0, 0));
+}
+
+#[test]
+#[should_panic]
+fn test_llvm_version_invalid_components() {
+    extract_llvm_version("4.x.6");
+}
+
+#[test]
+#[should_panic]
+fn test_llvm_version_invalid_prefix() {
+    extract_llvm_version("meow4.5.6");
+}
+
+#[test]
+#[should_panic]
+fn test_llvm_version_too_many_components() {
+    extract_llvm_version("4.5.6.7");
+}
+
+#[test]
 fn test_extract_version_range() {
-    use super::{extract_llvm_version, extract_version_range};
-
-    assert_eq!(extract_version_range("1.2.3 - 4.5.6", extract_llvm_version), Some((10203, 40506)));
-    assert_eq!(extract_version_range("0   - 4.5.6", extract_llvm_version), Some((0, 40506)));
-    assert_eq!(extract_version_range("1.2.3 -", extract_llvm_version), None);
-    assert_eq!(extract_version_range("1.2.3 - ", extract_llvm_version), None);
-    assert_eq!(extract_version_range("- 4.5.6", extract_llvm_version), None);
-    assert_eq!(extract_version_range("-", extract_llvm_version), None);
-    assert_eq!(extract_version_range(" - 4.5.6", extract_llvm_version), None);
-    assert_eq!(extract_version_range("   - 4.5.6", extract_llvm_version), None);
-    assert_eq!(extract_version_range("0  -", extract_llvm_version), None);
+    let wrapped_extract = |s: &str| Some(extract_llvm_version(s));
+
+    assert_eq!(
+        extract_version_range("1.2.3 - 4.5.6", wrapped_extract),
+        Some((Version::new(1, 2, 3), Version::new(4, 5, 6)))
+    );
+    assert_eq!(
+        extract_version_range("0   - 4.5.6", wrapped_extract),
+        Some((Version::new(0, 0, 0), Version::new(4, 5, 6)))
+    );
+    assert_eq!(extract_version_range("1.2.3 -", wrapped_extract), None);
+    assert_eq!(extract_version_range("1.2.3 - ", wrapped_extract), None);
+    assert_eq!(extract_version_range("- 4.5.6", wrapped_extract), None);
+    assert_eq!(extract_version_range("-", wrapped_extract), None);
+    assert_eq!(extract_version_range(" - 4.5.6", wrapped_extract), None);
+    assert_eq!(extract_version_range("   - 4.5.6", wrapped_extract), None);
+    assert_eq!(extract_version_range("0  -", wrapped_extract), None);
 }
 
 #[test]
diff --git a/src/tools/compiletest/src/lib.rs b/src/tools/compiletest/src/lib.rs
index 490df313228..ccf8057bf5c 100644
--- a/src/tools/compiletest/src/lib.rs
+++ b/src/tools/compiletest/src/lib.rs
@@ -228,7 +228,7 @@ pub fn parse_config(args: Vec<String>) -> Config {
         Some(x) => panic!("argument for --color must be auto, always, or never, but found `{}`", x),
     };
     let llvm_version =
-        matches.opt_str("llvm-version").as_deref().and_then(header::extract_llvm_version).or_else(
+        matches.opt_str("llvm-version").as_deref().map(header::extract_llvm_version).or_else(
             || header::extract_llvm_version_from_binary(&matches.opt_str("llvm-filecheck")?),
         );
 
diff --git a/src/tools/compiletest/src/tests.rs b/src/tools/compiletest/src/tests.rs
index 680579c59ae..fec746904de 100644
--- a/src/tools/compiletest/src/tests.rs
+++ b/src/tools/compiletest/src/tests.rs
@@ -1,7 +1,6 @@
 use std::ffi::OsString;
 
 use crate::debuggers::{extract_gdb_version, extract_lldb_version};
-use crate::header::extract_llvm_version;
 use crate::is_test;
 
 #[test]
@@ -67,15 +66,3 @@ fn is_test_test() {
     assert!(!is_test(&OsString::from("#a_dog_gif")));
     assert!(!is_test(&OsString::from("~a_temp_file")));
 }
-
-#[test]
-fn test_extract_llvm_version() {
-    assert_eq!(extract_llvm_version("8.1.2-rust"), Some(80102));
-    assert_eq!(extract_llvm_version("9.0.1-rust-1.43.0-dev"), Some(90001));
-    assert_eq!(extract_llvm_version("9.3.1-rust-1.43.0-dev"), Some(90301));
-    assert_eq!(extract_llvm_version("10.0.0-rust"), Some(100000));
-    assert_eq!(extract_llvm_version("11.1.0"), Some(110100));
-    assert_eq!(extract_llvm_version("12.0.0libcxx"), Some(120000));
-    assert_eq!(extract_llvm_version("12.0.0-rc3"), Some(120000));
-    assert_eq!(extract_llvm_version("13.0.0git"), Some(130000));
-}
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/rustdoc-ui/doctest/dead-code-2024.rs b/tests/rustdoc-ui/doctest/dead-code-2024.rs
new file mode 100644
index 00000000000..4c77112e61a
--- /dev/null
+++ b/tests/rustdoc-ui/doctest/dead-code-2024.rs
@@ -0,0 +1,15 @@
+// This test ensures that the 2024 edition merged doctest will not use `#[allow(unused)]`.
+
+//@ compile-flags:--test -Zunstable-options --edition 2024
+//@ normalize-stdout-test: "tests/rustdoc-ui/doctest" -> "$$DIR"
+//@ normalize-stdout-test: "finished in \d+\.\d+s" -> "finished in $$TIME"
+//@ failure-status: 101
+
+#![doc(test(attr(allow(unused_variables), deny(warnings))))]
+
+/// Example
+///
+/// ```rust,no_run
+/// trait T { fn f(); }
+/// ```
+pub fn f() {}
diff --git a/tests/rustdoc-ui/doctest/dead-code-2024.stdout b/tests/rustdoc-ui/doctest/dead-code-2024.stdout
new file mode 100644
index 00000000000..69dd4e2ede1
--- /dev/null
+++ b/tests/rustdoc-ui/doctest/dead-code-2024.stdout
@@ -0,0 +1,29 @@
+
+running 1 test
+test $DIR/dead-code-2024.rs - f (line 12) - compile ... FAILED
+
+failures:
+
+---- $DIR/dead-code-2024.rs - f (line 12) stdout ----
+error: trait `T` is never used
+  --> $DIR/dead-code-2024.rs:13:7
+   |
+LL | trait T { fn f(); }
+   |       ^
+   |
+note: the lint level is defined here
+  --> $DIR/dead-code-2024.rs:11:9
+   |
+LL | #![deny(warnings)]
+   |         ^^^^^^^^
+   = note: `#[deny(dead_code)]` implied by `#[deny(warnings)]`
+
+error: aborting due to 1 previous error
+
+Couldn't compile the test.
+
+failures:
+    $DIR/dead-code-2024.rs - f (line 12)
+
+test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME
+
diff --git a/tests/rustdoc-ui/doctest/dead-code.rs b/tests/rustdoc-ui/doctest/dead-code.rs
new file mode 100644
index 00000000000..cb9b4c28f6c
--- /dev/null
+++ b/tests/rustdoc-ui/doctest/dead-code.rs
@@ -0,0 +1,15 @@
+// This test ensures that the doctest will not use `#[allow(unused)]`.
+
+//@ compile-flags:--test
+//@ normalize-stdout-test: "tests/rustdoc-ui/doctest" -> "$$DIR"
+//@ normalize-stdout-test: "finished in \d+\.\d+s" -> "finished in $$TIME"
+//@ failure-status: 101
+
+#![doc(test(attr(allow(unused_variables), deny(warnings))))]
+
+/// Example
+///
+/// ```rust,no_run
+/// trait T { fn f(); }
+/// ```
+pub fn f() {}
diff --git a/tests/rustdoc-ui/doctest/dead-code.stdout b/tests/rustdoc-ui/doctest/dead-code.stdout
new file mode 100644
index 00000000000..38d15d5c1bc
--- /dev/null
+++ b/tests/rustdoc-ui/doctest/dead-code.stdout
@@ -0,0 +1,29 @@
+
+running 1 test
+test $DIR/dead-code.rs - f (line 12) - compile ... FAILED
+
+failures:
+
+---- $DIR/dead-code.rs - f (line 12) stdout ----
+error: trait `T` is never used
+  --> $DIR/dead-code.rs:13:7
+   |
+LL | trait T { fn f(); }
+   |       ^
+   |
+note: the lint level is defined here
+  --> $DIR/dead-code.rs:11:9
+   |
+LL | #![deny(warnings)]
+   |         ^^^^^^^^
+   = note: `#[deny(dead_code)]` implied by `#[deny(warnings)]`
+
+error: aborting due to 1 previous error
+
+Couldn't compile the test.
+
+failures:
+    $DIR/dead-code.rs - f (line 12)
+
+test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME
+
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
-
diff --git a/triagebot.toml b/triagebot.toml
index 6fa92b4af05..7f4def6a11b 100644
--- a/triagebot.toml
+++ b/triagebot.toml
@@ -966,7 +966,6 @@ cc = ["@kobzol"]
 warn_non_default_branch = true
 contributing_url = "https://rustc-dev-guide.rust-lang.org/getting-started.html"
 users_on_vacation = [
-    "BoxyUwU",
     "fmease",
     "jyn514",
     "oli-obk",