diff options
| author | Matthias Krüger <matthias.krueger@famsik.de> | 2023-12-19 10:50:08 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-12-19 10:50:08 +0100 |
| commit | 9a72b7d04f9eb23ea0c762b749f00c6985305db4 (patch) | |
| tree | 2ae8d825436401e38719e85bee7effabe52ce044 | |
| parent | d1e52a8f5c4677b258df4746b77db43a144d536a (diff) | |
| parent | 132a2884ad464b4faf4781de6bd8c6d255502592 (diff) | |
| download | rust-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
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`. |
