about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Goulet <michael@errs.io>2024-11-27 02:37:59 +0000
committerMichael Goulet <michael@errs.io>2024-12-02 22:51:17 +0000
commitabfa5c1dca4c549f0e196a872579434ff23a24bb (patch)
tree3d4a018033f0f10eef8224b525604cf243994caa
parentd49be02cf6d2e2a01264fcdef1e20c826710c0f5 (diff)
downloadrust-abfa5c1dca4c549f0e196a872579434ff23a24bb.tar.gz
rust-abfa5c1dca4c549f0e196a872579434ff23a24bb.zip
Deeply normalize when computing implied outlives bounds
-rw-r--r--compiler/rustc_trait_selection/src/traits/normalize.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs7
-rw-r--r--tests/ui/traits/next-solver/normalize-in-implied_outlives_bounds.rs46
3 files changed, 51 insertions, 4 deletions
diff --git a/compiler/rustc_trait_selection/src/traits/normalize.rs b/compiler/rustc_trait_selection/src/traits/normalize.rs
index e99c5eacbd8..2891df3ed2d 100644
--- a/compiler/rustc_trait_selection/src/traits/normalize.rs
+++ b/compiler/rustc_trait_selection/src/traits/normalize.rs
@@ -66,7 +66,7 @@ impl<'tcx> At<'_, 'tcx> {
             let value = self
                 .normalize(value)
                 .into_value_registering_obligations(self.infcx, &mut *fulfill_cx);
-            let errors = fulfill_cx.select_where_possible(self.infcx);
+            let errors = fulfill_cx.select_all_or_error(self.infcx);
             let value = self.infcx.resolve_vars_if_possible(value);
             if errors.is_empty() { Ok(value) } else { Err(errors) }
         }
diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs
index c6e41e57f0c..224a7271472 100644
--- a/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs
@@ -59,12 +59,13 @@ pub fn compute_implied_outlives_bounds_inner<'tcx>(
     param_env: ty::ParamEnv<'tcx>,
     ty: Ty<'tcx>,
 ) -> Result<Vec<OutlivesBound<'tcx>>, NoSolution> {
-    let normalize_op = |ty| {
-        let ty = ocx.normalize(&ObligationCause::dummy(), param_env, ty);
+    let normalize_op = |ty| -> Result<_, NoSolution> {
+        let ty = ocx
+            .deeply_normalize(&ObligationCause::dummy(), param_env, ty)
+            .map_err(|_| NoSolution)?;
         if !ocx.select_all_or_error().is_empty() {
             return Err(NoSolution);
         }
-        let ty = ocx.infcx.resolve_vars_if_possible(ty);
         let ty = OpportunisticRegionResolver::new(&ocx.infcx).fold_ty(ty);
         Ok(ty)
     };
diff --git a/tests/ui/traits/next-solver/normalize-in-implied_outlives_bounds.rs b/tests/ui/traits/next-solver/normalize-in-implied_outlives_bounds.rs
new file mode 100644
index 00000000000..1dca19d28e9
--- /dev/null
+++ b/tests/ui/traits/next-solver/normalize-in-implied_outlives_bounds.rs
@@ -0,0 +1,46 @@
+//@ check-pass
+//@ compile-flags: -Znext-solver
+
+// Minimized example from `rustc_type_ir` that demonstrates a missing deep normalization
+// in the new solver when computing the implies outlives bounds of an impl.
+
+use std::marker::PhantomData;
+use std::ops::Deref;
+
+pub struct SearchGraph<D: Delegate, X = <D as Delegate>::Cx> {
+    d: PhantomData<D>,
+    x: PhantomData<X>,
+}
+
+pub trait Delegate {
+    type Cx;
+}
+
+struct SearchGraphDelegate<D: SolverDelegate> {
+    _marker: PhantomData<D>,
+}
+
+impl<D> Delegate for SearchGraphDelegate<D>
+where
+    D: SolverDelegate,
+{
+    type Cx = D::Interner;
+}
+
+pub trait SolverDelegate {
+    type Interner;
+}
+
+struct EvalCtxt<'a, D, I>
+where
+    D: SolverDelegate<Interner = I>,
+{
+    search_graph: &'a SearchGraph<SearchGraphDelegate<D>>,
+}
+
+impl<'a, D, I> EvalCtxt<'a, D, <D as SolverDelegate>::Interner>
+where
+    D: SolverDelegate<Interner = I>
+{}
+
+fn main() {}