Skip to content

Commit b1efe1a

Browse files
Rework precise capturing syntax
1 parent 68bd001 commit b1efe1a

Some content is hidden

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

54 files changed

+405
-349
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
}
@@ -2162,7 +2165,7 @@ pub enum TyKind {
21622165
/// The `NodeId` exists to prevent lowering from having to
21632166
/// generate `NodeId`s on the fly, which would complicate
21642167
/// the generation of opaque `type Foo = impl Trait` items significantly.
2165-
ImplTrait(NodeId, GenericBounds, Option<P<(ThinVec<PreciseCapturingArg>, Span)>>),
2168+
ImplTrait(NodeId, GenericBounds),
21662169
/// No-op; kept solely so that we can pretty-print faithfully.
21672170
Paren(P<Ty>),
21682171
/// 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) => {
@@ -923,6 +918,11 @@ fn noop_visit_param_bound<T: MutVisitor>(pb: &mut GenericBound, vis: &mut T) {
923918
match pb {
924919
GenericBound::Trait(ty, _modifier) => vis.visit_poly_trait_ref(ty),
925920
GenericBound::Outlives(lifetime) => noop_visit_lifetime(lifetime, vis),
921+
GenericBound::Use(args, _) => {
922+
for arg in args {
923+
vis.visit_precise_capturing_arg(arg);
924+
}
925+
}
926926
}
927927
}
928928

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(_) => {}
@@ -688,6 +693,10 @@ pub fn walk_param_bound<'a, V: Visitor<'a>>(visitor: &mut V, bound: &'a GenericB
688693
match bound {
689694
GenericBound::Trait(typ, _modifier) => visitor.visit_poly_trait_ref(typ),
690695
GenericBound::Outlives(lifetime) => visitor.visit_lifetime(lifetime, LifetimeCtxt::Bound),
696+
GenericBound::Use(args, _) => {
697+
walk_list!(visitor, visit_precise_capturing_arg, args);
698+
V::Result::output()
699+
}
691700
}
692701
}
693702

compiler/rustc_ast_lowering/src/lib.rs

+64-68
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,9 @@ use rustc_data_structures::sorted_map::SortedMap;
5151
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
5252
use rustc_data_structures::sync::Lrc;
5353
use rustc_errors::{DiagArgFromDisplay, DiagCtxt, StashKey};
54-
use rustc_hir as hir;
5554
use rustc_hir::def::{DefKind, LifetimeRes, Namespace, PartialRes, PerNS, Res};
5655
use rustc_hir::def_id::{LocalDefId, LocalDefIdMap, CRATE_DEF_ID, LOCAL_CRATE};
56+
use rustc_hir::{self as hir};
5757
use rustc_hir::{
5858
ConstArg, GenericArg, HirId, ItemLocalMap, MissingLifetimeKind, ParamName, TraitCandidate,
5959
};
@@ -1384,14 +1384,16 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
13841384
}
13851385
None
13861386
}
1387+
// Ignore `use` syntax since that is not valid in objects.
1388+
GenericBound::Use(..) => None,
13871389
}));
13881390
let lifetime_bound =
13891391
lifetime_bound.unwrap_or_else(|| this.elided_dyn_bound(t.span));
13901392
(bounds, lifetime_bound)
13911393
});
13921394
hir::TyKind::TraitObject(bounds, lifetime_bound, *kind)
13931395
}
1394-
TyKind::ImplTrait(def_node_id, bounds, precise_capturing) => {
1396+
TyKind::ImplTrait(def_node_id, bounds) => {
13951397
let span = t.span;
13961398
match itctx {
13971399
ImplTraitContext::OpaqueTy { origin, fn_kind } => self.lower_opaque_impl_trait(
@@ -1401,12 +1403,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
14011403
bounds,
14021404
fn_kind,
14031405
itctx,
1404-
precise_capturing.as_deref().map(|(args, span)| (args.as_slice(), *span)),
14051406
),
14061407
ImplTraitContext::Universal => {
1407-
if let Some(&(_, span)) = precise_capturing.as_deref() {
1408+
if let Some(span) = bounds.iter().find_map(|bound| match *bound {
1409+
ast::GenericBound::Use(_, span) => Some(span),
1410+
_ => None,
1411+
}) {
14081412
self.tcx.dcx().emit_err(errors::NoPreciseCapturesOnApit { span });
1409-
};
1413+
}
1414+
14101415
let span = t.span;
14111416

14121417
// HACK: pprust breaks strings with newlines when the type
@@ -1517,7 +1522,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
15171522
bounds: &GenericBounds,
15181523
fn_kind: Option<FnDeclKind>,
15191524
itctx: ImplTraitContext,
1520-
precise_capturing_args: Option<(&[PreciseCapturingArg], Span)>,
15211525
) -> hir::TyKind<'hir> {
15221526
// Make sure we know that some funky desugaring has been going on here.
15231527
// This is a first: there is code in other places like for loop
@@ -1526,59 +1530,61 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
15261530
// frequently opened issues show.
15271531
let opaque_ty_span = self.mark_span_with_reason(DesugaringKind::OpaqueTy, span, None);
15281532

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

15841590
self.lower_opaque_inner(
@@ -1588,7 +1594,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
15881594
captured_lifetimes_to_duplicate,
15891595
span,
15901596
opaque_ty_span,
1591-
precise_capturing_args,
15921597
|this| this.lower_param_bounds(bounds, itctx),
15931598
)
15941599
}
@@ -1601,7 +1606,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
16011606
captured_lifetimes_to_duplicate: FxIndexSet<Lifetime>,
16021607
span: Span,
16031608
opaque_ty_span: Span,
1604-
precise_capturing_args: Option<(&[PreciseCapturingArg], Span)>,
16051609
lower_item_bounds: impl FnOnce(&mut Self) -> &'hir [hir::GenericBound<'hir>],
16061610
) -> hir::TyKind<'hir> {
16071611
let opaque_ty_def_id = self.create_def(
@@ -1688,18 +1692,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
16881692
// Install the remapping from old to new (if any). This makes sure that
16891693
// any lifetimes that would have resolved to the def-id of captured
16901694
// lifetimes are remapped to the new *synthetic* lifetimes of the opaque.
1691-
let (bounds, precise_capturing_args) =
1692-
this.with_remapping(captured_to_synthesized_mapping, |this| {
1693-
(
1694-
lower_item_bounds(this),
1695-
precise_capturing_args.map(|(precise_capturing, span)| {
1696-
(
1697-
this.lower_precise_capturing_args(precise_capturing),
1698-
this.lower_span(span),
1699-
)
1700-
}),
1701-
)
1702-
});
1695+
let bounds = this
1696+
.with_remapping(captured_to_synthesized_mapping, |this| lower_item_bounds(this));
17031697

17041698
let generic_params =
17051699
this.arena.alloc_from_iter(synthesized_lifetime_definitions.iter().map(
@@ -1744,7 +1738,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
17441738
origin,
17451739
lifetime_mapping,
17461740
in_trait,
1747-
precise_capturing_args,
17481741
};
17491742

17501743
// Generate an `type Foo = impl Trait;` declaration.
@@ -1955,7 +1948,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
19551948
captured_lifetimes,
19561949
span,
19571950
opaque_ty_span,
1958-
None,
19591951
|this| {
19601952
let bound = this.lower_coroutine_fn_output_type_to_bound(
19611953
output,
@@ -2038,6 +2030,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
20382030
GenericBound::Outlives(lifetime) => {
20392031
hir::GenericBound::Outlives(self.lower_lifetime(lifetime))
20402032
}
2033+
GenericBound::Use(args, span) => hir::GenericBound::Use(
2034+
self.lower_precise_capturing_args(args),
2035+
self.lower_span(*span),
2036+
),
20412037
}
20422038
}
20432039

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)