From 2733b8ab8d4407086eb41d615395a9a323a8fd77 Mon Sep 17 00:00:00 2001
From: Oli Scherer <git-spam-no-reply9815368754983@oli-obk.de>
Date: Tue, 11 Jun 2024 09:57:16 +0000
Subject: [PATCH 01/13] Avoid follow-up errors on erroneous patterns

---
 compiler/rustc_hir_typeck/src/pat.rs     | 13 +++++-----
 tests/crashes/109812.rs                  | 22 -----------------
 tests/crashes/125914.rs                  | 20 ----------------
 tests/ui/pattern/missing_lifetime.rs     | 25 ++++++++++++++++++++
 tests/ui/pattern/missing_lifetime.stderr | 25 ++++++++++++++++++++
 tests/ui/pattern/type_mismatch.rs        | 30 ++++++++++++++++++++++++
 tests/ui/pattern/type_mismatch.stderr    | 11 +++++++++
 7 files changed, 97 insertions(+), 49 deletions(-)
 delete mode 100644 tests/crashes/109812.rs
 delete mode 100644 tests/crashes/125914.rs
 create mode 100644 tests/ui/pattern/missing_lifetime.rs
 create mode 100644 tests/ui/pattern/missing_lifetime.stderr
 create mode 100644 tests/ui/pattern/type_mismatch.rs
 create mode 100644 tests/ui/pattern/type_mismatch.stderr

diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs
index 9476dc70483..814bdc07637 100644
--- a/compiler/rustc_hir_typeck/src/pat.rs
+++ b/compiler/rustc_hir_typeck/src/pat.rs
@@ -1223,12 +1223,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
         // Type-check the tuple struct pattern against the expected type.
         let diag = self.demand_eqtype_pat_diag(pat.span, expected, pat_ty, pat_info.top_info);
-        let had_err = if let Some(err) = diag {
-            err.emit();
-            true
-        } else {
-            false
-        };
+        let had_err = diag.map(|diag| diag.emit());
 
         // Type-check subpatterns.
         if subpats.len() == variant.fields.len()
@@ -1249,6 +1244,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     None,
                 );
             }
+            if let Some(e) = had_err {
+                on_error(e);
+                return Ty::new_error(tcx, e);
+            }
         } else {
             let e = self.emit_err_pat_wrong_number_of_fields(
                 pat.span,
@@ -1257,7 +1256,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 subpats,
                 &variant.fields.raw,
                 expected,
-                had_err,
+                had_err.is_some(),
             );
             on_error(e);
             return Ty::new_error(tcx, e);
diff --git a/tests/crashes/109812.rs b/tests/crashes/109812.rs
deleted file mode 100644
index c29b8746521..00000000000
--- a/tests/crashes/109812.rs
+++ /dev/null
@@ -1,22 +0,0 @@
-//@ known-bug: #109812
-
-#![warn(rust_2021_incompatible_closure_captures)]
-
-enum Either {
-    One(X),
-    Two(X),
-}
-
-struct X(Y);
-
-struct Y;
-
-fn move_into_fnmut() {
-    let x = X(Y);
-
-    consume_fnmut(|| {
-        let Either::Two(ref mut _t) = x;
-
-        let X(mut _t) = x;
-    });
-}
diff --git a/tests/crashes/125914.rs b/tests/crashes/125914.rs
deleted file mode 100644
index 77ccb9fb097..00000000000
--- a/tests/crashes/125914.rs
+++ /dev/null
@@ -1,20 +0,0 @@
-//@ known-bug: rust-lang/rust#125914
-enum AstKind<'ast> {
-    ExprInt,
-}
-
-enum Foo {
-    Bar(isize),
-    Baz,
-}
-
-enum Other {
-    Other1(Foo),
-    Other2(AstKind),
-}
-
-fn main() {
-    match Other::Other1(Foo::Baz) {
-        ::Other::Other2(::Foo::Bar(..)) => {}
-    }
-}
diff --git a/tests/ui/pattern/missing_lifetime.rs b/tests/ui/pattern/missing_lifetime.rs
new file mode 100644
index 00000000000..081f667d8f6
--- /dev/null
+++ b/tests/ui/pattern/missing_lifetime.rs
@@ -0,0 +1,25 @@
+//! This test used to ICE: rust-lang/rust#125914
+//! Instead of actually analyzing the erroneous patterns,
+//! we instead stop after typeck where errors are already
+//! reported.
+
+enum AstKind<'ast> {
+    //~^ ERROR: `'ast` is never used
+    ExprInt,
+}
+
+enum Foo {
+    Bar(isize),
+    Baz,
+}
+
+enum Other {
+    Other1(Foo),
+    Other2(AstKind), //~ ERROR: missing lifetime specifier
+}
+
+fn main() {
+    match Other::Other1(Foo::Baz) {
+        ::Other::Other2(::Foo::Bar(..)) => {}
+    }
+}
diff --git a/tests/ui/pattern/missing_lifetime.stderr b/tests/ui/pattern/missing_lifetime.stderr
new file mode 100644
index 00000000000..ec4063fd289
--- /dev/null
+++ b/tests/ui/pattern/missing_lifetime.stderr
@@ -0,0 +1,25 @@
+error[E0106]: missing lifetime specifier
+  --> $DIR/missing_lifetime.rs:18:12
+   |
+LL |     Other2(AstKind),
+   |            ^^^^^^^ expected named lifetime parameter
+   |
+help: consider introducing a named lifetime parameter
+   |
+LL ~ enum Other<'a> {
+LL |     Other1(Foo),
+LL ~     Other2(AstKind<'a>),
+   |
+
+error[E0392]: lifetime parameter `'ast` is never used
+  --> $DIR/missing_lifetime.rs:6:14
+   |
+LL | enum AstKind<'ast> {
+   |              ^^^^ unused lifetime parameter
+   |
+   = help: consider removing `'ast`, referring to it in a field, or using a marker such as `PhantomData`
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0106, E0392.
+For more information about an error, try `rustc --explain E0106`.
diff --git a/tests/ui/pattern/type_mismatch.rs b/tests/ui/pattern/type_mismatch.rs
new file mode 100644
index 00000000000..408ff758847
--- /dev/null
+++ b/tests/ui/pattern/type_mismatch.rs
@@ -0,0 +1,30 @@
+//! This test used to ICE: rust-lang/rust#109812
+//! Instead of actually analyzing the erroneous patterns,
+//! we instead stop after typeck where errors are already
+//! reported.
+
+#![warn(rust_2021_incompatible_closure_captures)]
+
+enum Either {
+    One(X),
+    Two(X),
+}
+
+struct X(Y);
+
+struct Y;
+
+fn consume_fnmut(_: impl FnMut()) {}
+
+fn move_into_fnmut() {
+    let x = X(Y);
+
+    consume_fnmut(|| {
+        let Either::Two(ref mut _t) = x;
+        //~^ ERROR: mismatched types
+
+        let X(mut _t) = x;
+    });
+}
+
+fn main() {}
diff --git a/tests/ui/pattern/type_mismatch.stderr b/tests/ui/pattern/type_mismatch.stderr
new file mode 100644
index 00000000000..b0441b1fadc
--- /dev/null
+++ b/tests/ui/pattern/type_mismatch.stderr
@@ -0,0 +1,11 @@
+error[E0308]: mismatched types
+  --> $DIR/type_mismatch.rs:23:13
+   |
+LL |         let Either::Two(ref mut _t) = x;
+   |             ^^^^^^^^^^^^^^^^^^^^^^^   - this expression has type `X`
+   |             |
+   |             expected `X`, found `Either`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0308`.

From a6217011f6aefde02af1a19a7716a411dd7803ff Mon Sep 17 00:00:00 2001
From: Oli Scherer <git-spam-no-reply9815368754983@oli-obk.de>
Date: Wed, 12 Jun 2024 14:59:32 +0000
Subject: [PATCH 02/13] Replace some `Option<Diag>` with `Result<(), Diag>`

---
 .../src/diagnostics/conflict_errors.rs        | 10 +--
 compiler/rustc_hir_typeck/src/demand.rs       | 57 ++++++++--------
 compiler/rustc_hir_typeck/src/expr.rs         | 11 ++-
 .../rustc_hir_typeck/src/fn_ctxt/checks.rs    |  4 +-
 compiler/rustc_hir_typeck/src/pat.rs          | 68 +++++++++----------
 .../pattern/box-pattern-type-mismatch.rs}     |  3 +-
 .../pattern/box-pattern-type-mismatch.stderr  | 19 ++++++
 7 files changed, 95 insertions(+), 77 deletions(-)
 rename tests/{crashes/124004.rs => ui/pattern/box-pattern-type-mismatch.rs} (74%)
 create mode 100644 tests/ui/pattern/box-pattern-type-mismatch.stderr

diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
index 821a9036654..808d8b78d2d 100644
--- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
@@ -2888,7 +2888,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
             ..
         } = explanation
         {
-            if let Some(diag) = self.try_report_cannot_return_reference_to_local(
+            if let Err(diag) = self.try_report_cannot_return_reference_to_local(
                 borrow,
                 borrow_span,
                 span,
@@ -3075,7 +3075,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         if let BorrowExplanation::MustBeValidFor { category, span, from_closure: false, .. } =
             explanation
         {
-            if let Some(diag) = self.try_report_cannot_return_reference_to_local(
+            if let Err(diag) = self.try_report_cannot_return_reference_to_local(
                 borrow,
                 proper_span,
                 span,
@@ -3237,11 +3237,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         return_span: Span,
         category: ConstraintCategory<'tcx>,
         opt_place_desc: Option<&String>,
-    ) -> Option<Diag<'tcx>> {
+    ) -> Result<(), Diag<'tcx>> {
         let return_kind = match category {
             ConstraintCategory::Return(_) => "return",
             ConstraintCategory::Yield => "yield",
-            _ => return None,
+            _ => return Ok(()),
         };
 
         // FIXME use a better heuristic than Spans
@@ -3317,7 +3317,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
             }
         }
 
-        Some(err)
+        Err(err)
     }
 
     #[instrument(level = "debug", skip(self))]
diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs
index d2a5924c8bb..f9720c9c307 100644
--- a/compiler/rustc_hir_typeck/src/demand.rs
+++ b/compiler/rustc_hir_typeck/src/demand.rs
@@ -4,7 +4,7 @@ use rustc_errors::{Applicability, Diag};
 use rustc_hir as hir;
 use rustc_hir::def::Res;
 use rustc_hir::intravisit::Visitor;
-use rustc_infer::infer::{DefineOpaqueTypes, InferOk};
+use rustc_infer::infer::DefineOpaqueTypes;
 use rustc_middle::bug;
 use rustc_middle::ty::adjustment::AllowTwoPhase;
 use rustc_middle::ty::error::{ExpectedFound, TypeError};
@@ -166,7 +166,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     /// Requires that the two types unify, and prints an error message if
     /// they don't.
     pub fn demand_suptype(&self, sp: Span, expected: Ty<'tcx>, actual: Ty<'tcx>) {
-        if let Some(e) = self.demand_suptype_diag(sp, expected, actual) {
+        if let Err(e) = self.demand_suptype_diag(sp, expected, actual) {
             e.emit();
         }
     }
@@ -176,7 +176,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         sp: Span,
         expected: Ty<'tcx>,
         actual: Ty<'tcx>,
-    ) -> Option<Diag<'tcx>> {
+    ) -> Result<(), Diag<'tcx>> {
         self.demand_suptype_with_origin(&self.misc(sp), expected, actual)
     }
 
@@ -186,18 +186,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         cause: &ObligationCause<'tcx>,
         expected: Ty<'tcx>,
         actual: Ty<'tcx>,
-    ) -> Option<Diag<'tcx>> {
-        match self.at(cause, self.param_env).sup(DefineOpaqueTypes::Yes, expected, actual) {
-            Ok(InferOk { obligations, value: () }) => {
-                self.register_predicates(obligations);
-                None
-            }
-            Err(e) => Some(self.err_ctxt().report_mismatched_types(cause, expected, actual, e)),
-        }
+    ) -> Result<(), Diag<'tcx>> {
+        self.at(cause, self.param_env)
+            .sup(DefineOpaqueTypes::Yes, expected, actual)
+            .map(|infer_ok| self.register_infer_ok_obligations(infer_ok))
+            .map_err(|e| self.err_ctxt().report_mismatched_types(cause, expected, actual, e))
     }
 
     pub fn demand_eqtype(&self, sp: Span, expected: Ty<'tcx>, actual: Ty<'tcx>) {
-        if let Some(err) = self.demand_eqtype_diag(sp, expected, actual) {
+        if let Err(err) = self.demand_eqtype_diag(sp, expected, actual) {
             err.emit();
         }
     }
@@ -207,7 +204,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         sp: Span,
         expected: Ty<'tcx>,
         actual: Ty<'tcx>,
-    ) -> Option<Diag<'tcx>> {
+    ) -> Result<(), Diag<'tcx>> {
         self.demand_eqtype_with_origin(&self.misc(sp), expected, actual)
     }
 
@@ -216,14 +213,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         cause: &ObligationCause<'tcx>,
         expected: Ty<'tcx>,
         actual: Ty<'tcx>,
-    ) -> Option<Diag<'tcx>> {
-        match self.at(cause, self.param_env).eq(DefineOpaqueTypes::Yes, expected, actual) {
-            Ok(InferOk { obligations, value: () }) => {
-                self.register_predicates(obligations);
-                None
-            }
-            Err(e) => Some(self.err_ctxt().report_mismatched_types(cause, expected, actual, e)),
-        }
+    ) -> Result<(), Diag<'tcx>> {
+        self.at(cause, self.param_env)
+            .eq(DefineOpaqueTypes::Yes, expected, actual)
+            .map(|infer_ok| self.register_infer_ok_obligations(infer_ok))
+            .map_err(|e| self.err_ctxt().report_mismatched_types(cause, expected, actual, e))
     }
 
     pub fn demand_coerce(
@@ -234,12 +228,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         expected_ty_expr: Option<&'tcx hir::Expr<'tcx>>,
         allow_two_phase: AllowTwoPhase,
     ) -> Ty<'tcx> {
-        let (ty, err) =
-            self.demand_coerce_diag(expr, checked_ty, expected, expected_ty_expr, allow_two_phase);
-        if let Some(err) = err {
-            err.emit();
+        match self.demand_coerce_diag(expr, checked_ty, expected, expected_ty_expr, allow_two_phase)
+        {
+            Ok(ty) => ty,
+            Err(err) => {
+                err.emit();
+                // Return the original type instead of an error type here, otherwise the type of `x` in
+                // `let x: u32 = ();` will be a type error, causing all subsequent usages of `x` to not
+                // report errors, even though `x` is definitely `u32`.
+                expected
+            }
         }
-        ty
     }
 
     /// Checks that the type of `expr` can be coerced to `expected`.
@@ -254,11 +253,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         expected: Ty<'tcx>,
         mut expected_ty_expr: Option<&'tcx hir::Expr<'tcx>>,
         allow_two_phase: AllowTwoPhase,
-    ) -> (Ty<'tcx>, Option<Diag<'tcx>>) {
+    ) -> Result<Ty<'tcx>, Diag<'tcx>> {
         let expected = self.resolve_vars_with_obligations(expected);
 
         let e = match self.coerce(expr, checked_ty, expected, allow_two_phase, None) {
-            Ok(ty) => return (ty, None),
+            Ok(ty) => return Ok(ty),
             Err(e) => e,
         };
 
@@ -275,7 +274,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
         self.emit_coerce_suggestions(&mut err, expr, expr_ty, expected, expected_ty_expr, Some(e));
 
-        (expected, Some(err))
+        Err(err)
     }
 
     /// Notes the point at which a variable is constrained to some type incompatible
diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs
index 5b27ebe3416..1f185a35000 100644
--- a/compiler/rustc_hir_typeck/src/expr.rs
+++ b/compiler/rustc_hir_typeck/src/expr.rs
@@ -87,7 +87,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             ty = adj_ty;
         }
 
-        if let Some(mut err) = self.demand_suptype_diag(expr.span, expected_ty, ty) {
+        if let Err(mut err) = self.demand_suptype_diag(expr.span, expected_ty, ty) {
             let _ = self.emit_type_mismatch_suggestions(
                 &mut err,
                 expr.peel_drop_temps(),
@@ -1132,7 +1132,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             // say that the user intended to write `lhs == rhs` instead of `lhs = rhs`.
             // The likely cause of this is `if foo = bar { .. }`.
             let actual_ty = self.tcx.types.unit;
-            let mut err = self.demand_suptype_diag(expr.span, expected_ty, actual_ty).unwrap();
+            let mut err = self.demand_suptype_diag(expr.span, expected_ty, actual_ty).unwrap_err();
             let lhs_ty = self.check_expr(lhs);
             let rhs_ty = self.check_expr(rhs);
             let refs_can_coerce = |lhs: Ty<'tcx>, rhs: Ty<'tcx>| {
@@ -1236,7 +1236,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         // This is (basically) inlined `check_expr_coercible_to_type`, but we want
         // to suggest an additional fixup here in `suggest_deref_binop`.
         let rhs_ty = self.check_expr_with_hint(rhs, lhs_ty);
-        if let (_, Some(mut diag)) =
+        if let Err(mut diag) =
             self.demand_coerce_diag(rhs, rhs_ty, lhs_ty, Some(lhs), AllowTwoPhase::No)
         {
             suggest_deref_binop(&mut diag, rhs_ty);
@@ -1741,10 +1741,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             // Make sure to give a type to the field even if there's
             // an error, so we can continue type-checking.
             let ty = self.check_expr_with_hint(field.expr, field_type);
-            let (_, diag) =
-                self.demand_coerce_diag(field.expr, ty, field_type, None, AllowTwoPhase::No);
+            let diag = self.demand_coerce_diag(field.expr, ty, field_type, None, AllowTwoPhase::No);
 
-            if let Some(diag) = diag {
+            if let Err(diag) = diag {
                 if idx == hir_fields.len() - 1 {
                     if remaining_fields.is_empty() {
                         self.suggest_fru_from_range_and_emit(field, variant, args, diag);
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
index b8333d47493..0428ec56c99 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
@@ -1578,7 +1578,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             // type of the place it is referencing, and not some
             // supertype thereof.
             let init_ty = self.check_expr_with_needs(init, Needs::maybe_mut_place(m));
-            if let Some(mut diag) = self.demand_eqtype_diag(init.span, local_ty, init_ty) {
+            if let Err(mut diag) = self.demand_eqtype_diag(init.span, local_ty, init_ty) {
                 self.emit_type_mismatch_suggestions(
                     &mut diag,
                     init.peel_drop_temps(),
@@ -1624,7 +1624,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             let previous_diverges = self.diverges.get();
             let else_ty = self.check_block_with_expected(blk, NoExpectation);
             let cause = self.cause(blk.span, ObligationCauseCode::LetElse);
-            if let Some(err) = self.demand_eqtype_with_origin(&cause, self.tcx.types.never, else_ty)
+            if let Err(err) = self.demand_eqtype_with_origin(&cause, self.tcx.types.never, else_ty)
             {
                 err.emit();
             }
diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs
index 814bdc07637..9d4ba1eb489 100644
--- a/compiler/rustc_hir_typeck/src/pat.rs
+++ b/compiler/rustc_hir_typeck/src/pat.rs
@@ -105,15 +105,16 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
         expected: Ty<'tcx>,
         actual: Ty<'tcx>,
         ti: &TopInfo<'tcx>,
-    ) -> Option<Diag<'tcx>> {
-        let mut diag =
-            self.demand_eqtype_with_origin(&self.pattern_cause(ti, cause_span), expected, actual)?;
-        if let Some(expr) = ti.origin_expr {
-            self.suggest_fn_call(&mut diag, expr, expected, |output| {
-                self.can_eq(self.param_env, output, actual)
-            });
-        }
-        Some(diag)
+    ) -> Result<(), Diag<'tcx>> {
+        self.demand_eqtype_with_origin(&self.pattern_cause(ti, cause_span), expected, actual)
+            .map_err(|mut diag| {
+                if let Some(expr) = ti.origin_expr {
+                    self.suggest_fn_call(&mut diag, expr, expected, |output| {
+                        self.can_eq(self.param_env, output, actual)
+                    });
+                }
+                diag
+            })
     }
 
     fn demand_eqtype_pat(
@@ -122,10 +123,8 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
         expected: Ty<'tcx>,
         actual: Ty<'tcx>,
         ti: &TopInfo<'tcx>,
-    ) {
-        if let Some(err) = self.demand_eqtype_pat_diag(cause_span, expected, actual, ti) {
-            err.emit();
-        }
+    ) -> Result<(), ErrorGuaranteed> {
+        self.demand_eqtype_pat_diag(cause_span, expected, actual, ti).map_err(|err| err.emit())
     }
 }
 
@@ -509,7 +508,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         //
         // then that's equivalent to there existing a LUB.
         let cause = self.pattern_cause(ti, span);
-        if let Some(err) = self.demand_suptype_with_origin(&cause, expected, pat_ty) {
+        if let Err(err) = self.demand_suptype_with_origin(&cause, expected, pat_ty) {
             err.emit_unless(
                 ti.span
                     .filter(|&s| {
@@ -562,7 +561,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         // Subtyping doesn't matter here, as the value is some kind of scalar.
         let demand_eqtype = |x: &mut _, y| {
             if let Some((ref mut fail, x_ty, x_span)) = *x
-                && let Some(mut err) = self.demand_eqtype_pat_diag(x_span, expected, x_ty, ti)
+                && let Err(mut err) = self.demand_eqtype_pat_diag(x_span, expected, x_ty, ti)
             {
                 if let Some((_, y_ty, y_span)) = y {
                     self.endpoint_has_type(&mut err, y_span, y_ty);
@@ -736,7 +735,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             // Otherwise, the type of x is the expected type `T`.
             ByRef::No => expected, // As above, `T <: typeof(x)` is required, but we use equality, see (note_1).
         };
-        self.demand_eqtype_pat(pat.span, eq_ty, local_ty, ti);
+
+        // We have a concrete type for the local, so we do not need to taint it and hide follow up errors *using* the local.
+        let _ = self.demand_eqtype_pat(pat.span, eq_ty, local_ty, ti);
 
         // If there are multiple arms, make sure they all agree on
         // what the type of the binding `x` ought to be.
@@ -763,7 +764,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         ti: &TopInfo<'tcx>,
     ) {
         let var_ty = self.local_ty(span, var_id);
-        if let Some(mut err) = self.demand_eqtype_pat_diag(span, var_ty, ty, ti) {
+        if let Err(mut err) = self.demand_eqtype_pat_diag(span, var_ty, ty, ti) {
             let hir = self.tcx.hir();
             let var_ty = self.resolve_vars_if_possible(var_ty);
             let msg = format!("first introduced with type `{var_ty}` here");
@@ -986,7 +987,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         };
 
         // Type-check the path.
-        self.demand_eqtype_pat(pat.span, expected, pat_ty, pat_info.top_info);
+        let _ = self.demand_eqtype_pat(pat.span, expected, pat_ty, pat_info.top_info);
 
         // Type-check subpatterns.
         if self.check_struct_pat_fields(pat_ty, pat, variant, fields, has_rest_pat, pat_info) {
@@ -1050,7 +1051,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         // Type-check the path.
         let (pat_ty, pat_res) =
             self.instantiate_value_path(segments, opt_ty, res, pat.span, pat.span, pat.hir_id);
-        if let Some(err) =
+        if let Err(err) =
             self.demand_suptype_with_origin(&self.pattern_cause(ti, pat.span), expected, pat_ty)
         {
             self.emit_bad_pat_path(err, pat, res, pat_res, pat_ty, segments);
@@ -1223,7 +1224,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
         // Type-check the tuple struct pattern against the expected type.
         let diag = self.demand_eqtype_pat_diag(pat.span, expected, pat_ty, pat_info.top_info);
-        let had_err = diag.map(|diag| diag.emit());
+        let had_err = diag.map_err(|diag| diag.emit());
 
         // Type-check subpatterns.
         if subpats.len() == variant.fields.len()
@@ -1244,7 +1245,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     None,
                 );
             }
-            if let Some(e) = had_err {
+            if let Err(e) = had_err {
                 on_error(e);
                 return Ty::new_error(tcx, e);
             }
@@ -1256,7 +1257,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 subpats,
                 &variant.fields.raw,
                 expected,
-                had_err.is_some(),
+                had_err.is_err(),
             );
             on_error(e);
             return Ty::new_error(tcx, e);
@@ -1444,8 +1445,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let element_tys_iter = (0..max_len).map(|_| self.next_ty_var(span));
         let element_tys = tcx.mk_type_list_from_iter(element_tys_iter);
         let pat_ty = Ty::new_tup(tcx, element_tys);
-        if let Some(err) = self.demand_eqtype_pat_diag(span, expected, pat_ty, pat_info.top_info) {
-            let reported = err.emit();
+        if let Err(reported) = self.demand_eqtype_pat(span, expected, pat_ty, pat_info.top_info) {
             // Walk subpatterns with an expected type of `err` in this case to silence
             // further errors being emitted when using the bindings. #50333
             let element_tys_iter = (0..max_len).map(|_| Ty::new_error(tcx, reported));
@@ -2064,20 +2064,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         pat_info: PatInfo<'tcx, '_>,
     ) -> Ty<'tcx> {
         let tcx = self.tcx;
-        let (box_ty, inner_ty) = match self.check_dereferenceable(span, expected, inner) {
-            Ok(()) => {
+        let (box_ty, inner_ty) = self
+            .check_dereferenceable(span, expected, inner)
+            .and_then(|()| {
                 // Here, `demand::subtype` is good enough, but I don't
                 // think any errors can be introduced by using `demand::eqtype`.
                 let inner_ty = self.next_ty_var(inner.span);
                 let box_ty = Ty::new_box(tcx, inner_ty);
-                self.demand_eqtype_pat(span, expected, box_ty, pat_info.top_info);
-                (box_ty, inner_ty)
-            }
-            Err(guar) => {
+                self.demand_eqtype_pat(span, expected, box_ty, pat_info.top_info)?;
+                Ok((box_ty, inner_ty))
+            })
+            .unwrap_or_else(|guar| {
                 let err = Ty::new_error(tcx, guar);
                 (err, err)
-            }
-        };
+            });
         self.check_pat(inner, inner_ty, pat_info);
         box_ty
     }
@@ -2221,7 +2221,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
                         // Look for a case like `fn foo(&foo: u32)` and suggest
                         // `fn foo(foo: &u32)`
-                        if let Some(mut err) = err {
+                        if let Err(mut err) = err {
                             self.borrow_pat_suggestion(&mut err, pat);
                             err.emit();
                         }
@@ -2326,7 +2326,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 self.try_resolve_slice_ty_to_array_ty(before, slice, span)
             {
                 debug!(?resolved_arr_ty);
-                self.demand_eqtype(span, expected, resolved_arr_ty);
+                let _ = self.demand_eqtype(span, expected, resolved_arr_ty);
             }
         }
 
diff --git a/tests/crashes/124004.rs b/tests/ui/pattern/box-pattern-type-mismatch.rs
similarity index 74%
rename from tests/crashes/124004.rs
rename to tests/ui/pattern/box-pattern-type-mismatch.rs
index 1fcf0785945..6c980503256 100644
--- a/tests/crashes/124004.rs
+++ b/tests/ui/pattern/box-pattern-type-mismatch.rs
@@ -1,10 +1,11 @@
-//@ known-bug: #124004
+//! This test used to ICE #124004
 
 #![feature(box_patterns)]
 
 use std::ops::{ Deref };
 
 struct X(dyn Iterator<Item = &'a ()>);
+//~^ ERROR: use of undeclared lifetime name `'a`
 
 impl Deref for X {
     type Target = isize;
diff --git a/tests/ui/pattern/box-pattern-type-mismatch.stderr b/tests/ui/pattern/box-pattern-type-mismatch.stderr
new file mode 100644
index 00000000000..14f7dbbd839
--- /dev/null
+++ b/tests/ui/pattern/box-pattern-type-mismatch.stderr
@@ -0,0 +1,19 @@
+error[E0261]: use of undeclared lifetime name `'a`
+  --> $DIR/box-pattern-type-mismatch.rs:7:31
+   |
+LL | struct X(dyn Iterator<Item = &'a ()>);
+   |                               ^^ undeclared lifetime
+   |
+   = note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html
+help: consider making the bound lifetime-generic with a new `'a` lifetime
+   |
+LL | struct X(dyn for<'a> Iterator<Item = &'a ()>);
+   |              +++++++
+help: consider introducing lifetime `'a` here
+   |
+LL | struct X<'a>(dyn Iterator<Item = &'a ()>);
+   |         ++++
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0261`.

From ece3e3e4c146a94996b4c0f6141caf0a0a877084 Mon Sep 17 00:00:00 2001
From: Oli Scherer <git-spam-no-reply9815368754983@oli-obk.de>
Date: Wed, 12 Jun 2024 15:09:03 +0000
Subject: [PATCH 03/13] Replace some `Option<Diag>` with `Result<(), Diag>`

---
 compiler/rustc_hir_typeck/src/pat.rs | 42 +++++++++++-----------------
 1 file changed, 17 insertions(+), 25 deletions(-)

diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs
index 9d4ba1eb489..a6f05e9b406 100644
--- a/compiler/rustc_hir_typeck/src/pat.rs
+++ b/compiler/rustc_hir_typeck/src/pat.rs
@@ -990,10 +990,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let _ = self.demand_eqtype_pat(pat.span, expected, pat_ty, pat_info.top_info);
 
         // Type-check subpatterns.
-        if self.check_struct_pat_fields(pat_ty, pat, variant, fields, has_rest_pat, pat_info) {
-            pat_ty
-        } else {
-            Ty::new_misc_error(self.tcx)
+        match self.check_struct_pat_fields(pat_ty, pat, variant, fields, has_rest_pat, pat_info) {
+            Ok(()) => pat_ty,
+            Err(guar) => Ty::new_error(self.tcx, guar),
         }
     }
 
@@ -1469,7 +1468,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         fields: &'tcx [hir::PatField<'tcx>],
         has_rest_pat: bool,
         pat_info: PatInfo<'tcx, '_>,
-    ) -> bool {
+    ) -> Result<(), ErrorGuaranteed> {
         let tcx = self.tcx;
 
         let ty::Adt(adt, args) = adt_ty.kind() else {
@@ -1485,7 +1484,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
         // Keep track of which fields have already appeared in the pattern.
         let mut used_fields = FxHashMap::default();
-        let mut no_field_errors = true;
+        let mut result = Ok(());
 
         let mut inexistent_fields = vec![];
         // Typecheck each field.
@@ -1494,8 +1493,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             let ident = tcx.adjust_ident(field.ident, variant.def_id);
             let field_ty = match used_fields.entry(ident) {
                 Occupied(occupied) => {
-                    no_field_errors = false;
                     let guar = self.error_field_already_bound(span, field.ident, *occupied.get());
+                    result = Err(guar);
                     Ty::new_error(tcx, guar)
                 }
                 Vacant(vacant) => {
@@ -1510,7 +1509,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         })
                         .unwrap_or_else(|| {
                             inexistent_fields.push(field);
-                            no_field_errors = false;
                             Ty::new_misc_error(tcx)
                         })
                 }
@@ -1589,32 +1587,26 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     // `Foo { a, b }` when it should have been `Foo(a, b)`.
                     i.delay_as_bug();
                     u.delay_as_bug();
-                    e.emit();
+                    Err(e.emit())
                 } else {
                     i.emit();
-                    u.emit();
+                    Err(u.emit())
                 }
             }
             (None, Some(u)) => {
                 if let Some(e) = self.error_tuple_variant_as_struct_pat(pat, fields, variant) {
                     u.delay_as_bug();
-                    e.emit();
+                    Err(e.emit())
                 } else {
-                    u.emit();
+                    Err(u.emit())
                 }
             }
-            (Some(err), None) => {
-                err.emit();
+            (Some(err), None) => Err(err.emit()),
+            (None, None) => {
+                self.error_tuple_variant_index_shorthand(variant, pat, fields)?;
+                result
             }
-            (None, None)
-                if let Some(err) =
-                    self.error_tuple_variant_index_shorthand(variant, pat, fields) =>
-            {
-                err.emit();
-            }
-            (None, None) => {}
         }
-        no_field_errors
     }
 
     fn error_tuple_variant_index_shorthand(
@@ -1622,7 +1614,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         variant: &VariantDef,
         pat: &'_ Pat<'_>,
         fields: &[hir::PatField<'_>],
-    ) -> Option<Diag<'_>> {
+    ) -> Result<(), ErrorGuaranteed> {
         // if this is a tuple struct, then all field names will be numbers
         // so if any fields in a struct pattern use shorthand syntax, they will
         // be invalid identifiers (for example, Foo { 0, 1 }).
@@ -1644,10 +1636,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     format!("({})", self.get_suggested_tuple_struct_pattern(fields, variant)),
                     Applicability::MaybeIncorrect,
                 );
-                return Some(err);
+                return Err(err.emit());
             }
         }
-        None
+        Ok(())
     }
 
     fn error_foreign_non_exhaustive_spat(&self, pat: &Pat<'_>, descr: &str, no_fields: bool) {

From e8d6170b8a6e70901b63ec967e37595949ecb66c Mon Sep 17 00:00:00 2001
From: Oli Scherer <git-spam-no-reply9815368754983@oli-obk.de>
Date: Wed, 12 Jun 2024 15:11:49 +0000
Subject: [PATCH 04/13] Replace some `Option<Diag>` with `Result<(), Diag>`

---
 compiler/rustc_hir_typeck/src/pat.rs | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs
index a6f05e9b406..898d90b9f45 100644
--- a/compiler/rustc_hir_typeck/src/pat.rs
+++ b/compiler/rustc_hir_typeck/src/pat.rs
@@ -1582,21 +1582,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         }
         match (inexistent_fields_err, unmentioned_err) {
             (Some(i), Some(u)) => {
-                if let Some(e) = self.error_tuple_variant_as_struct_pat(pat, fields, variant) {
+                if let Err(e) = self.error_tuple_variant_as_struct_pat(pat, fields, variant) {
                     // We don't want to show the nonexistent fields error when this was
                     // `Foo { a, b }` when it should have been `Foo(a, b)`.
                     i.delay_as_bug();
                     u.delay_as_bug();
-                    Err(e.emit())
+                    Err(e)
                 } else {
                     i.emit();
                     Err(u.emit())
                 }
             }
             (None, Some(u)) => {
-                if let Some(e) = self.error_tuple_variant_as_struct_pat(pat, fields, variant) {
+                if let Err(e) = self.error_tuple_variant_as_struct_pat(pat, fields, variant) {
                     u.delay_as_bug();
-                    Err(e.emit())
+                    Err(e)
                 } else {
                     Err(u.emit())
                 }
@@ -1795,14 +1795,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         pat: &Pat<'_>,
         fields: &'tcx [hir::PatField<'tcx>],
         variant: &ty::VariantDef,
-    ) -> Option<Diag<'tcx>> {
+    ) -> Result<(), ErrorGuaranteed> {
         if let (Some(CtorKind::Fn), PatKind::Struct(qpath, pattern_fields, ..)) =
             (variant.ctor_kind(), &pat.kind)
         {
             let is_tuple_struct_match = !pattern_fields.is_empty()
                 && pattern_fields.iter().map(|field| field.ident.name.as_str()).all(is_number);
             if is_tuple_struct_match {
-                return None;
+                return Ok(());
             }
 
             let path = rustc_hir_pretty::qpath_to_string(&self.tcx, qpath);
@@ -1830,9 +1830,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 format!("({sugg})"),
                 appl,
             );
-            return Some(err);
+            return Err(err.emit());
         }
-        None
+        Ok(())
     }
 
     fn get_suggested_tuple_struct_pattern(

From 7566307edc3b1e08b5bf08a664243fc4889e55c3 Mon Sep 17 00:00:00 2001
From: Oli Scherer <git-spam-no-reply9815368754983@oli-obk.de>
Date: Wed, 12 Jun 2024 15:19:57 +0000
Subject: [PATCH 05/13] Replace a `bool` with a `Result<(), ErrorGuaranteed>`

---
 compiler/rustc_hir_typeck/src/pat.rs | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs
index 898d90b9f45..220556fe256 100644
--- a/compiler/rustc_hir_typeck/src/pat.rs
+++ b/compiler/rustc_hir_typeck/src/pat.rs
@@ -1256,7 +1256,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 subpats,
                 &variant.fields.raw,
                 expected,
-                had_err.is_err(),
+                had_err,
             );
             on_error(e);
             return Ty::new_error(tcx, e);
@@ -1272,7 +1272,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         subpats: &'tcx [Pat<'tcx>],
         fields: &'tcx [ty::FieldDef],
         expected: Ty<'tcx>,
-        had_err: bool,
+        had_err: Result<(), ErrorGuaranteed>,
     ) -> ErrorGuaranteed {
         let subpats_ending = pluralize!(subpats.len());
         let fields_ending = pluralize!(fields.len());
@@ -1329,7 +1329,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             // #67037: only do this if we could successfully type-check the expected type against
             // the tuple struct pattern. Otherwise the args could get out of range on e.g.,
             // `let P() = U;` where `P != U` with `struct P<T>(T);`.
-            (ty::Adt(_, args), [field], false) => {
+            (ty::Adt(_, args), [field], Ok(())) => {
                 let field_ty = self.field_ty(pat_span, field, args);
                 match field_ty.kind() {
                     ty::Tuple(fields) => fields.len() == subpats.len(),

From b28221e74f5f05d0f7a6212f99c9d5af868c0ed3 Mon Sep 17 00:00:00 2001
From: Oli Scherer <git-spam-no-reply9815368754983@oli-obk.de>
Date: Mon, 15 Apr 2024 11:10:50 +0000
Subject: [PATCH 06/13] Use diagnostic method for diagnostics

---
 compiler/rustc_hir_typeck/src/callee.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs
index 9736c8b8920..93222c18686 100644
--- a/compiler/rustc_hir_typeck/src/callee.rs
+++ b/compiler/rustc_hir_typeck/src/callee.rs
@@ -628,7 +628,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 return;
             };
 
-            let pick = self.confirm_method(
+            let pick = self.confirm_method_for_diagnostic(
                 call_expr.span,
                 callee_expr,
                 call_expr,

From c75f7283bf52c6e2ec6a178f2b7717a4daddacf4 Mon Sep 17 00:00:00 2001
From: Oli Scherer <git-spam-no-reply9815368754983@oli-obk.de>
Date: Mon, 15 Apr 2024 11:20:33 +0000
Subject: [PATCH 07/13] Add some tests

---
 .../call_method_ambiguous.next.stderr         | 17 ++++++++
 tests/ui/impl-trait/call_method_ambiguous.rs  | 39 +++++++++++++++++
 .../call_method_on_inherent_impl.next.stderr  | 17 ++++++++
 .../call_method_on_inherent_impl.rs           | 25 +++++++++++
 ...inherent_impl_on_rigid_type.current.stderr | 16 +++++++
 ...on_inherent_impl_on_rigid_type.next.stderr | 17 ++++++++
 ...l_method_on_inherent_impl_on_rigid_type.rs | 22 ++++++++++
 ...method_on_inherent_impl_ref.current.stderr | 40 ++++++++++++++++++
 ...ll_method_on_inherent_impl_ref.next.stderr | 31 ++++++++++++++
 .../call_method_on_inherent_impl_ref.rs       | 35 ++++++++++++++++
 ...all_method_without_import.no_import.stderr | 37 ++++++++++++++++
 .../impl-trait/call_method_without_import.rs  | 42 +++++++++++++++++++
 .../method-resolution.current.stderr          | 36 ++++++++++++++++
 tests/ui/impl-trait/method-resolution.rs      | 29 +++++++++++++
 .../impl-trait/method-resolution2.next.stderr | 20 +++++++++
 tests/ui/impl-trait/method-resolution2.rs     | 31 ++++++++++++++
 .../method-resolution3.current.stderr         | 37 ++++++++++++++++
 .../impl-trait/method-resolution3.next.stderr | 20 +++++++++
 tests/ui/impl-trait/method-resolution3.rs     | 29 +++++++++++++
 .../impl-trait/method-resolution4.next.stderr | 22 ++++++++++
 tests/ui/impl-trait/method-resolution4.rs     | 20 +++++++++
 .../recursive-parent-trait-method-call.rs     | 42 +++++++++++++++++++
 .../method_resolution.current.stderr          | 15 +++++++
 .../method_resolution.next.stderr             | 12 ++++++
 .../method_resolution.rs                      | 30 +++++++++++++
 .../method_resolution2.current.stderr         | 36 ++++++++++++++++
 .../method_resolution2.rs                     | 30 +++++++++++++
 .../method_resolution3.current.stderr         | 21 ++++++++++
 .../method_resolution3.next.stderr            | 15 +++++++
 .../method_resolution3.rs                     | 36 ++++++++++++++++
 .../method_resolution4.current.stderr         | 21 ++++++++++
 .../method_resolution4.next.stderr            | 15 +++++++
 .../method_resolution4.rs                     | 39 +++++++++++++++++
 .../method_resolution5.current.stderr         | 15 +++++++
 .../method_resolution5.rs                     | 34 +++++++++++++++
 ...on_trait_method_from_opaque.current.stderr | 15 +++++++
 ...ution_trait_method_from_opaque.next.stderr |  9 ++++
 ...hod_resolution_trait_method_from_opaque.rs | 31 ++++++++++++++
 38 files changed, 998 insertions(+)
 create mode 100644 tests/ui/impl-trait/call_method_ambiguous.next.stderr
 create mode 100644 tests/ui/impl-trait/call_method_ambiguous.rs
 create mode 100644 tests/ui/impl-trait/call_method_on_inherent_impl.next.stderr
 create mode 100644 tests/ui/impl-trait/call_method_on_inherent_impl.rs
 create mode 100644 tests/ui/impl-trait/call_method_on_inherent_impl_on_rigid_type.current.stderr
 create mode 100644 tests/ui/impl-trait/call_method_on_inherent_impl_on_rigid_type.next.stderr
 create mode 100644 tests/ui/impl-trait/call_method_on_inherent_impl_on_rigid_type.rs
 create mode 100644 tests/ui/impl-trait/call_method_on_inherent_impl_ref.current.stderr
 create mode 100644 tests/ui/impl-trait/call_method_on_inherent_impl_ref.next.stderr
 create mode 100644 tests/ui/impl-trait/call_method_on_inherent_impl_ref.rs
 create mode 100644 tests/ui/impl-trait/call_method_without_import.no_import.stderr
 create mode 100644 tests/ui/impl-trait/call_method_without_import.rs
 create mode 100644 tests/ui/impl-trait/method-resolution.current.stderr
 create mode 100644 tests/ui/impl-trait/method-resolution.rs
 create mode 100644 tests/ui/impl-trait/method-resolution2.next.stderr
 create mode 100644 tests/ui/impl-trait/method-resolution2.rs
 create mode 100644 tests/ui/impl-trait/method-resolution3.current.stderr
 create mode 100644 tests/ui/impl-trait/method-resolution3.next.stderr
 create mode 100644 tests/ui/impl-trait/method-resolution3.rs
 create mode 100644 tests/ui/impl-trait/method-resolution4.next.stderr
 create mode 100644 tests/ui/impl-trait/method-resolution4.rs
 create mode 100644 tests/ui/impl-trait/recursive-parent-trait-method-call.rs
 create mode 100644 tests/ui/type-alias-impl-trait/method_resolution.current.stderr
 create mode 100644 tests/ui/type-alias-impl-trait/method_resolution.next.stderr
 create mode 100644 tests/ui/type-alias-impl-trait/method_resolution.rs
 create mode 100644 tests/ui/type-alias-impl-trait/method_resolution2.current.stderr
 create mode 100644 tests/ui/type-alias-impl-trait/method_resolution2.rs
 create mode 100644 tests/ui/type-alias-impl-trait/method_resolution3.current.stderr
 create mode 100644 tests/ui/type-alias-impl-trait/method_resolution3.next.stderr
 create mode 100644 tests/ui/type-alias-impl-trait/method_resolution3.rs
 create mode 100644 tests/ui/type-alias-impl-trait/method_resolution4.current.stderr
 create mode 100644 tests/ui/type-alias-impl-trait/method_resolution4.next.stderr
 create mode 100644 tests/ui/type-alias-impl-trait/method_resolution4.rs
 create mode 100644 tests/ui/type-alias-impl-trait/method_resolution5.current.stderr
 create mode 100644 tests/ui/type-alias-impl-trait/method_resolution5.rs
 create mode 100644 tests/ui/type-alias-impl-trait/method_resolution_trait_method_from_opaque.current.stderr
 create mode 100644 tests/ui/type-alias-impl-trait/method_resolution_trait_method_from_opaque.next.stderr
 create mode 100644 tests/ui/type-alias-impl-trait/method_resolution_trait_method_from_opaque.rs

diff --git a/tests/ui/impl-trait/call_method_ambiguous.next.stderr b/tests/ui/impl-trait/call_method_ambiguous.next.stderr
new file mode 100644
index 00000000000..cd222aa7ae9
--- /dev/null
+++ b/tests/ui/impl-trait/call_method_ambiguous.next.stderr
@@ -0,0 +1,17 @@
+error[E0282]: type annotations needed
+  --> $DIR/call_method_ambiguous.rs:29:13
+   |
+LL |         let mut iter = foo(n - 1, m);
+   |             ^^^^^^^^
+LL |
+LL |         assert_eq!(iter.get(), 1);
+   |                    ---- type must be known at this point
+   |
+help: consider giving `iter` an explicit type
+   |
+LL |         let mut iter: /* Type */ = foo(n - 1, m);
+   |                     ++++++++++++
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/tests/ui/impl-trait/call_method_ambiguous.rs b/tests/ui/impl-trait/call_method_ambiguous.rs
new file mode 100644
index 00000000000..c26c01e002d
--- /dev/null
+++ b/tests/ui/impl-trait/call_method_ambiguous.rs
@@ -0,0 +1,39 @@
+//@ revisions: current next
+//@[next] compile-flags: -Znext-solver
+//@[current] run-pass
+
+#![feature(precise_capturing)]
+#![allow(incomplete_features)]
+
+trait Get {
+    fn get(&mut self) -> u32;
+}
+
+impl Get for () {
+    fn get(&mut self) -> u32 {
+        0
+    }
+}
+
+impl<T> Get for &mut T
+where
+    T: Get,
+{
+    fn get(&mut self) -> u32 {
+        T::get(self) + 1
+    }
+}
+
+fn foo(n: usize, m: &mut ()) -> impl use<'_> Get {
+    if n > 0 {
+        let mut iter = foo(n - 1, m);
+        //[next]~^ type annotations needed
+        assert_eq!(iter.get(), 1);
+    }
+    m
+}
+
+fn main() {
+    let g = foo(1, &mut ()).get();
+    assert_eq!(g, 1);
+}
diff --git a/tests/ui/impl-trait/call_method_on_inherent_impl.next.stderr b/tests/ui/impl-trait/call_method_on_inherent_impl.next.stderr
new file mode 100644
index 00000000000..271051f120a
--- /dev/null
+++ b/tests/ui/impl-trait/call_method_on_inherent_impl.next.stderr
@@ -0,0 +1,17 @@
+error[E0282]: type annotations needed
+  --> $DIR/call_method_on_inherent_impl.rs:18:13
+   |
+LL |         let x = my_foo();
+   |             ^
+LL |
+LL |         x.my_debug();
+   |         - type must be known at this point
+   |
+help: consider giving `x` an explicit type
+   |
+LL |         let x: /* Type */ = my_foo();
+   |              ++++++++++++
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/tests/ui/impl-trait/call_method_on_inherent_impl.rs b/tests/ui/impl-trait/call_method_on_inherent_impl.rs
new file mode 100644
index 00000000000..17f7cad660d
--- /dev/null
+++ b/tests/ui/impl-trait/call_method_on_inherent_impl.rs
@@ -0,0 +1,25 @@
+//@ revisions: current next
+//@[next] compile-flags: -Znext-solver
+//@[current] check-pass
+
+trait MyDebug {
+    fn my_debug(&self);
+}
+
+impl<T> MyDebug for T
+where
+    T: std::fmt::Debug,
+{
+    fn my_debug(&self) {}
+}
+
+fn my_foo() -> impl std::fmt::Debug {
+    if false {
+        let x = my_foo();
+        //[next]~^ type annotations needed
+        x.my_debug();
+    }
+    ()
+}
+
+fn main() {}
diff --git a/tests/ui/impl-trait/call_method_on_inherent_impl_on_rigid_type.current.stderr b/tests/ui/impl-trait/call_method_on_inherent_impl_on_rigid_type.current.stderr
new file mode 100644
index 00000000000..6ecb2b05fc5
--- /dev/null
+++ b/tests/ui/impl-trait/call_method_on_inherent_impl_on_rigid_type.current.stderr
@@ -0,0 +1,16 @@
+error[E0599]: no method named `my_debug` found for reference `&impl Debug` in the current scope
+  --> $DIR/call_method_on_inherent_impl_on_rigid_type.rs:16:11
+   |
+LL |         x.my_debug();
+   |           ^^^^^^^^ method not found in `&impl Debug`
+   |
+   = help: items from traits can only be used if the trait is implemented and in scope
+note: `MyDebug` defines an item `my_debug`, perhaps you need to implement it
+  --> $DIR/call_method_on_inherent_impl_on_rigid_type.rs:4:1
+   |
+LL | trait MyDebug {
+   | ^^^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/tests/ui/impl-trait/call_method_on_inherent_impl_on_rigid_type.next.stderr b/tests/ui/impl-trait/call_method_on_inherent_impl_on_rigid_type.next.stderr
new file mode 100644
index 00000000000..5fb0b8f1d14
--- /dev/null
+++ b/tests/ui/impl-trait/call_method_on_inherent_impl_on_rigid_type.next.stderr
@@ -0,0 +1,17 @@
+error[E0282]: type annotations needed for `&_`
+  --> $DIR/call_method_on_inherent_impl_on_rigid_type.rs:14:13
+   |
+LL |         let x = &my_foo();
+   |             ^
+LL |
+LL |         x.my_debug();
+   |           -------- type must be known at this point
+   |
+help: consider giving `x` an explicit type, where the placeholders `_` are specified
+   |
+LL |         let x: &_ = &my_foo();
+   |              ++++
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/tests/ui/impl-trait/call_method_on_inherent_impl_on_rigid_type.rs b/tests/ui/impl-trait/call_method_on_inherent_impl_on_rigid_type.rs
new file mode 100644
index 00000000000..7fb2ff3b2bc
--- /dev/null
+++ b/tests/ui/impl-trait/call_method_on_inherent_impl_on_rigid_type.rs
@@ -0,0 +1,22 @@
+//@ revisions: current next
+//@[next] compile-flags: -Znext-solver
+
+trait MyDebug {
+    fn my_debug(&self);
+}
+
+impl MyDebug for &() {
+    fn my_debug(&self) {}
+}
+
+fn my_foo() -> impl std::fmt::Debug {
+    if false {
+        let x = &my_foo();
+        //[next]~^ ERROR: type annotations needed
+        x.my_debug();
+        //[current]~^ ERROR: no method named `my_debug`
+    }
+    ()
+}
+
+fn main() {}
diff --git a/tests/ui/impl-trait/call_method_on_inherent_impl_ref.current.stderr b/tests/ui/impl-trait/call_method_on_inherent_impl_ref.current.stderr
new file mode 100644
index 00000000000..fe6e166cb4f
--- /dev/null
+++ b/tests/ui/impl-trait/call_method_on_inherent_impl_ref.current.stderr
@@ -0,0 +1,40 @@
+error[E0599]: no method named `my_debug` found for opaque type `impl Debug` in the current scope
+  --> $DIR/call_method_on_inherent_impl_ref.rs:20:11
+   |
+LL |     fn my_debug(&self);
+   |        -------- the method is available for `&impl Debug` here
+...
+LL |         x.my_debug();
+   |           ^^^^^^^^ method not found in `impl Debug`
+   |
+   = help: items from traits can only be used if the trait is implemented and in scope
+note: `MyDebug` defines an item `my_debug`, perhaps you need to implement it
+  --> $DIR/call_method_on_inherent_impl_ref.rs:4:1
+   |
+LL | trait MyDebug {
+   | ^^^^^^^^^^^^^
+
+error[E0391]: cycle detected when computing type of opaque `my_foo::{opaque#0}`
+  --> $DIR/call_method_on_inherent_impl_ref.rs:15:16
+   |
+LL | fn my_foo() -> impl std::fmt::Debug {
+   |                ^^^^^^^^^^^^^^^^^^^^
+   |
+note: ...which requires type-checking `my_foo`...
+  --> $DIR/call_method_on_inherent_impl_ref.rs:20:9
+   |
+LL |         x.my_debug();
+   |         ^
+   = note: ...which requires evaluating trait selection obligation `my_foo::{opaque#0}: core::marker::Unpin`...
+   = note: ...which again requires computing type of opaque `my_foo::{opaque#0}`, completing the cycle
+note: cycle used when computing type of `my_foo::{opaque#0}`
+  --> $DIR/call_method_on_inherent_impl_ref.rs:15:16
+   |
+LL | fn my_foo() -> impl std::fmt::Debug {
+   |                ^^^^^^^^^^^^^^^^^^^^
+   = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0391, E0599.
+For more information about an error, try `rustc --explain E0391`.
diff --git a/tests/ui/impl-trait/call_method_on_inherent_impl_ref.next.stderr b/tests/ui/impl-trait/call_method_on_inherent_impl_ref.next.stderr
new file mode 100644
index 00000000000..327f6ca3450
--- /dev/null
+++ b/tests/ui/impl-trait/call_method_on_inherent_impl_ref.next.stderr
@@ -0,0 +1,31 @@
+error[E0282]: type annotations needed
+  --> $DIR/call_method_on_inherent_impl_ref.rs:18:13
+   |
+LL |         let x = my_foo();
+   |             ^
+LL |
+LL |         x.my_debug();
+   |         - type must be known at this point
+   |
+help: consider giving `x` an explicit type
+   |
+LL |         let x: /* Type */ = my_foo();
+   |              ++++++++++++
+
+error[E0282]: type annotations needed for `&_`
+  --> $DIR/call_method_on_inherent_impl_ref.rs:28:13
+   |
+LL |         let x = &my_bar();
+   |             ^
+LL |
+LL |         x.my_debug();
+   |           -------- type must be known at this point
+   |
+help: consider giving `x` an explicit type, where the placeholders `_` are specified
+   |
+LL |         let x: &_ = &my_bar();
+   |              ++++
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/tests/ui/impl-trait/call_method_on_inherent_impl_ref.rs b/tests/ui/impl-trait/call_method_on_inherent_impl_ref.rs
new file mode 100644
index 00000000000..40ad21532a4
--- /dev/null
+++ b/tests/ui/impl-trait/call_method_on_inherent_impl_ref.rs
@@ -0,0 +1,35 @@
+//@ revisions: current next
+//@[next] compile-flags: -Znext-solver
+
+trait MyDebug {
+    fn my_debug(&self);
+}
+
+impl<T> MyDebug for &T
+where
+    T: std::fmt::Debug,
+{
+    fn my_debug(&self) {}
+}
+
+fn my_foo() -> impl std::fmt::Debug {
+    //[current]~^ cycle
+    if false {
+        let x = my_foo();
+        //[next]~^ type annotations needed
+        x.my_debug();
+        //[current]~^ no method named `my_debug` found
+    }
+    ()
+}
+
+fn my_bar() -> impl std::fmt::Debug {
+    if false {
+        let x = &my_bar();
+        //[next]~^ type annotations needed
+        x.my_debug();
+    }
+    ()
+}
+
+fn main() {}
diff --git a/tests/ui/impl-trait/call_method_without_import.no_import.stderr b/tests/ui/impl-trait/call_method_without_import.no_import.stderr
new file mode 100644
index 00000000000..72982b695bb
--- /dev/null
+++ b/tests/ui/impl-trait/call_method_without_import.no_import.stderr
@@ -0,0 +1,37 @@
+error[E0599]: no method named `fmt` found for opaque type `impl Debug` in the current scope
+  --> $DIR/call_method_without_import.rs:17:11
+   |
+LL |         x.fmt(f);
+   |           ^^^ method not found in `impl Debug`
+  --> $SRC_DIR/core/src/fmt/mod.rs:LL:COL
+   |
+   = note: the method is available for `impl Debug` here
+   |
+   = help: items from traits can only be used if the trait is in scope
+help: trait `Debug` which provides `fmt` is implemented but not in scope; perhaps you want to import it
+   |
+LL + use std::fmt::Debug;
+   |
+
+error[E0599]: no method named `fmt` found for mutable reference `&mut impl Debug` in the current scope
+  --> $DIR/call_method_without_import.rs:26:11
+   |
+LL |         x.fmt(f);
+   |           ^^^ method not found in `&mut impl Debug`
+   |
+   = help: items from traits can only be used if the trait is in scope
+help: the following traits which provide `fmt` are implemented but not in scope; perhaps you want to import one of them
+   |
+LL + use std::fmt::Binary;
+   |
+LL + use std::fmt::Debug;
+   |
+LL + use std::fmt::Display;
+   |
+LL + use std::fmt::LowerExp;
+   |
+     and 5 other candidates
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/tests/ui/impl-trait/call_method_without_import.rs b/tests/ui/impl-trait/call_method_without_import.rs
new file mode 100644
index 00000000000..d62777ea283
--- /dev/null
+++ b/tests/ui/impl-trait/call_method_without_import.rs
@@ -0,0 +1,42 @@
+//! Test that opaque types only pick up methods from traits in their bounds
+//! if the trait is imported.
+//!
+//! FIXME: always look through the bounds of an opaque type to see if there are
+//! methods that could be called on any of the bound traits, irrespective of
+//! imported traits.
+
+//@ revisions: import no_import
+//@[import] check-pass
+
+#[cfg(import)]
+use std::fmt::Debug as _;
+
+fn foo(f: &mut std::fmt::Formatter<'_>) -> impl std::fmt::Debug {
+    if false {
+        let x = foo(f);
+        x.fmt(f);
+        //[no_import]~^ ERROR: no method named `fmt` found
+    }
+    ()
+}
+
+fn foo1(f: &mut std::fmt::Formatter<'_>) -> impl std::fmt::Debug {
+    if false {
+        let x = &mut foo(f);
+        x.fmt(f);
+        //[no_import]~^ ERROR: no method named `fmt` found
+    }
+    ()
+}
+
+// inconsistent with this
+fn bar<T>(t: impl std::fmt::Debug, f: &mut std::fmt::Formatter<'_>) {
+    t.fmt(f);
+}
+
+// and the desugared version, of course
+fn baz<T: std::fmt::Debug>(t: T, f: &mut std::fmt::Formatter<'_>) {
+    t.fmt(f);
+}
+
+fn main() {}
diff --git a/tests/ui/impl-trait/method-resolution.current.stderr b/tests/ui/impl-trait/method-resolution.current.stderr
new file mode 100644
index 00000000000..6d10693c893
--- /dev/null
+++ b/tests/ui/impl-trait/method-resolution.current.stderr
@@ -0,0 +1,36 @@
+error[E0599]: no method named `bar` found for struct `Bar<impl Sized>` in the current scope
+  --> $DIR/method-resolution.rs:23:11
+   |
+LL | struct Bar<T>(T);
+   | ------------- method `bar` not found for this struct
+...
+LL |         x.bar();
+   |           ^^^ method not found in `Bar<impl Sized>`
+   |
+   = note: the method was found for
+           - `Bar<u32>`
+
+error[E0391]: cycle detected when computing type of opaque `foo::{opaque#0}`
+  --> $DIR/method-resolution.rs:19:24
+   |
+LL | fn foo(x: bool) -> Bar<impl Sized> {
+   |                        ^^^^^^^^^^
+   |
+note: ...which requires type-checking `foo`...
+  --> $DIR/method-resolution.rs:23:9
+   |
+LL |         x.bar();
+   |         ^
+   = note: ...which requires evaluating trait selection obligation `Bar<foo::{opaque#0}>: core::marker::Unpin`...
+   = note: ...which again requires computing type of opaque `foo::{opaque#0}`, completing the cycle
+note: cycle used when computing type of `foo::{opaque#0}`
+  --> $DIR/method-resolution.rs:19:24
+   |
+LL | fn foo(x: bool) -> Bar<impl Sized> {
+   |                        ^^^^^^^^^^
+   = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0391, E0599.
+For more information about an error, try `rustc --explain E0391`.
diff --git a/tests/ui/impl-trait/method-resolution.rs b/tests/ui/impl-trait/method-resolution.rs
new file mode 100644
index 00000000000..07618aa6408
--- /dev/null
+++ b/tests/ui/impl-trait/method-resolution.rs
@@ -0,0 +1,29 @@
+//! Check that we do not constrain hidden types during method resolution.
+//! Otherwise we'd pick up that calling `bar` can be satisfied iff `u32`
+//! is the hidden type of the RPIT.
+
+//@ revisions: current next
+//@[next] compile-flags: -Znext-solver
+//@[next] check-pass
+
+trait Trait {}
+
+impl Trait for u32 {}
+
+struct Bar<T>(T);
+
+impl Bar<u32> {
+    fn bar(self) {}
+}
+
+fn foo(x: bool) -> Bar<impl Sized> {
+    //[current]~^ ERROR: cycle detected
+    if x {
+        let x = foo(false);
+        x.bar();
+        //[current]~^ ERROR: no method named `bar` found
+    }
+    todo!()
+}
+
+fn main() {}
diff --git a/tests/ui/impl-trait/method-resolution2.next.stderr b/tests/ui/impl-trait/method-resolution2.next.stderr
new file mode 100644
index 00000000000..223430e1658
--- /dev/null
+++ b/tests/ui/impl-trait/method-resolution2.next.stderr
@@ -0,0 +1,20 @@
+error[E0034]: multiple applicable items in scope
+  --> $DIR/method-resolution2.rs:25:11
+   |
+LL |         x.bar();
+   |           ^^^ multiple `bar` found
+   |
+note: candidate #1 is defined in an impl for the type `Bar<T>`
+  --> $DIR/method-resolution2.rs:19:5
+   |
+LL |     fn bar(self) {}
+   |     ^^^^^^^^^^^^
+note: candidate #2 is defined in an impl for the type `Bar<u32>`
+  --> $DIR/method-resolution2.rs:15:5
+   |
+LL |     fn bar(self) {}
+   |     ^^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0034`.
diff --git a/tests/ui/impl-trait/method-resolution2.rs b/tests/ui/impl-trait/method-resolution2.rs
new file mode 100644
index 00000000000..2930b42b8bc
--- /dev/null
+++ b/tests/ui/impl-trait/method-resolution2.rs
@@ -0,0 +1,31 @@
+//! Check that the method call does not constrain the RPIT to `i32`, even though
+//! `i32` is the only trait that satisfies the RPIT's trait bounds.
+
+//@ revisions: current next
+//@[next] compile-flags: -Znext-solver
+//@[current] check-pass
+
+trait Trait {}
+
+impl Trait for i32 {}
+
+struct Bar<T>(T);
+
+impl Bar<u32> {
+    fn bar(self) {}
+}
+
+impl<T: Trait> Bar<T> {
+    fn bar(self) {}
+}
+
+fn foo(x: bool) -> Bar<impl Trait> {
+    if x {
+        let x = foo(false);
+        x.bar();
+        //[next]~^ ERROR: multiple applicable items in scope
+    }
+    Bar(42_i32)
+}
+
+fn main() {}
diff --git a/tests/ui/impl-trait/method-resolution3.current.stderr b/tests/ui/impl-trait/method-resolution3.current.stderr
new file mode 100644
index 00000000000..7407b489e32
--- /dev/null
+++ b/tests/ui/impl-trait/method-resolution3.current.stderr
@@ -0,0 +1,37 @@
+error[E0599]: no method named `bar` found for struct `Bar<impl Sized>` in the current scope
+  --> $DIR/method-resolution3.rs:22:11
+   |
+LL | struct Bar<T>(T);
+   | ------------- method `bar` not found for this struct
+...
+LL |         x.bar();
+   |           ^^^ method not found in `Bar<impl Sized>`
+   |
+   = note: the method was found for
+           - `Bar<i32>`
+           - `Bar<u32>`
+
+error[E0391]: cycle detected when computing type of opaque `foo::{opaque#0}`
+  --> $DIR/method-resolution3.rs:18:24
+   |
+LL | fn foo(x: bool) -> Bar<impl Sized> {
+   |                        ^^^^^^^^^^
+   |
+note: ...which requires type-checking `foo`...
+  --> $DIR/method-resolution3.rs:22:9
+   |
+LL |         x.bar();
+   |         ^
+   = note: ...which requires evaluating trait selection obligation `Bar<foo::{opaque#0}>: core::marker::Unpin`...
+   = note: ...which again requires computing type of opaque `foo::{opaque#0}`, completing the cycle
+note: cycle used when computing type of `foo::{opaque#0}`
+  --> $DIR/method-resolution3.rs:18:24
+   |
+LL | fn foo(x: bool) -> Bar<impl Sized> {
+   |                        ^^^^^^^^^^
+   = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0391, E0599.
+For more information about an error, try `rustc --explain E0391`.
diff --git a/tests/ui/impl-trait/method-resolution3.next.stderr b/tests/ui/impl-trait/method-resolution3.next.stderr
new file mode 100644
index 00000000000..53b77c620ba
--- /dev/null
+++ b/tests/ui/impl-trait/method-resolution3.next.stderr
@@ -0,0 +1,20 @@
+error[E0034]: multiple applicable items in scope
+  --> $DIR/method-resolution3.rs:22:11
+   |
+LL |         x.bar();
+   |           ^^^ multiple `bar` found
+   |
+note: candidate #1 is defined in an impl for the type `Bar<i32>`
+  --> $DIR/method-resolution3.rs:15:5
+   |
+LL |     fn bar(self) {}
+   |     ^^^^^^^^^^^^
+note: candidate #2 is defined in an impl for the type `Bar<u32>`
+  --> $DIR/method-resolution3.rs:11:5
+   |
+LL |     fn bar(self) {}
+   |     ^^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0034`.
diff --git a/tests/ui/impl-trait/method-resolution3.rs b/tests/ui/impl-trait/method-resolution3.rs
new file mode 100644
index 00000000000..8474e2da7db
--- /dev/null
+++ b/tests/ui/impl-trait/method-resolution3.rs
@@ -0,0 +1,29 @@
+//! Check that we consider `Bar<impl Sized>` to successfully unify
+//! with both `Bar<u32>` and `Bar<i32>` (in isolation), so we bail
+//! out with ambiguity.
+
+//@ revisions: current next
+//@[next] compile-flags: -Znext-solver
+
+struct Bar<T>(T);
+
+impl Bar<u32> {
+    fn bar(self) {}
+}
+
+impl Bar<i32> {
+    fn bar(self) {}
+}
+
+fn foo(x: bool) -> Bar<impl Sized> {
+    //[current]~^ ERROR: cycle
+    if x {
+        let x = foo(false);
+        x.bar();
+        //[current]~^ ERROR: no method named `bar`
+        //[next]~^^ ERROR: multiple applicable items in scope
+    }
+    todo!()
+}
+
+fn main() {}
diff --git a/tests/ui/impl-trait/method-resolution4.next.stderr b/tests/ui/impl-trait/method-resolution4.next.stderr
new file mode 100644
index 00000000000..b48de0af357
--- /dev/null
+++ b/tests/ui/impl-trait/method-resolution4.next.stderr
@@ -0,0 +1,22 @@
+error[E0282]: type annotations needed
+  --> $DIR/method-resolution4.rs:13:9
+   |
+LL |         foo(false).next().unwrap();
+   |         ^^^^^^^^^^ cannot infer type
+
+error[E0308]: mismatched types
+  --> $DIR/method-resolution4.rs:16:5
+   |
+LL | fn foo(b: bool) -> impl Iterator<Item = ()> {
+   |                    ------------------------ the expected opaque type
+...
+LL |     std::iter::empty()
+   |     ^^^^^^^^^^^^^^^^^^ types differ
+   |
+   = note: expected opaque type `impl Iterator<Item = ()>`
+                   found struct `std::iter::Empty<_>`
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0282, E0308.
+For more information about an error, try `rustc --explain E0282`.
diff --git a/tests/ui/impl-trait/method-resolution4.rs b/tests/ui/impl-trait/method-resolution4.rs
new file mode 100644
index 00000000000..3578db7cb55
--- /dev/null
+++ b/tests/ui/impl-trait/method-resolution4.rs
@@ -0,0 +1,20 @@
+//! The recursive method call yields the opaque type. The
+//! `next` method call then constrains the hidden type to `&mut _`
+//! because `next` takes `&mut self`. We never resolve the inference
+//! variable, but get a type mismatch when comparing `&mut _` with
+//! `std::iter::Empty`.
+
+//@[current] check-pass
+//@ revisions: current next
+//@[next] compile-flags: -Znext-solver
+
+fn foo(b: bool) -> impl Iterator<Item = ()> {
+    if b {
+        foo(false).next().unwrap();
+        //[next]~^ type annotations needed
+    }
+    std::iter::empty()
+    //[next]~^ mismatched types
+}
+
+fn main() {}
diff --git a/tests/ui/impl-trait/recursive-parent-trait-method-call.rs b/tests/ui/impl-trait/recursive-parent-trait-method-call.rs
new file mode 100644
index 00000000000..4da9a06a465
--- /dev/null
+++ b/tests/ui/impl-trait/recursive-parent-trait-method-call.rs
@@ -0,0 +1,42 @@
+//! This test checks that we can resolve the `boxed` method call to `FutureExt`,
+//! because we know that the anonymous future does not implement `StreamExt`.
+
+//@ edition: 2021
+//@ check-pass
+
+use std::future::Future;
+use std::pin::Pin;
+
+trait FutureExt: Future + Sized + Send + 'static {
+    fn boxed(self) -> Pin<Box<dyn Future<Output = Self::Output> + Send + 'static>> {
+        Box::pin(self)
+    }
+}
+
+trait StreamExt: Future + Sized + Send + 'static {
+    fn boxed(self) -> Pin<Box<dyn Future<Output = Self::Output> + Send + 'static>> {
+        Box::pin(self)
+    }
+}
+
+impl<T: Future + Sized + Send + 'static> FutureExt for T {}
+
+fn go(i: usize) -> impl Future<Output = ()> + Send + 'static {
+    async move {
+        if i != 0 {
+            spawn(async move {
+                let fut = go(i - 1).boxed();
+                fut.await;
+            })
+            .await;
+        }
+    }
+}
+
+pub fn spawn<T: Send>(
+    _: impl Future<Output = T> + Send + 'static,
+) -> impl Future<Output = ()> + Send + 'static {
+    async move { todo!() }
+}
+
+fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/method_resolution.current.stderr b/tests/ui/type-alias-impl-trait/method_resolution.current.stderr
new file mode 100644
index 00000000000..a9c05ad3342
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/method_resolution.current.stderr
@@ -0,0 +1,15 @@
+error[E0599]: no method named `bar` found for struct `Bar<u32>` in the current scope
+  --> $DIR/method_resolution.rs:21:14
+   |
+LL | struct Bar<T>(T);
+   | ------------- method `bar` not found for this struct
+...
+LL |         self.bar()
+   |              ^^^ method not found in `Bar<u32>`
+   |
+   = note: the method was found for
+           - `Bar<Foo>`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/tests/ui/type-alias-impl-trait/method_resolution.next.stderr b/tests/ui/type-alias-impl-trait/method_resolution.next.stderr
new file mode 100644
index 00000000000..6b34358a56e
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/method_resolution.next.stderr
@@ -0,0 +1,12 @@
+error[E0599]: no method named `bar` found for struct `Bar<u32>` in the current scope
+  --> $DIR/method_resolution.rs:21:14
+   |
+LL | struct Bar<T>(T);
+   | ------------- method `bar` not found for this struct
+...
+LL |         self.bar()
+   |              ^^^ method cannot be called on `Bar<u32>` due to unsatisfied trait bounds
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/tests/ui/type-alias-impl-trait/method_resolution.rs b/tests/ui/type-alias-impl-trait/method_resolution.rs
new file mode 100644
index 00000000000..f636aba15c0
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/method_resolution.rs
@@ -0,0 +1,30 @@
+//! `Bar<u32>::foo` is not defining `Foo`, so it cannot rely on the fact that
+//! `u32` is the hidden type of `Foo` to call `bar`
+
+//@ revisions: current next
+//@[next] compile-flags: -Znext-solver
+
+#![feature(type_alias_impl_trait)]
+
+type Foo = impl Sized;
+
+struct Bar<T>(T);
+
+impl Bar<Foo> {
+    fn bar(mut self) {
+        self.0 = 42_u32;
+    }
+}
+
+impl Bar<u32> {
+    fn foo(self) {
+        self.bar()
+        //~^ ERROR: no method named `bar`
+    }
+}
+
+fn foo() -> Foo {
+    42_u32
+}
+
+fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/method_resolution2.current.stderr b/tests/ui/type-alias-impl-trait/method_resolution2.current.stderr
new file mode 100644
index 00000000000..e68ea70a8ef
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/method_resolution2.current.stderr
@@ -0,0 +1,36 @@
+error[E0599]: no method named `foo` found for struct `Bar<Foo>` in the current scope
+  --> $DIR/method_resolution2.rs:17:14
+   |
+LL | struct Bar<T>(T);
+   | ------------- method `foo` not found for this struct
+...
+LL |         self.foo()
+   |              ^^^ method not found in `Bar<Foo>`
+   |
+   = note: the method was found for
+           - `Bar<u32>`
+
+error[E0391]: cycle detected when computing type of opaque `Foo::{opaque#0}`
+  --> $DIR/method_resolution2.rs:10:12
+   |
+LL | type Foo = impl Sized;
+   |            ^^^^^^^^^^
+   |
+note: ...which requires type-checking `<impl at $DIR/method_resolution2.rs:15:1: 15:14>::bar`...
+  --> $DIR/method_resolution2.rs:17:9
+   |
+LL |         self.foo()
+   |         ^^^^
+   = note: ...which requires evaluating trait selection obligation `Bar<Foo>: core::marker::Unpin`...
+   = note: ...which again requires computing type of opaque `Foo::{opaque#0}`, completing the cycle
+note: cycle used when computing type of `Foo::{opaque#0}`
+  --> $DIR/method_resolution2.rs:10:12
+   |
+LL | type Foo = impl Sized;
+   |            ^^^^^^^^^^
+   = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0391, E0599.
+For more information about an error, try `rustc --explain E0391`.
diff --git a/tests/ui/type-alias-impl-trait/method_resolution2.rs b/tests/ui/type-alias-impl-trait/method_resolution2.rs
new file mode 100644
index 00000000000..d252f8640d4
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/method_resolution2.rs
@@ -0,0 +1,30 @@
+//! Check that we do not unify `Bar<Foo>` with `Bar<u32>`, even though the
+//! `foo` method call can be resolved unambiguously by doing so.
+
+//@ revisions: current next
+//@[next] compile-flags: -Znext-solver
+//@[next] check-pass
+
+#![feature(type_alias_impl_trait)]
+
+type Foo = impl Sized;
+//[current]~^ ERROR: cycle
+
+struct Bar<T>(T);
+
+impl Bar<Foo> {
+    fn bar(self) {
+        self.foo()
+        //[current]~^ ERROR: no method named `foo`
+    }
+}
+
+impl Bar<u32> {
+    fn foo(self) {}
+}
+
+fn foo() -> Foo {
+    42_u32
+}
+
+fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/method_resolution3.current.stderr b/tests/ui/type-alias-impl-trait/method_resolution3.current.stderr
new file mode 100644
index 00000000000..e992d059daf
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/method_resolution3.current.stderr
@@ -0,0 +1,21 @@
+error[E0307]: invalid `self` parameter type: `Bar<u32>`
+  --> $DIR/method_resolution3.rs:16:18
+   |
+LL |     fn bar(self: Bar<u32>) {
+   |                  ^^^^^^^^
+   |
+   = note: type of `self` must be `Self` or a type that dereferences to it
+   = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
+
+error[E0307]: invalid `self` parameter type: `&Bar<u32>`
+  --> $DIR/method_resolution3.rs:21:18
+   |
+LL |     fn baz(self: &Bar<u32>) {
+   |                  ^^^^^^^^^
+   |
+   = note: type of `self` must be `Self` or a type that dereferences to it
+   = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0307`.
diff --git a/tests/ui/type-alias-impl-trait/method_resolution3.next.stderr b/tests/ui/type-alias-impl-trait/method_resolution3.next.stderr
new file mode 100644
index 00000000000..9272017cdf5
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/method_resolution3.next.stderr
@@ -0,0 +1,15 @@
+error[E0271]: type mismatch resolving `Foo == u32`
+  --> $DIR/method_resolution3.rs:16:18
+   |
+LL |     fn bar(self: Bar<u32>) {
+   |                  ^^^^^^^^ types differ
+
+error[E0271]: type mismatch resolving `Foo == u32`
+  --> $DIR/method_resolution3.rs:21:18
+   |
+LL |     fn baz(self: &Bar<u32>) {
+   |                  ^^^^^^^^^ types differ
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0271`.
diff --git a/tests/ui/type-alias-impl-trait/method_resolution3.rs b/tests/ui/type-alias-impl-trait/method_resolution3.rs
new file mode 100644
index 00000000000..447f3144b82
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/method_resolution3.rs
@@ -0,0 +1,36 @@
+//! Check that one cannot use arbitrary self types where a generic parameter
+//! mismatches with an opaque type. In theory this could unify with the opaque
+//! type, registering the generic parameter as the hidden type of the opaque type.
+
+//@ revisions: current next
+//@[next] compile-flags: -Znext-solver
+
+#![feature(type_alias_impl_trait, arbitrary_self_types)]
+
+type Foo = impl Copy;
+
+#[derive(Copy, Clone)]
+struct Bar<T>(T);
+
+impl Bar<Foo> {
+    fn bar(self: Bar<u32>) {
+        //[current]~^ ERROR: invalid `self` parameter
+        //[next]~^^ ERROR: type mismatch resolving `Foo == u32`
+        self.foo()
+    }
+    fn baz(self: &Bar<u32>) {
+        //[current]~^ ERROR: invalid `self` parameter
+        //[next]~^^ ERROR: type mismatch resolving `Foo == u32`
+        self.foo()
+    }
+}
+
+impl Bar<u32> {
+    fn foo(self) {}
+}
+
+fn foo() -> Foo {
+    42_u32
+}
+
+fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/method_resolution4.current.stderr b/tests/ui/type-alias-impl-trait/method_resolution4.current.stderr
new file mode 100644
index 00000000000..3a2ca18f890
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/method_resolution4.current.stderr
@@ -0,0 +1,21 @@
+error[E0307]: invalid `self` parameter type: `Bar<Foo>`
+  --> $DIR/method_resolution4.rs:27:18
+   |
+LL |     fn foo(self: Bar<Foo>) {
+   |                  ^^^^^^^^
+   |
+   = note: type of `self` must be `Self` or a type that dereferences to it
+   = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
+
+error[E0307]: invalid `self` parameter type: `&Bar<Foo>`
+  --> $DIR/method_resolution4.rs:32:20
+   |
+LL |     fn foomp(self: &Bar<Foo>) {
+   |                    ^^^^^^^^^
+   |
+   = note: type of `self` must be `Self` or a type that dereferences to it
+   = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0307`.
diff --git a/tests/ui/type-alias-impl-trait/method_resolution4.next.stderr b/tests/ui/type-alias-impl-trait/method_resolution4.next.stderr
new file mode 100644
index 00000000000..33ed2800ebe
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/method_resolution4.next.stderr
@@ -0,0 +1,15 @@
+error[E0271]: type mismatch resolving `u32 == Foo`
+  --> $DIR/method_resolution4.rs:27:18
+   |
+LL |     fn foo(self: Bar<Foo>) {
+   |                  ^^^^^^^^ types differ
+
+error[E0271]: type mismatch resolving `u32 == Foo`
+  --> $DIR/method_resolution4.rs:32:20
+   |
+LL |     fn foomp(self: &Bar<Foo>) {
+   |                    ^^^^^^^^^ types differ
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0271`.
diff --git a/tests/ui/type-alias-impl-trait/method_resolution4.rs b/tests/ui/type-alias-impl-trait/method_resolution4.rs
new file mode 100644
index 00000000000..42ed04b3c30
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/method_resolution4.rs
@@ -0,0 +1,39 @@
+//! Check that one cannot use arbitrary self types where a generic parameter
+//! mismatches with an opaque type. In theory this could unify with the opaque
+//! type, registering the generic parameter as the hidden type of the opaque type.
+
+//@ revisions: current next
+//@[next] compile-flags: -Znext-solver
+
+#![feature(type_alias_impl_trait, arbitrary_self_types)]
+
+mod foo {
+    pub type Foo = impl Copy;
+
+    fn foo() -> Foo {
+        42_u32
+    }
+}
+use foo::Foo;
+
+#[derive(Copy, Clone)]
+struct Bar<T>(T);
+
+impl Bar<Foo> {
+    fn bar(self) {}
+}
+
+impl Bar<u32> {
+    fn foo(self: Bar<Foo>) {
+        //[current]~^ ERROR: invalid `self` parameter
+        //[next]~^^ ERROR: type mismatch resolving `u32 == Foo`
+        self.bar()
+    }
+    fn foomp(self: &Bar<Foo>) {
+        //[current]~^ ERROR: invalid `self` parameter
+        //[next]~^^ ERROR: type mismatch resolving `u32 == Foo`
+        self.bar()
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/method_resolution5.current.stderr b/tests/ui/type-alias-impl-trait/method_resolution5.current.stderr
new file mode 100644
index 00000000000..193e6e14709
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/method_resolution5.current.stderr
@@ -0,0 +1,15 @@
+error[E0599]: no method named `bar` found for struct `Bar<u32>` in the current scope
+  --> $DIR/method_resolution5.rs:25:14
+   |
+LL | struct Bar<T>(T);
+   | ------------- method `bar` not found for this struct
+...
+LL |         self.bar()
+   |              ^^^ method not found in `Bar<u32>`
+   |
+   = note: the method was found for
+           - `Bar<Foo>`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/tests/ui/type-alias-impl-trait/method_resolution5.rs b/tests/ui/type-alias-impl-trait/method_resolution5.rs
new file mode 100644
index 00000000000..69335c9dede
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/method_resolution5.rs
@@ -0,0 +1,34 @@
+//! Even though `Bar<u32>::foo` is defining `Foo`, the old solver does
+//! not figure out that `u32` is the hidden type of `Foo` to call `bar`.
+
+//@ revisions: current next
+//@[next] compile-flags: -Znext-solver
+//@[next] check-pass
+
+#![feature(type_alias_impl_trait)]
+
+type Foo = impl Sized;
+
+struct Bar<T>(T);
+
+impl Bar<Foo> {
+    fn bar(mut self) {
+        self.0 = 42_u32;
+    }
+}
+
+impl Bar<u32> {
+    fn foo(self)
+    where
+        Foo:,
+    {
+        self.bar()
+        //[current]~^ ERROR: no method named `bar`
+    }
+}
+
+fn foo() -> Foo {
+    42_u32
+}
+
+fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/method_resolution_trait_method_from_opaque.current.stderr b/tests/ui/type-alias-impl-trait/method_resolution_trait_method_from_opaque.current.stderr
new file mode 100644
index 00000000000..f331da1af87
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/method_resolution_trait_method_from_opaque.current.stderr
@@ -0,0 +1,15 @@
+error: item does not constrain `Tait::{opaque#0}`, but has it in its signature
+  --> $DIR/method_resolution_trait_method_from_opaque.rs:24:8
+   |
+LL |     fn foo(&mut self) {
+   |        ^^^
+   |
+   = note: consider moving the opaque type's declaration and defining uses into a separate module
+note: this opaque type is in the signature
+  --> $DIR/method_resolution_trait_method_from_opaque.rs:17:13
+   |
+LL | type Tait = impl Iterator<Item = ()>;
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/type-alias-impl-trait/method_resolution_trait_method_from_opaque.next.stderr b/tests/ui/type-alias-impl-trait/method_resolution_trait_method_from_opaque.next.stderr
new file mode 100644
index 00000000000..2617ce124c1
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/method_resolution_trait_method_from_opaque.next.stderr
@@ -0,0 +1,9 @@
+error[E0282]: type annotations needed
+  --> $DIR/method_resolution_trait_method_from_opaque.rs:26:9
+   |
+LL |         self.bar.next().unwrap();
+   |         ^^^^^^^^ cannot infer type
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/tests/ui/type-alias-impl-trait/method_resolution_trait_method_from_opaque.rs b/tests/ui/type-alias-impl-trait/method_resolution_trait_method_from_opaque.rs
new file mode 100644
index 00000000000..b6adf08853f
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/method_resolution_trait_method_from_opaque.rs
@@ -0,0 +1,31 @@
+//! This test demonstrates how method calls will attempt to unify an opaque type with a reference
+//! if the method takes `&self` as its argument. This is almost never what is desired, as the user
+//! would like to have method resolution happen on the opaque type instead of inferring the hidden
+//! type. Once type-alias-impl-trait requires annotating which functions should constrain the hidden
+//! type, this won't be as much of a problem, as most functions that do method calls on opaque types
+//! won't also be the ones defining the hidden type.
+
+//@ revisions: current next
+//@[next] compile-flags: -Znext-solver
+
+#![feature(type_alias_impl_trait)]
+
+pub struct Foo {
+    bar: Tait,
+}
+
+type Tait = impl Iterator<Item = ()>;
+
+impl Foo {
+    pub fn new() -> Foo {
+        Foo { bar: std::iter::empty() }
+    }
+
+    fn foo(&mut self) {
+        //[current]~^ ERROR: item does not constrain
+        self.bar.next().unwrap();
+        //[next]~^ ERROR: type annotations needed
+    }
+}
+
+fn main() {}

From 9cf60ee9d33fadff387d83d09aef1ce43589e233 Mon Sep 17 00:00:00 2001
From: Oli Scherer <git-spam-no-reply9815368754983@oli-obk.de>
Date: Mon, 15 Apr 2024 11:37:09 +0000
Subject: [PATCH 08/13] Method resolution constrains hidden types instead of
 rejecting method candidates

---
 .../rustc_hir_typeck/src/fn_ctxt/_impl.rs     |  2 +-
 .../rustc_hir_typeck/src/method/confirm.rs    |  2 +-
 compiler/rustc_hir_typeck/src/method/probe.rs | 65 +++++++++----------
 compiler/rustc_middle/src/traits/query.rs     |  2 +-
 .../method-resolution.current.stderr          | 36 ----------
 tests/ui/impl-trait/method-resolution.rs      |  9 +--
 tests/ui/impl-trait/method-resolution2.rs     |  2 +-
 .../method-resolution3.current.stderr         | 47 +++++---------
 .../impl-trait/method-resolution3.next.stderr |  2 +-
 tests/ui/impl-trait/method-resolution3.rs     |  4 +-
 tests/ui/impl-trait/method-resolution4.rs     |  2 +-
 tests/ui/methods/opaque_param_in_ufc.rs       |  6 +-
 tests/ui/methods/opaque_param_in_ufc.stderr   | 36 ----------
 .../method_resolution2.current.stderr         | 36 ----------
 .../method_resolution2.rs                     |  6 +-
 .../method_resolution5.current.stderr         | 15 -----
 .../method_resolution5.rs                     |  3 +-
 17 files changed, 60 insertions(+), 215 deletions(-)
 delete mode 100644 tests/ui/impl-trait/method-resolution.current.stderr
 delete mode 100644 tests/ui/methods/opaque_param_in_ufc.stderr
 delete mode 100644 tests/ui/type-alias-impl-trait/method_resolution2.current.stderr
 delete mode 100644 tests/ui/type-alias-impl-trait/method_resolution5.current.stderr

diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
index 94e879ae9c3..9531c002829 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
@@ -1418,7 +1418,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             let impl_ty = self.normalize(span, tcx.type_of(impl_def_id).instantiate(tcx, args));
             let self_ty = self.normalize(span, self_ty);
             match self.at(&self.misc(span), self.param_env).eq(
-                DefineOpaqueTypes::No,
+                DefineOpaqueTypes::Yes,
                 impl_ty,
                 self_ty,
             ) {
diff --git a/compiler/rustc_hir_typeck/src/method/confirm.rs b/compiler/rustc_hir_typeck/src/method/confirm.rs
index 3c9a49e91a3..120e3239d1f 100644
--- a/compiler/rustc_hir_typeck/src/method/confirm.rs
+++ b/compiler/rustc_hir_typeck/src/method/confirm.rs
@@ -497,7 +497,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
                 args,
             })),
         );
-        match self.at(&cause, self.param_env).sup(DefineOpaqueTypes::No, method_self_ty, self_ty) {
+        match self.at(&cause, self.param_env).sup(DefineOpaqueTypes::Yes, method_self_ty, self_ty) {
             Ok(InferOk { obligations, value: () }) => {
                 self.register_predicates(obligations);
             }
diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs
index e842bba34bf..3986374a343 100644
--- a/compiler/rustc_hir_typeck/src/method/probe.rs
+++ b/compiler/rustc_hir_typeck/src/method/probe.rs
@@ -634,8 +634,8 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
         }
     }
 
+    #[instrument(level = "debug", skip(self))]
     fn assemble_probe(&mut self, self_ty: &Canonical<'tcx, QueryResponse<'tcx, Ty<'tcx>>>) {
-        debug!("assemble_probe: self_ty={:?}", self_ty);
         let raw_self_ty = self_ty.value.value;
         match *raw_self_ty.kind() {
             ty::Dynamic(data, ..) if let Some(p) = data.principal() => {
@@ -713,13 +713,12 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
         }
     }
 
+    #[instrument(level = "debug", skip(self))]
     fn assemble_inherent_impl_probe(&mut self, impl_def_id: DefId) {
         if !self.impl_dups.insert(impl_def_id) {
             return; // already visited
         }
 
-        debug!("assemble_inherent_impl_probe {:?}", impl_def_id);
-
         for item in self.impl_or_trait_item(impl_def_id) {
             if !self.has_applicable_self(&item) {
                 // No receiver declared. Not a candidate.
@@ -737,9 +736,8 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
         }
     }
 
+    #[instrument(level = "debug", skip(self))]
     fn assemble_inherent_candidates_from_object(&mut self, self_ty: Ty<'tcx>) {
-        debug!("assemble_inherent_candidates_from_object(self_ty={:?})", self_ty);
-
         let principal = match self_ty.kind() {
             ty::Dynamic(ref data, ..) => Some(data),
             _ => None,
@@ -768,9 +766,9 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
         });
     }
 
+    #[instrument(level = "debug", skip(self))]
     fn assemble_inherent_candidates_from_param(&mut self, param_ty: ty::ParamTy) {
         // FIXME: do we want to commit to this behavior for param bounds?
-        debug!("assemble_inherent_candidates_from_param(param_ty={:?})", param_ty);
 
         let bounds = self.param_env.caller_bounds().iter().filter_map(|predicate| {
             let bound_predicate = predicate.kind();
@@ -826,6 +824,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
         }
     }
 
+    #[instrument(level = "debug", skip(self))]
     fn assemble_extension_candidates_for_traits_in_scope(&mut self) {
         let mut duplicates = FxHashSet::default();
         let opt_applicable_traits = self.tcx.in_scope_traits(self.scope_expr_id);
@@ -842,6 +841,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
         }
     }
 
+    #[instrument(level = "debug", skip(self))]
     fn assemble_extension_candidates_for_all_traits(&mut self) {
         let mut duplicates = FxHashSet::default();
         for trait_info in suggest::all_traits(self.tcx) {
@@ -863,12 +863,12 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
         }
     }
 
+    #[instrument(level = "debug", skip(self))]
     fn assemble_extension_candidates_for_trait(
         &mut self,
         import_ids: &SmallVec<[LocalDefId; 1]>,
         trait_def_id: DefId,
     ) {
-        debug!("assemble_extension_candidates_for_trait(trait_def_id={:?})", trait_def_id);
         let trait_args = self.fresh_args_for_item(self.span, trait_def_id);
         let trait_ref = ty::TraitRef::new(self.tcx, trait_def_id, trait_args);
 
@@ -958,6 +958,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
     ///////////////////////////////////////////////////////////////////////////
     // THE ACTUAL SEARCH
 
+    #[instrument(level = "debug", skip(self))]
     fn pick(mut self) -> PickResult<'tcx> {
         assert!(self.method_name.is_some());
 
@@ -1386,6 +1387,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
         }
     }
 
+    #[instrument(level = "trace", skip(self, possibly_unsatisfied_predicates), ret)]
     fn consider_probe(
         &self,
         self_ty: Ty<'tcx>,
@@ -1415,15 +1417,8 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
                     (xform_self_ty, xform_ret_ty) =
                         self.xform_self_ty(probe.item, impl_ty, impl_args);
                     xform_self_ty = ocx.normalize(cause, self.param_env, xform_self_ty);
-                    // FIXME: Make this `ocx.sup` once we define opaques more eagerly.
-                    match self.at(cause, self.param_env).sup(
-                        DefineOpaqueTypes::No,
-                        xform_self_ty,
-                        self_ty,
-                    ) {
-                        Ok(infer_ok) => {
-                            ocx.register_infer_ok_obligations(infer_ok);
-                        }
+                    match ocx.sup(cause, self.param_env, xform_self_ty, self_ty) {
+                        Ok(()) => {}
                         Err(err) => {
                             debug!("--> cannot relate self-types {:?}", err);
                             return ProbeResult::NoMatch;
@@ -1484,19 +1479,23 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
                     (xform_self_ty, xform_ret_ty) =
                         self.xform_self_ty(probe.item, trait_ref.self_ty(), trait_ref.args);
                     xform_self_ty = ocx.normalize(cause, self.param_env, xform_self_ty);
-                    // FIXME: Make this `ocx.sup` once we define opaques more eagerly.
-                    match self.at(cause, self.param_env).sup(
-                        DefineOpaqueTypes::No,
-                        xform_self_ty,
-                        self_ty,
-                    ) {
-                        Ok(infer_ok) => {
-                            ocx.register_infer_ok_obligations(infer_ok);
-                        }
-                        Err(err) => {
-                            debug!("--> cannot relate self-types {:?}", err);
+                    match self_ty.kind() {
+                        // HACK: opaque types will match anything for which their bounds hold.
+                        // Thus we need to prevent them from trying to match the `&_` autoref
+                        // candidates that get created for `&self` trait methods.
+                        ty::Alias(ty::Opaque, alias_ty)
+                            if self.infcx.can_define_opaque_ty(alias_ty.def_id)
+                                && !xform_self_ty.is_ty_var() =>
+                        {
                             return ProbeResult::NoMatch;
                         }
+                        _ => match ocx.sup(cause, self.param_env, xform_self_ty, self_ty) {
+                            Ok(()) => {}
+                            Err(err) => {
+                                debug!("--> cannot relate self-types {:?}", err);
+                                return ProbeResult::NoMatch;
+                            }
+                        },
                     }
                     let obligation = traits::Obligation::new(
                         self.tcx,
@@ -1536,15 +1535,8 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
                     (xform_self_ty, xform_ret_ty) =
                         self.xform_self_ty(probe.item, trait_ref.self_ty(), trait_ref.args);
                     xform_self_ty = ocx.normalize(cause, self.param_env, xform_self_ty);
-                    // FIXME: Make this `ocx.sup` once we define opaques more eagerly.
-                    match self.at(cause, self.param_env).sup(
-                        DefineOpaqueTypes::No,
-                        xform_self_ty,
-                        self_ty,
-                    ) {
-                        Ok(infer_ok) => {
-                            ocx.register_infer_ok_obligations(infer_ok);
-                        }
+                    match ocx.sup(cause, self.param_env, xform_self_ty, self_ty) {
+                        Ok(()) => {}
                         Err(err) => {
                             debug!("--> cannot relate self-types {:?}", err);
                             return ProbeResult::NoMatch;
@@ -1665,6 +1657,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
     /// Similarly to `probe_for_return_type`, this method attempts to find the best matching
     /// candidate method where the method name may have been misspelled. Similarly to other
     /// edit distance based suggestions, we provide at most one such suggestion.
+    #[instrument(level = "debug", skip(self))]
     pub(crate) fn probe_for_similar_candidate(
         &mut self,
     ) -> Result<Option<ty::AssocItem>, MethodError<'tcx>> {
diff --git a/compiler/rustc_middle/src/traits/query.rs b/compiler/rustc_middle/src/traits/query.rs
index 50b6c77e1b2..4fad721ce98 100644
--- a/compiler/rustc_middle/src/traits/query.rs
+++ b/compiler/rustc_middle/src/traits/query.rs
@@ -156,7 +156,7 @@ pub struct CandidateStep<'tcx> {
 
 #[derive(Copy, Clone, Debug, HashStable)]
 pub struct MethodAutoderefStepsResult<'tcx> {
-    /// The valid autoderef steps that could be find.
+    /// The valid autoderef steps that could be found.
     pub steps: &'tcx [CandidateStep<'tcx>],
     /// If Some(T), a type autoderef reported an error on.
     pub opt_bad_ty: Option<&'tcx MethodAutoderefBadTy<'tcx>>,
diff --git a/tests/ui/impl-trait/method-resolution.current.stderr b/tests/ui/impl-trait/method-resolution.current.stderr
deleted file mode 100644
index 6d10693c893..00000000000
--- a/tests/ui/impl-trait/method-resolution.current.stderr
+++ /dev/null
@@ -1,36 +0,0 @@
-error[E0599]: no method named `bar` found for struct `Bar<impl Sized>` in the current scope
-  --> $DIR/method-resolution.rs:23:11
-   |
-LL | struct Bar<T>(T);
-   | ------------- method `bar` not found for this struct
-...
-LL |         x.bar();
-   |           ^^^ method not found in `Bar<impl Sized>`
-   |
-   = note: the method was found for
-           - `Bar<u32>`
-
-error[E0391]: cycle detected when computing type of opaque `foo::{opaque#0}`
-  --> $DIR/method-resolution.rs:19:24
-   |
-LL | fn foo(x: bool) -> Bar<impl Sized> {
-   |                        ^^^^^^^^^^
-   |
-note: ...which requires type-checking `foo`...
-  --> $DIR/method-resolution.rs:23:9
-   |
-LL |         x.bar();
-   |         ^
-   = note: ...which requires evaluating trait selection obligation `Bar<foo::{opaque#0}>: core::marker::Unpin`...
-   = note: ...which again requires computing type of opaque `foo::{opaque#0}`, completing the cycle
-note: cycle used when computing type of `foo::{opaque#0}`
-  --> $DIR/method-resolution.rs:19:24
-   |
-LL | fn foo(x: bool) -> Bar<impl Sized> {
-   |                        ^^^^^^^^^^
-   = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
-
-error: aborting due to 2 previous errors
-
-Some errors have detailed explanations: E0391, E0599.
-For more information about an error, try `rustc --explain E0391`.
diff --git a/tests/ui/impl-trait/method-resolution.rs b/tests/ui/impl-trait/method-resolution.rs
index 07618aa6408..60fbacd8646 100644
--- a/tests/ui/impl-trait/method-resolution.rs
+++ b/tests/ui/impl-trait/method-resolution.rs
@@ -1,10 +1,9 @@
-//! Check that we do not constrain hidden types during method resolution.
-//! Otherwise we'd pick up that calling `bar` can be satisfied iff `u32`
-//! is the hidden type of the RPIT.
+//! Since there is only one possible `bar` method, we invoke it and subsequently
+//! constrain `foo`'s RPIT to `u32`.
 
 //@ revisions: current next
 //@[next] compile-flags: -Znext-solver
-//@[next] check-pass
+//@ check-pass
 
 trait Trait {}
 
@@ -17,11 +16,9 @@ impl Bar<u32> {
 }
 
 fn foo(x: bool) -> Bar<impl Sized> {
-    //[current]~^ ERROR: cycle detected
     if x {
         let x = foo(false);
         x.bar();
-        //[current]~^ ERROR: no method named `bar` found
     }
     todo!()
 }
diff --git a/tests/ui/impl-trait/method-resolution2.rs b/tests/ui/impl-trait/method-resolution2.rs
index 2930b42b8bc..88d4f3d9896 100644
--- a/tests/ui/impl-trait/method-resolution2.rs
+++ b/tests/ui/impl-trait/method-resolution2.rs
@@ -1,5 +1,5 @@
 //! Check that the method call does not constrain the RPIT to `i32`, even though
-//! `i32` is the only trait that satisfies the RPIT's trait bounds.
+//! `i32` is the only type that satisfies the RPIT's trait bounds.
 
 //@ revisions: current next
 //@[next] compile-flags: -Znext-solver
diff --git a/tests/ui/impl-trait/method-resolution3.current.stderr b/tests/ui/impl-trait/method-resolution3.current.stderr
index 7407b489e32..87dd862ef8f 100644
--- a/tests/ui/impl-trait/method-resolution3.current.stderr
+++ b/tests/ui/impl-trait/method-resolution3.current.stderr
@@ -1,37 +1,20 @@
-error[E0599]: no method named `bar` found for struct `Bar<impl Sized>` in the current scope
-  --> $DIR/method-resolution3.rs:22:11
-   |
-LL | struct Bar<T>(T);
-   | ------------- method `bar` not found for this struct
-...
-LL |         x.bar();
-   |           ^^^ method not found in `Bar<impl Sized>`
-   |
-   = note: the method was found for
-           - `Bar<i32>`
-           - `Bar<u32>`
-
-error[E0391]: cycle detected when computing type of opaque `foo::{opaque#0}`
-  --> $DIR/method-resolution3.rs:18:24
-   |
-LL | fn foo(x: bool) -> Bar<impl Sized> {
-   |                        ^^^^^^^^^^
-   |
-note: ...which requires type-checking `foo`...
-  --> $DIR/method-resolution3.rs:22:9
+error[E0034]: multiple applicable items in scope
+  --> $DIR/method-resolution3.rs:21:11
    |
 LL |         x.bar();
-   |         ^
-   = note: ...which requires evaluating trait selection obligation `Bar<foo::{opaque#0}>: core::marker::Unpin`...
-   = note: ...which again requires computing type of opaque `foo::{opaque#0}`, completing the cycle
-note: cycle used when computing type of `foo::{opaque#0}`
-  --> $DIR/method-resolution3.rs:18:24
+   |           ^^^ multiple `bar` found
    |
-LL | fn foo(x: bool) -> Bar<impl Sized> {
-   |                        ^^^^^^^^^^
-   = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
+note: candidate #1 is defined in an impl for the type `Bar<i32>`
+  --> $DIR/method-resolution3.rs:15:5
+   |
+LL |     fn bar(self) {}
+   |     ^^^^^^^^^^^^
+note: candidate #2 is defined in an impl for the type `Bar<u32>`
+  --> $DIR/method-resolution3.rs:11:5
+   |
+LL |     fn bar(self) {}
+   |     ^^^^^^^^^^^^
 
-error: aborting due to 2 previous errors
+error: aborting due to 1 previous error
 
-Some errors have detailed explanations: E0391, E0599.
-For more information about an error, try `rustc --explain E0391`.
+For more information about this error, try `rustc --explain E0034`.
diff --git a/tests/ui/impl-trait/method-resolution3.next.stderr b/tests/ui/impl-trait/method-resolution3.next.stderr
index 53b77c620ba..87dd862ef8f 100644
--- a/tests/ui/impl-trait/method-resolution3.next.stderr
+++ b/tests/ui/impl-trait/method-resolution3.next.stderr
@@ -1,5 +1,5 @@
 error[E0034]: multiple applicable items in scope
-  --> $DIR/method-resolution3.rs:22:11
+  --> $DIR/method-resolution3.rs:21:11
    |
 LL |         x.bar();
    |           ^^^ multiple `bar` found
diff --git a/tests/ui/impl-trait/method-resolution3.rs b/tests/ui/impl-trait/method-resolution3.rs
index 8474e2da7db..8c47ef4fc75 100644
--- a/tests/ui/impl-trait/method-resolution3.rs
+++ b/tests/ui/impl-trait/method-resolution3.rs
@@ -16,12 +16,10 @@ impl Bar<i32> {
 }
 
 fn foo(x: bool) -> Bar<impl Sized> {
-    //[current]~^ ERROR: cycle
     if x {
         let x = foo(false);
         x.bar();
-        //[current]~^ ERROR: no method named `bar`
-        //[next]~^^ ERROR: multiple applicable items in scope
+        //~^ ERROR: multiple applicable items in scope
     }
     todo!()
 }
diff --git a/tests/ui/impl-trait/method-resolution4.rs b/tests/ui/impl-trait/method-resolution4.rs
index 3578db7cb55..91884eb59fd 100644
--- a/tests/ui/impl-trait/method-resolution4.rs
+++ b/tests/ui/impl-trait/method-resolution4.rs
@@ -4,9 +4,9 @@
 //! variable, but get a type mismatch when comparing `&mut _` with
 //! `std::iter::Empty`.
 
-//@[current] check-pass
 //@ revisions: current next
 //@[next] compile-flags: -Znext-solver
+//@[current] check-pass
 
 fn foo(b: bool) -> impl Iterator<Item = ()> {
     if b {
diff --git a/tests/ui/methods/opaque_param_in_ufc.rs b/tests/ui/methods/opaque_param_in_ufc.rs
index a4b27a0131f..b170e6805f6 100644
--- a/tests/ui/methods/opaque_param_in_ufc.rs
+++ b/tests/ui/methods/opaque_param_in_ufc.rs
@@ -1,4 +1,7 @@
 #![feature(type_alias_impl_trait)]
+
+//@ check-pass
+
 struct Foo<T>(T);
 
 impl Foo<u32> {
@@ -15,14 +18,11 @@ fn bar() -> Bar {
 impl Foo<Bar> {
     fn foo() -> Bar {
         Self::method();
-        //~^ ERROR: no function or associated item named `method` found for struct `Foo<Bar>`
         Foo::<Bar>::method();
-        //~^ ERROR: no function or associated item named `method` found for struct `Foo<Bar>`
         let x = Foo(bar());
         Foo::method2(x);
         let x = Self(bar());
         Self::method2(x);
-        //~^ ERROR: no function or associated item named `method2` found for struct `Foo<Bar>`
         todo!()
     }
 }
diff --git a/tests/ui/methods/opaque_param_in_ufc.stderr b/tests/ui/methods/opaque_param_in_ufc.stderr
deleted file mode 100644
index 7e5bbbac8a9..00000000000
--- a/tests/ui/methods/opaque_param_in_ufc.stderr
+++ /dev/null
@@ -1,36 +0,0 @@
-error[E0599]: no function or associated item named `method` found for struct `Foo<Bar>` in the current scope
-  --> $DIR/opaque_param_in_ufc.rs:17:15
-   |
-LL | struct Foo<T>(T);
-   | ------------- function or associated item `method` not found for this struct
-...
-LL |         Self::method();
-   |               ^^^^^^ function or associated item not found in `Foo<Bar>`
-   |
-   = note: the function or associated item was found for
-           - `Foo<u32>`
-
-error[E0599]: no function or associated item named `method` found for struct `Foo<Bar>` in the current scope
-  --> $DIR/opaque_param_in_ufc.rs:19:21
-   |
-LL | struct Foo<T>(T);
-   | ------------- function or associated item `method` not found for this struct
-...
-LL |         Foo::<Bar>::method();
-   |                     ^^^^^^ function or associated item not found in `Foo<Bar>`
-   |
-   = note: the function or associated item was found for
-           - `Foo<u32>`
-
-error[E0599]: no function or associated item named `method2` found for struct `Foo<Bar>` in the current scope
-  --> $DIR/opaque_param_in_ufc.rs:24:15
-   |
-LL | struct Foo<T>(T);
-   | ------------- function or associated item `method2` not found for this struct
-...
-LL |         Self::method2(x);
-   |               ^^^^^^^ function or associated item not found in `Foo<Bar>`
-
-error: aborting due to 3 previous errors
-
-For more information about this error, try `rustc --explain E0599`.
diff --git a/tests/ui/type-alias-impl-trait/method_resolution2.current.stderr b/tests/ui/type-alias-impl-trait/method_resolution2.current.stderr
deleted file mode 100644
index e68ea70a8ef..00000000000
--- a/tests/ui/type-alias-impl-trait/method_resolution2.current.stderr
+++ /dev/null
@@ -1,36 +0,0 @@
-error[E0599]: no method named `foo` found for struct `Bar<Foo>` in the current scope
-  --> $DIR/method_resolution2.rs:17:14
-   |
-LL | struct Bar<T>(T);
-   | ------------- method `foo` not found for this struct
-...
-LL |         self.foo()
-   |              ^^^ method not found in `Bar<Foo>`
-   |
-   = note: the method was found for
-           - `Bar<u32>`
-
-error[E0391]: cycle detected when computing type of opaque `Foo::{opaque#0}`
-  --> $DIR/method_resolution2.rs:10:12
-   |
-LL | type Foo = impl Sized;
-   |            ^^^^^^^^^^
-   |
-note: ...which requires type-checking `<impl at $DIR/method_resolution2.rs:15:1: 15:14>::bar`...
-  --> $DIR/method_resolution2.rs:17:9
-   |
-LL |         self.foo()
-   |         ^^^^
-   = note: ...which requires evaluating trait selection obligation `Bar<Foo>: core::marker::Unpin`...
-   = note: ...which again requires computing type of opaque `Foo::{opaque#0}`, completing the cycle
-note: cycle used when computing type of `Foo::{opaque#0}`
-  --> $DIR/method_resolution2.rs:10:12
-   |
-LL | type Foo = impl Sized;
-   |            ^^^^^^^^^^
-   = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
-
-error: aborting due to 2 previous errors
-
-Some errors have detailed explanations: E0391, E0599.
-For more information about an error, try `rustc --explain E0391`.
diff --git a/tests/ui/type-alias-impl-trait/method_resolution2.rs b/tests/ui/type-alias-impl-trait/method_resolution2.rs
index d252f8640d4..f69661db799 100644
--- a/tests/ui/type-alias-impl-trait/method_resolution2.rs
+++ b/tests/ui/type-alias-impl-trait/method_resolution2.rs
@@ -1,21 +1,19 @@
-//! Check that we do not unify `Bar<Foo>` with `Bar<u32>`, even though the
+//! Check that we do unify `Bar<Foo>` with `Bar<u32>`, as the
 //! `foo` method call can be resolved unambiguously by doing so.
 
 //@ revisions: current next
 //@[next] compile-flags: -Znext-solver
-//@[next] check-pass
+//@ check-pass
 
 #![feature(type_alias_impl_trait)]
 
 type Foo = impl Sized;
-//[current]~^ ERROR: cycle
 
 struct Bar<T>(T);
 
 impl Bar<Foo> {
     fn bar(self) {
         self.foo()
-        //[current]~^ ERROR: no method named `foo`
     }
 }
 
diff --git a/tests/ui/type-alias-impl-trait/method_resolution5.current.stderr b/tests/ui/type-alias-impl-trait/method_resolution5.current.stderr
deleted file mode 100644
index 193e6e14709..00000000000
--- a/tests/ui/type-alias-impl-trait/method_resolution5.current.stderr
+++ /dev/null
@@ -1,15 +0,0 @@
-error[E0599]: no method named `bar` found for struct `Bar<u32>` in the current scope
-  --> $DIR/method_resolution5.rs:25:14
-   |
-LL | struct Bar<T>(T);
-   | ------------- method `bar` not found for this struct
-...
-LL |         self.bar()
-   |              ^^^ method not found in `Bar<u32>`
-   |
-   = note: the method was found for
-           - `Bar<Foo>`
-
-error: aborting due to 1 previous error
-
-For more information about this error, try `rustc --explain E0599`.
diff --git a/tests/ui/type-alias-impl-trait/method_resolution5.rs b/tests/ui/type-alias-impl-trait/method_resolution5.rs
index 69335c9dede..64355e4560d 100644
--- a/tests/ui/type-alias-impl-trait/method_resolution5.rs
+++ b/tests/ui/type-alias-impl-trait/method_resolution5.rs
@@ -3,7 +3,7 @@
 
 //@ revisions: current next
 //@[next] compile-flags: -Znext-solver
-//@[next] check-pass
+//@ check-pass
 
 #![feature(type_alias_impl_trait)]
 
@@ -23,7 +23,6 @@ impl Bar<u32> {
         Foo:,
     {
         self.bar()
-        //[current]~^ ERROR: no method named `bar`
     }
 }
 

From 9bff23005dc8cfca8fab4e5edaaf7d910b6c10f3 Mon Sep 17 00:00:00 2001
From: Guillaume Gomez <guillaume.gomez@huawei.com>
Date: Tue, 11 Jun 2024 14:05:30 +0200
Subject: [PATCH 09/13] Allow to bless diff tests

---
 src/tools/run-make-support/src/diff/mod.rs | 14 +++++++++++++-
 1 file changed, 13 insertions(+), 1 deletion(-)

diff --git a/src/tools/run-make-support/src/diff/mod.rs b/src/tools/run-make-support/src/diff/mod.rs
index 105cdbc7b32..d0be57ca9d7 100644
--- a/src/tools/run-make-support/src/diff/mod.rs
+++ b/src/tools/run-make-support/src/diff/mod.rs
@@ -1,6 +1,6 @@
 use regex::Regex;
 use similar::TextDiff;
-use std::path::Path;
+use std::path::{Path, PathBuf};
 
 use crate::drop_bomb::DropBomb;
 
@@ -17,6 +17,7 @@ pub fn diff() -> Diff {
 pub struct Diff {
     expected: Option<String>,
     expected_name: Option<String>,
+    expected_file: Option<PathBuf>,
     actual: Option<String>,
     actual_name: Option<String>,
     normalizers: Vec<(String, String)>,
@@ -30,6 +31,7 @@ impl Diff {
         Self {
             expected: None,
             expected_name: None,
+            expected_file: None,
             actual: None,
             actual_name: None,
             normalizers: Vec::new(),
@@ -43,6 +45,7 @@ impl Diff {
         let content = std::fs::read_to_string(path).expect("failed to read file");
         let name = path.to_string_lossy().to_string();
 
+        self.expected_file = Some(path.into());
         self.expected = Some(content);
         self.expected_name = Some(name);
         self
@@ -104,6 +107,15 @@ impl Diff {
             .to_string();
 
         if !output.is_empty() {
+            // If we can bless (meaning we have a file to write into and the `RUSTC_BLESS_TEST`
+            // environment variable set), then we write into the file and return.
+            if let Some(ref expected_file) = self.expected_file {
+                if std::env::var("RUSTC_BLESS_TEST").is_ok() {
+                    println!("Blessing `{}`", expected_file.display());
+                    std::fs::write(expected_file, actual).unwrap();
+                    return;
+                }
+            }
             panic!(
                 "test failed: `{}` is different from `{}`\n\n{}",
                 expected_name, actual_name, output

From be7b587cd13af17bd23dd8e38182c454df23e278 Mon Sep 17 00:00:00 2001
From: Guillaume Gomez <guillaume.gomez@huawei.com>
Date: Tue, 11 Jun 2024 14:05:55 +0200
Subject: [PATCH 10/13] Migrate `run-make/const_fn_mir` to `rmake.rs`

---
 src/tools/tidy/src/allowed_run_make_makefiles.txt | 1 -
 tests/run-make/const_fn_mir/Makefile              | 6 ------
 tests/run-make/const_fn_mir/rmake.rs              | 8 ++++++++
 3 files changed, 8 insertions(+), 7 deletions(-)
 delete mode 100644 tests/run-make/const_fn_mir/Makefile
 create mode 100644 tests/run-make/const_fn_mir/rmake.rs

diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt
index 37da5d9c88d..14d7bfe9ad4 100644
--- a/src/tools/tidy/src/allowed_run_make_makefiles.txt
+++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt
@@ -18,7 +18,6 @@ run-make/compiler-lookup-paths-2/Makefile
 run-make/compiler-lookup-paths/Makefile
 run-make/compiler-rt-works-on-mingw/Makefile
 run-make/compressed-debuginfo/Makefile
-run-make/const_fn_mir/Makefile
 run-make/crate-hash-rustc-version/Makefile
 run-make/crate-name-priority/Makefile
 run-make/cross-lang-lto-clang/Makefile
diff --git a/tests/run-make/const_fn_mir/Makefile b/tests/run-make/const_fn_mir/Makefile
deleted file mode 100644
index 3399446130d..00000000000
--- a/tests/run-make/const_fn_mir/Makefile
+++ /dev/null
@@ -1,6 +0,0 @@
-# needs-unwind -Cpanic=abort gives different MIR output
-include ../tools.mk
-
-all:
-	$(RUSTC) main.rs --emit=mir -o "$(TMPDIR)"/dump.mir
-	$(RUSTC_TEST_OP) "$(TMPDIR)"/dump.mir dump.mir
diff --git a/tests/run-make/const_fn_mir/rmake.rs b/tests/run-make/const_fn_mir/rmake.rs
new file mode 100644
index 00000000000..a4cc4299b1b
--- /dev/null
+++ b/tests/run-make/const_fn_mir/rmake.rs
@@ -0,0 +1,8 @@
+// The `needs-unwind -Cpanic=abort` gives a different MIR output.
+
+use run_make_support::{cwd, diff, rustc};
+
+fn main() {
+    rustc().input("main.rs").emit("mir").output("dump-actual.mir").run();
+    diff().expected_file("dump.mir").actual_file("dump-actual.mir").run();
+}

From 5f4111f781abcd8faca117e18e25c633f9effdcc Mon Sep 17 00:00:00 2001
From: Guillaume Gomez <guillaume.gomez@huawei.com>
Date: Thu, 13 Jun 2024 11:39:45 +0200
Subject: [PATCH 11/13] Update run-make-support/diff to new `fs_wrapper` API

---
 src/tools/run-make-support/src/diff/mod.rs | 10 ++++------
 1 file changed, 4 insertions(+), 6 deletions(-)

diff --git a/src/tools/run-make-support/src/diff/mod.rs b/src/tools/run-make-support/src/diff/mod.rs
index d0be57ca9d7..3e0bdc1c6f6 100644
--- a/src/tools/run-make-support/src/diff/mod.rs
+++ b/src/tools/run-make-support/src/diff/mod.rs
@@ -3,6 +3,7 @@ use similar::TextDiff;
 use std::path::{Path, PathBuf};
 
 use crate::drop_bomb::DropBomb;
+use crate::fs_wrapper;
 
 #[cfg(test)]
 mod tests;
@@ -42,7 +43,7 @@ impl Diff {
     /// Specify the expected output for the diff from a file.
     pub fn expected_file<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
         let path = path.as_ref();
-        let content = std::fs::read_to_string(path).expect("failed to read file");
+        let content = fs_wrapper::read_to_string(path);
         let name = path.to_string_lossy().to_string();
 
         self.expected_file = Some(path.into());
@@ -61,10 +62,7 @@ impl Diff {
     /// Specify the actual output for the diff from a file.
     pub fn actual_file<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
         let path = path.as_ref();
-        let content = match std::fs::read_to_string(path) {
-            Ok(c) => c,
-            Err(e) => panic!("failed to read `{}`: {:?}", path.display(), e),
-        };
+        let content = fs_wrapper::read_to_string(path);
         let name = path.to_string_lossy().to_string();
 
         self.actual = Some(content);
@@ -112,7 +110,7 @@ impl Diff {
             if let Some(ref expected_file) = self.expected_file {
                 if std::env::var("RUSTC_BLESS_TEST").is_ok() {
                     println!("Blessing `{}`", expected_file.display());
-                    std::fs::write(expected_file, actual).unwrap();
+                    fs_wrapper::write(expected_file, actual);
                     return;
                 }
             }

From 14014abf06712412b4e700b74c570148ac63de27 Mon Sep 17 00:00:00 2001
From: Erick Tryzelaar <etryzelaar@google.com>
Date: Mon, 10 Jun 2024 18:32:31 +0000
Subject: [PATCH 12/13] Update fuchsia commit, and SDK to 21.20240610.2.1

This includes a fix to the race when publishing multiple packages at the
same time.
---
 .../x86_64-gnu-integration/Dockerfile         | 28 +++++++++----------
 .../x86_64-gnu-integration/build-fuchsia.sh   |  2 +-
 .../docker/scripts/build-fuchsia-toolchain.sh |  8 +++---
 src/ci/docker/scripts/fuchsia-test-runner.py  |  2 +-
 4 files changed, 20 insertions(+), 20 deletions(-)

diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-integration/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-integration/Dockerfile
index d228dfc87eb..a944f370c6b 100644
--- a/src/ci/docker/host-x86_64/x86_64-gnu-integration/Dockerfile
+++ b/src/ci/docker/host-x86_64/x86_64-gnu-integration/Dockerfile
@@ -26,27 +26,27 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
 # Duplicated in dist-various-2 Dockerfile.
 # FIXME: Move to canonical triple
 ENV \
-    AR_x86_64_fuchsia=x86_64-unknown-fuchsia-ar \
-    CC_x86_64_fuchsia=x86_64-unknown-fuchsia-clang \
-    CFLAGS_x86_64_fuchsia="--target=x86_64-unknown-fuchsia --sysroot=/usr/local/core-linux-amd64-fuchsia-sdk/arch/x64/sysroot -I/usr/local/core-linux-amd64-fuchsia-sdk/pkg/fdio/include" \
-    CXX_x86_64_fuchsia=x86_64-unknown-fuchsia-clang++ \
-    CXXFLAGS_x86_64_fuchsia="--target=x86_64-unknown-fuchsia --sysroot=/usr/local/core-linux-amd64-fuchsia-sdk/arch/x64/sysroot -I/usr/local/core-linux-amd64-fuchsia-sdk/pkg/fdio/include" \
-    LDFLAGS_x86_64_fuchsia="--target=x86_64-unknown-fuchsia --sysroot=/usr/local/core-linux-amd64-fuchsia-sdk/arch/x64/sysroot -L/usr/local/core-linux-amd64-fuchsia-sdk/arch/x64/lib"
+    AR_x86_64_unknown_fuchsia=x86_64-unknown-fuchsia-ar \
+    CC_x86_64_unknown_fuchsia=x86_64-unknown-fuchsia-clang \
+    CFLAGS_x86_64_unknown_fuchsia="--target=x86_64-unknown-fuchsia --sysroot=/usr/local/core-linux-amd64-fuchsia-sdk/arch/x64/sysroot -I/usr/local/core-linux-amd64-fuchsia-sdk/pkg/fdio/include" \
+    CXX_x86_64_unknown_fuchsia=x86_64-unknown-fuchsia-clang++ \
+    CXXFLAGS_x86_64_unknown_fuchsia="--target=x86_64-unknown-fuchsia --sysroot=/usr/local/core-linux-amd64-fuchsia-sdk/arch/x64/sysroot -I/usr/local/core-linux-amd64-fuchsia-sdk/pkg/fdio/include" \
+    LDFLAGS_x86_64_unknown_fuchsia="--target=x86_64-unknown-fuchsia --sysroot=/usr/local/core-linux-amd64-fuchsia-sdk/arch/x64/sysroot -L/usr/local/core-linux-amd64-fuchsia-sdk/arch/x64/lib"
 
 WORKDIR /tmp
 COPY scripts/shared.sh /tmp/
 COPY scripts/build-fuchsia-toolchain.sh /tmp/
 RUN /tmp/build-fuchsia-toolchain.sh
 
-ENV CARGO_TARGET_X86_64_FUCHSIA_AR /usr/local/bin/llvm-ar
-ENV CARGO_TARGET_X86_64_FUCHSIA_RUSTFLAGS \
+ENV CARGO_TARGET_X86_64_UNKNOWN_FUCHSIA_AR /usr/local/bin/llvm-ar
+ENV CARGO_TARGET_X86_64_UNKNOWN_FUCHSIA_RUSTFLAGS \
   -C panic=abort \
   -C force-unwind-tables=yes \
   -C link-arg=--sysroot=/usr/local/core-linux-amd64-fuchsia-sdk/arch/x64/sysroot \
   -Lnative=/usr/local/core-linux-amd64-fuchsia-sdk/arch/x64/sysroot/lib \
   -Lnative=/usr/local/core-linux-amd64-fuchsia-sdk/arch/x64/lib
 
-ENV TARGETS=x86_64-fuchsia
+ENV TARGETS=x86_64-unknown-fuchsia
 ENV TARGETS=$TARGETS,x86_64-unknown-linux-gnu
 ENV TARGETS=$TARGETS,wasm32-unknown-unknown
 
@@ -69,11 +69,11 @@ ENV RUST_CONFIGURE_ARGS \
   --llvm-libunwind=in-tree \
   --enable-extended \
   --disable-docs \
-  --set target.x86_64-fuchsia.cc=/usr/local/bin/clang \
-  --set target.x86_64-fuchsia.cxx=/usr/local/bin/clang++ \
-  --set target.x86_64-fuchsia.ar=/usr/local/bin/llvm-ar \
-  --set target.x86_64-fuchsia.ranlib=/usr/local/bin/llvm-ranlib \
-  --set target.x86_64-fuchsia.linker=/usr/local/bin/ld.lld
+  --set target.x86_64-unknown-fuchsia.cc=/usr/local/bin/clang \
+  --set target.x86_64-unknown-fuchsia.cxx=/usr/local/bin/clang++ \
+  --set target.x86_64-unknown-fuchsia.ar=/usr/local/bin/llvm-ar \
+  --set target.x86_64-unknown-fuchsia.ranlib=/usr/local/bin/llvm-ranlib \
+  --set target.x86_64-unknown-fuchsia.linker=/usr/local/bin/ld.lld
 ENV SCRIPT \
     python3 ../x.py install --target $TARGETS compiler/rustc library/std clippy && \
     bash ../src/ci/docker/host-x86_64/x86_64-gnu-integration/build-fuchsia.sh
diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-integration/build-fuchsia.sh b/src/ci/docker/host-x86_64/x86_64-gnu-integration/build-fuchsia.sh
index 913a0b0c09c..2bb1d0a6338 100755
--- a/src/ci/docker/host-x86_64/x86_64-gnu-integration/build-fuchsia.sh
+++ b/src/ci/docker/host-x86_64/x86_64-gnu-integration/build-fuchsia.sh
@@ -35,7 +35,7 @@ PICK_REFS=()
 # commit hash of fuchsia.git and some other repos in the "monorepo" checkout, in
 # addition to versions of prebuilts. It should be bumped regularly by the
 # Fuchsia team – we aim for every 1-2 months.
-INTEGRATION_SHA=1011e3298775ee7cdf6f6dc73e808d6a86e33bd6
+INTEGRATION_SHA=737ebdd83afa47b742ca8325fad0176952fcefbd
 
 checkout=fuchsia
 jiri=.jiri_root/bin/jiri
diff --git a/src/ci/docker/scripts/build-fuchsia-toolchain.sh b/src/ci/docker/scripts/build-fuchsia-toolchain.sh
index 7a0d4fcffc1..027d412d250 100755
--- a/src/ci/docker/scripts/build-fuchsia-toolchain.sh
+++ b/src/ci/docker/scripts/build-fuchsia-toolchain.sh
@@ -4,13 +4,13 @@ set -ex
 source shared.sh
 
 FUCHSIA_SDK_URL=https://chrome-infra-packages.appspot.com/dl/fuchsia/sdk/core/linux-amd64
-FUCHSIA_SDK_ID=version:20.20240412.3.1
-FUCHSIA_SDK_SHA256=cc52f3497487dd813c89d9316e6967efcea89c7759edccf3e40fcf3662e53f19
+FUCHSIA_SDK_ID=version:21.20240610.2.1
+FUCHSIA_SDK_SHA256=2d2d057fc3f0404197cced2200f88cbcdaaf5fbf6475955045091f8676791ce7
 FUCHSIA_SDK_USR_DIR=/usr/local/core-linux-amd64-fuchsia-sdk
 CLANG_DOWNLOAD_URL=\
 https://chrome-infra-packages.appspot.com/dl/fuchsia/third_party/clang/linux-amd64
-CLANG_DOWNLOAD_ID=git_revision:c777c011a709dffd4fa5e79cad7947b7c3405d02
-CLANG_DOWNLOAD_SHA256=779167422ad73c292f049dcea5569f84577af9292189ed2749518b966a4d0844
+CLANG_DOWNLOAD_ID=git_revision:3809e20afc68d7d03821f0ec59b928dcf9befbf4
+CLANG_DOWNLOAD_SHA256=3c2c442b61cd9e8f1b567738f6d53cffe11b3fc820e7dae87a82a0859be8f204
 
 install_clang() {
   mkdir -p clang_download
diff --git a/src/ci/docker/scripts/fuchsia-test-runner.py b/src/ci/docker/scripts/fuchsia-test-runner.py
index 4f504341d52..d791550a8db 100755
--- a/src/ci/docker/scripts/fuchsia-test-runner.py
+++ b/src/ci/docker/scripts/fuchsia-test-runner.py
@@ -286,7 +286,7 @@ class TestEnvironment:
         # Look up the product bundle transfer manifest.
         self.log_info("Looking up the product bundle transfer manifest...")
         product_name = "minimal." + self.triple_to_arch(self.target)
-        fuchsia_version = "20.20240412.3.1"
+        fuchsia_version = "21.20240610.2.1"
 
         out = self.check_output(
             [

From efbfcdd220a9f7ccdee235e0839e1848a554c4a5 Mon Sep 17 00:00:00 2001
From: Chris Denton <chris@chrisdenton.dev>
Date: Fri, 14 Jun 2024 00:18:21 +0000
Subject: [PATCH 13/13] Fill out missing Windows support information

---
 src/doc/rustc/src/platform-support.md | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md
index c672cff7452..e55bb3bd155 100644
--- a/src/doc/rustc/src/platform-support.md
+++ b/src/doc/rustc/src/platform-support.md
@@ -259,7 +259,7 @@ target | std | host | notes
 [`aarch64-unknown-netbsd`](platform-support/netbsd.md) | ✓ | ✓ | ARM64 NetBSD
 [`aarch64-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | ARM64 OpenBSD
 `aarch64-unknown-redox` | ? |  | ARM64 Redox OS
-`aarch64-uwp-windows-msvc` | ? |  |
+`aarch64-uwp-windows-msvc` | ✓ |  |
 `aarch64-wrs-vxworks` | ? |  |
 `aarch64_be-unknown-linux-gnu_ilp32` | ✓ | ✓ | ARM64 Linux (big-endian, ILP32 ABI)
 `aarch64_be-unknown-linux-gnu` | ✓ | ✓ | ARM64 Linux (big-endian)
@@ -300,8 +300,8 @@ target | std | host | notes
 [`i686-unknown-hurd-gnu`](platform-support/hurd.md) | ✓ | ✓ | 32-bit GNU/Hurd [^x86_32-floats-return-ABI]
 [`i686-unknown-netbsd`](platform-support/netbsd.md) | ✓ | ✓ | NetBSD/i386 with SSE2 [^x86_32-floats-return-ABI]
 [`i686-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | 32-bit OpenBSD [^x86_32-floats-return-ABI]
-`i686-uwp-windows-gnu` | ? |  | [^x86_32-floats-return-ABI]
-`i686-uwp-windows-msvc` | ? |  | [^x86_32-floats-return-ABI]
+`i686-uwp-windows-gnu` | ✓ |  | [^x86_32-floats-return-ABI]
+`i686-uwp-windows-msvc` | ✓ |  | [^x86_32-floats-return-ABI]
 [`i686-win7-windows-msvc`](platform-support/win7-windows-msvc.md) | ✓ |   | 32-bit Windows 7 support [^x86_32-floats-return-ABI]
 `i686-wrs-vxworks` | ? |  | [^x86_32-floats-return-ABI]
 [`loongarch64-unknown-linux-musl`](platform-support/loongarch-linux.md) | ? |  | LoongArch64 Linux (LP64D ABI) with musl 1.2.3
@@ -362,7 +362,7 @@ target | std | host | notes
 [`sparc64-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | OpenBSD/sparc64
 [`thumbv4t-none-eabi`](platform-support/armv4t-none-eabi.md) | * |  | Thumb-mode Bare Armv4T
 [`thumbv5te-none-eabi`](platform-support/armv5te-none-eabi.md) | * |  | Thumb-mode Bare Armv5TE
-`thumbv7a-pc-windows-msvc` | ? |  |
+`thumbv7a-pc-windows-msvc` | ✓ |  |
 `thumbv7a-uwp-windows-msvc` | ✓ |  |
 `thumbv7neon-unknown-linux-musleabihf` | ? |  | Thumb2-mode Armv7-A Linux with NEON, musl 1.2.3
 [`wasm32-wasip2`](platform-support/wasm32-wasip2.md) | ✓ |  | WebAssembly