Use alias-eq in structural normalization

This commit is contained in:
Michael Goulet 2023-12-18 19:22:43 +00:00
parent 2a7634047a
commit 132a2884ad
7 changed files with 49 additions and 49 deletions

View File

@ -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); let ty = self.resolve_vars_with_obligations(ty);
if self.next_trait_solver() if self.next_trait_solver()
&& let ty::Alias(ty::Projection | ty::Inherent | ty::Weak, _) = ty.kind() && let ty::Alias(..) = ty.kind()
{ {
match self match self
.at(&self.misc(sp), self.param_env) .at(&self.misc(sp), self.param_env)

View File

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

View File

@ -23,7 +23,7 @@ fn main() {
let x = String::from("hello, world"); let x = String::from("hello, world");
drop(<() as Foo>::copy_me(&x)); drop(<() as Foo>::copy_me(&x));
//~^ ERROR overflow evaluating the requirement `<() as Foo>::Item: Sized` //~^ 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 `<() as Foo>::Item well-formed`
//~| ERROR overflow evaluating the requirement `String <: <() as Foo>::Item` //~| ERROR overflow evaluating the requirement `String <: <() as Foo>::Item`
//~| ERROR overflow evaluating the requirement `&<() as Foo>::Item well-formed` //~| ERROR overflow evaluating the requirement `&<() as Foo>::Item well-formed`

View File

@ -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`) = 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 --> $DIR/alias-bound-unsound.rs:24:10
| |
LL | drop(<() as Foo>::copy_me(&x)); 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`) = 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 error: aborting due to 7 previous errors

View File

@ -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() {}

View File

@ -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 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 the trait bound `dyn Setup<From = T>: Setup` is not satisfied
//~| ERROR mismatched types //~| ERROR mismatched types
//~| ERROR mismatched types
//~| ERROR the type `<dyn Setup<From = T> as Setup>::From` is not well-formed //~| 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 //~| ERROR the size for values of type `<dyn Setup<From = T> as Setup>::From` cannot be known at compilation time

View File

@ -36,20 +36,6 @@ note: function defined here
LL | fn copy<U: Setup + ?Sized>(from: &U::From) -> U::From { 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 error: the type `<dyn Setup<From = T> as Setup>::From` is not well-formed
--> $DIR/object-unsafety.rs:12:5 --> $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 { 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. Some errors have detailed explanations: E0277, E0308.
For more information about an error, try `rustc --explain E0277`. For more information about an error, try `rustc --explain E0277`.