Skip to content

Commit 9b53b64

Browse files
Allow use<> syntax in RPITIT, fix test example
1 parent b56a74f commit 9b53b64

File tree

19 files changed

+165
-128
lines changed

19 files changed

+165
-128
lines changed

compiler/rustc_ast_lowering/messages.ftl

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -130,9 +130,6 @@ 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-
136133
ast_lowering_previously_used_here = previously used here
137134
138135
ast_lowering_register1 = register `{$reg1_name}`

compiler/rustc_ast_lowering/src/errors.rs

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -424,14 +424,6 @@ 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-
435427
#[derive(Diagnostic)]
436428
#[diag(ast_lowering_yield_in_closure)]
437429
pub(crate) struct YieldInClosure {

compiler/rustc_ast_lowering/src/lib.rs

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1594,26 +1594,6 @@ 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-
16171597
self.lower_opaque_inner(
16181598
opaque_ty_node_id,
16191599
origin,

compiler/rustc_hir_analysis/messages.ftl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,9 @@ hir_analysis_late_bound_lifetime_in_apit = `impl Trait` can only mention lifetim
229229
hir_analysis_late_bound_type_in_apit = `impl Trait` can only mention type parameters from an fn or impl
230230
.label = type parameter declared here
231231
232+
hir_analysis_lifetime_implicitly_captured = `impl Trait` captures lifetime parameter, but it is not mentioned in `use<...>` precise captures list
233+
.param_label = all lifetime parameters originating from a trait are captured implicitly
234+
232235
hir_analysis_lifetime_must_be_first = lifetime parameter `{$name}` must be listed before non-lifetime parameters
233236
.label = move the lifetime before this parameter
234237

compiler/rustc_hir_analysis/src/check/check.rs

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -593,15 +593,22 @@ fn check_opaque_precise_captures<'tcx>(tcx: TyCtxt<'tcx>, opaque_def_id: LocalDe
593593
param_span: tcx.def_span(def_id),
594594
});
595595
} else {
596-
// If the `use_span` is actually just the param itself, then we must
597-
// have not duplicated the lifetime but captured the original.
598-
// The "effective" `use_span` will be the span of the opaque itself,
599-
// and the param span will be the def span of the param.
600-
tcx.dcx().emit_err(errors::LifetimeNotCaptured {
601-
opaque_span,
602-
use_span: opaque_span,
603-
param_span: use_span,
604-
});
596+
if tcx.def_kind(tcx.parent(param.def_id)) == DefKind::Trait {
597+
tcx.dcx().emit_err(errors::LifetimeImplicitlyCaptured {
598+
opaque_span,
599+
param_span: tcx.def_span(param.def_id),
600+
});
601+
} else {
602+
// If the `use_span` is actually just the param itself, then we must
603+
// have not duplicated the lifetime but captured the original.
604+
// The "effective" `use_span` will be the span of the opaque itself,
605+
// and the param span will be the def span of the param.
606+
tcx.dcx().emit_err(errors::LifetimeNotCaptured {
607+
opaque_span,
608+
use_span: opaque_span,
609+
param_span: use_span,
610+
});
611+
}
605612
}
606613
continue;
607614
}

compiler/rustc_hir_analysis/src/errors/precise_captures.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,15 @@ pub struct LifetimeNotCaptured {
3333
pub opaque_span: Span,
3434
}
3535

36+
#[derive(Diagnostic)]
37+
#[diag(hir_analysis_lifetime_implicitly_captured)]
38+
pub struct LifetimeImplicitlyCaptured {
39+
#[primary_span]
40+
pub opaque_span: Span,
41+
#[label(hir_analysis_param_label)]
42+
pub param_span: Span,
43+
}
44+
3645
#[derive(Diagnostic)]
3746
#[diag(hir_analysis_bad_precise_capture)]
3847
pub struct BadPreciseCapture {

compiler/rustc_hir_analysis/src/variance/mod.rs

Lines changed: 40 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
66
use itertools::Itertools;
77
use rustc_arena::DroplessArena;
8+
use rustc_hir as hir;
89
use rustc_hir::def::DefKind;
910
use rustc_hir::def_id::{DefId, LocalDefId};
1011
use rustc_middle::query::Providers;
@@ -63,13 +64,27 @@ fn variances_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Variance] {
6364
}
6465
DefKind::AssocTy => match tcx.opt_rpitit_info(item_def_id.to_def_id()) {
6566
Some(ty::ImplTraitInTraitData::Trait { opaque_def_id, .. }) => {
66-
return variance_of_opaque(tcx, opaque_def_id.expect_local());
67+
return variance_of_opaque(
68+
tcx,
69+
opaque_def_id.expect_local(),
70+
ForceCaptureTraitArgs::Yes,
71+
);
6772
}
68-
None => {}
69-
Some(ty::ImplTraitInTraitData::Impl { .. }) => {}
73+
None | Some(ty::ImplTraitInTraitData::Impl { .. }) => {}
7074
},
7175
DefKind::OpaqueTy => {
72-
return variance_of_opaque(tcx, item_def_id);
76+
let force_capture_trait_args = if let hir::OpaqueTyOrigin::FnReturn(fn_def_id) =
77+
tcx.hir_node_by_def_id(item_def_id).expect_item().expect_opaque_ty().origin
78+
&& let Some(ty::AssocItem {
79+
container: ty::AssocItemContainer::TraitContainer, ..
80+
}) = tcx.opt_associated_item(fn_def_id.to_def_id())
81+
{
82+
ForceCaptureTraitArgs::Yes
83+
} else {
84+
ForceCaptureTraitArgs::No
85+
};
86+
87+
return variance_of_opaque(tcx, item_def_id, force_capture_trait_args);
7388
}
7489
_ => {}
7590
}
@@ -78,8 +93,18 @@ fn variances_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Variance] {
7893
span_bug!(tcx.def_span(item_def_id), "asked to compute variance for wrong kind of item");
7994
}
8095

96+
#[derive(Debug, Copy, Clone)]
97+
enum ForceCaptureTraitArgs {
98+
Yes,
99+
No,
100+
}
101+
81102
#[instrument(level = "trace", skip(tcx), ret)]
82-
fn variance_of_opaque(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Variance] {
103+
fn variance_of_opaque(
104+
tcx: TyCtxt<'_>,
105+
item_def_id: LocalDefId,
106+
force_capture_trait_args: ForceCaptureTraitArgs,
107+
) -> &[ty::Variance] {
83108
let generics = tcx.generics_of(item_def_id);
84109

85110
// Opaque types may only use regions that are bound. So for
@@ -120,9 +145,7 @@ fn variance_of_opaque(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Varianc
120145
#[instrument(level = "trace", skip(self), ret)]
121146
fn visit_ty(&mut self, t: Ty<'tcx>) {
122147
match t.kind() {
123-
ty::Alias(_, ty::AliasTy { def_id, args, .. })
124-
if matches!(self.tcx.def_kind(*def_id), DefKind::OpaqueTy) =>
125-
{
148+
ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) => {
126149
self.visit_opaque(*def_id, args);
127150
}
128151
_ => t.super_visit_with(self),
@@ -140,6 +163,15 @@ fn variance_of_opaque(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Varianc
140163
let mut generics = generics;
141164
while let Some(def_id) = generics.parent {
142165
generics = tcx.generics_of(def_id);
166+
167+
// Don't mark trait params generic if we're in an RPITIT.
168+
if matches!(force_capture_trait_args, ForceCaptureTraitArgs::Yes)
169+
&& generics.parent.is_none()
170+
{
171+
debug_assert_eq!(tcx.def_kind(def_id), DefKind::Trait);
172+
break;
173+
}
174+
143175
for param in &generics.own_params {
144176
match param.kind {
145177
ty::GenericParamDefKind::Lifetime => {

compiler/rustc_middle/src/ty/context.rs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -580,10 +580,7 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
580580
placeholder.find_const_ty_from_env(param_env)
581581
}
582582

583-
fn is_impl_trait_in_trait(
584-
self,
585-
def_id: DefId,
586-
) -> bool {
583+
fn is_impl_trait_in_trait(self, def_id: DefId) -> bool {
587584
self.is_impl_trait_in_trait(def_id)
588585
}
589586
}

compiler/rustc_type_ir/src/interner.rs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -278,10 +278,7 @@ pub trait Interner:
278278
placeholder: Self::PlaceholderConst,
279279
) -> Self::Ty;
280280

281-
fn is_impl_trait_in_trait(
282-
self,
283-
def_id: Self::DefId,
284-
) -> bool;
281+
fn is_impl_trait_in_trait(self, def_id: Self::DefId) -> bool;
285282
}
286283

287284
/// Imagine you have a function `F: FnOnce(&[T]) -> R`, plus an iterator `iter`

tests/ui/impl-trait/in-trait/variance.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,14 @@ impl<T> Captures<'_> for T {}
77

88
trait Foo<'i> {
99
fn implicit_capture_early<'a: 'a>() -> impl Sized {}
10-
//~^ [o, *, *, o, o]
10+
//~^ [o, o, *, o, o]
1111
// Self, 'i, 'a, 'i_duplicated, 'a_duplicated
1212

13-
fn explicit_capture_early<'a: 'a>() -> impl Sized + Captures<'a> {} //~ [o, *, *, o, o]
13+
fn explicit_capture_early<'a: 'a>() -> impl Sized + Captures<'a> {} //~ [o, o, *, o, o]
1414

15-
fn implicit_capture_late<'a>(_: &'a ()) -> impl Sized {} //~ [o, *, o, o]
15+
fn implicit_capture_late<'a>(_: &'a ()) -> impl Sized {} //~ [o, o, o, o]
1616

17-
fn explicit_capture_late<'a>(_: &'a ()) -> impl Sized + Captures<'a> {} //~ [o, *, o, o]
17+
fn explicit_capture_late<'a>(_: &'a ()) -> impl Sized + Captures<'a> {} //~ [o, o, o, o]
1818
}
1919

2020
fn main() {}

tests/ui/impl-trait/in-trait/variance.stderr

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,22 @@
1-
error: [o, *, *, o, o]
1+
error: [o, o, *, o, o]
22
--> $DIR/variance.rs:9:44
33
|
44
LL | fn implicit_capture_early<'a: 'a>() -> impl Sized {}
55
| ^^^^^^^^^^
66

7-
error: [o, *, *, o, o]
7+
error: [o, o, *, o, o]
88
--> $DIR/variance.rs:13:44
99
|
1010
LL | fn explicit_capture_early<'a: 'a>() -> impl Sized + Captures<'a> {}
1111
| ^^^^^^^^^^^^^^^^^^^^^^^^^
1212

13-
error: [o, *, o, o]
13+
error: [o, o, o, o]
1414
--> $DIR/variance.rs:15:48
1515
|
1616
LL | fn implicit_capture_late<'a>(_: &'a ()) -> impl Sized {}
1717
| ^^^^^^^^^^
1818

19-
error: [o, *, o, o]
19+
error: [o, o, o, o]
2020
--> $DIR/variance.rs:17:48
2121
|
2222
LL | fn explicit_capture_late<'a>(_: &'a ()) -> impl Sized + Captures<'a> {}

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

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ 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
109
}
1110

1211
fn main() {}

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

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,3 @@
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-
91
error: `impl Trait` must mention all type parameters in scope in `use<...>`
102
--> $DIR/forgot-to-capture-type.rs:3:23
113
|
@@ -26,5 +18,5 @@ LL | fn bar() -> impl Sized + use<>;
2618
|
2719
= note: currently, all type parameters are required to be mentioned in the precise captures list
2820

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

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,24 @@
11
//@ compile-flags: -Zunstable-options --edition=2024
2-
//@ revisions: normal rpitit
3-
//@[normal] check-pass
2+
//@ check-pass
43

54
#![feature(precise_capturing)]
65

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

109
struct Inherent;
1110
impl Inherent {
1211
fn inherent(&self) -> impl Sized + use<'_> {}
13-
//[normal]~^ WARN all possible in-scope parameters are already captured
12+
//~^ WARN all possible in-scope parameters are already captured
1413
}
1514

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

2724
fn main() {}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
warning: all possible in-scope parameters are already captured, so `use<...>` syntax is redundant
2+
--> $DIR/redundant.rs:6: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:11:27
13+
|
14+
LL | fn inherent(&self) -> impl Sized + use<'_> {}
15+
| ^^^^^^^^^^^^^-------
16+
| |
17+
| help: remove the `use<...>` syntax
18+
19+
warning: all possible in-scope parameters are already captured, so `use<...>` syntax is redundant
20+
--> $DIR/redundant.rs:16:22
21+
|
22+
LL | fn in_trait() -> impl Sized + use<'a, Self>;
23+
| ^^^^^^^^^^^^^-------------
24+
| |
25+
| help: remove the `use<...>` syntax
26+
27+
warning: all possible in-scope parameters are already captured, so `use<...>` syntax is redundant
28+
--> $DIR/redundant.rs:20:22
29+
|
30+
LL | fn in_trait() -> impl Sized + use<'a> {}
31+
| ^^^^^^^^^^^^^-------
32+
| |
33+
| help: remove the `use<...>` syntax
34+
35+
warning: 4 warnings emitted
36+

0 commit comments

Comments
 (0)