Skip to content

Commit f3bfb47

Browse files
committed
Enhance Scope Enum with Late Types and Consts Handling
1 parent d5b4c2e commit f3bfb47

File tree

5 files changed

+155
-13
lines changed

5 files changed

+155
-13
lines changed

compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs

+42-13
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,7 @@ enum Scope<'a> {
151151
s: ScopeRef<'a>,
152152
what: &'static str,
153153
deny_late_regions: bool,
154+
deny_late_types_and_consts: bool,
154155
},
155156

156157
Root {
@@ -190,10 +191,11 @@ impl<'a> Scope<'a> {
190191
.field("s", &"..")
191192
.finish(),
192193
Self::TraitRefBoundary { s: _ } => f.debug_struct("TraitRefBoundary").finish(),
193-
Self::LateBoundary { s: _, what, deny_late_regions } => f
194+
Self::LateBoundary { s: _, what, deny_late_regions, deny_late_types_and_consts } => f
194195
.debug_struct("LateBoundary")
195196
.field("what", what)
196197
.field("deny_late_regions", deny_late_regions)
198+
.field("deny_late_types_and_consts", deny_late_types_and_consts)
197199
.finish(),
198200
Self::Root { opt_parent_item } => {
199201
f.debug_struct("Root").field("opt_parent_item", &opt_parent_item).finish()
@@ -586,10 +588,9 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
586588
this.with(scope, |this| {
587589
let scope = Scope::LateBoundary {
588590
s: this.scope,
589-
what: "nested `impl Trait`",
590-
// We can capture late-bound regions; we just don't duplicate
591-
// lifetime or const params, so we can't allow those.
591+
what: "associated type bounds",
592592
deny_late_regions: false,
593+
deny_late_types_and_consts: false,
593594
};
594595
this.with(scope, |this| intravisit::walk_opaque_ty(this, opaque))
595596
})
@@ -809,8 +810,9 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
809810
self.with(scope, |this| {
810811
let scope = Scope::LateBoundary {
811812
s: this.scope,
812-
what: "`impl Trait` in binding",
813-
deny_late_regions: true,
813+
what: "nested `impl Trait`",
814+
deny_late_regions: false,
815+
deny_late_types_and_consts: true,
814816
};
815817
this.with(scope, |this| {
816818
for bound in bounds {
@@ -999,7 +1001,12 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
9991001

10001002
fn visit_anon_const(&mut self, c: &'tcx hir::AnonConst) {
10011003
self.with(
1002-
Scope::LateBoundary { s: self.scope, what: "constant", deny_late_regions: true },
1004+
Scope::LateBoundary {
1005+
s: self.scope,
1006+
what: "constant",
1007+
deny_late_regions: true,
1008+
deny_late_types_and_consts: true,
1009+
},
10031010
|this| {
10041011
intravisit::walk_anon_const(this, c);
10051012
},
@@ -1298,8 +1305,18 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
12981305
scope = s;
12991306
}
13001307

1301-
Scope::LateBoundary { s, what, deny_late_regions } => {
1302-
if deny_late_regions {
1308+
Scope::LateBoundary {
1309+
s,
1310+
what,
1311+
deny_late_regions: _,
1312+
deny_late_types_and_consts,
1313+
} => {
1314+
// For debugging purposes
1315+
println!(
1316+
"DEBUG: LateBoundary in resolve_type_ref - what: {}, deny_late_types_and_consts: {}",
1317+
what, deny_late_types_and_consts
1318+
);
1319+
if deny_late_types_and_consts {
13031320
crossed_late_boundary = Some(what);
13041321
}
13051322
scope = s;
@@ -1518,8 +1535,20 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
15181535
scope = s;
15191536
}
15201537

1521-
Scope::LateBoundary { s, what, deny_late_regions: _ } => {
1522-
crossed_late_boundary = Some(what);
1538+
Scope::LateBoundary {
1539+
s,
1540+
what,
1541+
deny_late_regions: _,
1542+
deny_late_types_and_consts,
1543+
} => {
1544+
// For debugging purposes
1545+
println!(
1546+
"DEBUG: LateBoundary in resolve_type_ref - what: {}, deny_late_types_and_consts: {}",
1547+
what, deny_late_types_and_consts
1548+
);
1549+
if deny_late_types_and_consts {
1550+
crossed_late_boundary = Some(what);
1551+
}
15231552
scope = s;
15241553
}
15251554
}
@@ -1763,8 +1792,8 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
17631792
// trait Foo<'a> {
17641793
// type Item: 'a;
17651794
// }
1766-
// ```
1767-
//
1795+
// //
1796+
//```
17681797
// but if we just have `type Item;`, then it would be
17691798
// `'static`. However, we don't get all of this logic correct.
17701799
//
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// compile-flags: --edition=2021
2+
#![feature(non_lifetime_binders)]
3+
#![feature(associated_type_defaults)]
4+
#![allow(incomplete_features)]
5+
6+
trait Trait<T: ?Sized> {
7+
type Assoc<'a> = i32;
8+
}
9+
10+
fn produce() -> impl for<T> Trait<(), Assoc = impl Trait<T>> {
11+
//~^ ERROR missing generics for associated type
12+
//~| ERROR the trait bound
13+
//~| ERROR missing generics for associated type
14+
//~| note: associated type defined here
15+
//~| help: add missing lifetime argument
16+
//~| note: duplicate diagnostic
17+
//~| help: add missing lifetime argument
18+
16
19+
}
20+
21+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
error[E0107]: missing generics for associated type `Trait::Assoc`
2+
--> $DIR/non-lifetime-binder-in-nested-impl-trait.rs:10:39
3+
|
4+
LL | fn produce() -> impl for<T> Trait<(), Assoc = impl Trait<T>> {
5+
| ^^^^^ expected 1 lifetime argument
6+
|
7+
note: associated type defined here, with 1 lifetime parameter: `'a`
8+
--> $DIR/non-lifetime-binder-in-nested-impl-trait.rs:7:10
9+
|
10+
LL | type Assoc<'a> = i32;
11+
| ^^^^^ --
12+
help: add missing lifetime argument
13+
|
14+
LL | fn produce() -> impl for<T> Trait<(), Assoc<'a> = impl Trait<T>> {
15+
| ++++
16+
17+
error[E0107]: missing generics for associated type `Trait::Assoc`
18+
--> $DIR/non-lifetime-binder-in-nested-impl-trait.rs:10:39
19+
|
20+
LL | fn produce() -> impl for<T> Trait<(), Assoc = impl Trait<T>> {
21+
| ^^^^^ expected 1 lifetime argument
22+
|
23+
note: associated type defined here, with 1 lifetime parameter: `'a`
24+
--> $DIR/non-lifetime-binder-in-nested-impl-trait.rs:7:10
25+
|
26+
LL | type Assoc<'a> = i32;
27+
| ^^^^^ --
28+
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
29+
help: add missing lifetime argument
30+
|
31+
LL | fn produce() -> impl for<T> Trait<(), Assoc<'a> = impl Trait<T>> {
32+
| ++++
33+
34+
error[E0277]: the trait bound `{integer}: Trait<()>` is not satisfied
35+
--> $DIR/non-lifetime-binder-in-nested-impl-trait.rs:10:17
36+
|
37+
LL | fn produce() -> impl for<T> Trait<(), Assoc = impl Trait<T>> {
38+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait<()>` is not implemented for `{integer}`
39+
...
40+
LL | 16
41+
| -- return type was inferred to be `{integer}` here
42+
|
43+
help: this trait has no implementations, consider adding one
44+
--> $DIR/non-lifetime-binder-in-nested-impl-trait.rs:6:1
45+
|
46+
LL | trait Trait<T: ?Sized> {
47+
| ^^^^^^^^^^^^^^^^^^^^^^
48+
49+
error: aborting due to 3 previous errors
50+
51+
Some errors have detailed explanations: E0107, E0277.
52+
For more information about an error, try `rustc --explain E0107`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#![allow(incomplete_features)]
2+
#![feature(non_lifetime_binders)]
3+
4+
trait Trait<T> {}
5+
6+
fn f() -> impl for<T> Trait<impl Trait<T>> {
7+
//~^ ERROR nested `impl Trait` is not allowed
8+
//~| ERROR cannot capture late-bound type parameter in nested `impl Trait`
9+
()
10+
}
11+
12+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
error[E0666]: nested `impl Trait` is not allowed
2+
--> $DIR/non-lifetime-binder-nested.rs:6:29
3+
|
4+
LL | fn f() -> impl for<T> Trait<impl Trait<T>> {
5+
| ------------------^^^^^^^^^^^^^-
6+
| | |
7+
| | nested `impl Trait` here
8+
| outer `impl Trait`
9+
10+
error[E0277]: the trait bound `(): Trait<impl Trait<T>>` is not satisfied
11+
--> $DIR/non-lifetime-binder-nested.rs:6:11
12+
|
13+
LL | fn f() -> impl for<T> Trait<impl Trait<T>> {
14+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait<impl Trait<T>>` is not implemented for `()`
15+
...
16+
LL | ()
17+
| -- return type was inferred to be `()` here
18+
|
19+
help: this trait has no implementations, consider adding one
20+
--> $DIR/non-lifetime-binder-nested.rs:4:1
21+
|
22+
LL | trait Trait<T> {}
23+
| ^^^^^^^^^^^^^^
24+
25+
error: aborting due to 2 previous errors
26+
27+
Some errors have detailed explanations: E0277, E0666.
28+
For more information about an error, try `rustc --explain E0277`.

0 commit comments

Comments
 (0)