use rustc::session::Session;
use rustc::util::nodemap::FxHashSet;
use rustc::{ty, lint, span_bug};
+use rustc_feature::is_builtin_attr_name;
use syntax::ast::{self, NodeId, Ident};
use syntax::attr::{self, StabilityLevel};
use syntax::edition::Edition;
-use syntax::feature_gate::{emit_feature_err, is_builtin_attr_name};
-use syntax::feature_gate::GateIssue;
+use syntax::feature_gate::feature_err;
use syntax::print::pprust;
-use syntax::symbol::{Symbol, kw, sym};
use syntax_expand::base::{self, InvocationRes, Indeterminate};
use syntax_expand::base::SyntaxExtension;
use syntax_expand::expand::{AstFragment, AstFragmentKind, Invocation, InvocationKind};
use syntax_expand::compile_declarative_macro;
use syntax_pos::hygiene::{self, ExpnId, ExpnData, ExpnKind};
+use syntax_pos::symbol::{Symbol, kw, sym};
use syntax_pos::{Span, DUMMY_SP};
use std::{mem, ptr};
segment.ident.as_str().starts_with("rustc") {
let msg =
"attributes starting with `rustc` are reserved for use by the `rustc` compiler";
- emit_feature_err(
- &self.session.parse_sess,
- sym::rustc_attrs,
- segment.ident.span,
- GateIssue::Language,
- msg,
- );
+ feature_err(&self.session.parse_sess, sym::rustc_attrs, segment.ident.span, msg)
+ .emit();
}
}
) -> Result<&'a NameBinding<'a>, Determinacy> {
bitflags::bitflags! {
struct Flags: u8 {
- const MACRO_RULES = 1 << 0;
- const MODULE = 1 << 1;
- const MISC_SUGGEST_CRATE = 1 << 2;
- const MISC_SUGGEST_SELF = 1 << 3;
- const MISC_FROM_PRELUDE = 1 << 4;
+ const MACRO_RULES = 1 << 0;
+ const MODULE = 1 << 1;
+ const DERIVE_HELPER_COMPAT = 1 << 2;
+ const MISC_SUGGEST_CRATE = 1 << 3;
+ const MISC_SUGGEST_SELF = 1 << 4;
+ const MISC_FROM_PRELUDE = 1 << 5;
}
}
match this.resolve_macro_path(derive, Some(MacroKind::Derive),
parent_scope, true, force) {
Ok((Some(ext), _)) => if ext.helper_attrs.contains(&ident.name) {
- let res = Res::NonMacroAttr(NonMacroAttrKind::DeriveHelper);
- result = ok(res, derive.span, this.arenas);
+ let binding = (Res::NonMacroAttr(NonMacroAttrKind::DeriveHelper),
+ ty::Visibility::Public, derive.span, ExpnId::root())
+ .to_name_binding(this.arenas);
+ result = Ok((binding, Flags::DERIVE_HELPER_COMPAT));
break;
}
Ok(_) | Err(Determinacy::Determined) => {}
let (res, innermost_res) = (binding.res(), innermost_binding.res());
if res != innermost_res {
let builtin = Res::NonMacroAttr(NonMacroAttrKind::Builtin);
- let derive_helper = Res::NonMacroAttr(NonMacroAttrKind::DeriveHelper);
+ let is_derive_helper_compat = |res, flags: Flags| {
+ res == Res::NonMacroAttr(NonMacroAttrKind::DeriveHelper) &&
+ flags.contains(Flags::DERIVE_HELPER_COMPAT)
+ };
let ambiguity_error_kind = if is_import {
Some(AmbiguityKind::Import)
} else if innermost_res == builtin || res == builtin {
Some(AmbiguityKind::BuiltinAttr)
- } else if innermost_res == derive_helper || res == derive_helper {
+ } else if is_derive_helper_compat(innermost_res, innermost_flags) ||
+ is_derive_helper_compat(res, flags) {
Some(AmbiguityKind::DeriveHelper)
} else if innermost_flags.contains(Flags::MACRO_RULES) &&
flags.contains(Flags::MODULE) &&
}
}
- /// Compile the macro into a `SyntaxExtension` and possibly replace it with a pre-defined
- /// extension partially or entirely for built-in macros and legacy plugin macros.
+ /// Compile the macro into a `SyntaxExtension` and possibly replace
+ /// its expander to a pre-defined one for built-in macros.
crate fn compile_macro(&mut self, item: &ast::Item, edition: Edition) -> SyntaxExtension {
let mut result = compile_declarative_macro(
&self.session.parse_sess, self.session.features_untracked(), item, edition
if result.is_builtin {
// The macro was marked with `#[rustc_builtin_macro]`.
if let Some(ext) = self.builtin_macros.remove(&item.ident.name) {
- if ext.is_builtin {
- // The macro is a built-in, replace only the expander function.
- result.kind = ext.kind;
- } else {
- // The macro is from a plugin, the in-source definition is dummy,
- // take all the data from the resolver.
- result = ext;
- }
+ // The macro is a built-in, replace its expander function
+ // while still taking everything else from the source code.
+ result.kind = ext.kind;
} else {
let msg = format!("cannot find a built-in macro with name `{}`", item.ident);
self.session.span_err(item.span, &msg);