Skip to content

Commit 41cf87b

Browse files
Lower and resolve precise captures in HIR
1 parent c897092 commit 41cf87b

File tree

8 files changed

+108
-46
lines changed

8 files changed

+108
-46
lines changed

compiler/rustc_ast/src/ast.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ impl fmt::Debug for Label {
6363

6464
/// A "Lifetime" is an annotation of the scope in which variable
6565
/// can be used, e.g. `'a` in `&'a i32`.
66-
#[derive(Clone, Encodable, Decodable, Copy, PartialEq, Eq)]
66+
#[derive(Clone, Encodable, Decodable, Copy, PartialEq, Eq, Hash)]
6767
pub struct Lifetime {
6868
pub id: NodeId,
6969
pub ident: Ident,

compiler/rustc_ast/src/mut_visit.rs

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -259,10 +259,6 @@ 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-
266262
fn visit_precise_capturing_arg(&mut self, arg: &mut PreciseCapturingArg) {
267263
noop_visit_precise_capturing_arg(arg, self);
268264
}
@@ -530,7 +526,9 @@ pub fn noop_visit_ty<T: MutVisitor>(ty: &mut P<Ty>, vis: &mut T) {
530526
vis.visit_id(id);
531527
visit_vec(bounds, |bound| vis.visit_param_bound(bound));
532528
visit_opt(precise_capturing, |precise_capturing| {
533-
vis.visit_precise_capturing_args(precise_capturing);
529+
for arg in precise_capturing {
530+
vis.visit_precise_capturing_arg(arg);
531+
}
534532
});
535533
}
536534
TyKind::MacCall(mac) => vis.visit_mac_call(mac),
@@ -925,15 +923,6 @@ pub fn noop_visit_param_bound<T: MutVisitor>(pb: &mut GenericBound, vis: &mut T)
925923
}
926924
}
927925

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-
937926
pub fn noop_visit_precise_capturing_arg<T: MutVisitor>(arg: &mut PreciseCapturingArg, vis: &mut T) {
938927
match arg {
939928
PreciseCapturingArg::Lifetime(lt) => {

compiler/rustc_ast/src/visit.rs

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ 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;
2423

2524
#[derive(Copy, Clone, Debug, PartialEq)]
2625
pub enum AssocCtxt {
@@ -185,9 +184,6 @@ pub trait Visitor<'ast>: Sized {
185184
fn visit_param_bound(&mut self, bounds: &'ast GenericBound, _ctxt: BoundKind) -> Self::Result {
186185
walk_param_bound(self, bounds)
187186
}
188-
fn visit_precise_capturing_args(&mut self, args: &'ast ThinVec<PreciseCapturingArg>) {
189-
walk_precise_capturing_args(self, args);
190-
}
191187
fn visit_precise_capturing_arg(&mut self, arg: &'ast PreciseCapturingArg) {
192188
walk_precise_capturing_arg(self, arg);
193189
}
@@ -466,7 +462,11 @@ pub fn walk_ty<'a, V: Visitor<'a>>(visitor: &mut V, typ: &'a Ty) -> V::Result {
466462
}
467463
TyKind::ImplTrait(_, bounds, precise_capturing) => {
468464
walk_list!(visitor, visit_param_bound, bounds, BoundKind::Impl);
469-
visit_opt!(visitor, visit_precise_capturing_args, precise_capturing);
465+
if let Some(precise_capturing) = precise_capturing {
466+
for arg in precise_capturing {
467+
try_visit!(visitor.visit_precise_capturing_arg(arg));
468+
}
469+
}
470470
}
471471
TyKind::Typeof(expression) => try_visit!(visitor.visit_anon_const(expression)),
472472
TyKind::Infer | TyKind::ImplicitSelf | TyKind::Dummy | TyKind::Err(_) => {}
@@ -645,15 +645,6 @@ pub fn walk_param_bound<'a, V: Visitor<'a>>(visitor: &mut V, bound: &'a GenericB
645645
}
646646
}
647647

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-
657648
pub fn walk_precise_capturing_arg<'a, V: Visitor<'a>>(
658649
visitor: &mut V,
659650
arg: &'a PreciseCapturingArg,

compiler/rustc_ast_lowering/src/lib.rs

Lines changed: 40 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ use rustc_ast::{self as ast, *};
4848
use rustc_ast_pretty::pprust;
4949
use rustc_data_structures::captures::Captures;
5050
use rustc_data_structures::fingerprint::Fingerprint;
51+
use rustc_data_structures::fx::FxIndexSet;
5152
use rustc_data_structures::sorted_map::SortedMap;
5253
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
5354
use rustc_data_structures::sync::Lrc;
@@ -1525,7 +1526,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
15251526
bounds: &GenericBounds,
15261527
fn_kind: Option<FnDeclKind>,
15271528
itctx: ImplTraitContext,
1528-
precise_capturing: Option<&[ast::PreciseCapturingArg]>,
1529+
precise_capturing_args: Option<&[PreciseCapturingArg]>,
15291530
) -> hir::TyKind<'hir> {
15301531
// Make sure we know that some funky desugaring has been going on here.
15311532
// This is a first: there is code in other places like for loop
@@ -1541,9 +1542,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
15411542
precise_capturing
15421543
.iter()
15431544
.filter_map(|arg| match arg {
1544-
ast::PreciseCapturingArg::Lifetime(lt) => Some(*lt),
1545-
ast::PreciseCapturingArg::Arg(..) => None,
1545+
PreciseCapturingArg::Lifetime(lt) => Some(*lt),
1546+
PreciseCapturingArg::Arg(..) => None,
15461547
})
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))
15471552
.collect()
15481553
} else {
15491554
match origin {
@@ -1592,6 +1597,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
15921597
captured_lifetimes_to_duplicate,
15931598
span,
15941599
opaque_ty_span,
1600+
precise_capturing_args,
15951601
|this| this.lower_param_bounds(bounds, itctx),
15961602
)
15971603
}
@@ -1601,9 +1607,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
16011607
opaque_ty_node_id: NodeId,
16021608
origin: hir::OpaqueTyOrigin,
16031609
in_trait: bool,
1604-
captured_lifetimes_to_duplicate: Vec<Lifetime>,
1610+
captured_lifetimes_to_duplicate: FxIndexSet<Lifetime>,
16051611
span: Span,
16061612
opaque_ty_span: Span,
1613+
precise_capturing_args: Option<&[PreciseCapturingArg]>,
16071614
lower_item_bounds: impl FnOnce(&mut Self) -> &'hir [hir::GenericBound<'hir>],
16081615
) -> hir::TyKind<'hir> {
16091616
let opaque_ty_def_id = self.create_def(
@@ -1690,8 +1697,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
16901697
// Install the remapping from old to new (if any). This makes sure that
16911698
// any lifetimes that would have resolved to the def-id of captured
16921699
// lifetimes are remapped to the new *synthetic* lifetimes of the opaque.
1693-
let bounds = this
1694-
.with_remapping(captured_to_synthesized_mapping, |this| lower_item_bounds(this));
1700+
let (bounds, precise_capturing_args) =
1701+
this.with_remapping(captured_to_synthesized_mapping, |this| {
1702+
(
1703+
lower_item_bounds(this),
1704+
precise_capturing_args.map(|precise_capturing| {
1705+
this.lower_precise_capturing_args(precise_capturing)
1706+
}),
1707+
)
1708+
});
16951709

16961710
let generic_params =
16971711
this.arena.alloc_from_iter(synthesized_lifetime_definitions.iter().map(
@@ -1736,6 +1750,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
17361750
origin,
17371751
lifetime_mapping,
17381752
in_trait,
1753+
precise_capturing_args,
17391754
};
17401755

17411756
// Generate an `type Foo = impl Trait;` declaration.
@@ -1768,6 +1783,23 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
17681783
)
17691784
}
17701785

1786+
fn lower_precise_capturing_args(
1787+
&mut self,
1788+
precise_capturing_args: &[PreciseCapturingArg],
1789+
) -> &'hir [hir::PreciseCapturingArg<'hir>] {
1790+
self.arena.alloc_from_iter(precise_capturing_args.iter().map(|arg| match arg {
1791+
PreciseCapturingArg::Lifetime(lt) => {
1792+
hir::PreciseCapturingArg::Lifetime(self.lower_lifetime(lt))
1793+
}
1794+
PreciseCapturingArg::Arg(_, node_id) => {
1795+
let res = self.resolver.get_partial_res(*node_id).map_or(Res::Err, |partial_res| {
1796+
partial_res.full_res().expect("no partial res expected for precise capture arg")
1797+
});
1798+
hir::PreciseCapturingArg::Param(self.lower_res(res), self.lower_node_id(*node_id))
1799+
}
1800+
}))
1801+
}
1802+
17711803
fn lower_fn_params_to_names(&mut self, decl: &FnDecl) -> &'hir [Ident] {
17721804
self.arena.alloc_from_iter(decl.inputs.iter().map(|param| match param.pat.kind {
17731805
PatKind::Ident(_, ident, _) => self.lower_ident(ident),
@@ -1908,7 +1940,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
19081940
let opaque_ty_span =
19091941
self.mark_span_with_reason(DesugaringKind::Async, span, allowed_features);
19101942

1911-
let captured_lifetimes: Vec<_> = self
1943+
let captured_lifetimes = self
19121944
.resolver
19131945
.take_extra_lifetime_params(opaque_ty_node_id)
19141946
.into_iter()
@@ -1922,6 +1954,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
19221954
captured_lifetimes,
19231955
span,
19241956
opaque_ty_span,
1957+
None,
19251958
|this| {
19261959
let bound = this.lower_coroutine_fn_output_type_to_bound(
19271960
output,

compiler/rustc_ast_lowering/src/lifetime_collector.rs

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use super::ResolverAstLoweringExt;
22
use rustc_ast::visit::{self, BoundKind, LifetimeCtxt, Visitor};
33
use rustc_ast::{GenericBounds, Lifetime, NodeId, PathSegment, PolyTraitRef, Ty, TyKind};
4+
use rustc_data_structures::fx::FxIndexSet;
45
use rustc_hir::def::{DefKind, LifetimeRes, Res};
56
use rustc_middle::span_bug;
67
use rustc_middle::ty::ResolverAstLowering;
@@ -10,27 +11,23 @@ use rustc_span::Span;
1011
struct LifetimeCollectVisitor<'ast> {
1112
resolver: &'ast ResolverAstLowering,
1213
current_binders: Vec<NodeId>,
13-
collected_lifetimes: Vec<Lifetime>,
14+
collected_lifetimes: FxIndexSet<Lifetime>,
1415
}
1516

1617
impl<'ast> LifetimeCollectVisitor<'ast> {
1718
fn new(resolver: &'ast ResolverAstLowering) -> Self {
18-
Self { resolver, current_binders: Vec::new(), collected_lifetimes: Vec::new() }
19+
Self { resolver, current_binders: Vec::new(), collected_lifetimes: FxIndexSet::default() }
1920
}
2021

2122
fn record_lifetime_use(&mut self, lifetime: Lifetime) {
2223
match self.resolver.get_lifetime_res(lifetime.id).unwrap_or(LifetimeRes::Error) {
2324
LifetimeRes::Param { binder, .. } | LifetimeRes::Fresh { binder, .. } => {
2425
if !self.current_binders.contains(&binder) {
25-
if !self.collected_lifetimes.contains(&lifetime) {
26-
self.collected_lifetimes.push(lifetime);
27-
}
26+
self.collected_lifetimes.insert(lifetime);
2827
}
2928
}
3029
LifetimeRes::Static | LifetimeRes::Error => {
31-
if !self.collected_lifetimes.contains(&lifetime) {
32-
self.collected_lifetimes.push(lifetime);
33-
}
30+
self.collected_lifetimes.insert(lifetime);
3431
}
3532
LifetimeRes::Infer => {}
3633
res => {
@@ -111,7 +108,7 @@ impl<'ast> Visitor<'ast> for LifetimeCollectVisitor<'ast> {
111108
pub(crate) fn lifetimes_in_bounds(
112109
resolver: &ResolverAstLowering,
113110
bounds: &GenericBounds,
114-
) -> Vec<Lifetime> {
111+
) -> FxIndexSet<Lifetime> {
115112
let mut visitor = LifetimeCollectVisitor::new(resolver);
116113
for bound in bounds {
117114
visitor.visit_param_bound(bound, BoundKind::Bound);

compiler/rustc_hir/src/hir.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2557,6 +2557,15 @@ pub struct OpaqueTy<'hir> {
25572557
/// originating from a trait method. This makes it so that the opaque is
25582558
/// lowered as an associated type.
25592559
pub in_trait: bool,
2560+
/// List of arguments captured via `impl use<'a, P, ...> Trait` syntax.
2561+
pub precise_capturing_args: Option<&'hir [PreciseCapturingArg<'hir>]>,
2562+
}
2563+
2564+
#[derive(Debug, Clone, Copy, HashStable_Generic)]
2565+
pub enum PreciseCapturingArg<'hir> {
2566+
Lifetime(&'hir Lifetime),
2567+
/// Non-lifetime argument (type or const)
2568+
Param(Res, HirId),
25602569
}
25612570

25622571
/// From whence the opaque type came.

compiler/rustc_hir/src/intravisit.rs

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -413,6 +413,9 @@ pub trait Visitor<'v>: Sized {
413413
fn visit_param_bound(&mut self, bounds: &'v GenericBound<'v>) -> Self::Result {
414414
walk_param_bound(self, bounds)
415415
}
416+
fn visit_precise_capturing_arg(&mut self, arg: &'v PreciseCapturingArg<'v>) -> Self::Result {
417+
walk_precise_capturing_arg(self, arg)
418+
}
416419
fn visit_poly_trait_ref(&mut self, t: &'v PolyTraitRef<'v>) -> Self::Result {
417420
walk_poly_trait_ref(self, t)
418421
}
@@ -526,10 +529,15 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) -> V::
526529
try_visit!(visitor.visit_ty(ty));
527530
try_visit!(visitor.visit_generics(generics));
528531
}
529-
ItemKind::OpaqueTy(&OpaqueTy { generics, bounds, .. }) => {
532+
ItemKind::OpaqueTy(&OpaqueTy { generics, bounds, precise_capturing_args, .. }) => {
530533
try_visit!(visitor.visit_id(item.hir_id()));
531534
try_visit!(walk_generics(visitor, generics));
532535
walk_list!(visitor, visit_param_bound, bounds);
536+
if let Some(precise_capturing_args) = precise_capturing_args {
537+
for arg in precise_capturing_args {
538+
try_visit!(visitor.visit_precise_capturing_arg(arg));
539+
}
540+
}
533541
}
534542
ItemKind::Enum(ref enum_definition, ref generics) => {
535543
try_visit!(visitor.visit_generics(generics));
@@ -1137,6 +1145,16 @@ pub fn walk_param_bound<'v, V: Visitor<'v>>(
11371145
}
11381146
}
11391147

1148+
pub fn walk_precise_capturing_arg<'v, V: Visitor<'v>>(
1149+
visitor: &mut V,
1150+
arg: &'v PreciseCapturingArg<'v>,
1151+
) -> V::Result {
1152+
match *arg {
1153+
PreciseCapturingArg::Lifetime(lt) => visitor.visit_lifetime(lt),
1154+
PreciseCapturingArg::Param(_, hir_id) => visitor.visit_id(hir_id),
1155+
}
1156+
}
1157+
11401158
pub fn walk_poly_trait_ref<'v, V: Visitor<'v>>(
11411159
visitor: &mut V,
11421160
trait_ref: &'v PolyTraitRef<'v>,

compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -557,6 +557,31 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
557557
}
558558
}
559559

560+
fn visit_precise_capturing_arg(
561+
&mut self,
562+
arg: &'tcx hir::PreciseCapturingArg<'tcx>,
563+
) -> Self::Result {
564+
match *arg {
565+
hir::PreciseCapturingArg::Lifetime(lt) => match lt.res {
566+
LifetimeName::Param(def_id) => {
567+
self.resolve_lifetime_ref(def_id, lt);
568+
}
569+
LifetimeName::Error => {}
570+
LifetimeName::ImplicitObjectLifetimeDefault
571+
| LifetimeName::Infer
572+
| LifetimeName::Static => todo!("TODO: Error on invalid lifetime"),
573+
},
574+
hir::PreciseCapturingArg::Param(res, hir_id) => match res {
575+
Res::Def(DefKind::TyParam | DefKind::ConstParam, def_id)
576+
| Res::SelfTyParam { trait_: def_id } => {
577+
self.resolve_type_ref(def_id.expect_local(), hir_id);
578+
}
579+
Res::Err => {}
580+
_ => todo!("TODO: Error on invalid param res"),
581+
},
582+
}
583+
}
584+
560585
fn visit_foreign_item(&mut self, item: &'tcx hir::ForeignItem<'tcx>) {
561586
match item.kind {
562587
hir::ForeignItemKind::Fn(_, _, generics) => {

0 commit comments

Comments
 (0)