Skip to content

Commit c1f62a7

Browse files
committed
Auto merge of #126049 - compiler-errors:rework-use, r=oli-obk
Rework `feature(precise_capturing)` to represent `use<...>` as a syntactical bound Reworks `precise_capturing` for a recent lang-team consensus. Specifically: > The conclusion of the team is that we'll make use<..> a bound. That is, we'll support impl use<..> + Trait, impl Trait + use<..>, etc. > For now, we will support at most one such bound in a list of bounds, and semantically we'll only support these bounds in the item bounds of RPIT-like impl Trait opaque types (i.e., in the places discussed in the RFC). Lang decision in favor of this approach: - #125836 (comment) Tracking: - #123432
2 parents f873ae0 + 2273747 commit c1f62a7

File tree

76 files changed

+628
-574
lines changed

Some content is hidden

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

76 files changed

+628
-574
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/messages.ftl

+1-1
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ ast_lowering_never_pattern_with_guard =
128128
a guard on a never pattern will never be run
129129
.suggestion = remove this guard
130130
131-
ast_lowering_no_precise_captures_on_apit = `use<...>` precise capturing syntax not allowed on argument-position `impl Trait`
131+
ast_lowering_no_precise_captures_on_apit = `use<...>` precise capturing syntax not allowed in argument-position `impl Trait`
132132
133133
ast_lowering_previously_used_here = previously used here
134134

compiler/rustc_ast_lowering/src/lib.rs

+71-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,20 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
13841384
}
13851385
None
13861386
}
1387+
// Ignore `use` syntax since that is not valid in objects.
1388+
GenericBound::Use(_, span) => {
1389+
this.dcx()
1390+
.span_delayed_bug(*span, "use<> not allowed in dyn types");
1391+
None
1392+
}
13871393
}));
13881394
let lifetime_bound =
13891395
lifetime_bound.unwrap_or_else(|| this.elided_dyn_bound(t.span));
13901396
(bounds, lifetime_bound)
13911397
});
13921398
hir::TyKind::TraitObject(bounds, lifetime_bound, *kind)
13931399
}
1394-
TyKind::ImplTrait(def_node_id, bounds, precise_capturing) => {
1400+
TyKind::ImplTrait(def_node_id, bounds) => {
13951401
let span = t.span;
13961402
match itctx {
13971403
ImplTraitContext::OpaqueTy { origin, fn_kind } => self.lower_opaque_impl_trait(
@@ -1401,12 +1407,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
14011407
bounds,
14021408
fn_kind,
14031409
itctx,
1404-
precise_capturing.as_deref().map(|(args, span)| (args.as_slice(), *span)),
14051410
),
14061411
ImplTraitContext::Universal => {
1407-
if let Some(&(_, span)) = precise_capturing.as_deref() {
1412+
if let Some(span) = bounds.iter().find_map(|bound| match *bound {
1413+
ast::GenericBound::Use(_, span) => Some(span),
1414+
_ => None,
1415+
}) {
14081416
self.tcx.dcx().emit_err(errors::NoPreciseCapturesOnApit { span });
1409-
};
1417+
}
1418+
14101419
let span = t.span;
14111420

14121421
// HACK: pprust breaks strings with newlines when the type
@@ -1517,7 +1526,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
15171526
bounds: &GenericBounds,
15181527
fn_kind: Option<FnDeclKind>,
15191528
itctx: ImplTraitContext,
1520-
precise_capturing_args: Option<(&[PreciseCapturingArg], Span)>,
15211529
) -> hir::TyKind<'hir> {
15221530
// Make sure we know that some funky desugaring has been going on here.
15231531
// This is a first: there is code in other places like for loop
@@ -1526,59 +1534,64 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
15261534
// frequently opened issues show.
15271535
let opaque_ty_span = self.mark_span_with_reason(DesugaringKind::OpaqueTy, span, None);
15281536

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

15841597
self.lower_opaque_inner(
@@ -1588,7 +1601,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
15881601
captured_lifetimes_to_duplicate,
15891602
span,
15901603
opaque_ty_span,
1591-
precise_capturing_args,
15921604
|this| this.lower_param_bounds(bounds, itctx),
15931605
)
15941606
}
@@ -1601,7 +1613,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
16011613
captured_lifetimes_to_duplicate: FxIndexSet<Lifetime>,
16021614
span: Span,
16031615
opaque_ty_span: Span,
1604-
precise_capturing_args: Option<(&[PreciseCapturingArg], Span)>,
16051616
lower_item_bounds: impl FnOnce(&mut Self) -> &'hir [hir::GenericBound<'hir>],
16061617
) -> hir::TyKind<'hir> {
16071618
let opaque_ty_def_id = self.create_def(
@@ -1688,18 +1699,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
16881699
// Install the remapping from old to new (if any). This makes sure that
16891700
// any lifetimes that would have resolved to the def-id of captured
16901701
// 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-
});
1702+
let bounds = this
1703+
.with_remapping(captured_to_synthesized_mapping, |this| lower_item_bounds(this));
17031704

17041705
let generic_params =
17051706
this.arena.alloc_from_iter(synthesized_lifetime_definitions.iter().map(
@@ -1744,7 +1745,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
17441745
origin,
17451746
lifetime_mapping,
17461747
in_trait,
1747-
precise_capturing_args,
17481748
};
17491749

17501750
// Generate an `type Foo = impl Trait;` declaration.
@@ -1955,7 +1955,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
19551955
captured_lifetimes,
19561956
span,
19571957
opaque_ty_span,
1958-
None,
19591958
|this| {
19601959
let bound = this.lower_coroutine_fn_output_type_to_bound(
19611960
output,
@@ -2038,6 +2037,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
20382037
GenericBound::Outlives(lifetime) => {
20392038
hir::GenericBound::Outlives(self.lower_lifetime(lifetime))
20402039
}
2040+
GenericBound::Use(args, span) => hir::GenericBound::Use(
2041+
self.lower_precise_capturing_args(args),
2042+
self.lower_span(*span),
2043+
),
20412044
}
20422045
}
20432046

compiler/rustc_ast_passes/messages.ftl

+5
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,11 @@ ast_passes_pattern_in_fn_pointer = patterns aren't allowed in function pointer t
215215
ast_passes_pattern_in_foreign = patterns aren't allowed in foreign function declarations
216216
.label = pattern not allowed in foreign function
217217
218+
ast_passes_precise_capturing_duplicated = duplicate `use<...>` precise capturing syntax
219+
.label = second `use<...>` here
220+
221+
ast_passes_precise_capturing_not_allowed_here = `use<...>` precise capturing syntax not allowed in {$loc}
222+
218223
ast_passes_show_span = {$msg}
219224
220225
ast_passes_stability_outside_std = stability attributes may not be used outside of the standard library

0 commit comments

Comments
 (0)