Skip to content

Commit 996e8cb

Browse files
Rework precise capturing syntax
1 parent 693fba1 commit 996e8cb

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

53 files changed

+404
-348
lines changed

compiler/rustc_ast/src/ast.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -307,13 +307,16 @@ impl TraitBoundModifiers {
307307
pub enum GenericBound {
308308
Trait(PolyTraitRef, TraitBoundModifiers),
309309
Outlives(Lifetime),
310+
/// Precise capturing syntax: `impl Sized + use<'a>`
311+
Use(ThinVec<PreciseCapturingArg>, Span),
310312
}
311313

312314
impl GenericBound {
313315
pub fn span(&self) -> Span {
314316
match self {
315317
GenericBound::Trait(t, ..) => t.span,
316318
GenericBound::Outlives(l) => l.ident.span,
319+
GenericBound::Use(_, span) => *span,
317320
}
318321
}
319322
}
@@ -2161,7 +2164,7 @@ pub enum TyKind {
21612164
/// The `NodeId` exists to prevent lowering from having to
21622165
/// generate `NodeId`s on the fly, which would complicate
21632166
/// the generation of opaque `type Foo = impl Trait` items significantly.
2164-
ImplTrait(NodeId, GenericBounds, Option<P<(ThinVec<PreciseCapturingArg>, Span)>>),
2167+
ImplTrait(NodeId, GenericBounds),
21652168
/// No-op; kept solely so that we can pretty-print faithfully.
21662169
Paren(P<Ty>),
21672170
/// Unused for now.

compiler/rustc_ast/src/mut_visit.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -523,14 +523,9 @@ pub fn noop_visit_ty<T: MutVisitor>(ty: &mut P<Ty>, vis: &mut T) {
523523
TyKind::TraitObject(bounds, _syntax) => {
524524
visit_vec(bounds, |bound| vis.visit_param_bound(bound))
525525
}
526-
TyKind::ImplTrait(id, bounds, precise_capturing) => {
526+
TyKind::ImplTrait(id, bounds) => {
527527
vis.visit_id(id);
528528
visit_vec(bounds, |bound| vis.visit_param_bound(bound));
529-
if let Some((precise_capturing, _span)) = precise_capturing.as_deref_mut() {
530-
for arg in precise_capturing {
531-
vis.visit_precise_capturing_arg(arg);
532-
}
533-
}
534529
}
535530
TyKind::MacCall(mac) => vis.visit_mac_call(mac),
536531
TyKind::AnonStruct(id, fields) | TyKind::AnonUnion(id, fields) => {
@@ -920,6 +915,11 @@ fn noop_visit_param_bound<T: MutVisitor>(pb: &mut GenericBound, vis: &mut T) {
920915
match pb {
921916
GenericBound::Trait(ty, _modifier) => vis.visit_poly_trait_ref(ty),
922917
GenericBound::Outlives(lifetime) => noop_visit_lifetime(lifetime, vis),
918+
GenericBound::Use(args, _) => {
919+
for arg in args {
920+
vis.visit_precise_capturing_arg(arg);
921+
}
922+
}
923923
}
924924
}
925925

compiler/rustc_ast/src/util/classify.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -184,15 +184,17 @@ fn type_trailing_braced_mac_call(mut ty: &ast::Ty) -> Option<&ast::MacCall> {
184184
None => break None,
185185
},
186186

187-
ast::TyKind::TraitObject(bounds, _) | ast::TyKind::ImplTrait(_, bounds, _) => {
187+
ast::TyKind::TraitObject(bounds, _) | ast::TyKind::ImplTrait(_, bounds) => {
188188
match bounds.last() {
189189
Some(ast::GenericBound::Trait(bound, _)) => {
190190
match path_return_type(&bound.trait_ref.path) {
191191
Some(trailing_ty) => ty = trailing_ty,
192192
None => break None,
193193
}
194194
}
195-
Some(ast::GenericBound::Outlives(_)) | None => break None,
195+
Some(ast::GenericBound::Outlives(_) | ast::GenericBound::Use(..)) | None => {
196+
break None;
197+
}
196198
}
197199
}
198200

compiler/rustc_ast/src/visit.rs

+15-6
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,16 @@ pub enum BoundKind {
5252
/// E.g., `trait A: B`
5353
SuperTraits,
5454
}
55+
impl BoundKind {
56+
pub fn descr(self) -> &'static str {
57+
match self {
58+
BoundKind::Bound => "bounds",
59+
BoundKind::Impl => "`impl Trait`",
60+
BoundKind::TraitObject => "`dyn` trait object bounds",
61+
BoundKind::SuperTraits => "supertrait bounds",
62+
}
63+
}
64+
}
5565

5666
#[derive(Copy, Clone, Debug)]
5767
pub enum FnKind<'a> {
@@ -497,13 +507,8 @@ pub fn walk_ty<'a, V: Visitor<'a>>(visitor: &mut V, typ: &'a Ty) -> V::Result {
497507
TyKind::TraitObject(bounds, ..) => {
498508
walk_list!(visitor, visit_param_bound, bounds, BoundKind::TraitObject);
499509
}
500-
TyKind::ImplTrait(_, bounds, precise_capturing) => {
510+
TyKind::ImplTrait(_, bounds) => {
501511
walk_list!(visitor, visit_param_bound, bounds, BoundKind::Impl);
502-
if let Some((precise_capturing, _span)) = precise_capturing.as_deref() {
503-
for arg in precise_capturing {
504-
try_visit!(visitor.visit_precise_capturing_arg(arg));
505-
}
506-
}
507512
}
508513
TyKind::Typeof(expression) => try_visit!(visitor.visit_anon_const(expression)),
509514
TyKind::Infer | TyKind::ImplicitSelf | TyKind::Dummy | TyKind::Err(_) => {}
@@ -683,6 +688,10 @@ pub fn walk_param_bound<'a, V: Visitor<'a>>(visitor: &mut V, bound: &'a GenericB
683688
match bound {
684689
GenericBound::Trait(typ, _modifier) => visitor.visit_poly_trait_ref(typ),
685690
GenericBound::Outlives(lifetime) => visitor.visit_lifetime(lifetime, LifetimeCtxt::Bound),
691+
GenericBound::Use(args, _) => {
692+
walk_list!(visitor, visit_precise_capturing_arg, args);
693+
V::Result::output()
694+
}
686695
}
687696
}
688697

compiler/rustc_ast_lowering/src/lib.rs

+64-68
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,9 @@ use rustc_data_structures::sorted_map::SortedMap;
4949
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
5050
use rustc_data_structures::sync::Lrc;
5151
use rustc_errors::{DiagArgFromDisplay, DiagCtxt, StashKey};
52-
use rustc_hir as hir;
5352
use rustc_hir::def::{DefKind, LifetimeRes, Namespace, PartialRes, PerNS, Res};
5453
use rustc_hir::def_id::{LocalDefId, LocalDefIdMap, CRATE_DEF_ID, LOCAL_CRATE};
54+
use rustc_hir::{self as hir};
5555
use rustc_hir::{
5656
ConstArg, GenericArg, HirId, ItemLocalMap, MissingLifetimeKind, ParamName, TraitCandidate,
5757
};
@@ -1387,14 +1387,16 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
13871387
}
13881388
None
13891389
}
1390+
// Ignore `use` syntax since that is not valid in objects.
1391+
GenericBound::Use(..) => None,
13901392
}));
13911393
let lifetime_bound =
13921394
lifetime_bound.unwrap_or_else(|| this.elided_dyn_bound(t.span));
13931395
(bounds, lifetime_bound)
13941396
});
13951397
hir::TyKind::TraitObject(bounds, lifetime_bound, *kind)
13961398
}
1397-
TyKind::ImplTrait(def_node_id, bounds, precise_capturing) => {
1399+
TyKind::ImplTrait(def_node_id, bounds) => {
13981400
let span = t.span;
13991401
match itctx {
14001402
ImplTraitContext::OpaqueTy { origin, fn_kind } => self.lower_opaque_impl_trait(
@@ -1404,12 +1406,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
14041406
bounds,
14051407
fn_kind,
14061408
itctx,
1407-
precise_capturing.as_deref().map(|(args, span)| (args.as_slice(), *span)),
14081409
),
14091410
ImplTraitContext::Universal => {
1410-
if let Some(&(_, span)) = precise_capturing.as_deref() {
1411+
if let Some(span) = bounds.iter().find_map(|bound| match *bound {
1412+
ast::GenericBound::Use(_, span) => Some(span),
1413+
_ => None,
1414+
}) {
14111415
self.tcx.dcx().emit_err(errors::NoPreciseCapturesOnApit { span });
1412-
};
1416+
}
1417+
14131418
let span = t.span;
14141419

14151420
// HACK: pprust breaks strings with newlines when the type
@@ -1520,7 +1525,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
15201525
bounds: &GenericBounds,
15211526
fn_kind: Option<FnDeclKind>,
15221527
itctx: ImplTraitContext,
1523-
precise_capturing_args: Option<(&[PreciseCapturingArg], Span)>,
15241528
) -> hir::TyKind<'hir> {
15251529
// Make sure we know that some funky desugaring has been going on here.
15261530
// This is a first: there is code in other places like for loop
@@ -1529,59 +1533,61 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
15291533
// frequently opened issues show.
15301534
let opaque_ty_span = self.mark_span_with_reason(DesugaringKind::OpaqueTy, span, None);
15311535

1532-
let captured_lifetimes_to_duplicate =
1533-
if let Some((precise_capturing, _)) = precise_capturing_args {
1534-
// We'll actually validate these later on; all we need is the list of
1535-
// lifetimes to duplicate during this portion of lowering.
1536-
precise_capturing
1537-
.iter()
1538-
.filter_map(|arg| match arg {
1539-
PreciseCapturingArg::Lifetime(lt) => Some(*lt),
1540-
PreciseCapturingArg::Arg(..) => None,
1541-
})
1542-
// Add in all the lifetimes mentioned in the bounds. We will error
1543-
// them out later, but capturing them here is important to make sure
1544-
// they actually get resolved in resolve_bound_vars.
1545-
.chain(lifetime_collector::lifetimes_in_bounds(self.resolver, bounds))
1546-
.collect()
1547-
} else {
1548-
match origin {
1549-
hir::OpaqueTyOrigin::TyAlias { .. } => {
1550-
// type alias impl trait and associated type position impl trait were
1551-
// decided to capture all in-scope lifetimes, which we collect for
1552-
// all opaques during resolution.
1536+
let captured_lifetimes_to_duplicate = if let Some(args) =
1537+
bounds.iter().find_map(|bound| match bound {
1538+
ast::GenericBound::Use(a, _) => Some(a),
1539+
_ => None,
1540+
}) {
1541+
// We'll actually validate these later on; all we need is the list of
1542+
// lifetimes to duplicate during this portion of lowering.
1543+
args.iter()
1544+
.filter_map(|arg| match arg {
1545+
PreciseCapturingArg::Lifetime(lt) => Some(*lt),
1546+
PreciseCapturingArg::Arg(..) => None,
1547+
})
1548+
// Add in all the lifetimes mentioned in the bounds. We will error
1549+
// them out later, but capturing them here is important to make sure
1550+
// they actually get resolved in resolve_bound_vars.
1551+
.chain(lifetime_collector::lifetimes_in_bounds(self.resolver, bounds))
1552+
.collect()
1553+
} else {
1554+
match origin {
1555+
hir::OpaqueTyOrigin::TyAlias { .. } => {
1556+
// type alias impl trait and associated type position impl trait were
1557+
// decided to capture all in-scope lifetimes, which we collect for
1558+
// all opaques during resolution.
1559+
self.resolver
1560+
.take_extra_lifetime_params(opaque_ty_node_id)
1561+
.into_iter()
1562+
.map(|(ident, id, _)| Lifetime { id, ident })
1563+
.collect()
1564+
}
1565+
hir::OpaqueTyOrigin::FnReturn(..) => {
1566+
if matches!(
1567+
fn_kind.expect("expected RPITs to be lowered with a FnKind"),
1568+
FnDeclKind::Impl | FnDeclKind::Trait
1569+
) || self.tcx.features().lifetime_capture_rules_2024
1570+
|| span.at_least_rust_2024()
1571+
{
1572+
// return-position impl trait in trait was decided to capture all
1573+
// in-scope lifetimes, which we collect for all opaques during resolution.
15531574
self.resolver
15541575
.take_extra_lifetime_params(opaque_ty_node_id)
15551576
.into_iter()
15561577
.map(|(ident, id, _)| Lifetime { id, ident })
15571578
.collect()
1558-
}
1559-
hir::OpaqueTyOrigin::FnReturn(..) => {
1560-
if matches!(
1561-
fn_kind.expect("expected RPITs to be lowered with a FnKind"),
1562-
FnDeclKind::Impl | FnDeclKind::Trait
1563-
) || self.tcx.features().lifetime_capture_rules_2024
1564-
|| span.at_least_rust_2024()
1565-
{
1566-
// return-position impl trait in trait was decided to capture all
1567-
// in-scope lifetimes, which we collect for all opaques during resolution.
1568-
self.resolver
1569-
.take_extra_lifetime_params(opaque_ty_node_id)
1570-
.into_iter()
1571-
.map(|(ident, id, _)| Lifetime { id, ident })
1572-
.collect()
1573-
} else {
1574-
// in fn return position, like the `fn test<'a>() -> impl Debug + 'a`
1575-
// example, we only need to duplicate lifetimes that appear in the
1576-
// bounds, since those are the only ones that are captured by the opaque.
1577-
lifetime_collector::lifetimes_in_bounds(self.resolver, bounds)
1578-
}
1579-
}
1580-
hir::OpaqueTyOrigin::AsyncFn(..) => {
1581-
unreachable!("should be using `lower_async_fn_ret_ty`")
1579+
} else {
1580+
// in fn return position, like the `fn test<'a>() -> impl Debug + 'a`
1581+
// example, we only need to duplicate lifetimes that appear in the
1582+
// bounds, since those are the only ones that are captured by the opaque.
1583+
lifetime_collector::lifetimes_in_bounds(self.resolver, bounds)
15821584
}
15831585
}
1584-
};
1586+
hir::OpaqueTyOrigin::AsyncFn(..) => {
1587+
unreachable!("should be using `lower_async_fn_ret_ty`")
1588+
}
1589+
}
1590+
};
15851591
debug!(?captured_lifetimes_to_duplicate);
15861592

15871593
self.lower_opaque_inner(
@@ -1591,7 +1597,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
15911597
captured_lifetimes_to_duplicate,
15921598
span,
15931599
opaque_ty_span,
1594-
precise_capturing_args,
15951600
|this| this.lower_param_bounds(bounds, itctx),
15961601
)
15971602
}
@@ -1604,7 +1609,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
16041609
captured_lifetimes_to_duplicate: FxIndexSet<Lifetime>,
16051610
span: Span,
16061611
opaque_ty_span: Span,
1607-
precise_capturing_args: Option<(&[PreciseCapturingArg], Span)>,
16081612
lower_item_bounds: impl FnOnce(&mut Self) -> &'hir [hir::GenericBound<'hir>],
16091613
) -> hir::TyKind<'hir> {
16101614
let opaque_ty_def_id = self.create_def(
@@ -1691,18 +1695,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
16911695
// Install the remapping from old to new (if any). This makes sure that
16921696
// any lifetimes that would have resolved to the def-id of captured
16931697
// lifetimes are remapped to the new *synthetic* lifetimes of the opaque.
1694-
let (bounds, precise_capturing_args) =
1695-
this.with_remapping(captured_to_synthesized_mapping, |this| {
1696-
(
1697-
lower_item_bounds(this),
1698-
precise_capturing_args.map(|(precise_capturing, span)| {
1699-
(
1700-
this.lower_precise_capturing_args(precise_capturing),
1701-
this.lower_span(span),
1702-
)
1703-
}),
1704-
)
1705-
});
1698+
let bounds = this
1699+
.with_remapping(captured_to_synthesized_mapping, |this| lower_item_bounds(this));
17061700

17071701
let generic_params =
17081702
this.arena.alloc_from_iter(synthesized_lifetime_definitions.iter().map(
@@ -1747,7 +1741,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
17471741
origin,
17481742
lifetime_mapping,
17491743
in_trait,
1750-
precise_capturing_args,
17511744
};
17521745

17531746
// Generate an `type Foo = impl Trait;` declaration.
@@ -1958,7 +1951,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
19581951
captured_lifetimes,
19591952
span,
19601953
opaque_ty_span,
1961-
None,
19621954
|this| {
19631955
let bound = this.lower_coroutine_fn_output_type_to_bound(
19641956
output,
@@ -2041,6 +2033,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
20412033
GenericBound::Outlives(lifetime) => {
20422034
hir::GenericBound::Outlives(self.lower_lifetime(lifetime))
20432035
}
2036+
GenericBound::Use(args, span) => hir::GenericBound::Use(
2037+
self.lower_precise_capturing_args(args),
2038+
self.lower_span(*span),
2039+
),
20442040
}
20452041
}
20462042

compiler/rustc_ast_passes/messages.ftl

+2
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ ast_passes_assoc_type_without_body =
1414
associated type in `impl` without body
1515
.suggestion = provide a definition for the type
1616
17+
ast_passes_precise_capturing_not_allowed_here = `use<...>` precise capturing syntax is not allowed in {$loc}
18+
1719
ast_passes_at_least_one_trait = at least one trait must be specified
1820
1921
ast_passes_auto_generic = auto traits cannot have generic parameters

0 commit comments

Comments
 (0)