about summary refs log tree commit diff
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
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
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/structural_normalize.rs61
-rw-r--r--tests/ui/traits/next-solver/alias-bound-unsound.rs2
-rw-r--r--tests/ui/traits/next-solver/alias-bound-unsound.stderr3
-rw-r--r--tests/ui/traits/next-solver/coerce-ambig-alias-to-rigid-alias.rs15
-rw-r--r--tests/ui/traits/next-solver/object-unsafety.rs1
-rw-r--r--tests/ui/traits/next-solver/object-unsafety.stderr16
7 files changed, 50 insertions, 50 deletions
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
index 24b577fd3c5..4bc237c2383 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
@@ -1498,7 +1498,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let ty = self.resolve_vars_with_obligations(ty);
 
         if self.next_trait_solver()
-            && let ty::Alias(ty::Projection | ty::Inherent | ty::Weak, _) = ty.kind()
+            && let ty::Alias(..) = ty.kind()
         {
             match self
                 .at(&self.misc(sp), self.param_env)
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))
         }
diff --git a/tests/ui/traits/next-solver/alias-bound-unsound.rs b/tests/ui/traits/next-solver/alias-bound-unsound.rs
index 565bfe1186e..4e279a84a33 100644
--- a/tests/ui/traits/next-solver/alias-bound-unsound.rs
+++ b/tests/ui/traits/next-solver/alias-bound-unsound.rs
@@ -23,7 +23,7 @@ fn main() {
     let x = String::from("hello, world");
     drop(<() as Foo>::copy_me(&x));
     //~^ ERROR overflow evaluating the requirement `<() as Foo>::Item: Sized`
-    //~| ERROR overflow evaluating the requirement `<() as Foo>::Item normalizes-to _`
+    //~| ERROR overflow evaluating the requirement `<() as Foo>::Item == _`
     //~| ERROR overflow evaluating the requirement `<() as Foo>::Item well-formed`
     //~| ERROR overflow evaluating the requirement `String <: <() as Foo>::Item`
     //~| ERROR overflow evaluating the requirement `&<() as Foo>::Item well-formed`
diff --git a/tests/ui/traits/next-solver/alias-bound-unsound.stderr b/tests/ui/traits/next-solver/alias-bound-unsound.stderr
index b09c22f3f41..ac3f19b3fe6 100644
--- a/tests/ui/traits/next-solver/alias-bound-unsound.stderr
+++ b/tests/ui/traits/next-solver/alias-bound-unsound.stderr
@@ -19,7 +19,7 @@ LL |     drop(<() as Foo>::copy_me(&x));
    |
    = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`alias_bound_unsound`)
 
-error[E0275]: overflow evaluating the requirement `<() as Foo>::Item normalizes-to _`
+error[E0275]: overflow evaluating the requirement `<() as Foo>::Item == _`
   --> $DIR/alias-bound-unsound.rs:24:10
    |
 LL |     drop(<() as Foo>::copy_me(&x));
@@ -59,7 +59,6 @@ LL |     drop(<() as Foo>::copy_me(&x));
    |          ^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`alias_bound_unsound`)
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: aborting due to 7 previous errors
 
diff --git a/tests/ui/traits/next-solver/coerce-ambig-alias-to-rigid-alias.rs b/tests/ui/traits/next-solver/coerce-ambig-alias-to-rigid-alias.rs
new file mode 100644
index 00000000000..bcb48b5acc7
--- /dev/null
+++ b/tests/ui/traits/next-solver/coerce-ambig-alias-to-rigid-alias.rs
@@ -0,0 +1,15 @@
+// compile-flags: -Znext-solver
+// check-pass
+
+trait Trait {
+    type Assoc;
+}
+
+fn call<T: Trait>(_: <T as Trait>::Assoc, _: T) {}
+
+fn foo<T: Trait>(rigid: <T as Trait>::Assoc, t: T) {
+    // Check that we can coerce `<?0 as Trait>::Assoc` to `<T as Trait>::Assoc`.
+    call::<_ /* ?0 */>(rigid, t);
+}
+
+fn main() {}
diff --git a/tests/ui/traits/next-solver/object-unsafety.rs b/tests/ui/traits/next-solver/object-unsafety.rs
index 8aae7217398..cfa53948b97 100644
--- a/tests/ui/traits/next-solver/object-unsafety.rs
+++ b/tests/ui/traits/next-solver/object-unsafety.rs
@@ -13,7 +13,6 @@ pub fn copy_any<T>(t: &T) -> T {
     //~^ ERROR the type `&<dyn Setup<From = T> as Setup>::From` is not well-formed
     //~| ERROR the trait bound `dyn Setup<From = T>: Setup` is not satisfied
     //~| ERROR mismatched types
-    //~| ERROR mismatched types
     //~| ERROR the type `<dyn Setup<From = T> as Setup>::From` is not well-formed
     //~| ERROR the size for values of type `<dyn Setup<From = T> as Setup>::From` cannot be known at compilation time
 
diff --git a/tests/ui/traits/next-solver/object-unsafety.stderr b/tests/ui/traits/next-solver/object-unsafety.stderr
index 914a8f9d4c5..ee38c256e5f 100644
--- a/tests/ui/traits/next-solver/object-unsafety.stderr
+++ b/tests/ui/traits/next-solver/object-unsafety.stderr
@@ -36,20 +36,6 @@ note: function defined here
 LL | fn copy<U: Setup + ?Sized>(from: &U::From) -> U::From {
    |    ^^^^                    --------------
 
-error[E0308]: mismatched types
-  --> $DIR/object-unsafety.rs:12:5
-   |
-LL | pub fn copy_any<T>(t: &T) -> T {
-   |                 -            - expected `T` because of return type
-   |                 |
-   |                 expected this type parameter
-LL |     copy::<dyn Setup<From=T>>(t)
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ types differ
-   |
-   = note: expected type parameter `T`
-             found associated type `<dyn Setup<From = T> as Setup>::From`
-   = note: you might be missing a type parameter or trait bound
-
 error: the type `<dyn Setup<From = T> as Setup>::From` is not well-formed
   --> $DIR/object-unsafety.rs:12:5
    |
@@ -72,7 +58,7 @@ help: consider further restricting the associated type
 LL | pub fn copy_any<T>(t: &T) -> T where <dyn Setup<From = T> as Setup>::From: Sized {
    |                                +++++++++++++++++++++++++++++++++++++++++++++++++
 
-error: aborting due to 6 previous errors
+error: aborting due to 5 previous errors
 
 Some errors have detailed explanations: E0277, E0308.
 For more information about an error, try `rustc --explain E0277`.