about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc_resolve/def_collector.rs83
-rw-r--r--src/test/ui/async-await/expansion-in-attrs.rs13
2 files changed, 35 insertions, 61 deletions
diff --git a/src/librustc_resolve/def_collector.rs b/src/librustc_resolve/def_collector.rs
index c55090d7e93..16359cc7437 100644
--- a/src/librustc_resolve/def_collector.rs
+++ b/src/librustc_resolve/def_collector.rs
@@ -2,7 +2,7 @@ use log::debug;
 use rustc::hir::map::definitions::*;
 use rustc_ast::ast::*;
 use rustc_ast::token::{self, Token};
-use rustc_ast::visit;
+use rustc_ast::visit::{self, FnKind};
 use rustc_expand::expand::AstFragment;
 use rustc_hir::def_id::DefIndex;
 use rustc_span::hygiene::ExpnId;
@@ -38,42 +38,6 @@ impl<'a> DefCollector<'a> {
         self.parent_def = orig_parent_def;
     }
 
-    fn visit_async_fn(
-        &mut self,
-        id: NodeId,
-        name: Name,
-        span: Span,
-        header: &FnHeader,
-        generics: &'a Generics,
-        decl: &'a FnDecl,
-        body: Option<&'a Block>,
-    ) {
-        let (closure_id, return_impl_trait_id) = match header.asyncness {
-            Async::Yes { span: _, closure_id, return_impl_trait_id } => {
-                (closure_id, return_impl_trait_id)
-            }
-            _ => unreachable!(),
-        };
-
-        // For async functions, we need to create their inner defs inside of a
-        // closure to match their desugared representation.
-        let fn_def_data = DefPathData::ValueNs(name);
-        let fn_def = self.create_def(id, fn_def_data, span);
-        return self.with_parent(fn_def, |this| {
-            this.create_def(return_impl_trait_id, DefPathData::ImplTrait, span);
-
-            visit::walk_generics(this, generics);
-            visit::walk_fn_decl(this, decl);
-
-            let closure_def = this.create_def(closure_id, DefPathData::ClosureExpr, span);
-            this.with_parent(closure_def, |this| {
-                if let Some(body) = body {
-                    visit::walk_block(this, body);
-                }
-            })
-        });
-    }
-
     fn collect_field(&mut self, field: &'a StructField, index: Option<usize>) {
         let index = |this: &Self| {
             index.unwrap_or_else(|| {
@@ -117,17 +81,6 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
             | ItemKind::ExternCrate(..)
             | ItemKind::ForeignMod(..)
             | ItemKind::TyAlias(..) => DefPathData::TypeNs(i.ident.name),
-            ItemKind::Fn(_, sig, generics, body) if sig.header.asyncness.is_async() => {
-                return self.visit_async_fn(
-                    i.id,
-                    i.ident.name,
-                    i.span,
-                    &sig.header,
-                    generics,
-                    &sig.decl,
-                    body.as_deref(),
-                );
-            }
             ItemKind::Static(..) | ItemKind::Const(..) | ItemKind::Fn(..) => {
                 DefPathData::ValueNs(i.ident.name)
             }
@@ -154,6 +107,27 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
         });
     }
 
+    fn visit_fn(&mut self, fn_kind: FnKind<'a>, span: Span, _: NodeId) {
+        if let FnKind::Fn(_, _, sig, _, body) = fn_kind {
+            if let Async::Yes { closure_id, return_impl_trait_id, .. } = sig.header.asyncness {
+                self.create_def(return_impl_trait_id, DefPathData::ImplTrait, span);
+
+                // For async functions, we need to create their inner defs inside of a
+                // closure to match their desugared representation. Besides that,
+                // we must mirror everything that `visit::walk_fn` below does.
+                self.visit_fn_header(&sig.header);
+                visit::walk_fn_decl(self, &sig.decl);
+                if let Some(body) = body {
+                    let closure_def = self.create_def(closure_id, DefPathData::ClosureExpr, span);
+                    self.with_parent(closure_def, |this| this.visit_block(body));
+                }
+                return;
+            }
+        }
+
+        visit::walk_fn(self, fn_kind, span);
+    }
+
     fn visit_use_tree(&mut self, use_tree: &'a UseTree, id: NodeId, _nested: bool) {
         self.create_def(id, DefPathData::Misc, use_tree.span);
         visit::walk_use_tree(self, use_tree, id);
@@ -215,19 +189,6 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
 
     fn visit_assoc_item(&mut self, i: &'a AssocItem, ctxt: visit::AssocCtxt) {
         let def_data = match &i.kind {
-            AssocItemKind::Fn(_, FnSig { header, decl }, generics, body)
-                if header.asyncness.is_async() =>
-            {
-                return self.visit_async_fn(
-                    i.id,
-                    i.ident.name,
-                    i.span,
-                    header,
-                    generics,
-                    decl,
-                    body.as_deref(),
-                );
-            }
             AssocItemKind::Fn(..) | AssocItemKind::Const(..) => DefPathData::ValueNs(i.ident.name),
             AssocItemKind::TyAlias(..) => DefPathData::TypeNs(i.ident.name),
             AssocItemKind::MacCall(..) => return self.visit_macro_invoc(i.id),
diff --git a/src/test/ui/async-await/expansion-in-attrs.rs b/src/test/ui/async-await/expansion-in-attrs.rs
new file mode 100644
index 00000000000..af77c3463b5
--- /dev/null
+++ b/src/test/ui/async-await/expansion-in-attrs.rs
@@ -0,0 +1,13 @@
+// check-pass
+// edition:2018
+
+macro_rules! with_doc {
+    ($doc: expr) => {
+        #[doc = $doc]
+        async fn f() {}
+    };
+}
+
+with_doc!(concat!(""));
+
+fn main() {}