about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJubilee <workingjubilee@gmail.com>2025-01-14 19:56:30 -0800
committerGitHub <noreply@github.com>2025-01-14 19:56:30 -0800
commitaa8bc2563eca051546bbaff9b9552e5edf5a64f1 (patch)
tree8fff712393b991e147f34eb385ba1ec1f95d4507
parent8f7e62268ab7408c54ee5205c975e40bd8d2cc3b (diff)
parent5775190dbacd8334e6b146180c9268a33be15a25 (diff)
downloadrust-aa8bc2563eca051546bbaff9b9552e5edf5a64f1.tar.gz
rust-aa8bc2563eca051546bbaff9b9552e5edf5a64f1.zip
Rollup merge of #134940 - compiler-errors:scrape, r=lcnr
Make sure to scrape region constraints from deeply normalizing type outlives assumptions in borrowck

Otherwise we're just randomly registering these region relations into the infcx which isn't good

r? lcnr
-rw-r--r--compiler/rustc_borrowck/src/type_check/free_region_relations.rs67
-rw-r--r--tests/ui/traits/next-solver/known-type-outlives-has-constraints.rs13
2 files changed, 61 insertions, 19 deletions
diff --git a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs
index ea965eb6545..edf612f4e97 100644
--- a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs
+++ b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs
@@ -5,13 +5,14 @@ use rustc_infer::infer::canonical::QueryRegionConstraints;
 use rustc_infer::infer::outlives::env::RegionBoundPairs;
 use rustc_infer::infer::region_constraints::GenericKind;
 use rustc_infer::infer::{InferCtxt, outlives};
+use rustc_infer::traits::ScrubbedTraitError;
 use rustc_middle::mir::ConstraintCategory;
 use rustc_middle::traits::ObligationCause;
 use rustc_middle::traits::query::OutlivesBound;
 use rustc_middle::ty::{self, RegionVid, Ty, TypeVisitableExt};
 use rustc_span::{ErrorGuaranteed, Span};
-use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
-use rustc_trait_selection::solve::deeply_normalize;
+use rustc_trait_selection::solve::NoSolution;
+use rustc_trait_selection::traits::query::type_op::custom::CustomTypeOp;
 use rustc_trait_selection::traits::query::type_op::{self, TypeOp};
 use tracing::{debug, instrument};
 use type_op::TypeOpOutput;
@@ -229,24 +230,14 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
         let mut constraints = vec![];
         let mut known_type_outlives_obligations = vec![];
         for bound in param_env.caller_bounds() {
-            let Some(mut outlives) = bound.as_type_outlives_clause() else { continue };
-
-            // In the new solver, normalize the type-outlives obligation assumptions.
-            if self.infcx.next_trait_solver() {
-                match deeply_normalize(
-                    self.infcx.at(&ObligationCause::misc(span, defining_ty_def_id), param_env),
+            if let Some(outlives) = bound.as_type_outlives_clause() {
+                self.normalize_and_push_type_outlives_obligation(
                     outlives,
-                ) {
-                    Ok(normalized_outlives) => {
-                        outlives = normalized_outlives;
-                    }
-                    Err(e) => {
-                        self.infcx.err_ctxt().report_fulfillment_errors(e);
-                    }
-                }
-            }
-
-            known_type_outlives_obligations.push(outlives);
+                    span,
+                    &mut known_type_outlives_obligations,
+                    &mut constraints,
+                );
+            };
         }
 
         let unnormalized_input_output_tys = self
@@ -356,6 +347,44 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
         }
     }
 
+    fn normalize_and_push_type_outlives_obligation(
+        &self,
+        mut outlives: ty::PolyTypeOutlivesPredicate<'tcx>,
+        span: Span,
+        known_type_outlives_obligations: &mut Vec<ty::PolyTypeOutlivesPredicate<'tcx>>,
+        constraints: &mut Vec<&QueryRegionConstraints<'tcx>>,
+    ) {
+        // In the new solver, normalize the type-outlives obligation assumptions.
+        if self.infcx.next_trait_solver() {
+            let Ok(TypeOpOutput {
+                output: normalized_outlives,
+                constraints: constraints_normalize,
+                error_info: _,
+            }) = CustomTypeOp::new(
+                |ocx| {
+                    ocx.deeply_normalize(
+                        &ObligationCause::dummy_with_span(span),
+                        self.param_env,
+                        outlives,
+                    )
+                    .map_err(|_: Vec<ScrubbedTraitError<'tcx>>| NoSolution)
+                },
+                "normalize type outlives obligation",
+            )
+            .fully_perform(self.infcx, span)
+            else {
+                self.infcx.dcx().delayed_bug(format!("could not normalize {outlives:?}"));
+                return;
+            };
+            outlives = normalized_outlives;
+            if let Some(c) = constraints_normalize {
+                constraints.push(c);
+            }
+        }
+
+        known_type_outlives_obligations.push(outlives);
+    }
+
     /// Update the type of a single local, which should represent
     /// either the return type of the MIR or one of its arguments. At
     /// the same time, compute and add any implied bounds that come
diff --git a/tests/ui/traits/next-solver/known-type-outlives-has-constraints.rs b/tests/ui/traits/next-solver/known-type-outlives-has-constraints.rs
new file mode 100644
index 00000000000..55fea005ea1
--- /dev/null
+++ b/tests/ui/traits/next-solver/known-type-outlives-has-constraints.rs
@@ -0,0 +1,13 @@
+//@ compile-flags: -Znext-solver
+//@ check-pass
+
+trait Norm {
+    type Out;
+}
+impl<'a, T: 'a> Norm for &'a T {
+    type Out = T;
+}
+
+fn hello<'a, T: 'a>() where <&'a T as Norm>::Out: 'a {}
+
+fn main() {}