Skip to content

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

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jan 12, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion compiler/rustc_hir_analysis/src/autoderef.rs
Original file line number Diff line number Diff line change
@@ -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);
41 changes: 22 additions & 19 deletions compiler/rustc_trait_selection/src/solve/normalize.rs
Original file line number Diff line number Diff line change
@@ -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))
}
}

Original file line number Diff line number Diff line change
@@ -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);
};

52 changes: 52 additions & 0 deletions tests/ui/coroutine/clone-rpit.next.stderr
Original file line number Diff line number Diff line change
@@ -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`.
3 changes: 2 additions & 1 deletion tests/ui/coroutine/clone-rpit.rs
Original file line number Diff line number Diff line change
@@ -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)]

13 changes: 13 additions & 0 deletions tests/ui/impl-trait/eagerly-reveal-in-local-body.rs
Original file line number Diff line number Diff line change
@@ -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);
}
Original file line number Diff line number Diff line change
@@ -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 || {
| ^^^^^^^
Original file line number Diff line number Diff line change
@@ -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 || {
| ^^^^^^^
4 changes: 4 additions & 0 deletions tests/ui/impl-trait/recursive-coroutine-indirect.rs
Original file line number Diff line number Diff line change
@@ -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 {
Original file line number Diff line number Diff line change
@@ -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`
Original file line number Diff line number Diff line change
@@ -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`.
Original file line number Diff line number Diff line change
@@ -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() {}
Original file line number Diff line number Diff line change
@@ -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`.
6 changes: 3 additions & 3 deletions tests/ui/traits/next-solver/alias-bound-unsound.rs
Original file line number Diff line number Diff line change
@@ -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}");
}
3 changes: 2 additions & 1 deletion tests/ui/traits/next-solver/alias-bound-unsound.stderr
Original file line number Diff line number Diff line change
@@ -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

Original file line number Diff line number Diff line change
@@ -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() {}
Loading