Skip to content

Commit 9eb7561

Browse files
committed
Generate DefIds for the impl trait of async functions
1 parent 2ec5eab commit 9eb7561

File tree

7 files changed

+102
-56
lines changed

7 files changed

+102
-56
lines changed

src/librustc/hir/lowering.rs

Lines changed: 44 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -863,7 +863,7 @@ impl<'a> LoweringContext<'a> {
863863

864864
let capture_clause = self.lower_capture_clause(capture_clause);
865865
let closure_hir_id = self.lower_node_id(closure_node_id).hir_id;
866-
let decl = self.lower_fn_decl(&decl, None, /* impl trait allowed */ false, false);
866+
let decl = self.lower_fn_decl(&decl, None, /* impl trait allowed */ false, None);
867867
let generator = hir::Expr {
868868
id: closure_node_id,
869869
hir_id: closure_hir_id,
@@ -1106,7 +1106,7 @@ impl<'a> LoweringContext<'a> {
11061106
),
11071107
unsafety: this.lower_unsafety(f.unsafety),
11081108
abi: f.abi,
1109-
decl: this.lower_fn_decl(&f.decl, None, false, false),
1109+
decl: this.lower_fn_decl(&f.decl, None, false, None),
11101110
arg_names: this.lower_fn_args_to_names(&f.decl),
11111111
}))
11121112
},
@@ -1176,7 +1176,7 @@ impl<'a> LoweringContext<'a> {
11761176
|this| this.lower_param_bounds(bounds, itctx),
11771177
)
11781178
}
1179-
ImplTraitContext::Universal(def_id) => {
1179+
ImplTraitContext::Universal(_def_id) => {
11801180
self.lower_node_id(def_node_id);
11811181
// Add a definition for the in-band TyParam
11821182
let def_index = self
@@ -1866,18 +1866,18 @@ impl<'a> LoweringContext<'a> {
18661866
// decl: the unlowered (ast) function declaration.
18671867
// fn_def_id: if `Some`, impl Trait arguments are lowered into generic parameters on the
18681868
// given DefId, otherwise impl Trait is disallowed. Must be `Some` if
1869-
// make_ret_async is true.
1869+
// make_ret_async is also `Some`.
18701870
// impl_trait_return_allow: determines whether impl Trait can be used in return position.
18711871
// This guards against trait declarations and implementations where impl Trait is
18721872
// disallowed.
1873-
// make_ret_async: if enabled, converts `-> T` into `-> impl Future<Output = T>` in the
1873+
// make_ret_async: if `Some`, converts `-> T` into `-> impl Future<Output = T>` in the
18741874
// return type. This is used for `async fn` declarations.
18751875
fn lower_fn_decl(
18761876
&mut self,
18771877
decl: &FnDecl,
18781878
fn_def_id: Option<DefId>,
18791879
impl_trait_return_allow: bool,
1880-
make_ret_async: bool,
1880+
make_ret_async: Option<NodeId>,
18811881
) -> P<hir::FnDecl> {
18821882
let inputs = decl.inputs
18831883
.iter()
@@ -1890,9 +1890,9 @@ impl<'a> LoweringContext<'a> {
18901890
})
18911891
.collect::<HirVec<_>>();
18921892

1893-
let output = if make_ret_async {
1893+
let output = if let Some(ret_id) = make_ret_async {
18941894
self.lower_async_fn_ret_ty(
1895-
&inputs, &decl.output, fn_def_id.expect("make_ret_async but no fn_def_id"))
1895+
&inputs, &decl.output, fn_def_id.expect("make_ret_async but no fn_def_id"), ret_id)
18961896
} else {
18971897
match decl.output {
18981898
FunctionRetTy::Ty(ref ty) => match fn_def_id {
@@ -1928,6 +1928,7 @@ impl<'a> LoweringContext<'a> {
19281928
inputs: &[P<hir::Ty>],
19291929
output: &FunctionRetTy,
19301930
fn_def_id: DefId,
1931+
return_impl_trait_id: NodeId,
19311932
) -> hir::FunctionRetTy {
19321933
// Get lifetimes used in the input arguments to the function. Our output type must also
19331934
// have the same lifetime. FIXME(cramertj) multiple different lifetimes are not allowed
@@ -2079,7 +2080,7 @@ impl<'a> LoweringContext<'a> {
20792080
};
20802081

20812082
let impl_trait_ty = self.lower_existential_impl_trait(
2082-
span, fn_def_id, |this| {
2083+
span, fn_def_id, return_impl_trait_id, |this| {
20832084
let output_ty = match output {
20842085
FunctionRetTy::Ty(ty) =>
20852086
this.lower_ty(ty, ImplTraitContext::Existential(fn_def_id)),
@@ -2564,9 +2565,9 @@ impl<'a> LoweringContext<'a> {
25642565
// only cares about the input argument patterns in the function
25652566
// declaration (decl), not the return types.
25662567
let body_id = this.lower_body(Some(decl), |this| {
2567-
if let IsAsync::Async(async_node_id) = header.asyncness {
2568+
if let IsAsync::Async { closure_id, .. } = header.asyncness {
25682569
let async_expr = this.make_async_expr(
2569-
CaptureBy::Value, async_node_id, None,
2570+
CaptureBy::Value, closure_id, None,
25702571
|this| {
25712572
let body = this.lower_block(body, false);
25722573
this.expr_block(body, ThinVec::new())
@@ -2578,12 +2579,17 @@ impl<'a> LoweringContext<'a> {
25782579
}
25792580
});
25802581

2582+
let asyncness = match header.asyncness {
2583+
IsAsync::Async { return_impl_trait_id, .. } => Some(return_impl_trait_id),
2584+
IsAsync::NotAsync => None,
2585+
};
2586+
25812587
let (generics, fn_decl) = this.add_in_band_defs(
25822588
generics,
25832589
fn_def_id,
25842590
AnonymousLifetimeMode::PassThrough,
25852591
|this| this.lower_fn_decl(
2586-
decl, Some(fn_def_id), true, header.asyncness.is_async())
2592+
decl, Some(fn_def_id), true, asyncness)
25872593
);
25882594

25892595
hir::ItemFn(
@@ -2906,7 +2912,7 @@ impl<'a> LoweringContext<'a> {
29062912
AnonymousLifetimeMode::PassThrough,
29072913
|this| {
29082914
hir::TraitItemKind::Method(
2909-
this.lower_method_sig(sig, trait_item_def_id, false, false),
2915+
this.lower_method_sig(sig, trait_item_def_id, false, None),
29102916
hir::TraitMethod::Required(names),
29112917
)
29122918
},
@@ -2924,7 +2930,7 @@ impl<'a> LoweringContext<'a> {
29242930
AnonymousLifetimeMode::PassThrough,
29252931
|this| {
29262932
hir::TraitItemKind::Method(
2927-
this.lower_method_sig(sig, trait_item_def_id, false, false),
2933+
this.lower_method_sig(sig, trait_item_def_id, false, None),
29282934
hir::TraitMethod::Provided(body_id),
29292935
)
29302936
},
@@ -2995,9 +3001,9 @@ impl<'a> LoweringContext<'a> {
29953001
}
29963002
ImplItemKind::Method(ref sig, ref body) => {
29973003
let body_id = self.lower_body(Some(&sig.decl), |this| {
2998-
if let IsAsync::Async(async_node_id) = sig.header.asyncness {
3004+
if let IsAsync::Async { closure_id, .. } = sig.header.asyncness {
29993005
let async_expr = this.make_async_expr(
3000-
CaptureBy::Value, async_node_id, None,
3006+
CaptureBy::Value, closure_id, None,
30013007
|this| {
30023008
let body = this.lower_block(body, false);
30033009
this.expr_block(body, ThinVec::new())
@@ -3010,6 +3016,11 @@ impl<'a> LoweringContext<'a> {
30103016
});
30113017
let impl_trait_return_allow = !self.is_in_trait_impl;
30123018

3019+
let asyncness = match sig.header.asyncness {
3020+
IsAsync::Async { return_impl_trait_id, .. } => Some(return_impl_trait_id),
3021+
IsAsync::NotAsync => None,
3022+
};
3023+
30133024
self.add_in_band_defs(
30143025
&i.generics,
30153026
impl_item_def_id,
@@ -3020,7 +3031,7 @@ impl<'a> LoweringContext<'a> {
30203031
sig,
30213032
impl_item_def_id,
30223033
impl_trait_return_allow,
3023-
sig.header.asyncness.is_async(),
3034+
asyncness,
30243035
),
30253036
body_id,
30263037
)
@@ -3100,8 +3111,8 @@ impl<'a> LoweringContext<'a> {
31003111
path_span: Span,
31013112
path_segment: &'v PathSegment,
31023113
) {
3103-
if let Some(ref p) = path_segment.parameters {
3104-
if let PathParameters::Parenthesized(..) = **p {
3114+
if let Some(ref p) = path_segment.args {
3115+
if let GenericArgs::Parenthesized(_) = **p {
31053116
return;
31063117
}
31073118
}
@@ -3123,15 +3134,21 @@ impl<'a> LoweringContext<'a> {
31233134
vec
31243135
}
31253136
ItemKind::MacroDef(..) => SmallVector::new(),
3126-
ItemKind::Fn(ref decl, ..) => {
3137+
ItemKind::Fn(ref decl, ref header, ..) => {
31273138
let mut ids = SmallVector::one(hir::ItemId { id: i.id });
3139+
if let IsAsync::Async { return_impl_trait_id, .. } = header.asyncness {
3140+
ids.push(hir::ItemId { id: return_impl_trait_id });
3141+
}
31283142
self.lower_impl_trait_ids(decl, &mut ids);
31293143
ids
31303144
},
31313145
ItemKind::Impl(.., ref items) => {
31323146
let mut ids = SmallVector::one(hir::ItemId { id: i.id });
31333147
for item in items {
31343148
if let ImplItemKind::Method(ref sig, _) = item.node {
3149+
if let IsAsync::Async { return_impl_trait_id, .. } = sig.header.asyncness {
3150+
ids.push(hir::ItemId { id: return_impl_trait_id });
3151+
}
31353152
self.lower_impl_trait_ids(&sig.decl, &mut ids);
31363153
}
31373154
}
@@ -3214,7 +3231,7 @@ impl<'a> LoweringContext<'a> {
32143231
|this| {
32153232
(
32163233
// Disallow impl Trait in foreign items
3217-
this.lower_fn_decl(fdec, None, false, false),
3234+
this.lower_fn_decl(fdec, None, false, None),
32183235
this.lower_fn_args_to_names(fdec),
32193236
)
32203237
},
@@ -3238,7 +3255,7 @@ impl<'a> LoweringContext<'a> {
32383255
sig: &MethodSig,
32393256
fn_def_id: DefId,
32403257
impl_trait_return_allow: bool,
3241-
is_async: bool,
3258+
is_async: Option<NodeId>,
32423259
) -> hir::MethodSig {
32433260
hir::MethodSig {
32443261
header: self.lower_fn_header(sig.header),
@@ -3278,7 +3295,7 @@ impl<'a> LoweringContext<'a> {
32783295

32793296
fn lower_asyncness(&mut self, a: IsAsync) -> hir::IsAsync {
32803297
match a {
3281-
IsAsync::Async(_) => hir::IsAsync::Async,
3298+
IsAsync::Async { .. } => hir::IsAsync::Async,
32823299
IsAsync::NotAsync => hir::IsAsync::NotAsync,
32833300
}
32843301
}
@@ -3581,7 +3598,7 @@ impl<'a> LoweringContext<'a> {
35813598
ExprKind::Closure(
35823599
capture_clause, asyncness, movability, ref decl, ref body, fn_decl_span
35833600
) => {
3584-
if let IsAsync::Async(async_closure_node_id) = asyncness {
3601+
if let IsAsync::Async { async_closure_node_id, .. } = asyncness {
35853602
let outer_decl = FnDecl {
35863603
inputs: decl.inputs.clone(),
35873604
output: FunctionRetTy::Default(fn_decl_span),
@@ -3590,7 +3607,7 @@ impl<'a> LoweringContext<'a> {
35903607
// We need to lower the declaration outside the new scope, because we
35913608
// have to conserve the state of being inside a loop condition for the
35923609
// closure argument types.
3593-
let fn_decl = self.lower_fn_decl(&outer_decl, None, false, false);
3610+
let fn_decl = self.lower_fn_decl(&outer_decl, None, false, None);
35943611

35953612
self.with_new_scopes(|this| {
35963613
// FIXME(cramertj) allow `async` non-`move` closures with
@@ -3617,7 +3634,7 @@ impl<'a> LoweringContext<'a> {
36173634
Some(&**ty)
36183635
} else { None };
36193636
let async_body = this.make_async_expr(
3620-
capture_clause, async_closure_node_id, async_ret_ty,
3637+
capture_clause, closure_id, async_ret_ty,
36213638
|this| {
36223639
this.with_new_scopes(|this| this.lower_expr(body))
36233640
});
@@ -3633,7 +3650,7 @@ impl<'a> LoweringContext<'a> {
36333650
})
36343651
} else {
36353652
// Lower outside new scope to preserve `is_in_loop_condition`.
3636-
let fn_decl = self.lower_fn_decl(decl, None, false, false);
3653+
let fn_decl = self.lower_fn_decl(decl, None, false, None);
36373654

36383655
self.with_new_scopes(|this| {
36393656
let mut is_generator = false;

src/librustc/hir/map/def_collector.rs

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ impl<'a> DefCollector<'a> {
7777
&mut self,
7878
id: NodeId,
7979
async_node_id: NodeId,
80+
return_impl_trait_id: NodeId,
8081
name: Name,
8182
span: Span,
8283
visit_fn: impl FnOnce(&mut DefCollector<'a>)
@@ -86,6 +87,7 @@ impl<'a> DefCollector<'a> {
8687
let fn_def_data = DefPathData::ValueNs(name.as_interned_str());
8788
let fn_def = self.create_def(id, fn_def_data, ITEM_LIKE_SPACE, span);
8889
return self.with_parent(fn_def, |this| {
90+
this.create_def(return_impl_trait_id, DefPathData::ImplTrait, REGULAR_SPACE, span);
8991
let closure_def = this.create_def(async_node_id,
9092
DefPathData::ClosureExpr,
9193
REGULAR_SPACE,
@@ -120,10 +122,14 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
120122
ItemKind::Mod(..) if i.ident == keywords::Invalid.ident() => {
121123
return visit::walk_item(self, i);
122124
}
123-
ItemKind::Fn(_, FnHeader { asyncness: IsAsync::Async(async_node_id), .. }, ..) => {
125+
ItemKind::Fn(_, FnHeader { asyncness: IsAsync::Async {
126+
closure_id,
127+
return_impl_trait_id,
128+
}, .. }, ..) => {
124129
return self.visit_async_fn(
125130
i.id,
126-
async_node_id,
131+
closure_id,
132+
return_impl_trait_id,
127133
i.ident.name,
128134
i.span,
129135
|this| visit::walk_item(this, i)
@@ -228,11 +234,15 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
228234
fn visit_impl_item(&mut self, ii: &'a ImplItem) {
229235
let def_data = match ii.node {
230236
ImplItemKind::Method(MethodSig {
231-
header: FnHeader { asyncness: IsAsync::Async(async_node_id), .. }, ..
237+
header: FnHeader { asyncness: IsAsync::Async {
238+
closure_id,
239+
return_impl_trait_id,
240+
}, .. }, ..
232241
}, ..) => {
233242
return self.visit_async_fn(
234243
ii.id,
235-
async_node_id,
244+
closure_id,
245+
return_impl_trait_id,
236246
ii.ident.name,
237247
ii.span,
238248
|this| visit::walk_impl_item(this, ii)
@@ -277,8 +287,8 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
277287

278288
// Async closures desugar to closures inside of closures, so
279289
// we must create two defs.
280-
if let IsAsync::Async(async_id) = asyncness {
281-
let async_def = self.create_def(async_id,
290+
if let IsAsync::Async { closure_id, .. } = asyncness {
291+
let async_def = self.create_def(closure_id,
282292
DefPathData::ClosureExpr,
283293
REGULAR_SPACE,
284294
expr.span);

src/librustc_resolve/lib.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -777,8 +777,8 @@ impl<'a, 'tcx> Visitor<'tcx> for Resolver<'a> {
777777
visit::walk_fn_ret_ty(self, &declaration.output);
778778

779779
// Resolve the function body, potentially inside the body of an async closure
780-
if let IsAsync::Async(async_closure_id) = asyncness {
781-
let rib_kind = ClosureRibKind(async_closure_id);
780+
if let IsAsync::Async { closure_id, .. } = asyncness {
781+
let rib_kind = ClosureRibKind(closure_id);
782782
self.ribs[ValueNS].push(Rib::new(rib_kind));
783783
self.label_ribs.push(Rib::new(rib_kind));
784784
}
@@ -3935,8 +3935,9 @@ impl<'a> Resolver<'a> {
39353935
// resolve the arguments within the proper scopes so that usages of them inside the
39363936
// closure are detected as upvars rather than normal closure arg usages.
39373937
ExprKind::Closure(
3938-
_, IsAsync::Async(inner_closure_id), _, ref fn_decl, ref body, _span) =>
3939-
{
3938+
_, IsAsync::Async { closure_id: inner_closure_id, .. }, _,
3939+
ref fn_decl, ref body, _span,
3940+
) => {
39403941
let rib_kind = ClosureRibKind(expr.id);
39413942
self.ribs[ValueNS].push(Rib::new(rib_kind));
39423943
self.label_ribs.push(Rib::new(rib_kind));

src/libsyntax/ast.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1722,13 +1722,16 @@ pub enum Unsafety {
17221722

17231723
#[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
17241724
pub enum IsAsync {
1725-
Async(NodeId),
1725+
Async {
1726+
closure_id: NodeId,
1727+
return_impl_trait_id: NodeId,
1728+
},
17261729
NotAsync,
17271730
}
17281731

17291732
impl IsAsync {
17301733
pub fn is_async(self) -> bool {
1731-
if let IsAsync::Async(_) = self {
1734+
if let IsAsync::Async { .. } = self {
17321735
true
17331736
} else {
17341737
false

src/libsyntax/feature_gate.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1726,7 +1726,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
17261726
"labels on blocks are unstable");
17271727
}
17281728
}
1729-
ast::ExprKind::Closure(_, ast::IsAsync::Async(_), ..) => {
1729+
ast::ExprKind::Closure(_, ast::IsAsync::Async { .. }, ..) => {
17301730
gate_feature_post!(&self, async_await, e.span, "async closures are unstable");
17311731
}
17321732
ast::ExprKind::Async(..) => {

0 commit comments

Comments
 (0)