]> git.proxmox.com Git - rustc.git/blobdiff - src/libsyntax_expand/expand.rs
New upstream version 1.41.1+dfsg1
[rustc.git] / src / libsyntax_expand / expand.rs
index c96b4a93dbddc8d269ce151820bcba0f66a0b2d0..9bfedb3b6174edf5eca8b32bb38dfa50a5e75af1 100644 (file)
@@ -1,29 +1,31 @@
 use crate::base::*;
-use crate::proc_macro::{collect_derives, MarkAttrs};
+use crate::proc_macro::collect_derives;
 use crate::hygiene::{ExpnId, SyntaxContext, ExpnData, ExpnKind};
 use crate::mbe::macro_rules::annotate_err_with_kind;
 use crate::placeholders::{placeholder, PlaceholderExpander};
+use crate::config::StripUnconfigured;
 
+use rustc_feature::Features;
+use rustc_parse::configure;
+use rustc_parse::DirectoryOwnership;
+use rustc_parse::parser::Parser;
+use rustc_parse::validate_attr;
 use syntax::ast::{self, AttrItem, Block, Ident, LitKind, NodeId, PatKind, Path};
-use syntax::ast::{MacStmtStyle, StmtKind, ItemKind};
-use syntax::attr::{self, HasAttrs};
+use syntax::ast::{MacArgs, MacStmtStyle, StmtKind, ItemKind};
+use syntax::attr::{self, HasAttrs, is_builtin_attr};
 use syntax::source_map::respan;
-use syntax::configure;
-use syntax::config::StripUnconfigured;
-use syntax::feature_gate::{self, Features, GateIssue, is_builtin_attr, emit_feature_err};
+use syntax::feature_gate::{self, feature_err};
 use syntax::mut_visit::*;
-use syntax::parse::{DirectoryOwnership, PResult};
-use syntax::parse::token;
-use syntax::parse::parser::Parser;
 use syntax::print::pprust;
 use syntax::ptr::P;
 use syntax::sess::ParseSess;
 use syntax::symbol::{sym, Symbol};
+use syntax::token;
 use syntax::tokenstream::{TokenStream, TokenTree};
 use syntax::visit::{self, Visitor};
 use syntax::util::map_in_place::MapInPlace;
 
-use errors::{Applicability, FatalError};
+use errors::{PResult, Applicability, FatalError};
 use smallvec::{smallvec, SmallVec};
 use syntax_pos::{Span, DUMMY_SP, FileName};
 
@@ -410,7 +412,9 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
                     let fragment = self.expand_invoc(invoc, &ext.kind);
                     self.collect_invocations(fragment, &[])
                 }
-                InvocationRes::DeriveContainer(exts) => {
+                InvocationRes::DeriveContainer(_exts) => {
+                    // FIXME: Consider using the derive resolutions (`_exts`) immediately,
+                    // instead of enqueuing the derives to be resolved again later.
                     let (derives, item) = match invoc.kind {
                         InvocationKind::DeriveContainer { derives, item } => (derives, item),
                         _ => unreachable!(),
@@ -436,21 +440,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
                     }
 
                     let mut item = self.fully_configure(item);
-                    item.visit_attrs(|attrs| attrs.retain(|a| a.path != sym::derive));
-                    let mut helper_attrs = Vec::new();
-                    let mut has_copy = false;
-                    for ext in exts {
-                        helper_attrs.extend(&ext.helper_attrs);
-                        has_copy |= ext.is_derive_copy;
-                    }
-                    // Mark derive helpers inside this item as known and used.
-                    // FIXME: This is a hack, derive helpers should be integrated with regular name
-                    // resolution instead. For example, helpers introduced by a derive container
-                    // can be in scope for all code produced by that container's expansion.
-                    item.visit_with(&mut MarkAttrs(&helper_attrs));
-                    if has_copy {
-                        self.cx.resolver.add_derives(invoc.expansion_data.id, SpecialDerives::COPY);
-                    }
+                    item.visit_attrs(|attrs| attrs.retain(|a| !a.has_name(sym::derive)));
 
                     let mut derive_placeholders = Vec::with_capacity(derives.len());
                     invocations.reserve(derives.len());
@@ -607,13 +597,13 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
             InvocationKind::Bang { mac, .. } => match ext {
                 SyntaxExtensionKind::Bang(expander) => {
                     self.gate_proc_macro_expansion_kind(span, fragment_kind);
-                    let tok_result = expander.expand(self.cx, span, mac.stream());
+                    let tok_result = expander.expand(self.cx, span, mac.args.inner_tokens());
                     self.parse_ast_fragment(tok_result, fragment_kind, &mac.path, span)
                 }
                 SyntaxExtensionKind::LegacyBang(expander) => {
                     let prev = self.cx.current_expansion.prior_type_ascription;
                     self.cx.current_expansion.prior_type_ascription = mac.prior_type_ascription;
-                    let tok_result = expander.expand(self.cx, span, mac.stream());
+                    let tok_result = expander.expand(self.cx, span, mac.args.inner_tokens());
                     let result = if let Some(result) = fragment_kind.make_from(tok_result) {
                         result
                     } else {
@@ -651,12 +641,16 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
                         | Annotatable::Variant(..)
                             => panic!("unexpected annotatable"),
                     })), DUMMY_SP).into();
-                    let input = self.extract_proc_macro_attr_input(attr.item.tokens, span);
-                    let tok_result = expander.expand(self.cx, span, input, item_tok);
-                    self.parse_ast_fragment(tok_result, fragment_kind, &attr.item.path, span)
+                    let item = attr.unwrap_normal_item();
+                    if let MacArgs::Eq(..) = item.args {
+                        self.cx.span_err(span, "key-value macro attributes are not supported");
+                    }
+                    let tok_result =
+                        expander.expand(self.cx, span, item.args.inner_tokens(), item_tok);
+                    self.parse_ast_fragment(tok_result, fragment_kind, &item.path, span)
                 }
                 SyntaxExtensionKind::LegacyAttr(expander) => {
-                    match attr.parse_meta(self.cx.parse_sess) {
+                    match validate_attr::parse_meta(self.cx.parse_sess, &attr) {
                         Ok(meta) => {
                             let item = expander.expand(self.cx, span, &meta, item);
                             fragment_kind.expect_from_annotatables(item)
@@ -696,23 +690,6 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
         }
     }
 
-    fn extract_proc_macro_attr_input(&self, tokens: TokenStream, span: Span) -> TokenStream {
-        let mut trees = tokens.trees();
-        match trees.next() {
-            Some(TokenTree::Delimited(_, _, tts)) => {
-                if trees.next().is_none() {
-                    return tts.into()
-                }
-            }
-            Some(TokenTree::Token(..)) => {}
-            None => return TokenStream::default(),
-        }
-        self.cx.span_err(span, "custom attribute invocations must be \
-            of the form `#[foo]` or `#[foo(..)]`, the macro name must only be \
-            followed by a delimiter token");
-        TokenStream::default()
-    }
-
     fn gate_proc_macro_attr_item(&self, span: Span, item: &Annotatable) {
         let kind = match item {
             Annotatable::Item(item) => match &item.kind {
@@ -736,13 +713,13 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
         if self.cx.ecfg.proc_macro_hygiene() {
             return
         }
-        emit_feature_err(
+        feature_err(
             self.cx.parse_sess,
             sym::proc_macro_hygiene,
             span,
-            GateIssue::Language,
             &format!("custom attributes cannot be applied to {}", kind),
-        );
+        )
+        .emit();
     }
 
     fn gate_proc_macro_input(&self, annotatable: &Annotatable) {
@@ -754,13 +731,13 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
             fn visit_item(&mut self, item: &'ast ast::Item) {
                 match &item.kind {
                     ast::ItemKind::Mod(module) if !module.inline => {
-                        emit_feature_err(
+                        feature_err(
                             self.parse_sess,
                             sym::proc_macro_hygiene,
                             item.span,
-                            GateIssue::Language,
                             "non-inline modules in proc macro input are unstable",
-                        );
+                        )
+                        .emit();
                     }
                     _ => {}
                 }
@@ -799,13 +776,13 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
         if self.cx.ecfg.proc_macro_hygiene() {
             return
         }
-        emit_feature_err(
+        feature_err(
             self.cx.parse_sess,
             sym::proc_macro_hygiene,
             span,
-            GateIssue::Language,
             &format!("procedural macros cannot be expanded to {}", kind),
-        );
+        )
+        .emit();
     }
 
     fn parse_ast_fragment(
@@ -992,7 +969,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
                        -> Option<ast::Attribute> {
         let attr = attrs.iter()
                         .position(|a| {
-                            if a.path == sym::derive {
+                            if a.has_name(sym::derive) {
                                 *after_derive = true;
                             }
                             !attr::is_known(a) && !is_builtin_attr(a)
@@ -1000,10 +977,12 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
                         .map(|i| attrs.remove(i));
         if let Some(attr) = &attr {
             if !self.cx.ecfg.custom_inner_attributes() &&
-               attr.style == ast::AttrStyle::Inner && attr.path != sym::test {
-                emit_feature_err(&self.cx.parse_sess, sym::custom_inner_attributes,
-                                 attr.span, GateIssue::Language,
-                                 "non-builtin inner attributes are unstable");
+               attr.style == ast::AttrStyle::Inner && !attr.has_name(sym::test) {
+                feature_err(
+                    &self.cx.parse_sess, sym::custom_inner_attributes, attr.span,
+                    "non-builtin inner attributes are unstable"
+                )
+                .emit();
             }
         }
         attr
@@ -1048,9 +1027,10 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
         let features = self.cx.ecfg.features.unwrap();
         for attr in attrs.iter() {
             feature_gate::check_attribute(attr, self.cx.parse_sess, features);
+            validate_attr::check_meta(self.cx.parse_sess, attr);
 
             // macros are expanded before any lint passes so this warning has to be hardcoded
-            if attr.path == sym::derive {
+            if attr.has_name(sym::derive) {
                 self.cx.struct_span_warn(attr.span, "`#[derive]` does nothing on macro invocations")
                     .note("this may become a hard error in a future release")
                     .emit();
@@ -1318,7 +1298,7 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
                         Some(_) => DirectoryOwnership::Owned {
                             relative: Some(item.ident),
                         },
-                        None => DirectoryOwnership::UnownedViaMod(false),
+                        None => DirectoryOwnership::UnownedViaMod,
                     };
                     path.pop();
                     module.directory = path;
@@ -1565,11 +1545,12 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
 
             let meta = attr::mk_list_item(Ident::with_dummy_span(sym::doc), items);
             *at = attr::Attribute {
-                item: AttrItem { path: meta.path, tokens: meta.kind.tokens(meta.span) },
+                kind: ast::AttrKind::Normal(
+                    AttrItem { path: meta.path, args: meta.kind.mac_args(meta.span) },
+                ),
                 span: at.span,
                 id: at.id,
                 style: at.style,
-                is_sugared_doc: false,
             };
         } else {
             noop_visit_attribute(at, self)