about summary refs log tree commit diff
path: root/compiler/rustc_trait_selection/src/traits
diff options
context:
space:
mode:
authorMatthias Krüger <matthias.krueger@famsik.de>2023-12-19 10:50:08 +0100
committerGitHub <noreply@github.com>2023-12-19 10:50:08 +0100
commit9a72b7d04f9eb23ea0c762b749f00c6985305db4 (patch)
tree2ae8d825436401e38719e85bee7effabe52ce044 /compiler/rustc_trait_selection/src/traits
parentd1e52a8f5c4677b258df4746b77db43a144d536a (diff)
parent132a2884ad464b4faf4781de6bd8c6d255502592 (diff)
downloadrust-9a72b7d04f9eb23ea0c762b749f00c6985305db4.tar.gz
rust-9a72b7d04f9eb23ea0c762b749f00c6985305db4.zip
Rollup merge of #119091 - compiler-errors:alias-eq-in-structural-normalize, r=lcnr
Use alias-eq in structural normalization

We don't need to register repeated normalizes-to goals in a loop in structural normalize, but instead we can piggyback on the fact that alias-eq will already normalize aliases until they are rigid.

This fixes rust-lang/trait-system-refactor-initiative#78.

r? lcnr
Diffstat (limited to 'compiler/rustc_trait_selection/src/traits')
-rw-r--r--compiler/rustc_trait_selection/src/traits/structural_normalize.rs61
1 files changed, 31 insertions, 30 deletions
diff --git a/compiler/rustc_trait_selection/src/traits/structural_normalize.rs b/compiler/rustc_trait_selection/src/traits/structural_normalize.rs
index b9ab26fe2fe..e0f9fdc3827 100644
--- a/compiler/rustc_trait_selection/src/traits/structural_normalize.rs
+++ b/compiler/rustc_trait_selection/src/traits/structural_normalize.rs
@@ -3,7 +3,7 @@ use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKi
 use rustc_infer::traits::{FulfillmentError, TraitEngine};
 use rustc_middle::ty::{self, Ty};
 
-use crate::traits::{query::evaluate_obligation::InferCtxtExt, NormalizeExt, Obligation};
+use crate::traits::{NormalizeExt, Obligation};
 
 pub trait StructurallyNormalizeExt<'tcx> {
     fn structurally_normalize(
@@ -16,42 +16,43 @@ pub trait StructurallyNormalizeExt<'tcx> {
 impl<'tcx> StructurallyNormalizeExt<'tcx> for At<'_, 'tcx> {
     fn structurally_normalize(
         &self,
-        mut ty: Ty<'tcx>,
+        ty: Ty<'tcx>,
         fulfill_cx: &mut dyn TraitEngine<'tcx>,
     ) -> Result<Ty<'tcx>, Vec<FulfillmentError<'tcx>>> {
         assert!(!ty.is_ty_var(), "should have resolved vars before calling");
 
         if self.infcx.next_trait_solver() {
-            // FIXME(-Znext-solver): correctly handle
-            // overflow here.
-            for _ in 0..256 {
-                let ty::Alias(ty::Projection | ty::Inherent | ty::Weak, alias) = *ty.kind() else {
-                    break;
-                };
-
-                let new_infer_ty = self.infcx.next_ty_var(TypeVariableOrigin {
-                    kind: TypeVariableOriginKind::NormalizeProjectionType,
-                    span: self.cause.span,
-                });
-                let obligation = Obligation::new(
-                    self.infcx.tcx,
-                    self.cause.clone(),
-                    self.param_env,
-                    ty::NormalizesTo { alias, term: new_infer_ty.into() },
-                );
-                if self.infcx.predicate_may_hold(&obligation) {
-                    fulfill_cx.register_predicate_obligation(self.infcx, obligation);
-                    let errors = fulfill_cx.select_where_possible(self.infcx);
-                    if !errors.is_empty() {
-                        return Err(errors);
-                    }
-                    ty = self.infcx.resolve_vars_if_possible(new_infer_ty);
-                } else {
-                    break;
-                }
+            // FIXME(-Znext-solver): Should we resolve opaques here?
+            let ty::Alias(ty::Projection | ty::Inherent | ty::Weak, _) = *ty.kind() else {
+                return Ok(ty);
+            };
+
+            let new_infer_ty = self.infcx.next_ty_var(TypeVariableOrigin {
+                kind: TypeVariableOriginKind::NormalizeProjectionType,
+                span: self.cause.span,
+            });
+
+            // We simply emit an `alias-eq` goal here, since that will take care of
+            // normalizing the LHS of the projection until it is a rigid projection
+            // (or a not-yet-defined opaque in scope).
+            let obligation = Obligation::new(
+                self.infcx.tcx,
+                self.cause.clone(),
+                self.param_env,
+                ty::PredicateKind::AliasRelate(
+                    ty.into(),
+                    new_infer_ty.into(),
+                    ty::AliasRelationDirection::Equate,
+                ),
+            );
+
+            fulfill_cx.register_predicate_obligation(self.infcx, obligation);
+            let errors = fulfill_cx.select_where_possible(self.infcx);
+            if !errors.is_empty() {
+                return Err(errors);
             }
 
-            Ok(ty)
+            Ok(self.infcx.resolve_vars_if_possible(new_infer_ty))
         } else {
             Ok(self.normalize(ty).into_value_registering_obligations(self.infcx, fulfill_cx))
         }