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};
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!(),
}
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());
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 {
| 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)
}
}
- 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 {
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) {
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();
}
_ => {}
}
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(
-> 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)
.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
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();
Some(_) => DirectoryOwnership::Owned {
relative: Some(item.ident),
},
- None => DirectoryOwnership::UnownedViaMod(false),
+ None => DirectoryOwnership::UnownedViaMod,
};
path.pop();
module.directory = path;
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)