Skip to content

Commit 46c3c01

Browse files
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
2 parents 174e73a + 68c2f11 commit 46c3c01

19 files changed

+158
-96
lines changed

compiler/rustc_hir_analysis/src/autoderef.rs

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

compiler/rustc_trait_selection/src/solve/normalize.rs

+22-19
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use rustc_infer::infer::InferCtxt;
88
use rustc_infer::traits::TraitEngineExt;
99
use rustc_infer::traits::{FulfillmentError, Obligation, TraitEngine};
1010
use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind};
11-
use rustc_middle::traits::{ObligationCause, Reveal};
11+
use rustc_middle::traits::ObligationCause;
1212
use rustc_middle::ty::{self, AliasTy, Ty, TyCtxt, UniverseIndex};
1313
use rustc_middle::ty::{FallibleTypeFolder, TypeFolder, TypeSuperFoldable};
1414
use rustc_middle::ty::{TypeFoldable, TypeVisitableExt};
@@ -52,14 +52,16 @@ struct NormalizationFolder<'me, 'tcx> {
5252
impl<'tcx> NormalizationFolder<'_, 'tcx> {
5353
fn normalize_alias_ty(
5454
&mut self,
55-
alias: AliasTy<'tcx>,
55+
alias_ty: Ty<'tcx>,
5656
) -> Result<Ty<'tcx>, Vec<FulfillmentError<'tcx>>> {
57+
assert!(matches!(alias_ty.kind(), ty::Alias(..)));
58+
5759
let infcx = self.at.infcx;
5860
let tcx = infcx.tcx;
5961
let recursion_limit = tcx.recursion_limit();
6062
if !recursion_limit.value_within_limit(self.depth) {
6163
self.at.infcx.err_ctxt().report_overflow_error(
62-
&alias.to_ty(tcx),
64+
&alias_ty,
6365
self.at.cause.span,
6466
true,
6567
|_| {},
@@ -76,7 +78,11 @@ impl<'tcx> NormalizationFolder<'_, 'tcx> {
7678
tcx,
7779
self.at.cause.clone(),
7880
self.at.param_env,
79-
ty::NormalizesTo { alias, term: new_infer_ty.into() },
81+
ty::PredicateKind::AliasRelate(
82+
alias_ty.into(),
83+
new_infer_ty.into(),
84+
ty::AliasRelationDirection::Equate,
85+
),
8086
);
8187

8288
// Do not emit an error if normalization is known to fail but instead
@@ -90,9 +96,12 @@ impl<'tcx> NormalizationFolder<'_, 'tcx> {
9096
return Err(errors);
9197
}
9298
let ty = infcx.resolve_vars_if_possible(new_infer_ty);
93-
ty.try_fold_with(self)?
99+
100+
// Alias is guaranteed to be fully structurally resolved,
101+
// so we can super fold here.
102+
ty.try_super_fold_with(self)?
94103
} else {
95-
alias.to_ty(tcx).try_super_fold_with(self)?
104+
alias_ty.try_super_fold_with(self)?
96105
};
97106

98107
self.depth -= 1;
@@ -170,24 +179,18 @@ impl<'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for NormalizationFolder<'_, 'tcx> {
170179
}
171180

172181
fn try_fold_ty(&mut self, ty: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
173-
let reveal = self.at.param_env.reveal();
174182
let infcx = self.at.infcx;
175183
debug_assert_eq!(ty, infcx.shallow_resolve(ty));
176-
if !needs_normalization(&ty, reveal) {
184+
if !ty.has_projections() {
177185
return Ok(ty);
178186
}
179187

180-
// We don't normalize opaque types unless we have
181-
// `Reveal::All`, even if we're in the defining scope.
182-
let data = match *ty.kind() {
183-
ty::Alias(kind, alias_ty) if kind != ty::Opaque || reveal == Reveal::All => alias_ty,
184-
_ => return ty.try_super_fold_with(self),
185-
};
188+
let ty::Alias(..) = *ty.kind() else { return ty.try_super_fold_with(self) };
186189

187-
if data.has_escaping_bound_vars() {
188-
let (data, mapped_regions, mapped_types, mapped_consts) =
189-
BoundVarReplacer::replace_bound_vars(infcx, &mut self.universes, data);
190-
let result = ensure_sufficient_stack(|| self.normalize_alias_ty(data))?;
190+
if ty.has_escaping_bound_vars() {
191+
let (ty, mapped_regions, mapped_types, mapped_consts) =
192+
BoundVarReplacer::replace_bound_vars(infcx, &mut self.universes, ty);
193+
let result = ensure_sufficient_stack(|| self.normalize_alias_ty(ty))?;
191194
Ok(PlaceholderReplacer::replace_placeholders(
192195
infcx,
193196
mapped_regions,
@@ -197,7 +200,7 @@ impl<'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for NormalizationFolder<'_, 'tcx> {
197200
result,
198201
))
199202
} else {
200-
ensure_sufficient_stack(|| self.normalize_alias_ty(data))
203+
ensure_sufficient_stack(|| self.normalize_alias_ty(ty))
201204
}
202205
}
203206

compiler/rustc_trait_selection/src/traits/structural_normalize.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,7 @@ impl<'tcx> StructurallyNormalizeExt<'tcx> for At<'_, 'tcx> {
2222
assert!(!ty.is_ty_var(), "should have resolved vars before calling");
2323

2424
if self.infcx.next_trait_solver() {
25-
// FIXME(-Znext-solver): Should we resolve opaques here?
26-
let ty::Alias(ty::Projection | ty::Inherent | ty::Weak, _) = *ty.kind() else {
25+
let ty::Alias(..) = *ty.kind() else {
2726
return Ok(ty);
2827
};
2928

+52
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
error[E0391]: cycle detected when type-checking `foo`
2+
--> $DIR/clone-rpit.rs:12:1
3+
|
4+
LL | pub fn foo<'a, 'b>() -> impl Clone {
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6+
|
7+
note: ...which requires coroutine witness types for `foo::{closure#0}`...
8+
--> $DIR/clone-rpit.rs:13:5
9+
|
10+
LL | move |_: ()| {
11+
| ^^^^^^^^^^^^
12+
note: ...which requires promoting constants in MIR for `foo::{closure#0}`...
13+
--> $DIR/clone-rpit.rs:13:5
14+
|
15+
LL | move |_: ()| {
16+
| ^^^^^^^^^^^^
17+
note: ...which requires preparing `foo::{closure#0}` for borrow checking...
18+
--> $DIR/clone-rpit.rs:13:5
19+
|
20+
LL | move |_: ()| {
21+
| ^^^^^^^^^^^^
22+
note: ...which requires checking if `foo::{closure#0}` contains FFI-unwind calls...
23+
--> $DIR/clone-rpit.rs:13:5
24+
|
25+
LL | move |_: ()| {
26+
| ^^^^^^^^^^^^
27+
note: ...which requires building MIR for `foo::{closure#0}`...
28+
--> $DIR/clone-rpit.rs:13:5
29+
|
30+
LL | move |_: ()| {
31+
| ^^^^^^^^^^^^
32+
note: ...which requires match-checking `foo::{closure#0}`...
33+
--> $DIR/clone-rpit.rs:13:5
34+
|
35+
LL | move |_: ()| {
36+
| ^^^^^^^^^^^^
37+
note: ...which requires type-checking `foo::{closure#0}`...
38+
--> $DIR/clone-rpit.rs:13:5
39+
|
40+
LL | move |_: ()| {
41+
| ^^^^^^^^^^^^
42+
= note: ...which again requires type-checking `foo`, completing the cycle
43+
note: cycle used when computing type of opaque `foo::{opaque#0}`
44+
--> $DIR/clone-rpit.rs:12:25
45+
|
46+
LL | pub fn foo<'a, 'b>() -> impl Clone {
47+
| ^^^^^^^^^^
48+
= 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
49+
50+
error: aborting due to 1 previous error
51+
52+
For more information about this error, try `rustc --explain E0391`.

tests/ui/coroutine/clone-rpit.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// revisions: current next
22
//[next] compile-flags: -Znext-solver
3-
// check-pass
3+
//[current] check-pass
4+
//[next] known-bug: trait-system-refactor-initiative#82
45

56
#![feature(coroutines, coroutine_trait, coroutine_clone)]
67

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// check-pass
2+
// compile-flags: -Znext-solver
3+
4+
#![feature(type_alias_impl_trait)]
5+
6+
fn main() {
7+
type Tait = impl Sized;
8+
struct S {
9+
i: i32,
10+
}
11+
let x: Tait = S { i: 0 };
12+
println!("{}", x.i);
13+
}

tests/ui/impl-trait/recursive-coroutine-indirect.current.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0733]: recursion in a coroutine requires boxing
2-
--> $DIR/recursive-coroutine-indirect.rs:6:5
2+
--> $DIR/recursive-coroutine-indirect.rs:10:5
33
|
44
LL | move || {
55
| ^^^^^^^

tests/ui/impl-trait/recursive-coroutine-indirect.next.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0733]: recursion in a coroutine requires boxing
2-
--> $DIR/recursive-coroutine-indirect.rs:6:5
2+
--> $DIR/recursive-coroutine-indirect.rs:10:5
33
|
44
LL | move || {
55
| ^^^^^^^

tests/ui/impl-trait/recursive-coroutine-indirect.rs

+4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
// revisions: current next
22
//[next] compile-flags: -Znext-solver
3+
4+
//[next] build-fail
5+
// Deeply normalizing writeback results of opaques makes this into a post-mono error :(
6+
37
#![feature(coroutines)]
48
#![allow(unconditional_recursion)]
59
fn coroutine_hold() -> impl Sized {

tests/ui/traits/negative-bounds/opaque-type-unsatisfied-bound.rs

+3-6
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,8 @@ fn main() {
1313
}
1414

1515
fn weird0() -> impl Sized + !Sized {}
16-
//~^ ERROR mismatched types
17-
//~| ERROR type mismatch resolving `() == impl !Sized + Sized`
16+
//~^ ERROR type mismatch resolving `() == impl !Sized + Sized`
1817
fn weird1() -> impl !Sized + Sized {}
19-
//~^ ERROR mismatched types
20-
//~| ERROR type mismatch resolving `() == impl !Sized + Sized`
18+
//~^ ERROR type mismatch resolving `() == impl !Sized + Sized`
2119
fn weird2() -> impl !Sized {}
22-
//~^ ERROR mismatched types
23-
//~| ERROR type mismatch resolving `() == impl !Sized`
20+
//~^ ERROR type mismatch resolving `() == impl !Sized`
Original file line numberDiff line numberDiff line change
@@ -1,50 +1,17 @@
1-
error[E0308]: mismatched types
2-
--> $DIR/opaque-type-unsatisfied-bound.rs:15:36
3-
|
4-
LL | fn weird0() -> impl Sized + !Sized {}
5-
| ------------------- ^^ types differ
6-
| |
7-
| the expected opaque type
8-
|
9-
= note: expected opaque type `impl !Sized + Sized`
10-
found unit type `()`
11-
121
error[E0271]: type mismatch resolving `() == impl !Sized + Sized`
132
--> $DIR/opaque-type-unsatisfied-bound.rs:15:16
143
|
154
LL | fn weird0() -> impl Sized + !Sized {}
165
| ^^^^^^^^^^^^^^^^^^^ types differ
176

18-
error[E0308]: mismatched types
19-
--> $DIR/opaque-type-unsatisfied-bound.rs:18:36
20-
|
21-
LL | fn weird1() -> impl !Sized + Sized {}
22-
| ------------------- ^^ types differ
23-
| |
24-
| the expected opaque type
25-
|
26-
= note: expected opaque type `impl !Sized + Sized`
27-
found unit type `()`
28-
297
error[E0271]: type mismatch resolving `() == impl !Sized + Sized`
30-
--> $DIR/opaque-type-unsatisfied-bound.rs:18:16
8+
--> $DIR/opaque-type-unsatisfied-bound.rs:17:16
319
|
3210
LL | fn weird1() -> impl !Sized + Sized {}
3311
| ^^^^^^^^^^^^^^^^^^^ types differ
3412

35-
error[E0308]: mismatched types
36-
--> $DIR/opaque-type-unsatisfied-bound.rs:21:28
37-
|
38-
LL | fn weird2() -> impl !Sized {}
39-
| ----------- ^^ types differ
40-
| |
41-
| the expected opaque type
42-
|
43-
= note: expected opaque type `impl !Sized`
44-
found unit type `()`
45-
4613
error[E0271]: type mismatch resolving `() == impl !Sized`
47-
--> $DIR/opaque-type-unsatisfied-bound.rs:21:16
14+
--> $DIR/opaque-type-unsatisfied-bound.rs:19:16
4815
|
4916
LL | fn weird2() -> impl !Sized {}
5017
| ^^^^^^^^^^^ types differ
@@ -63,7 +30,7 @@ note: required by a bound in `consume`
6330
LL | fn consume(_: impl Trait) {}
6431
| ^^^^^ required by this bound in `consume`
6532

66-
error: aborting due to 7 previous errors
33+
error: aborting due to 4 previous errors
6734

68-
Some errors have detailed explanations: E0271, E0277, E0308.
35+
Some errors have detailed explanations: E0271, E0277.
6936
For more information about an error, try `rustc --explain E0271`.

tests/ui/traits/negative-bounds/opaque-type-unsatisfied-fn-bound.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
#![feature(negative_bounds, unboxed_closures)]
44

55
fn produce() -> impl !Fn<(u32,)> {}
6-
//~^ ERROR mismatched types
7-
//~| ERROR type mismatch resolving `() == impl !Fn<(u32,)>`
6+
//~^ ERROR type mismatch resolving `() == impl !Fn<(u32,)>`
87

98
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,9 @@
1-
error[E0308]: mismatched types
2-
--> $DIR/opaque-type-unsatisfied-fn-bound.rs:5:34
3-
|
4-
LL | fn produce() -> impl !Fn<(u32,)> {}
5-
| ---------------- ^^ types differ
6-
| |
7-
| the expected opaque type
8-
|
9-
= note: expected opaque type `impl !Fn<(u32,)>`
10-
found unit type `()`
11-
121
error[E0271]: type mismatch resolving `() == impl !Fn<(u32,)>`
132
--> $DIR/opaque-type-unsatisfied-fn-bound.rs:5:17
143
|
154
LL | fn produce() -> impl !Fn<(u32,)> {}
165
| ^^^^^^^^^^^^^^^^ types differ
176

18-
error: aborting due to 2 previous errors
7+
error: aborting due to 1 previous error
198

20-
Some errors have detailed explanations: E0271, E0308.
21-
For more information about an error, try `rustc --explain E0271`.
9+
For more information about this error, try `rustc --explain E0271`.

tests/ui/traits/next-solver/alias-bound-unsound.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,10 @@ fn main() {
2323
let x = String::from("hello, world");
2424
drop(<() as Foo>::copy_me(&x));
2525
//~^ ERROR overflow evaluating the requirement `<() as Foo>::Item: Sized`
26-
//~| ERROR overflow evaluating the requirement `<() as Foo>::Item == _`
27-
//~| ERROR overflow evaluating the requirement `<() as Foo>::Item well-formed`
2826
//~| ERROR overflow evaluating the requirement `String <: <() as Foo>::Item`
27+
//~| ERROR overflow evaluating the requirement `<() as Foo>::Item well-formed`
2928
//~| ERROR overflow evaluating the requirement `&<() as Foo>::Item well-formed`
30-
//~| ERROR overflow evaluating the requirement `<() as Foo>::Item normalizes-to _`
29+
//~| ERROR overflow evaluating the requirement `<() as Foo>::Item == _`
30+
//~| ERROR overflow evaluating the requirement `<() as Foo>::Item == _`
3131
println!("{x}");
3232
}

tests/ui/traits/next-solver/alias-bound-unsound.stderr

+2-1
Original file line numberDiff line numberDiff line change
@@ -52,13 +52,14 @@ LL | drop(<() as Foo>::copy_me(&x));
5252
|
5353
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`alias_bound_unsound`)
5454

55-
error[E0275]: overflow evaluating the requirement `<() as Foo>::Item normalizes-to _`
55+
error[E0275]: overflow evaluating the requirement `<() as Foo>::Item == _`
5656
--> $DIR/alias-bound-unsound.rs:24:10
5757
|
5858
LL | drop(<() as Foo>::copy_me(&x));
5959
| ^^^^^^^^^^^^^^^^^^^^^^^^
6060
|
6161
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`alias_bound_unsound`)
62+
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
6263

6364
error: aborting due to 7 previous errors
6465

tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,10 @@ fn needs_bar<S: Bar>() {}
1313

1414
fn test<T: Foo1<Assoc1 = <T as Foo2>::Assoc2> + Foo2<Assoc2 = <T as Foo1>::Assoc1>>() {
1515
needs_bar::<T::Assoc1>();
16-
//~^ ERROR overflow evaluating the requirement `<T as Foo1>::Assoc1: Bar`
17-
//~| ERROR overflow evaluating the requirement `<T as Foo2>::Assoc2`
16+
//~^ ERROR overflow evaluating the requirement `<T as Foo1>::Assoc1 == _`
17+
//~| ERROR overflow evaluating the requirement `<T as Foo1>::Assoc1 == _`
18+
//~| ERROR overflow evaluating the requirement `<T as Foo1>::Assoc1 == _`
19+
//~| ERROR overflow evaluating the requirement `<T as Foo1>::Assoc1: Bar`
1820
}
1921

2022
fn main() {}

0 commit comments

Comments
 (0)