Skip to content

Commit 70b7b78

Browse files
committed
Add AsyncArgument to AST.
This commit adds an `AsyncArgument` struct to the AST that contains the generated argument and statement that will be used in HIR lowering, name resolution and def collection.
1 parent d1be529 commit 70b7b78

File tree

11 files changed

+153
-52
lines changed

11 files changed

+153
-52
lines changed

src/librustc/hir/lowering.rs

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2816,13 +2816,13 @@ impl<'a> LoweringContext<'a> {
28162816
fn lower_async_body(
28172817
&mut self,
28182818
decl: &FnDecl,
2819-
asyncness: IsAsync,
2819+
asyncness: &IsAsync,
28202820
body: &Block,
28212821
) -> hir::BodyId {
28222822
self.lower_body(Some(decl), |this| {
28232823
if let IsAsync::Async { closure_id, .. } = asyncness {
28242824
let async_expr = this.make_async_expr(
2825-
CaptureBy::Value, closure_id, None,
2825+
CaptureBy::Value, *closure_id, None,
28262826
|this| {
28272827
let body = this.lower_block(body, false);
28282828
this.expr_block(body, ThinVec::new())
@@ -2883,14 +2883,14 @@ impl<'a> LoweringContext<'a> {
28832883
value
28842884
)
28852885
}
2886-
ItemKind::Fn(ref decl, header, ref generics, ref body) => {
2886+
ItemKind::Fn(ref decl, ref header, ref generics, ref body) => {
28872887
let fn_def_id = self.resolver.definitions().local_def_id(id);
28882888
self.with_new_scopes(|this| {
28892889
// Note: we don't need to change the return type from `T` to
28902890
// `impl Future<Output = T>` here because lower_body
28912891
// only cares about the input argument patterns in the function
28922892
// declaration (decl), not the return types.
2893-
let body_id = this.lower_async_body(decl, header.asyncness.node, body);
2893+
let body_id = this.lower_async_body(decl, &header.asyncness.node, body);
28942894

28952895
let (generics, fn_decl) = this.add_in_band_defs(
28962896
generics,
@@ -3391,7 +3391,7 @@ impl<'a> LoweringContext<'a> {
33913391
)
33923392
}
33933393
ImplItemKind::Method(ref sig, ref body) => {
3394-
let body_id = self.lower_async_body(&sig.decl, sig.header.asyncness.node, body);
3394+
let body_id = self.lower_async_body(&sig.decl, &sig.header.asyncness.node, body);
33953395
let impl_trait_return_allow = !self.is_in_trait_impl;
33963396
let (generics, sig) = self.lower_method_sig(
33973397
&i.generics,
@@ -3589,7 +3589,7 @@ impl<'a> LoweringContext<'a> {
35893589
impl_trait_return_allow: bool,
35903590
is_async: Option<NodeId>,
35913591
) -> (hir::Generics, hir::MethodSig) {
3592-
let header = self.lower_fn_header(sig.header);
3592+
let header = self.lower_fn_header(&sig.header);
35933593
let (generics, decl) = self.add_in_band_defs(
35943594
generics,
35953595
fn_def_id,
@@ -3611,10 +3611,10 @@ impl<'a> LoweringContext<'a> {
36113611
}
36123612
}
36133613

3614-
fn lower_fn_header(&mut self, h: FnHeader) -> hir::FnHeader {
3614+
fn lower_fn_header(&mut self, h: &FnHeader) -> hir::FnHeader {
36153615
hir::FnHeader {
36163616
unsafety: self.lower_unsafety(h.unsafety),
3617-
asyncness: self.lower_asyncness(h.asyncness.node),
3617+
asyncness: self.lower_asyncness(&h.asyncness.node),
36183618
constness: self.lower_constness(h.constness),
36193619
abi: h.abi,
36203620
}
@@ -3634,7 +3634,7 @@ impl<'a> LoweringContext<'a> {
36343634
}
36353635
}
36363636

3637-
fn lower_asyncness(&mut self, a: IsAsync) -> hir::IsAsync {
3637+
fn lower_asyncness(&mut self, a: &IsAsync) -> hir::IsAsync {
36383638
match a {
36393639
IsAsync::Async { .. } => hir::IsAsync::Async,
36403640
IsAsync::NotAsync => hir::IsAsync::NotAsync,
@@ -3947,7 +3947,7 @@ impl<'a> LoweringContext<'a> {
39473947
})
39483948
}
39493949
ExprKind::Closure(
3950-
capture_clause, asyncness, movability, ref decl, ref body, fn_decl_span
3950+
capture_clause, ref asyncness, movability, ref decl, ref body, fn_decl_span
39513951
) => {
39523952
if let IsAsync::Async { closure_id, .. } = asyncness {
39533953
let outer_decl = FnDecl {
@@ -3985,7 +3985,7 @@ impl<'a> LoweringContext<'a> {
39853985
Some(&**ty)
39863986
} else { None };
39873987
let async_body = this.make_async_expr(
3988-
capture_clause, closure_id, async_ret_ty,
3988+
capture_clause, *closure_id, async_ret_ty,
39893989
|this| {
39903990
this.with_new_scopes(|this| this.lower_expr(body))
39913991
});

src/librustc/hir/map/def_collector.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ impl<'a> DefCollector<'a> {
6868
id: NodeId,
6969
name: Name,
7070
span: Span,
71-
header: &FnHeader,
71+
header: &'a FnHeader,
7272
generics: &'a Generics,
7373
decl: &'a FnDecl,
7474
body: &'a Block,
@@ -86,12 +86,12 @@ impl<'a> DefCollector<'a> {
8686
let fn_def_data = DefPathData::ValueNs(name.as_interned_str());
8787
let fn_def = self.create_def(id, fn_def_data, ITEM_LIKE_SPACE, span);
8888
return self.with_parent(fn_def, |this| {
89-
this.create_def(return_impl_trait_id, DefPathData::ImplTrait, REGULAR_SPACE, span);
89+
this.create_def(*return_impl_trait_id, DefPathData::ImplTrait, REGULAR_SPACE, span);
9090

9191
visit::walk_generics(this, generics);
9292
visit::walk_fn_decl(this, decl);
9393

94-
let closure_def = this.create_def(closure_id,
94+
let closure_def = this.create_def(*closure_id,
9595
DefPathData::ClosureExpr,
9696
REGULAR_SPACE,
9797
span);
@@ -288,7 +288,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
288288

289289
match expr.node {
290290
ExprKind::Mac(..) => return self.visit_macro_invoc(expr.id),
291-
ExprKind::Closure(_, asyncness, ..) => {
291+
ExprKind::Closure(_, ref asyncness, ..) => {
292292
let closure_def = self.create_def(expr.id,
293293
DefPathData::ClosureExpr,
294294
REGULAR_SPACE,
@@ -298,7 +298,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
298298
// Async closures desugar to closures inside of closures, so
299299
// we must create two defs.
300300
if let IsAsync::Async { closure_id, .. } = asyncness {
301-
let async_def = self.create_def(closure_id,
301+
let async_def = self.create_def(*closure_id,
302302
DefPathData::ClosureExpr,
303303
REGULAR_SPACE,
304304
expr.span);

src/librustc_passes/ast_validation.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,7 @@ impl<'a> AstValidator<'a> {
230230
}
231231
}
232232

233-
fn check_trait_fn_not_async(&self, span: Span, asyncness: IsAsync) {
233+
fn check_trait_fn_not_async(&self, span: Span, asyncness: &IsAsync) {
234234
if asyncness.is_async() {
235235
struct_span_err!(self.session, span, E0706,
236236
"trait fns cannot be declared `async`").emit()
@@ -560,7 +560,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
560560
self.invalid_visibility(&impl_item.vis, None);
561561
if let ImplItemKind::Method(ref sig, _) = impl_item.node {
562562
self.check_trait_fn_not_const(sig.header.constness);
563-
self.check_trait_fn_not_async(impl_item.span, sig.header.asyncness.node);
563+
self.check_trait_fn_not_async(impl_item.span, &sig.header.asyncness.node);
564564
}
565565
}
566566
}
@@ -633,7 +633,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
633633
self.no_questions_in_bounds(bounds, "supertraits", true);
634634
for trait_item in trait_items {
635635
if let TraitItemKind::Method(ref sig, ref block) = trait_item.node {
636-
self.check_trait_fn_not_async(trait_item.span, sig.header.asyncness.node);
636+
self.check_trait_fn_not_async(trait_item.span, &sig.header.asyncness.node);
637637
self.check_trait_fn_not_const(sig.header.constness);
638638
if block.is_none() {
639639
self.check_decl_no_pat(&sig.decl, |span, mut_ident| {

src/librustc_resolve/lib.rs

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -814,13 +814,13 @@ impl<'a, 'tcx> Visitor<'tcx> for Resolver<'a> {
814814
debug!("(resolving function) entering function");
815815
let (rib_kind, asyncness) = match function_kind {
816816
FnKind::ItemFn(_, ref header, ..) =>
817-
(FnItemRibKind, header.asyncness.node),
817+
(FnItemRibKind, &header.asyncness.node),
818818
FnKind::Method(_, ref sig, _, _) =>
819-
(TraitOrImplItemRibKind, sig.header.asyncness.node),
819+
(TraitOrImplItemRibKind, &sig.header.asyncness.node),
820820
FnKind::Closure(_) =>
821821
// Async closures aren't resolved through `visit_fn`-- they're
822822
// processed separately
823-
(ClosureRibKind(node_id), IsAsync::NotAsync),
823+
(ClosureRibKind(node_id), &IsAsync::NotAsync),
824824
};
825825

826826
// Create a value rib for the function.
@@ -833,16 +833,14 @@ impl<'a, 'tcx> Visitor<'tcx> for Resolver<'a> {
833833
let mut bindings_list = FxHashMap::default();
834834
for argument in &declaration.inputs {
835835
self.resolve_pattern(&argument.pat, PatternSource::FnParam, &mut bindings_list);
836-
837836
self.visit_ty(&argument.ty);
838-
839837
debug!("(resolving function) recorded argument");
840838
}
841839
visit::walk_fn_ret_ty(self, &declaration.output);
842840

843841
// Resolve the function body, potentially inside the body of an async closure
844842
if let IsAsync::Async { closure_id, .. } = asyncness {
845-
let rib_kind = ClosureRibKind(closure_id);
843+
let rib_kind = ClosureRibKind(*closure_id);
846844
self.ribs[ValueNS].push(Rib::new(rib_kind));
847845
self.label_ribs.push(Rib::new(rib_kind));
848846
}

src/librustc_save_analysis/sig.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -374,7 +374,7 @@ impl Sig for ast::Item {
374374

375375
Ok(extend_sig(ty, text, defs, vec![]))
376376
}
377-
ast::ItemKind::Fn(ref decl, header, ref generics, _) => {
377+
ast::ItemKind::Fn(ref decl, ref header, ref generics, _) => {
378378
let mut text = String::new();
379379
if header.constness.node == ast::Constness::Const {
380380
text.push_str("const ");

src/libsyntax/ast.rs

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1837,31 +1837,48 @@ pub enum Unsafety {
18371837
Normal,
18381838
}
18391839

1840-
#[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug)]
1840+
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
1841+
pub struct AsyncArgument {
1842+
/// `__arg0`
1843+
pub ident: Ident,
1844+
/// `__arg0: <ty>` argument to replace existing function argument `<pat>: <ty>`.
1845+
pub arg: Arg,
1846+
/// `let <pat>: <ty> = __arg0;` statement to be inserted at the start of the block.
1847+
pub stmt: Stmt,
1848+
}
1849+
1850+
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
18411851
pub enum IsAsync {
18421852
Async {
18431853
closure_id: NodeId,
18441854
return_impl_trait_id: NodeId,
1855+
/// This field stores the arguments and statements that are used in HIR lowering to
1856+
/// ensure that `async fn` arguments are dropped at the correct time.
1857+
///
1858+
/// The argument and statements here are generated at parse time as they are required in
1859+
/// both the hir lowering, def collection and name resolution and this stops them needing
1860+
/// to be created in each place.
1861+
arguments: Vec<AsyncArgument>,
18451862
},
18461863
NotAsync,
18471864
}
18481865

18491866
impl IsAsync {
1850-
pub fn is_async(self) -> bool {
1851-
if let IsAsync::Async { .. } = self {
1867+
pub fn is_async(&self) -> bool {
1868+
if let IsAsync::Async { .. } = *self {
18521869
true
18531870
} else {
18541871
false
18551872
}
18561873
}
18571874

18581875
/// In ths case this is an `async` return, the `NodeId` for the generated `impl Trait` item.
1859-
pub fn opt_return_id(self) -> Option<NodeId> {
1876+
pub fn opt_return_id(&self) -> Option<NodeId> {
18601877
match self {
18611878
IsAsync::Async {
18621879
return_impl_trait_id,
18631880
..
1864-
} => Some(return_impl_trait_id),
1881+
} => Some(*return_impl_trait_id),
18651882
IsAsync::NotAsync => None,
18661883
}
18671884
}
@@ -2223,7 +2240,7 @@ impl Item {
22232240
///
22242241
/// All the information between the visibility and the name of the function is
22252242
/// included in this struct (e.g., `async unsafe fn` or `const extern "C" fn`).
2226-
#[derive(Clone, Copy, RustcEncodable, RustcDecodable, Debug)]
2243+
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
22272244
pub struct FnHeader {
22282245
pub unsafety: Unsafety,
22292246
pub asyncness: Spanned<IsAsync>,

src/libsyntax/ext/placeholders.rs

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,13 @@ impl<'a, 'b> PlaceholderExpander<'a, 'b> {
102102
fn remove(&mut self, id: ast::NodeId) -> AstFragment {
103103
self.expanded_fragments.remove(&id).unwrap()
104104
}
105+
106+
fn next_id(&mut self, id: &mut ast::NodeId) {
107+
if self.monotonic {
108+
assert_eq!(*id, ast::DUMMY_NODE_ID);
109+
*id = self.cx.resolver.next_node_id()
110+
}
111+
}
105112
}
106113

107114
impl<'a, 'b> MutVisitor for PlaceholderExpander<'a, 'b> {
@@ -183,9 +190,16 @@ impl<'a, 'b> MutVisitor for PlaceholderExpander<'a, 'b> {
183190
noop_visit_block(block, self);
184191

185192
for stmt in block.stmts.iter_mut() {
186-
if self.monotonic {
187-
assert_eq!(stmt.id, ast::DUMMY_NODE_ID);
188-
stmt.id = self.cx.resolver.next_node_id();
193+
self.next_id(&mut stmt.id);
194+
}
195+
}
196+
197+
fn visit_asyncness(&mut self, a: &mut ast::IsAsync) {
198+
noop_visit_asyncness(a, self);
199+
200+
if let ast::IsAsync::Async { ref mut arguments, .. } = a {
201+
for argument in arguments.iter_mut() {
202+
self.next_id(&mut argument.stmt.id);
189203
}
190204
}
191205
}

src/libsyntax/feature_gate.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1898,7 +1898,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
18981898
span: Span,
18991899
_node_id: NodeId) {
19001900
match fn_kind {
1901-
FnKind::ItemFn(_, header, _, _) => {
1901+
FnKind::ItemFn(_, ref header, _, _) => {
19021902
// Check for const fn and async fn declarations.
19031903
if header.asyncness.node.is_async() {
19041904
gate_feature_post!(&self, async_await, span, "async fn is unstable");

src/libsyntax/mut_visit.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -678,9 +678,17 @@ pub fn noop_visit_interpolated<T: MutVisitor>(nt: &mut token::Nonterminal, vis:
678678

679679
pub fn noop_visit_asyncness<T: MutVisitor>(asyncness: &mut IsAsync, vis: &mut T) {
680680
match asyncness {
681-
IsAsync::Async { closure_id, return_impl_trait_id } => {
681+
IsAsync::Async { closure_id, return_impl_trait_id, ref mut arguments } => {
682682
vis.visit_id(closure_id);
683683
vis.visit_id(return_impl_trait_id);
684+
for AsyncArgument { ident, arg, stmt } in arguments.iter_mut() {
685+
vis.visit_ident(ident);
686+
vis.visit_arg(arg);
687+
visit_clobber(stmt, |stmt| {
688+
vis.flat_map_stmt(stmt)
689+
.expect_one("expected visitor to produce exactly one item")
690+
});
691+
}
684692
}
685693
IsAsync::NotAsync => {}
686694
}

0 commit comments

Comments
 (0)