about summary refs log tree commit diff
diff options
context:
space:
mode:
authordianqk <dianqk@dianqk.net>2025-06-30 19:23:18 +0800
committerGitHub <noreply@github.com>2025-06-30 19:23:18 +0800
commit3a35f36ae848290fbdc7b3e18555a0f94d1ce7a2 (patch)
tree0817e1f7e102356430078078e0efdcf751ce4ac7
parent0952f86de31f90b0e9f2bc700243fcc711990aa9 (diff)
parent1347b485848029278bfcb955fb579ba5ca3d4710 (diff)
downloadrust-3a35f36ae848290fbdc7b3e18555a0f94d1ce7a2.tar.gz
rust-3a35f36ae848290fbdc7b3e18555a0f94d1ce7a2.zip
Rollup merge of #143159 - compiler-errors:freshen-re-error, r=oli-obk
Do not freshen `ReError`

Because `ReError` has `ErrorGuaranteed` in it, it affects candidate selection and thus causes incompleteness which leads to weirdness in eval. See the comment in the test.

Also remove an unnecessary `lookup_op_method` since it doesn't effect tests.

Fixes rust-lang/rust#132882.

r? types
-rw-r--r--compiler/rustc_hir_typeck/src/method/suggest.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/op.rs22
-rw-r--r--compiler/rustc_infer/src/infer/freshen.rs9
-rw-r--r--tests/crashes/132882.rs13
-rw-r--r--tests/ui/traits/eval-caching-error-region.rs23
-rw-r--r--tests/ui/traits/eval-caching-error-region.stderr33
6 files changed, 64 insertions, 38 deletions
diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs
index d0a48872f75..df1ee0e79c2 100644
--- a/compiler/rustc_hir_typeck/src/method/suggest.rs
+++ b/compiler/rustc_hir_typeck/src/method/suggest.rs
@@ -3055,7 +3055,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     pub(crate) fn note_unmet_impls_on_type(
         &self,
         err: &mut Diag<'_>,
-        errors: Vec<FulfillmentError<'tcx>>,
+        errors: &[FulfillmentError<'tcx>],
         suggest_derive: bool,
     ) {
         let preds: Vec<_> = errors
diff --git a/compiler/rustc_hir_typeck/src/op.rs b/compiler/rustc_hir_typeck/src/op.rs
index b9d24506986..87a7cd62ae5 100644
--- a/compiler/rustc_hir_typeck/src/op.rs
+++ b/compiler/rustc_hir_typeck/src/op.rs
@@ -322,7 +322,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             lhs_expr.span,
                             format!("cannot use `{}` on type `{}`", s, lhs_ty_str),
                         );
-                        self.note_unmet_impls_on_type(&mut err, errors, false);
+                        self.note_unmet_impls_on_type(&mut err, &errors, false);
                         (err, None)
                     }
                     Op::BinOp(bin_op) => {
@@ -382,7 +382,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             err.span_label(rhs_expr.span, rhs_ty_str);
                         }
                         let suggest_derive = self.can_eq(self.param_env, lhs_ty, rhs_ty);
-                        self.note_unmet_impls_on_type(&mut err, errors, suggest_derive);
+                        self.note_unmet_impls_on_type(&mut err, &errors, suggest_derive);
                         (err, output_def_id)
                     }
                 };
@@ -582,22 +582,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         // concatenation (e.g., "Hello " + "World!"). This means
                         // we don't want the note in the else clause to be emitted
                     } else if lhs_ty.has_non_region_param() {
-                        // Look for a TraitPredicate in the Fulfillment errors,
-                        // and use it to generate a suggestion.
-                        //
-                        // Note that lookup_op_method must be called again but
-                        // with a specific rhs_ty instead of a placeholder so
-                        // the resulting predicate generates a more specific
-                        // suggestion for the user.
-                        let errors = self
-                            .lookup_op_method(
-                                (lhs_expr, lhs_ty),
-                                Some((rhs_expr, rhs_ty)),
-                                lang_item_for_binop(self.tcx, op),
-                                op.span(),
-                                expected,
-                            )
-                            .unwrap_err();
                         if !errors.is_empty() {
                             for error in errors {
                                 if let Some(trait_pred) =
@@ -946,7 +930,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             ty::Str | ty::Never | ty::Char | ty::Tuple(_) | ty::Array(_, _) => {}
                             ty::Ref(_, lty, _) if *lty.kind() == ty::Str => {}
                             _ => {
-                                self.note_unmet_impls_on_type(&mut err, errors, true);
+                                self.note_unmet_impls_on_type(&mut err, &errors, true);
                             }
                         }
                     }
diff --git a/compiler/rustc_infer/src/infer/freshen.rs b/compiler/rustc_infer/src/infer/freshen.rs
index cae674165f0..ddc0b116806 100644
--- a/compiler/rustc_infer/src/infer/freshen.rs
+++ b/compiler/rustc_infer/src/infer/freshen.rs
@@ -110,17 +110,16 @@ impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for TypeFreshener<'a, 'tcx> {
 
     fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
         match r.kind() {
-            ty::ReBound(..) => {
-                // leave bound regions alone
-                r
-            }
+            // Leave bound regions alone, since they affect selection via the leak check.
+            ty::ReBound(..) => r,
+            // Leave error regions alone, since they affect selection b/c of incompleteness.
+            ty::ReError(_) => r,
 
             ty::ReEarlyParam(..)
             | ty::ReLateParam(_)
             | ty::ReVar(_)
             | ty::RePlaceholder(..)
             | ty::ReStatic
-            | ty::ReError(_)
             | ty::ReErased => self.cx().lifetimes.re_erased,
         }
     }
diff --git a/tests/crashes/132882.rs b/tests/crashes/132882.rs
deleted file mode 100644
index 6b5e4dba803..00000000000
--- a/tests/crashes/132882.rs
+++ /dev/null
@@ -1,13 +0,0 @@
-//@ known-bug: #132882
-
-use std::ops::Add;
-
-pub trait Numoid
-where
-    for<N: Numoid> &'a Self: Add<Self>,
-{
-}
-
-pub fn compute<N: Numoid>(a: N) -> N {
-    &a + a
-}
diff --git a/tests/ui/traits/eval-caching-error-region.rs b/tests/ui/traits/eval-caching-error-region.rs
new file mode 100644
index 00000000000..831b5ab80c1
--- /dev/null
+++ b/tests/ui/traits/eval-caching-error-region.rs
@@ -0,0 +1,23 @@
+// Regression test for #132882.
+
+use std::ops::Add;
+
+pub trait Numoid: Sized
+where
+    &'missing Self: Add<Self>,
+    //~^ ERROR use of undeclared lifetime name `'missing`
+{
+}
+
+// Proving `N: Numoid`'s well-formedness causes us to have to prove `&'missing N: Add<N>`.
+// Since `'missing` is a region error, that will lead to us consider the predicate to hold,
+// since it references errors. Since the freshener turns error regions into fresh regions,
+// this means that subsequent lookups of `&'?0 N: Add<N>` will also hit this cache entry
+// even if candidate assembly can't assemble anything for `&'?0 N: Add<?1>` anyways. This
+// led to an ICE.
+pub fn compute<N: Numoid>(a: N) {
+    let _ = &a + a;
+    //~^ ERROR cannot add `N` to `&N`
+}
+
+fn main() {}
diff --git a/tests/ui/traits/eval-caching-error-region.stderr b/tests/ui/traits/eval-caching-error-region.stderr
new file mode 100644
index 00000000000..6365d242d2e
--- /dev/null
+++ b/tests/ui/traits/eval-caching-error-region.stderr
@@ -0,0 +1,33 @@
+error[E0261]: use of undeclared lifetime name `'missing`
+  --> $DIR/eval-caching-error-region.rs:7:6
+   |
+LL |     &'missing Self: Add<Self>,
+   |      ^^^^^^^^ 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 `'missing` lifetime
+   |
+LL |     for<'missing> &'missing Self: Add<Self>,
+   |     +++++++++++++
+help: consider introducing lifetime `'missing` here
+   |
+LL | pub trait Numoid<'missing>: Sized
+   |                 ++++++++++
+
+error[E0369]: cannot add `N` to `&N`
+  --> $DIR/eval-caching-error-region.rs:19:16
+   |
+LL |     let _ = &a + a;
+   |             -- ^ - N
+   |             |
+   |             &N
+   |
+help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
+   |
+LL | pub fn compute<N: Numoid>(a: N) where &N: Add<N> {
+   |                                 ++++++++++++++++
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0261, E0369.
+For more information about an error, try `rustc --explain E0261`.