Skip to content

Commit 0e91505

Browse files
Rollup merge of rust-lang#126746 - compiler-errors:no-rpitit, r=oli-obk
Deny `use<>` for RPITITs Precise capturing `use<>` syntax is currently a no-op on RPITITs, since GATs have no variance, so all captured lifetimes are captured invariantly. We don't currently *need* to support `use<>` on RPITITs, since `use<>` is initially intended for migrating RPIT *overcaptures* from edition 2021->2024, but since RPITITs currently capture all in-scope lifetimes, we'll never need to write `use<>` on an RPITIT. Eventually, though, it would be desirable to support precise capturing on RPITITs, since RPITITs overcapturing by default can be annoying to some folks. But let's separate that (which will likely require some delicate types team work for adding variances to GATs and adjusting the refinement rules) from the stabilization of the feature for edition 2024. r? oli-obk cc `@traviscross` Tracking: - rust-lang#123432
2 parents f9a58c6 + 6521c39 commit 0e91505

13 files changed

+169
-44
lines changed

compiler/rustc_ast_lowering/messages.ftl

+3
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,9 @@ ast_lowering_never_pattern_with_guard =
130130
131131
ast_lowering_no_precise_captures_on_apit = `use<...>` precise capturing syntax not allowed in argument-position `impl Trait`
132132
133+
ast_lowering_no_precise_captures_on_rpitit = `use<...>` precise capturing syntax is currently not allowed in return-position `impl Trait` in traits
134+
.note = currently, return-position `impl Trait` in traits and trait implementations capture all lifetimes in scope
135+
133136
ast_lowering_previously_used_here = previously used here
134137
135138
ast_lowering_register1 = register `{$reg1_name}`

compiler/rustc_ast_lowering/src/errors.rs

+8
Original file line numberDiff line numberDiff line change
@@ -424,6 +424,14 @@ pub(crate) struct NoPreciseCapturesOnApit {
424424
pub span: Span,
425425
}
426426

427+
#[derive(Diagnostic)]
428+
#[diag(ast_lowering_no_precise_captures_on_rpitit)]
429+
#[note]
430+
pub(crate) struct NoPreciseCapturesOnRpitit {
431+
#[primary_span]
432+
pub span: Span,
433+
}
434+
427435
#[derive(Diagnostic)]
428436
#[diag(ast_lowering_yield_in_closure)]
429437
pub(crate) struct YieldInClosure {

compiler/rustc_ast_lowering/src/lib.rs

+20
Original file line numberDiff line numberDiff line change
@@ -1594,6 +1594,26 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
15941594
};
15951595
debug!(?captured_lifetimes_to_duplicate);
15961596

1597+
match fn_kind {
1598+
// Deny `use<>` on RPITIT in trait/trait-impl for now.
1599+
Some(FnDeclKind::Trait | FnDeclKind::Impl) => {
1600+
if let Some(span) = bounds.iter().find_map(|bound| match *bound {
1601+
ast::GenericBound::Use(_, span) => Some(span),
1602+
_ => None,
1603+
}) {
1604+
self.tcx.dcx().emit_err(errors::NoPreciseCapturesOnRpitit { span });
1605+
}
1606+
}
1607+
None
1608+
| Some(
1609+
FnDeclKind::Fn
1610+
| FnDeclKind::Inherent
1611+
| FnDeclKind::ExternFn
1612+
| FnDeclKind::Closure
1613+
| FnDeclKind::Pointer,
1614+
) => {}
1615+
}
1616+
15971617
self.lower_opaque_inner(
15981618
opaque_ty_node_id,
15991619
origin,

tests/ui/impl-trait/precise-capturing/forgot-to-capture-type.rs

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ fn type_param<T>() -> impl Sized + use<> {}
66
trait Foo {
77
fn bar() -> impl Sized + use<>;
88
//~^ ERROR `impl Trait` must mention the `Self` type of the trait
9+
//~| ERROR `use<...>` precise capturing syntax is currently not allowed in return-position `impl Trait` in traits
910
}
1011

1112
fn main() {}

tests/ui/impl-trait/precise-capturing/forgot-to-capture-type.stderr

+9-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
1+
error: `use<...>` precise capturing syntax is currently not allowed in return-position `impl Trait` in traits
2+
--> $DIR/forgot-to-capture-type.rs:7:30
3+
|
4+
LL | fn bar() -> impl Sized + use<>;
5+
| ^^^^^
6+
|
7+
= note: currently, return-position `impl Trait` in traits and trait implementations capture all lifetimes in scope
8+
19
error: `impl Trait` must mention all type parameters in scope in `use<...>`
210
--> $DIR/forgot-to-capture-type.rs:3:23
311
|
@@ -18,5 +26,5 @@ LL | fn bar() -> impl Sized + use<>;
1826
|
1927
= note: currently, all type parameters are required to be mentioned in the precise captures list
2028

21-
error: aborting due to 2 previous errors
29+
error: aborting due to 3 previous errors
2230

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
warning: all possible in-scope parameters are already captured, so `use<...>` syntax is redundant
2+
--> $DIR/redundant.rs:7:19
3+
|
4+
LL | fn hello<'a>() -> impl Sized + use<'a> {}
5+
| ^^^^^^^^^^^^^-------
6+
| |
7+
| help: remove the `use<...>` syntax
8+
|
9+
= note: `#[warn(impl_trait_redundant_captures)]` on by default
10+
11+
warning: all possible in-scope parameters are already captured, so `use<...>` syntax is redundant
12+
--> $DIR/redundant.rs:12:27
13+
|
14+
LL | fn inherent(&self) -> impl Sized + use<'_> {}
15+
| ^^^^^^^^^^^^^-------
16+
| |
17+
| help: remove the `use<...>` syntax
18+
19+
warning: 2 warnings emitted
20+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
error: `use<...>` precise capturing syntax is currently not allowed in return-position `impl Trait` in traits
2+
--> $DIR/redundant.rs:18:35
3+
|
4+
LL | fn in_trait() -> impl Sized + use<'a, Self>;
5+
| ^^^^^^^^^^^^^
6+
|
7+
= note: currently, return-position `impl Trait` in traits and trait implementations capture all lifetimes in scope
8+
9+
error: `use<...>` precise capturing syntax is currently not allowed in return-position `impl Trait` in traits
10+
--> $DIR/redundant.rs:23:35
11+
|
12+
LL | fn in_trait() -> impl Sized + use<'a> {}
13+
| ^^^^^^^
14+
|
15+
= note: currently, return-position `impl Trait` in traits and trait implementations capture all lifetimes in scope
16+
17+
error: aborting due to 2 previous errors
18+
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,27 @@
11
//@ compile-flags: -Zunstable-options --edition=2024
2-
//@ check-pass
2+
//@ revisions: normal rpitit
3+
//@[normal] check-pass
34

45
#![feature(precise_capturing)]
56

67
fn hello<'a>() -> impl Sized + use<'a> {}
7-
//~^ WARN all possible in-scope parameters are already captured
8+
//[normal]~^ WARN all possible in-scope parameters are already captured
89

910
struct Inherent;
1011
impl Inherent {
1112
fn inherent(&self) -> impl Sized + use<'_> {}
12-
//~^ WARN all possible in-scope parameters are already captured
13+
//[normal]~^ WARN all possible in-scope parameters are already captured
1314
}
1415

16+
#[cfg(rpitit)]
1517
trait Test<'a> {
1618
fn in_trait() -> impl Sized + use<'a, Self>;
17-
//~^ WARN all possible in-scope parameters are already captured
19+
//[rpitit]~^ ERROR `use<...>` precise capturing syntax is currently not allowed in return-position `impl Trait` in traits
1820
}
21+
#[cfg(rpitit)]
1922
impl<'a> Test<'a> for () {
2023
fn in_trait() -> impl Sized + use<'a> {}
21-
//~^ WARN all possible in-scope parameters are already captured
24+
//[rpitit]~^ ERROR `use<...>` precise capturing syntax is currently not allowed in return-position `impl Trait` in traits
2225
}
2326

2427
fn main() {}

tests/ui/impl-trait/precise-capturing/redundant.stderr

-36
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
//@ known-bug: unknown
2+
3+
// RPITITs don't have variances in their GATs, so they always relate invariantly
4+
// and act as if they capture all their args.
5+
// To fix this soundly, we need to make sure that all the trait header args
6+
// remain captured, since they affect trait selection.
7+
8+
#![feature(precise_capturing)]
9+
10+
trait Foo<'a> {
11+
fn hello() -> impl PartialEq + use<Self>;
12+
}
13+
14+
fn test<'a, 'b, T: for<'r> Foo<'r>>() {
15+
PartialEq::eq(
16+
&<T as Foo<'a>>::hello(),
17+
&<T as Foo<'b>>::hello(),
18+
);
19+
}
20+
21+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
error: `use<...>` precise capturing syntax is currently not allowed in return-position `impl Trait` in traits
2+
--> $DIR/rpitit.rs:11:36
3+
|
4+
LL | fn hello() -> impl PartialEq + use<Self>;
5+
| ^^^^^^^^^
6+
|
7+
= note: currently, return-position `impl Trait` in traits and trait implementations capture all lifetimes in scope
8+
9+
error: `impl Trait` captures lifetime parameter, but it is not mentioned in `use<...>` precise captures list
10+
--> $DIR/rpitit.rs:11:19
11+
|
12+
LL | trait Foo<'a> {
13+
| -- this lifetime parameter is captured
14+
LL | fn hello() -> impl PartialEq + use<Self>;
15+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime captured due to being mentioned in the bounds of the `impl Trait`
16+
17+
error: lifetime may not live long enough
18+
--> $DIR/rpitit.rs:15:5
19+
|
20+
LL | fn test<'a, 'b, T: for<'r> Foo<'r>>() {
21+
| -- -- lifetime `'b` defined here
22+
| |
23+
| lifetime `'a` defined here
24+
LL | / PartialEq::eq(
25+
LL | | &<T as Foo<'a>>::hello(),
26+
LL | | &<T as Foo<'b>>::hello(),
27+
LL | | );
28+
| |_____^ argument requires that `'a` must outlive `'b`
29+
|
30+
= help: consider adding the following bound: `'a: 'b`
31+
32+
error: lifetime may not live long enough
33+
--> $DIR/rpitit.rs:15:5
34+
|
35+
LL | fn test<'a, 'b, T: for<'r> Foo<'r>>() {
36+
| -- -- lifetime `'b` defined here
37+
| |
38+
| lifetime `'a` defined here
39+
LL | / PartialEq::eq(
40+
LL | | &<T as Foo<'a>>::hello(),
41+
LL | | &<T as Foo<'b>>::hello(),
42+
LL | | );
43+
| |_____^ argument requires that `'b` must outlive `'a`
44+
|
45+
= help: consider adding the following bound: `'b: 'a`
46+
47+
help: `'a` and `'b` must be the same: replace one with the other
48+
49+
error: aborting due to 4 previous errors
50+
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
1-
//@ check-pass
2-
31
#![feature(precise_capturing)]
42

53
trait Foo {
64
fn bar<'a>() -> impl Sized + use<Self>;
5+
//~^ ERROR `use<...>` precise capturing syntax is currently not allowed in return-position `impl Trait` in traits
76
}
87

98
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
error: `use<...>` precise capturing syntax is currently not allowed in return-position `impl Trait` in traits
2+
--> $DIR/self-capture.rs:4:34
3+
|
4+
LL | fn bar<'a>() -> impl Sized + use<Self>;
5+
| ^^^^^^^^^
6+
|
7+
= note: currently, return-position `impl Trait` in traits and trait implementations capture all lifetimes in scope
8+
9+
error: aborting due to 1 previous error
10+

0 commit comments

Comments
 (0)