Rollup merge of #119817 - compiler-errors:normalize-opaques, r=lcnr

Remove special-casing around `AliasKind::Opaque` when structurally resolving in new solver

This fixes a few inconsistencies around where we don't eagerly resolve opaques to their (locally-defined) hidden types in the new solver. It essentially allows this code to work:
```rust
fn main() {
    type Tait = impl Sized;
    struct S {
        i: i32,
    }
    let x: Tait = S { i: 0 };
    println!("{}", x.i);
}
```

Since `Tait` is defined in `main`, we are able to poke through the type of `x` with deref.

r? lcnr
This commit is contained in:
Guillaume Gomez 2024-01-12 15:16:56 +01:00 committed by GitHub
commit 46c3c014eb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 158 additions and 96 deletions

View File

@ -74,7 +74,7 @@ impl<'a, 'tcx> Iterator for Autoderef<'a, 'tcx> {
// we have some type like `&<Ty as Trait>::Assoc`, since users of
// autoderef expect this type to have been structurally normalized.
if self.infcx.next_trait_solver()
&& let ty::Alias(ty::Projection | ty::Inherent | ty::Weak, _) = ty.kind()
&& let ty::Alias(..) = ty.kind()
{
let (normalized_ty, obligations) = self.structurally_normalize(ty)?;
self.state.obligations.extend(obligations);

View File

@ -8,7 +8,7 @@ use rustc_infer::infer::InferCtxt;
use rustc_infer::traits::TraitEngineExt;
use rustc_infer::traits::{FulfillmentError, Obligation, TraitEngine};
use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind};
use rustc_middle::traits::{ObligationCause, Reveal};
use rustc_middle::traits::ObligationCause;
use rustc_middle::ty::{self, AliasTy, Ty, TyCtxt, UniverseIndex};
use rustc_middle::ty::{FallibleTypeFolder, TypeFolder, TypeSuperFoldable};
use rustc_middle::ty::{TypeFoldable, TypeVisitableExt};
@ -52,14 +52,16 @@ struct NormalizationFolder<'me, 'tcx> {
impl<'tcx> NormalizationFolder<'_, 'tcx> {
fn normalize_alias_ty(
&mut self,
alias: AliasTy<'tcx>,
alias_ty: Ty<'tcx>,
) -> Result<Ty<'tcx>, Vec<FulfillmentError<'tcx>>> {
assert!(matches!(alias_ty.kind(), ty::Alias(..)));
let infcx = self.at.infcx;
let tcx = infcx.tcx;
let recursion_limit = tcx.recursion_limit();
if !recursion_limit.value_within_limit(self.depth) {
self.at.infcx.err_ctxt().report_overflow_error(
&alias.to_ty(tcx),
&alias_ty,
self.at.cause.span,
true,
|_| {},
@ -76,7 +78,11 @@ impl<'tcx> NormalizationFolder<'_, 'tcx> {
tcx,
self.at.cause.clone(),
self.at.param_env,
ty::NormalizesTo { alias, term: new_infer_ty.into() },
ty::PredicateKind::AliasRelate(
alias_ty.into(),
new_infer_ty.into(),
ty::AliasRelationDirection::Equate,
),
);
// Do not emit an error if normalization is known to fail but instead
@ -90,9 +96,12 @@ impl<'tcx> NormalizationFolder<'_, 'tcx> {
return Err(errors);
}
let ty = infcx.resolve_vars_if_possible(new_infer_ty);
ty.try_fold_with(self)?
// Alias is guaranteed to be fully structurally resolved,
// so we can super fold here.
ty.try_super_fold_with(self)?
} else {
alias.to_ty(tcx).try_super_fold_with(self)?
alias_ty.try_super_fold_with(self)?
};
self.depth -= 1;
@ -170,24 +179,18 @@ impl<'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for NormalizationFolder<'_, 'tcx> {
}
fn try_fold_ty(&mut self, ty: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
let reveal = self.at.param_env.reveal();
let infcx = self.at.infcx;
debug_assert_eq!(ty, infcx.shallow_resolve(ty));
if !needs_normalization(&ty, reveal) {
if !ty.has_projections() {
return Ok(ty);
}
// We don't normalize opaque types unless we have
// `Reveal::All`, even if we're in the defining scope.
let data = match *ty.kind() {
ty::Alias(kind, alias_ty) if kind != ty::Opaque || reveal == Reveal::All => alias_ty,
_ => return ty.try_super_fold_with(self),
};
let ty::Alias(..) = *ty.kind() else { return ty.try_super_fold_with(self) };
if data.has_escaping_bound_vars() {
let (data, mapped_regions, mapped_types, mapped_consts) =
BoundVarReplacer::replace_bound_vars(infcx, &mut self.universes, data);
let result = ensure_sufficient_stack(|| self.normalize_alias_ty(data))?;
if ty.has_escaping_bound_vars() {
let (ty, mapped_regions, mapped_types, mapped_consts) =
BoundVarReplacer::replace_bound_vars(infcx, &mut self.universes, ty);
let result = ensure_sufficient_stack(|| self.normalize_alias_ty(ty))?;
Ok(PlaceholderReplacer::replace_placeholders(
infcx,
mapped_regions,
@ -197,7 +200,7 @@ impl<'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for NormalizationFolder<'_, 'tcx> {
result,
))
} else {
ensure_sufficient_stack(|| self.normalize_alias_ty(data))
ensure_sufficient_stack(|| self.normalize_alias_ty(ty))
}
}

View File

@ -22,8 +22,7 @@ impl<'tcx> StructurallyNormalizeExt<'tcx> for At<'_, 'tcx> {
assert!(!ty.is_ty_var(), "should have resolved vars before calling");
if self.infcx.next_trait_solver() {
// FIXME(-Znext-solver): Should we resolve opaques here?
let ty::Alias(ty::Projection | ty::Inherent | ty::Weak, _) = *ty.kind() else {
let ty::Alias(..) = *ty.kind() else {
return Ok(ty);
};

View File

@ -0,0 +1,52 @@
error[E0391]: cycle detected when type-checking `foo`
--> $DIR/clone-rpit.rs:12:1
|
LL | pub fn foo<'a, 'b>() -> impl Clone {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: ...which requires coroutine witness types for `foo::{closure#0}`...
--> $DIR/clone-rpit.rs:13:5
|
LL | move |_: ()| {
| ^^^^^^^^^^^^
note: ...which requires promoting constants in MIR for `foo::{closure#0}`...
--> $DIR/clone-rpit.rs:13:5
|
LL | move |_: ()| {
| ^^^^^^^^^^^^
note: ...which requires preparing `foo::{closure#0}` for borrow checking...
--> $DIR/clone-rpit.rs:13:5
|
LL | move |_: ()| {
| ^^^^^^^^^^^^
note: ...which requires checking if `foo::{closure#0}` contains FFI-unwind calls...
--> $DIR/clone-rpit.rs:13:5
|
LL | move |_: ()| {
| ^^^^^^^^^^^^
note: ...which requires building MIR for `foo::{closure#0}`...
--> $DIR/clone-rpit.rs:13:5
|
LL | move |_: ()| {
| ^^^^^^^^^^^^
note: ...which requires match-checking `foo::{closure#0}`...
--> $DIR/clone-rpit.rs:13:5
|
LL | move |_: ()| {
| ^^^^^^^^^^^^
note: ...which requires type-checking `foo::{closure#0}`...
--> $DIR/clone-rpit.rs:13:5
|
LL | move |_: ()| {
| ^^^^^^^^^^^^
= note: ...which again requires type-checking `foo`, completing the cycle
note: cycle used when computing type of opaque `foo::{opaque#0}`
--> $DIR/clone-rpit.rs:12:25
|
LL | pub fn foo<'a, 'b>() -> impl Clone {
| ^^^^^^^^^^
= note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0391`.

View File

@ -1,6 +1,7 @@
// revisions: current next
//[next] compile-flags: -Znext-solver
// check-pass
//[current] check-pass
//[next] known-bug: trait-system-refactor-initiative#82
#![feature(coroutines, coroutine_trait, coroutine_clone)]

View File

@ -0,0 +1,13 @@
// check-pass
// compile-flags: -Znext-solver
#![feature(type_alias_impl_trait)]
fn main() {
type Tait = impl Sized;
struct S {
i: i32,
}
let x: Tait = S { i: 0 };
println!("{}", x.i);
}

View File

@ -1,5 +1,5 @@
error[E0733]: recursion in a coroutine requires boxing
--> $DIR/recursive-coroutine-indirect.rs:6:5
--> $DIR/recursive-coroutine-indirect.rs:10:5
|
LL | move || {
| ^^^^^^^

View File

@ -1,5 +1,5 @@
error[E0733]: recursion in a coroutine requires boxing
--> $DIR/recursive-coroutine-indirect.rs:6:5
--> $DIR/recursive-coroutine-indirect.rs:10:5
|
LL | move || {
| ^^^^^^^

View File

@ -1,5 +1,9 @@
// revisions: current next
//[next] compile-flags: -Znext-solver
//[next] build-fail
// Deeply normalizing writeback results of opaques makes this into a post-mono error :(
#![feature(coroutines)]
#![allow(unconditional_recursion)]
fn coroutine_hold() -> impl Sized {

View File

@ -13,11 +13,8 @@ fn main() {
}
fn weird0() -> impl Sized + !Sized {}
//~^ ERROR mismatched types
//~| ERROR type mismatch resolving `() == impl !Sized + Sized`
//~^ ERROR type mismatch resolving `() == impl !Sized + Sized`
fn weird1() -> impl !Sized + Sized {}
//~^ ERROR mismatched types
//~| ERROR type mismatch resolving `() == impl !Sized + Sized`
//~^ ERROR type mismatch resolving `() == impl !Sized + Sized`
fn weird2() -> impl !Sized {}
//~^ ERROR mismatched types
//~| ERROR type mismatch resolving `() == impl !Sized`
//~^ ERROR type mismatch resolving `() == impl !Sized`

View File

@ -1,50 +1,17 @@
error[E0308]: mismatched types
--> $DIR/opaque-type-unsatisfied-bound.rs:15:36
|
LL | fn weird0() -> impl Sized + !Sized {}
| ------------------- ^^ types differ
| |
| the expected opaque type
|
= note: expected opaque type `impl !Sized + Sized`
found unit type `()`
error[E0271]: type mismatch resolving `() == impl !Sized + Sized`
--> $DIR/opaque-type-unsatisfied-bound.rs:15:16
|
LL | fn weird0() -> impl Sized + !Sized {}
| ^^^^^^^^^^^^^^^^^^^ types differ
error[E0308]: mismatched types
--> $DIR/opaque-type-unsatisfied-bound.rs:18:36
|
LL | fn weird1() -> impl !Sized + Sized {}
| ------------------- ^^ types differ
| |
| the expected opaque type
|
= note: expected opaque type `impl !Sized + Sized`
found unit type `()`
error[E0271]: type mismatch resolving `() == impl !Sized + Sized`
--> $DIR/opaque-type-unsatisfied-bound.rs:18:16
--> $DIR/opaque-type-unsatisfied-bound.rs:17:16
|
LL | fn weird1() -> impl !Sized + Sized {}
| ^^^^^^^^^^^^^^^^^^^ types differ
error[E0308]: mismatched types
--> $DIR/opaque-type-unsatisfied-bound.rs:21:28
|
LL | fn weird2() -> impl !Sized {}
| ----------- ^^ types differ
| |
| the expected opaque type
|
= note: expected opaque type `impl !Sized`
found unit type `()`
error[E0271]: type mismatch resolving `() == impl !Sized`
--> $DIR/opaque-type-unsatisfied-bound.rs:21:16
--> $DIR/opaque-type-unsatisfied-bound.rs:19:16
|
LL | fn weird2() -> impl !Sized {}
| ^^^^^^^^^^^ types differ
@ -63,7 +30,7 @@ note: required by a bound in `consume`
LL | fn consume(_: impl Trait) {}
| ^^^^^ required by this bound in `consume`
error: aborting due to 7 previous errors
error: aborting due to 4 previous errors
Some errors have detailed explanations: E0271, E0277, E0308.
Some errors have detailed explanations: E0271, E0277.
For more information about an error, try `rustc --explain E0271`.

View File

@ -3,7 +3,6 @@
#![feature(negative_bounds, unboxed_closures)]
fn produce() -> impl !Fn<(u32,)> {}
//~^ ERROR mismatched types
//~| ERROR type mismatch resolving `() == impl !Fn<(u32,)>`
//~^ ERROR type mismatch resolving `() == impl !Fn<(u32,)>`
fn main() {}

View File

@ -1,21 +1,9 @@
error[E0308]: mismatched types
--> $DIR/opaque-type-unsatisfied-fn-bound.rs:5:34
|
LL | fn produce() -> impl !Fn<(u32,)> {}
| ---------------- ^^ types differ
| |
| the expected opaque type
|
= note: expected opaque type `impl !Fn<(u32,)>`
found unit type `()`
error[E0271]: type mismatch resolving `() == impl !Fn<(u32,)>`
--> $DIR/opaque-type-unsatisfied-fn-bound.rs:5:17
|
LL | fn produce() -> impl !Fn<(u32,)> {}
| ^^^^^^^^^^^^^^^^ types differ
error: aborting due to 2 previous errors
error: aborting due to 1 previous error
Some errors have detailed explanations: E0271, E0308.
For more information about an error, try `rustc --explain E0271`.
For more information about this error, try `rustc --explain E0271`.

View File

@ -23,10 +23,10 @@ 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 == _`
//~| 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`
//~| ERROR overflow evaluating the requirement `&<() as Foo>::Item well-formed`
//~| 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 == _`
println!("{x}");
}

View File

@ -52,13 +52,14 @@ 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));
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
= 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

View File

@ -13,8 +13,10 @@ fn needs_bar<S: Bar>() {}
fn test<T: Foo1<Assoc1 = <T as Foo2>::Assoc2> + Foo2<Assoc2 = <T as Foo1>::Assoc1>>() {
needs_bar::<T::Assoc1>();
//~^ ERROR overflow evaluating the requirement `<T as Foo1>::Assoc1: Bar`
//~| ERROR overflow evaluating the requirement `<T as Foo2>::Assoc2`
//~^ ERROR overflow evaluating the requirement `<T as Foo1>::Assoc1 == _`
//~| ERROR overflow evaluating the requirement `<T as Foo1>::Assoc1 == _`
//~| ERROR overflow evaluating the requirement `<T as Foo1>::Assoc1 == _`
//~| ERROR overflow evaluating the requirement `<T as Foo1>::Assoc1: Bar`
}
fn main() {}

View File

@ -11,7 +11,7 @@ note: required by a bound in `needs_bar`
LL | fn needs_bar<S: Bar>() {}
| ^^^ required by this bound in `needs_bar`
error[E0275]: overflow evaluating the requirement `<T as Foo2>::Assoc2`
error[E0275]: overflow evaluating the requirement `<T as Foo1>::Assoc1 == _`
--> $DIR/recursive-self-normalization-2.rs:15:5
|
LL | needs_bar::<T::Assoc1>();
@ -19,6 +19,23 @@ LL | needs_bar::<T::Assoc1>();
|
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`recursive_self_normalization_2`)
error: aborting due to 2 previous errors
error[E0275]: overflow evaluating the requirement `<T as Foo1>::Assoc1 == _`
--> $DIR/recursive-self-normalization-2.rs:15:5
|
LL | needs_bar::<T::Assoc1>();
| ^^^^^^^^^^^^^^^^^^^^^^
|
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`recursive_self_normalization_2`)
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error[E0275]: overflow evaluating the requirement `<T as Foo1>::Assoc1 == _`
--> $DIR/recursive-self-normalization-2.rs:15:17
|
LL | needs_bar::<T::Assoc1>();
| ^^^^^^^^^
|
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`recursive_self_normalization_2`)
error: aborting due to 4 previous errors
For more information about this error, try `rustc --explain E0275`.

View File

@ -9,8 +9,10 @@ fn needs_bar<S: Bar>() {}
fn test<T: Foo<Assoc = <T as Foo>::Assoc>>() {
needs_bar::<T::Assoc>();
//~^ ERROR overflow evaluating the requirement `<T as Foo>::Assoc: Bar`
//~| ERROR overflow evaluating the requirement `<T as Foo>::Assoc` [E0275]
//~^ ERROR overflow evaluating the requirement `<T as Foo>::Assoc == _`
//~| ERROR overflow evaluating the requirement `<T as Foo>::Assoc == _`
//~| ERROR overflow evaluating the requirement `<T as Foo>::Assoc == _`
//~| ERROR overflow evaluating the requirement `<T as Foo>::Assoc: Bar`
}
fn main() {}

View File

@ -11,7 +11,7 @@ note: required by a bound in `needs_bar`
LL | fn needs_bar<S: Bar>() {}
| ^^^ required by this bound in `needs_bar`
error[E0275]: overflow evaluating the requirement `<T as Foo>::Assoc`
error[E0275]: overflow evaluating the requirement `<T as Foo>::Assoc == _`
--> $DIR/recursive-self-normalization.rs:11:5
|
LL | needs_bar::<T::Assoc>();
@ -19,6 +19,23 @@ LL | needs_bar::<T::Assoc>();
|
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`recursive_self_normalization`)
error: aborting due to 2 previous errors
error[E0275]: overflow evaluating the requirement `<T as Foo>::Assoc == _`
--> $DIR/recursive-self-normalization.rs:11:5
|
LL | needs_bar::<T::Assoc>();
| ^^^^^^^^^^^^^^^^^^^^^
|
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`recursive_self_normalization`)
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error[E0275]: overflow evaluating the requirement `<T as Foo>::Assoc == _`
--> $DIR/recursive-self-normalization.rs:11:17
|
LL | needs_bar::<T::Assoc>();
| ^^^^^^^^
|
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`recursive_self_normalization`)
error: aborting due to 4 previous errors
For more information about this error, try `rustc --explain E0275`.