Skip to content

Commit fc9e344

Browse files
Use dedicated PreciseCapturingArg for representing what goes in use<>
1 parent 647b672 commit fc9e344

File tree

6 files changed

+146
-56
lines changed

6 files changed

+146
-56
lines changed

compiler/rustc_ast/src/ast.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2132,7 +2132,7 @@ pub enum TyKind {
21322132
/// The `NodeId` exists to prevent lowering from having to
21332133
/// generate `NodeId`s on the fly, which would complicate
21342134
/// the generation of opaque `type Foo = impl Trait` items significantly.
2135-
ImplTrait(NodeId, GenericBounds, Option<P<GenericArgs>>),
2135+
ImplTrait(NodeId, GenericBounds, Option<ThinVec<PreciseCapturingArg>>),
21362136
/// No-op; kept solely so that we can pretty-print faithfully.
21372137
Paren(P<Ty>),
21382138
/// Unused for now.
@@ -2188,6 +2188,14 @@ pub enum TraitObjectSyntax {
21882188
None,
21892189
}
21902190

2191+
#[derive(Clone, PartialEq, Encodable, Decodable, Debug)]
2192+
pub enum PreciseCapturingArg {
2193+
/// Lifetime parameter
2194+
Lifetime(Lifetime),
2195+
/// Type or const parameter
2196+
Arg(Ident, NodeId),
2197+
}
2198+
21912199
/// Inline assembly operand explicit register or register class.
21922200
///
21932201
/// E.g., `"eax"` as in `asm!("mov eax, 2", out("eax") result)`.

compiler/rustc_ast/src/mut_visit.rs

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,14 @@ pub trait MutVisitor: Sized {
259259
noop_visit_param_bound(tpb, self);
260260
}
261261

262+
fn visit_precise_capturing_args(&mut self, args: &mut ThinVec<PreciseCapturingArg>) {
263+
noop_visit_precise_capturing_args(args, self);
264+
}
265+
266+
fn visit_precise_capturing_arg(&mut self, arg: &mut PreciseCapturingArg) {
267+
noop_visit_precise_capturing_arg(arg, self);
268+
}
269+
262270
fn visit_mt(&mut self, mt: &mut MutTy) {
263271
noop_visit_mt(mt, self);
264272
}
@@ -522,7 +530,7 @@ pub fn noop_visit_ty<T: MutVisitor>(ty: &mut P<Ty>, vis: &mut T) {
522530
vis.visit_id(id);
523531
visit_vec(bounds, |bound| vis.visit_param_bound(bound));
524532
visit_opt(precise_capturing, |precise_capturing| {
525-
vis.visit_generic_args(precise_capturing);
533+
vis.visit_precise_capturing_args(precise_capturing);
526534
});
527535
}
528536
TyKind::MacCall(mac) => vis.visit_mac_call(mac),
@@ -917,6 +925,27 @@ pub fn noop_visit_param_bound<T: MutVisitor>(pb: &mut GenericBound, vis: &mut T)
917925
}
918926
}
919927

928+
pub fn noop_visit_precise_capturing_args<T: MutVisitor>(
929+
args: &mut ThinVec<PreciseCapturingArg>,
930+
vis: &mut T,
931+
) {
932+
for arg in args {
933+
vis.visit_precise_capturing_arg(arg);
934+
}
935+
}
936+
937+
pub fn noop_visit_precise_capturing_arg<T: MutVisitor>(arg: &mut PreciseCapturingArg, vis: &mut T) {
938+
match arg {
939+
PreciseCapturingArg::Lifetime(lt) => {
940+
vis.visit_lifetime(lt);
941+
}
942+
PreciseCapturingArg::Arg(ident, id) => {
943+
vis.visit_ident(ident);
944+
vis.visit_id(id);
945+
}
946+
}
947+
}
948+
920949
pub fn noop_flat_map_generic_param<T: MutVisitor>(
921950
mut param: GenericParam,
922951
vis: &mut T,

compiler/rustc_ast/src/visit.rs

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ use rustc_span::Span;
2020

2121
pub use rustc_ast_ir::visit::VisitorResult;
2222
pub use rustc_ast_ir::{try_visit, visit_opt, walk_list, walk_visitable_list};
23+
use thin_vec::ThinVec;
2324

2425
#[derive(Copy, Clone, Debug, PartialEq)]
2526
pub enum AssocCtxt {
@@ -184,6 +185,12 @@ pub trait Visitor<'ast>: Sized {
184185
fn visit_param_bound(&mut self, bounds: &'ast GenericBound, _ctxt: BoundKind) -> Self::Result {
185186
walk_param_bound(self, bounds)
186187
}
188+
fn visit_precise_capturing_args(&mut self, args: &'ast ThinVec<PreciseCapturingArg>) {
189+
walk_precise_capturing_args(self, args);
190+
}
191+
fn visit_precise_capturing_arg(&mut self, arg: &'ast PreciseCapturingArg) {
192+
walk_precise_capturing_arg(self, arg);
193+
}
187194
fn visit_poly_trait_ref(&mut self, t: &'ast PolyTraitRef) -> Self::Result {
188195
walk_poly_trait_ref(self, t)
189196
}
@@ -459,7 +466,7 @@ pub fn walk_ty<'a, V: Visitor<'a>>(visitor: &mut V, typ: &'a Ty) -> V::Result {
459466
}
460467
TyKind::ImplTrait(_, bounds, precise_capturing) => {
461468
walk_list!(visitor, visit_param_bound, bounds, BoundKind::Impl);
462-
visit_opt!(visitor, visit_generic_args, precise_capturing);
469+
visit_opt!(visitor, visit_precise_capturing_args, precise_capturing);
463470
}
464471
TyKind::Typeof(expression) => try_visit!(visitor.visit_anon_const(expression)),
465472
TyKind::Infer | TyKind::ImplicitSelf | TyKind::Dummy | TyKind::Err(_) => {}
@@ -638,6 +645,29 @@ pub fn walk_param_bound<'a, V: Visitor<'a>>(visitor: &mut V, bound: &'a GenericB
638645
}
639646
}
640647

648+
pub fn walk_precise_capturing_args<'a, V: Visitor<'a>>(
649+
visitor: &mut V,
650+
args: &'a ThinVec<PreciseCapturingArg>,
651+
) {
652+
for arg in args {
653+
visitor.visit_precise_capturing_arg(arg);
654+
}
655+
}
656+
657+
pub fn walk_precise_capturing_arg<'a, V: Visitor<'a>>(
658+
visitor: &mut V,
659+
arg: &'a PreciseCapturingArg,
660+
) {
661+
match arg {
662+
PreciseCapturingArg::Lifetime(lt) => {
663+
visitor.visit_lifetime(lt, LifetimeCtxt::GenericArg);
664+
}
665+
PreciseCapturingArg::Arg(ident, _) => {
666+
visitor.visit_ident(*ident);
667+
}
668+
}
669+
}
670+
641671
pub fn walk_generic_param<'a, V: Visitor<'a>>(
642672
visitor: &mut V,
643673
param: &'a GenericParam,

compiler/rustc_ast_lowering/src/lib.rs

Lines changed: 43 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1525,7 +1525,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
15251525
bounds: &GenericBounds,
15261526
fn_kind: Option<FnDeclKind>,
15271527
itctx: ImplTraitContext,
1528-
precise_capturing: Option<&ast::GenericArgs>,
1528+
precise_capturing: Option<&[ast::PreciseCapturingArg]>,
15291529
) -> hir::TyKind<'hir> {
15301530
// Make sure we know that some funky desugaring has been going on here.
15311531
// This is a first: there is code in other places like for loop
@@ -1534,58 +1534,55 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
15341534
// frequently opened issues show.
15351535
let opaque_ty_span = self.mark_span_with_reason(DesugaringKind::OpaqueTy, span, None);
15361536

1537-
let captured_lifetimes_to_duplicate = if let Some(precise_capturing) = precise_capturing {
1538-
let ast::GenericArgs::AngleBracketed(precise_capturing) = precise_capturing else {
1539-
panic!("we only parse angle-bracketed args")
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-
precise_capturing
1544-
.args
1545-
.iter()
1546-
.filter_map(|arg| match arg {
1547-
ast::AngleBracketedArg::Arg(ast::GenericArg::Lifetime(lt)) => Some(*lt),
1548-
_ => None,
1549-
})
1550-
.collect()
1551-
} else {
1552-
match origin {
1553-
hir::OpaqueTyOrigin::TyAlias { .. } => {
1554-
// type alias impl trait and associated type position impl trait were
1555-
// decided to capture all in-scope lifetimes, which we collect for
1556-
// all opaques during resolution.
1557-
self.resolver
1558-
.take_extra_lifetime_params(opaque_ty_node_id)
1559-
.into_iter()
1560-
.map(|(ident, id, _)| Lifetime { id, ident })
1561-
.collect()
1562-
}
1563-
hir::OpaqueTyOrigin::FnReturn(..) => {
1564-
if matches!(
1565-
fn_kind.expect("expected RPITs to be lowered with a FnKind"),
1566-
FnDeclKind::Impl | FnDeclKind::Trait
1567-
) || self.tcx.features().lifetime_capture_rules_2024
1568-
|| span.at_least_rust_2024()
1569-
{
1570-
// return-position impl trait in trait was decided to capture all
1571-
// in-scope lifetimes, which we collect for all opaques during resolution.
1537+
let captured_lifetimes_to_duplicate =
1538+
if let Some(precise_capturing) = precise_capturing_args {
1539+
// We'll actually validate these later on; all we need is the list of
1540+
// lifetimes to duplicate during this portion of lowering.
1541+
precise_capturing
1542+
.iter()
1543+
.filter_map(|arg| match arg {
1544+
ast::PreciseCapturingArg::Lifetime(lt) => Some(*lt),
1545+
ast::PreciseCapturingArg::Arg(..) => None,
1546+
})
1547+
.collect()
1548+
} else {
1549+
match origin {
1550+
hir::OpaqueTyOrigin::TyAlias { .. } => {
1551+
// type alias impl trait and associated type position impl trait were
1552+
// decided to capture all in-scope lifetimes, which we collect for
1553+
// all opaques during resolution.
15721554
self.resolver
15731555
.take_extra_lifetime_params(opaque_ty_node_id)
15741556
.into_iter()
15751557
.map(|(ident, id, _)| Lifetime { id, ident })
15761558
.collect()
1577-
} else {
1578-
// in fn return position, like the `fn test<'a>() -> impl Debug + 'a`
1579-
// example, we only need to duplicate lifetimes that appear in the
1580-
// bounds, since those are the only ones that are captured by the opaque.
1581-
lifetime_collector::lifetimes_in_bounds(self.resolver, bounds)
1559+
}
1560+
hir::OpaqueTyOrigin::FnReturn(..) => {
1561+
if matches!(
1562+
fn_kind.expect("expected RPITs to be lowered with a FnKind"),
1563+
FnDeclKind::Impl | FnDeclKind::Trait
1564+
) || self.tcx.features().lifetime_capture_rules_2024
1565+
|| span.at_least_rust_2024()
1566+
{
1567+
// return-position impl trait in trait was decided to capture all
1568+
// in-scope lifetimes, which we collect for all opaques during resolution.
1569+
self.resolver
1570+
.take_extra_lifetime_params(opaque_ty_node_id)
1571+
.into_iter()
1572+
.map(|(ident, id, _)| Lifetime { id, ident })
1573+
.collect()
1574+
} else {
1575+
// in fn return position, like the `fn test<'a>() -> impl Debug + 'a`
1576+
// example, we only need to duplicate lifetimes that appear in the
1577+
// bounds, since those are the only ones that are captured by the opaque.
1578+
lifetime_collector::lifetimes_in_bounds(self.resolver, bounds)
1579+
}
1580+
}
1581+
hir::OpaqueTyOrigin::AsyncFn(..) => {
1582+
unreachable!("should be using `lower_async_fn_ret_ty`")
15821583
}
15831584
}
1584-
hir::OpaqueTyOrigin::AsyncFn(..) => {
1585-
unreachable!("should be using `lower_async_fn_ret_ty`")
1586-
}
1587-
}
1588-
};
1585+
};
15891586
debug!(?captured_lifetimes_to_duplicate);
15901587

15911588
self.lower_opaque_inner(

compiler/rustc_parse/src/parser/ty.rs

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use super::{Parser, PathStyle, TokenType, Trailing};
1+
use super::{Parser, PathStyle, SeqSep, TokenType, Trailing};
22

33
use crate::errors::{
44
self, DynAfterMut, ExpectedFnPathFoundFnKeyword, ExpectedMutOrConstInRawPointerType,
@@ -14,7 +14,7 @@ use rustc_ast::util::case::Case;
1414
use rustc_ast::{
1515
self as ast, BareFnTy, BoundAsyncness, BoundConstness, BoundPolarity, FnRetTy, GenericBound,
1616
GenericBounds, GenericParam, Generics, Lifetime, MacCall, MutTy, Mutability, PolyTraitRef,
17-
TraitBoundModifiers, TraitObjectSyntax, Ty, TyKind, DUMMY_NODE_ID,
17+
PreciseCapturingArg, TraitBoundModifiers, TraitObjectSyntax, Ty, TyKind, DUMMY_NODE_ID,
1818
};
1919
use rustc_errors::{Applicability, PResult};
2020
use rustc_span::symbol::{kw, sym, Ident};
@@ -671,13 +671,10 @@ impl<'a> Parser<'a> {
671671

672672
// parse precise captures, if any.
673673
let precise_capturing = if self.eat_keyword(kw::Use) {
674-
self.expect_lt()?;
675674
let use_span = self.prev_token.span;
676675
self.psess.gated_spans.gate(sym::precise_capturing, use_span);
677-
let lo = self.token.span;
678-
let args = self.parse_angle_args(None)?;
679-
self.expect_gt()?;
680-
Some(ast::AngleBracketedArgs { args, span: lo.to(self.prev_token.span) }.into())
676+
let args = self.parse_precise_capturing_args()?;
677+
Some(args)
681678
} else {
682679
None
683680
};
@@ -690,6 +687,25 @@ impl<'a> Parser<'a> {
690687
Ok(TyKind::ImplTrait(ast::DUMMY_NODE_ID, bounds, precise_capturing))
691688
}
692689

690+
fn parse_precise_capturing_args(&mut self) -> PResult<'a, ThinVec<PreciseCapturingArg>> {
691+
Ok(self
692+
.parse_unspanned_seq(
693+
&TokenKind::Lt,
694+
&TokenKind::Gt,
695+
SeqSep::trailing_allowed(token::Comma),
696+
|self_| {
697+
if self_.check_ident() {
698+
Ok(PreciseCapturingArg::Arg(self_.parse_ident().unwrap(), DUMMY_NODE_ID))
699+
} else if self_.check_lifetime() {
700+
Ok(PreciseCapturingArg::Lifetime(self_.expect_lifetime()))
701+
} else {
702+
self_.unexpected_any()
703+
}
704+
},
705+
)?
706+
.0)
707+
}
708+
693709
/// Is a `dyn B0 + ... + Bn` type allowed here?
694710
fn is_explicit_dyn_type(&mut self) -> bool {
695711
self.check_keyword(kw::Dyn)

compiler/rustc_resolve/src/late.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1047,10 +1047,20 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast,
10471047
});
10481048
self.diag_metadata.current_function = previous_value;
10491049
}
1050+
10501051
fn visit_lifetime(&mut self, lifetime: &'ast Lifetime, use_ctxt: visit::LifetimeCtxt) {
10511052
self.resolve_lifetime(lifetime, use_ctxt)
10521053
}
10531054

1055+
fn visit_precise_capturing_arg(&mut self, arg: &'ast PreciseCapturingArg) {
1056+
match arg {
1057+
PreciseCapturingArg::Lifetime(_) => visit::walk_precise_capturing_arg(self, arg),
1058+
PreciseCapturingArg::Arg(ident, _) => {
1059+
todo!("cannot resolve args yet: {ident}");
1060+
}
1061+
}
1062+
}
1063+
10541064
fn visit_generics(&mut self, generics: &'ast Generics) {
10551065
self.visit_generic_params(&generics.params, self.diag_metadata.current_self_item.is_some());
10561066
for p in &generics.where_clause.predicates {

0 commit comments

Comments
 (0)