]> git.lizzy.rs Git - rust.git/blobdiff - src/librustc_expand/expand.rs
Rollup merge of #68894 - JohnTitor:update-e0565, r=Dylan-DPC
[rust.git] / src / librustc_expand / expand.rs
index f915f44c17ab977d3928106defede80da0073d31..90692fe1ec9dd39e5c22bdfcaa577ee03de6c775 100644 (file)
@@ -5,6 +5,8 @@
 use crate::placeholders::{placeholder, PlaceholderExpander};
 use crate::proc_macro::collect_derives;
 
+use rustc_ast_pretty::pprust;
+use rustc_attr::{self as attr, is_builtin_attr, HasAttrs};
 use rustc_data_structures::sync::Lrc;
 use rustc_errors::{Applicability, FatalError, PResult};
 use rustc_feature::Features;
 use rustc_parse::parser::Parser;
 use rustc_parse::validate_attr;
 use rustc_parse::DirectoryOwnership;
+use rustc_session::parse::{feature_err, ParseSess};
 use rustc_span::source_map::respan;
 use rustc_span::symbol::{sym, Symbol};
 use rustc_span::{FileName, Span, DUMMY_SP};
 use syntax::ast::{self, AttrItem, Block, Ident, LitKind, NodeId, PatKind, Path};
 use syntax::ast::{ItemKind, MacArgs, MacStmtStyle, StmtKind};
-use syntax::attr::{self, is_builtin_attr, HasAttrs};
 use syntax::mut_visit::*;
-use syntax::print::pprust;
 use syntax::ptr::P;
-use syntax::sess::{feature_err, ParseSess};
 use syntax::token;
 use syntax::tokenstream::{TokenStream, TokenTree};
 use syntax::util::map_in_place::MapInPlace;
-use syntax::visit::{self, Visitor};
+use syntax::visit::{self, AssocCtxt, Visitor};
 
 use smallvec::{smallvec, SmallVec};
 use std::io::ErrorKind;
@@ -39,7 +39,7 @@ macro_rules! ast_fragments {
         $($Kind:ident($AstTy:ty) {
             $kind_name:expr;
             $(one fn $mut_visit_ast:ident; fn $visit_ast:ident;)?
-            $(many fn $flat_map_ast_elt:ident; fn $visit_ast_elt:ident;)?
+            $(many fn $flat_map_ast_elt:ident; fn $visit_ast_elt:ident($($args:tt)*);)?
             fn $make_ast:ident;
         })*
     ) => {
@@ -127,7 +127,7 @@ pub fn visit_with<'a, V: Visitor<'a>>(&'a self, visitor: &mut V) {
                     AstFragment::OptExpr(None) => {}
                     $($(AstFragment::$Kind(ref ast) => visitor.$visit_ast(ast),)?)*
                     $($(AstFragment::$Kind(ref ast) => for ast_elt in &ast[..] {
-                        visitor.$visit_ast_elt(ast_elt);
+                        visitor.$visit_ast_elt(ast_elt, $($args)*);
                     })?)*
                 }
             }
@@ -147,52 +147,58 @@ impl<'a> MacResult for crate::mbe::macro_rules::ParserAnyMacro<'a> {
     Pat(P<ast::Pat>) { "pattern"; one fn visit_pat; fn visit_pat; fn make_pat; }
     Ty(P<ast::Ty>) { "type"; one fn visit_ty; fn visit_ty; fn make_ty; }
     Stmts(SmallVec<[ast::Stmt; 1]>) {
-        "statement"; many fn flat_map_stmt; fn visit_stmt; fn make_stmts;
+        "statement"; many fn flat_map_stmt; fn visit_stmt(); fn make_stmts;
     }
     Items(SmallVec<[P<ast::Item>; 1]>) {
-        "item"; many fn flat_map_item; fn visit_item; fn make_items;
+        "item"; many fn flat_map_item; fn visit_item(); fn make_items;
     }
-    TraitItems(SmallVec<[ast::AssocItem; 1]>) {
-        "trait item"; many fn flat_map_trait_item; fn visit_trait_item; fn make_trait_items;
+    TraitItems(SmallVec<[P<ast::AssocItem>; 1]>) {
+        "trait item";
+        many fn flat_map_trait_item;
+        fn visit_assoc_item(AssocCtxt::Trait);
+        fn make_trait_items;
     }
-    ImplItems(SmallVec<[ast::AssocItem; 1]>) {
-        "impl item"; many fn flat_map_impl_item; fn visit_impl_item; fn make_impl_items;
+    ImplItems(SmallVec<[P<ast::AssocItem>; 1]>) {
+        "impl item";
+        many fn flat_map_impl_item;
+        fn visit_assoc_item(AssocCtxt::Impl);
+        fn make_impl_items;
     }
-    ForeignItems(SmallVec<[ast::ForeignItem; 1]>) {
+    ForeignItems(SmallVec<[P<ast::ForeignItem>; 1]>) {
         "foreign item";
         many fn flat_map_foreign_item;
-        fn visit_foreign_item;
+        fn visit_foreign_item();
         fn make_foreign_items;
     }
     Arms(SmallVec<[ast::Arm; 1]>) {
-        "match arm"; many fn flat_map_arm; fn visit_arm; fn make_arms;
+        "match arm"; many fn flat_map_arm; fn visit_arm(); fn make_arms;
     }
     Fields(SmallVec<[ast::Field; 1]>) {
-        "field expression"; many fn flat_map_field; fn visit_field; fn make_fields;
+        "field expression"; many fn flat_map_field; fn visit_field(); fn make_fields;
     }
     FieldPats(SmallVec<[ast::FieldPat; 1]>) {
         "field pattern";
         many fn flat_map_field_pattern;
-        fn visit_field_pattern;
+        fn visit_field_pattern();
         fn make_field_patterns;
     }
     GenericParams(SmallVec<[ast::GenericParam; 1]>) {
         "generic parameter";
         many fn flat_map_generic_param;
-        fn visit_generic_param;
+        fn visit_generic_param();
         fn make_generic_params;
     }
     Params(SmallVec<[ast::Param; 1]>) {
-        "function parameter"; many fn flat_map_param; fn visit_param; fn make_params;
+        "function parameter"; many fn flat_map_param; fn visit_param(); fn make_params;
     }
     StructFields(SmallVec<[ast::StructField; 1]>) {
         "field";
         many fn flat_map_struct_field;
-        fn visit_struct_field;
+        fn visit_struct_field();
         fn make_struct_fields;
     }
     Variants(SmallVec<[ast::Variant; 1]>) {
-        "variant"; many fn flat_map_variant; fn visit_variant; fn make_variants;
+        "variant"; many fn flat_map_variant; fn visit_variant(); fn make_variants;
     }
 }
 
@@ -363,7 +369,17 @@ pub fn expand_crate(&mut self, mut krate: ast::Crate) -> ast::Crate {
                 krate.attrs = vec![];
                 krate.module = ast::Mod { inner: orig_mod_span, items: vec![], inline: true };
             }
-            _ => unreachable!(),
+            Some(ast::Item { span, kind, .. }) => {
+                krate.attrs = vec![];
+                krate.module = ast::Mod { inner: orig_mod_span, items: vec![], inline: true };
+                self.cx.span_err(
+                    span,
+                    &format!(
+                        "expected crate top-level item to be a module after macro expansion, found a {}",
+                        kind.descriptive_variant()
+                    ),
+                );
+            }
         };
         self.cx.trace_macros_diag();
         krate
@@ -554,15 +570,15 @@ fn fully_configure(&mut self, item: Annotatable) -> Annotatable {
         // we know that fold result vector will contain exactly one element
         match item {
             Annotatable::Item(item) => Annotatable::Item(cfg.flat_map_item(item).pop().unwrap()),
-            Annotatable::TraitItem(item) => Annotatable::TraitItem(
-                item.map(|item| cfg.flat_map_trait_item(item).pop().unwrap()),
-            ),
+            Annotatable::TraitItem(item) => {
+                Annotatable::TraitItem(cfg.flat_map_trait_item(item).pop().unwrap())
+            }
             Annotatable::ImplItem(item) => {
-                Annotatable::ImplItem(item.map(|item| cfg.flat_map_impl_item(item).pop().unwrap()))
+                Annotatable::ImplItem(cfg.flat_map_impl_item(item).pop().unwrap())
+            }
+            Annotatable::ForeignItem(item) => {
+                Annotatable::ForeignItem(cfg.flat_map_foreign_item(item).pop().unwrap())
             }
-            Annotatable::ForeignItem(item) => Annotatable::ForeignItem(
-                item.map(|item| cfg.flat_map_foreign_item(item).pop().unwrap()),
-            ),
             Annotatable::Stmt(stmt) => {
                 Annotatable::Stmt(stmt.map(|stmt| cfg.flat_map_stmt(stmt).pop().unwrap()))
             }
@@ -599,8 +615,8 @@ fn expand_invoc(&mut self, invoc: Invocation, ext: &SyntaxExtensionKind) -> AstF
                 &format!("recursion limit reached while expanding `{}`", expn_data.kind.descr()),
             );
             err.help(&format!(
-                "consider adding a `#![recursion_limit=\"{}\"]` attribute to your crate",
-                suggested_limit
+                "consider adding a `#![recursion_limit=\"{}\"]` attribute to your crate (`{}`)",
+                suggested_limit, self.cx.ecfg.crate_name,
             ));
             err.emit();
             self.cx.trace_macros_diag();
@@ -643,11 +659,9 @@ fn expand_invoc(&mut self, invoc: Invocation, ext: &SyntaxExtensionKind) -> AstF
                     let item_tok = TokenTree::token(
                         token::Interpolated(Lrc::new(match item {
                             Annotatable::Item(item) => token::NtItem(item),
-                            Annotatable::TraitItem(item) => token::NtTraitItem(item.into_inner()),
-                            Annotatable::ImplItem(item) => token::NtImplItem(item.into_inner()),
-                            Annotatable::ForeignItem(item) => {
-                                token::NtForeignItem(item.into_inner())
-                            }
+                            Annotatable::TraitItem(item) => token::NtTraitItem(item),
+                            Annotatable::ImplItem(item) => token::NtImplItem(item),
+                            Annotatable::ForeignItem(item) => token::NtForeignItem(item),
                             Annotatable::Stmt(stmt) => token::NtStmt(stmt.into_inner()),
                             Annotatable::Expr(expr) => token::NtExpr(expr),
                             Annotatable::Arm(..)
@@ -853,7 +867,7 @@ pub fn parse_ast_fragment<'a>(
         AstFragmentKind::ForeignItems => {
             let mut items = SmallVec::new();
             while this.token != token::Eof {
-                items.push(this.parse_foreign_item(DUMMY_SP)?);
+                items.push(this.parse_foreign_item()?);
             }
             AstFragment::ForeignItems(items)
         }
@@ -1411,7 +1425,7 @@ fn visit_block(&mut self, block: &mut P<Block>) {
         }
     }
 
-    fn flat_map_trait_item(&mut self, item: ast::AssocItem) -> SmallVec<[ast::AssocItem; 1]> {
+    fn flat_map_trait_item(&mut self, item: P<ast::AssocItem>) -> SmallVec<[P<ast::AssocItem>; 1]> {
         let mut item = configure!(self, item);
 
         let (attr, traits, after_derive) = self.classify_item(&mut item);
@@ -1420,7 +1434,7 @@ fn visit_block(&mut self, block: &mut P<Block>) {
                 .collect_attr(
                     attr,
                     traits,
-                    Annotatable::TraitItem(P(item)),
+                    Annotatable::TraitItem(item),
                     AstFragmentKind::TraitItems,
                     after_derive,
                 )
@@ -1428,16 +1442,20 @@ fn visit_block(&mut self, block: &mut P<Block>) {
         }
 
         match item.kind {
-            ast::AssocItemKind::Macro(mac) => {
-                let ast::AssocItem { attrs, span, .. } = item;
-                self.check_attributes(&attrs);
-                self.collect_bang(mac, span, AstFragmentKind::TraitItems).make_trait_items()
+            ast::AssocItemKind::Macro(..) => {
+                self.check_attributes(&item.attrs);
+                item.and_then(|item| match item.kind {
+                    ast::AssocItemKind::Macro(mac) => self
+                        .collect_bang(mac, item.span, AstFragmentKind::TraitItems)
+                        .make_trait_items(),
+                    _ => unreachable!(),
+                })
             }
             _ => noop_flat_map_assoc_item(item, self),
         }
     }
 
-    fn flat_map_impl_item(&mut self, item: ast::AssocItem) -> SmallVec<[ast::AssocItem; 1]> {
+    fn flat_map_impl_item(&mut self, item: P<ast::AssocItem>) -> SmallVec<[P<ast::AssocItem>; 1]> {
         let mut item = configure!(self, item);
 
         let (attr, traits, after_derive) = self.classify_item(&mut item);
@@ -1446,7 +1464,7 @@ fn visit_block(&mut self, block: &mut P<Block>) {
                 .collect_attr(
                     attr,
                     traits,
-                    Annotatable::ImplItem(P(item)),
+                    Annotatable::ImplItem(item),
                     AstFragmentKind::ImplItems,
                     after_derive,
                 )
@@ -1454,10 +1472,14 @@ fn visit_block(&mut self, block: &mut P<Block>) {
         }
 
         match item.kind {
-            ast::AssocItemKind::Macro(mac) => {
-                let ast::AssocItem { attrs, span, .. } = item;
-                self.check_attributes(&attrs);
-                self.collect_bang(mac, span, AstFragmentKind::ImplItems).make_impl_items()
+            ast::AssocItemKind::Macro(..) => {
+                self.check_attributes(&item.attrs);
+                item.and_then(|item| match item.kind {
+                    ast::AssocItemKind::Macro(mac) => self
+                        .collect_bang(mac, item.span, AstFragmentKind::ImplItems)
+                        .make_impl_items(),
+                    _ => unreachable!(),
+                })
             }
             _ => noop_flat_map_assoc_item(item, self),
         }
@@ -1482,8 +1504,8 @@ fn visit_foreign_mod(&mut self, foreign_mod: &mut ast::ForeignMod) {
 
     fn flat_map_foreign_item(
         &mut self,
-        mut foreign_item: ast::ForeignItem,
-    ) -> SmallVec<[ast::ForeignItem; 1]> {
+        mut foreign_item: P<ast::ForeignItem>,
+    ) -> SmallVec<[P<ast::ForeignItem>; 1]> {
         let (attr, traits, after_derive) = self.classify_item(&mut foreign_item);
 
         if attr.is_some() || !traits.is_empty() {
@@ -1491,21 +1513,25 @@ fn flat_map_foreign_item(
                 .collect_attr(
                     attr,
                     traits,
-                    Annotatable::ForeignItem(P(foreign_item)),
+                    Annotatable::ForeignItem(foreign_item),
                     AstFragmentKind::ForeignItems,
                     after_derive,
                 )
                 .make_foreign_items();
         }
 
-        if let ast::ForeignItemKind::Macro(mac) = foreign_item.kind {
-            self.check_attributes(&foreign_item.attrs);
-            return self
-                .collect_bang(mac, foreign_item.span, AstFragmentKind::ForeignItems)
-                .make_foreign_items();
+        match foreign_item.kind {
+            ast::ForeignItemKind::Macro(..) => {
+                self.check_attributes(&foreign_item.attrs);
+                foreign_item.and_then(|item| match item.kind {
+                    ast::ForeignItemKind::Macro(mac) => self
+                        .collect_bang(mac, item.span, AstFragmentKind::ForeignItems)
+                        .make_foreign_items(),
+                    _ => unreachable!(),
+                })
+            }
+            _ => noop_flat_map_foreign_item(foreign_item, self),
         }
-
-        noop_flat_map_foreign_item(foreign_item, self)
     }
 
     fn visit_item_kind(&mut self, item: &mut ast::ItemKind) {
@@ -1661,7 +1687,7 @@ fn visit_attribute(&mut self, at: &mut ast::Attribute) {
             }
 
             let meta = attr::mk_list_item(Ident::with_dummy_span(sym::doc), items);
-            *at = attr::Attribute {
+            *at = ast::Attribute {
                 kind: ast::AttrKind::Normal(AttrItem {
                     path: meta.path,
                     args: meta.kind.mac_args(meta.span),