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
This commit is contained in:
commit
9a72b7d04f
@ -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)
|
||||||
|
@ -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,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 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(
|
let obligation = Obligation::new(
|
||||||
self.infcx.tcx,
|
self.infcx.tcx,
|
||||||
self.cause.clone(),
|
self.cause.clone(),
|
||||||
self.param_env,
|
self.param_env,
|
||||||
ty::NormalizesTo { alias, term: new_infer_ty.into() },
|
ty::PredicateKind::AliasRelate(
|
||||||
|
ty.into(),
|
||||||
|
new_infer_ty.into(),
|
||||||
|
ty::AliasRelationDirection::Equate,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
if self.infcx.predicate_may_hold(&obligation) {
|
|
||||||
fulfill_cx.register_predicate_obligation(self.infcx, obligation);
|
fulfill_cx.register_predicate_obligation(self.infcx, obligation);
|
||||||
let errors = fulfill_cx.select_where_possible(self.infcx);
|
let errors = fulfill_cx.select_where_possible(self.infcx);
|
||||||
if !errors.is_empty() {
|
if !errors.is_empty() {
|
||||||
return Err(errors);
|
return Err(errors);
|
||||||
}
|
}
|
||||||
ty = self.infcx.resolve_vars_if_possible(new_infer_ty);
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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))
|
||||||
}
|
}
|
||||||
|
@ -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`
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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() {}
|
@ -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
|
||||||
|
|
||||||
|
@ -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`.
|
||||||
|
Loading…
Reference in New Issue
Block a user