From 132a2884ad464b4faf4781de6bd8c6d255502592 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 18 Dec 2023 19:22:43 +0000 Subject: [PATCH] Use alias-eq in structural normalization --- .../rustc_hir_typeck/src/fn_ctxt/_impl.rs | 2 +- .../src/traits/structural_normalize.rs | 59 ++++++++++--------- .../traits/next-solver/alias-bound-unsound.rs | 2 +- .../next-solver/alias-bound-unsound.stderr | 3 +- .../coerce-ambig-alias-to-rigid-alias.rs | 15 +++++ .../ui/traits/next-solver/object-unsafety.rs | 1 - .../traits/next-solver/object-unsafety.stderr | 16 +---- 7 files changed, 49 insertions(+), 49 deletions(-) create mode 100644 tests/ui/traits/next-solver/coerce-ambig-alias-to-rigid-alias.rs 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 @@ pub fn try_structurally_resolve_type(&self, sp: Span, ty: Ty<'tcx>) -> Ty<'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::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 @@ fn structurally_normalize( 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, Vec>> { 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; - }; + // 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, - }); - 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; - } + 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(_: ::Assoc, _: T) {} + +fn foo(rigid: ::Assoc, t: T) { + // Check that we can coerce `::Assoc` to `::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 { //~^ ERROR the type `& as Setup>::From` is not well-formed //~| ERROR the trait bound `dyn Setup: Setup` is not satisfied //~| ERROR mismatched types - //~| ERROR mismatched types //~| ERROR the type ` as Setup>::From` is not well-formed //~| ERROR the size for values of type ` 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(from: &U::From) -> U::From { | ^^^^ -------------- -error[E0308]: mismatched types - --> $DIR/object-unsafety.rs:12:5 - | -LL | pub fn copy_any(t: &T) -> T { - | - - expected `T` because of return type - | | - | expected this type parameter -LL | copy::>(t) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ types differ - | - = note: expected type parameter `T` - found associated type ` as Setup>::From` - = note: you might be missing a type parameter or trait bound - error: the type ` 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 where 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`.