1124 lines
55 KiB
Rust
Raw Normal View History

use {AmbiguityError, AmbiguityKind, AmbiguityErrorMisc};
use {CrateLint, Resolver, ResolutionError, ScopeSet, Weak};
use {Module, ModuleKind, NameBinding, NameBindingKind, PathResult, Segment, ToNameBinding};
2018-11-18 14:41:06 +03:00
use {is_known_tool, resolve_error};
use ModuleOrUniformRoot;
use Namespace::*;
use build_reduced_graph::{BuildReducedGraphVisitor, IsMacroExport};
2016-11-10 10:11:25 +00:00
use resolve_imports::ImportResolver;
use rustc::hir::def_id::{DefId, CRATE_DEF_INDEX, DefIndex,
CrateNum, DefIndexAddressSpace};
2018-05-14 03:22:52 +03:00
use rustc::hir::def::{Def, NonMacroAttrKind};
use rustc::hir::map::{self, DefCollector};
2017-05-11 10:26:07 +02:00
use rustc::{ty, lint};
use syntax::ast::{self, Ident};
use syntax::attr;
use syntax::errors::DiagnosticBuilder;
use syntax::ext::base::{self, Determinacy};
use syntax::ext::base::{Annotatable, MacroKind, SyntaxExtension};
use syntax::ext::expand::{AstFragment, Invocation, InvocationKind};
use syntax::ext::hygiene::{self, Mark};
use syntax::ext::tt::macro_rules;
use syntax::feature_gate::{feature_err, is_builtin_attr_name, GateIssue};
use syntax::symbol::{Symbol, keywords};
use syntax::visit::Visitor;
use syntax::util::lev_distance::find_best_match_for_name;
use syntax_pos::{Span, DUMMY_SP};
use errors::Applicability;
use std::cell::Cell;
use std::{mem, ptr};
2018-02-27 17:11:14 +01:00
use rustc_data_structures::sync::Lrc;
#[derive(Clone, Debug)]
pub struct InvocationData<'a> {
def_index: DefIndex,
/// Module in which the macro was invoked.
crate module: Cell<Module<'a>>,
/// Legacy scope in which the macro was invoked.
/// The invocation path is resolved in this scope.
crate parent_legacy_scope: Cell<LegacyScope<'a>>,
/// Legacy scope *produced* by expanding this macro invocation,
/// includes all the macro_rules items, other invocations, etc generated by it.
/// `None` if the macro is not expanded yet.
crate output_legacy_scope: Cell<Option<LegacyScope<'a>>>,
}
impl<'a> InvocationData<'a> {
pub fn root(graph_root: Module<'a>) -> Self {
InvocationData {
2016-09-16 08:50:34 +00:00
module: Cell::new(graph_root),
def_index: CRATE_DEF_INDEX,
parent_legacy_scope: Cell::new(LegacyScope::Empty),
output_legacy_scope: Cell::new(Some(LegacyScope::Empty)),
}
}
}
/// Binding produced by a `macro_rules` item.
/// Not modularized, can shadow previous legacy bindings, etc.
#[derive(Debug)]
pub struct LegacyBinding<'a> {
binding: &'a NameBinding<'a>,
/// Legacy scope into which the `macro_rules` item was planted.
parent_legacy_scope: LegacyScope<'a>,
ident: Ident,
}
/// Scope introduced by a `macro_rules!` macro.
/// Starts at the macro's definition and ends at the end of the macro's parent module
/// (named or unnamed), or even further if it escapes with `#[macro_use]`.
/// Some macro invocations need to introduce legacy scopes too because they
/// potentially can expand into macro definitions.
#[derive(Copy, Clone, Debug)]
2016-10-06 08:04:30 +00:00
pub enum LegacyScope<'a> {
/// Created when invocation data is allocated in the arena,
/// must be replaced with a proper scope later.
Uninitialized,
/// Empty "root" scope at the crate start containing no names.
2016-10-06 08:04:30 +00:00
Empty,
/// Scope introduced by a `macro_rules!` macro definition.
2016-10-06 08:04:30 +00:00
Binding(&'a LegacyBinding<'a>),
/// Scope introduced by a macro invocation that can potentially
/// create a `macro_rules!` macro definition.
Invocation(&'a InvocationData<'a>),
}
/// Everything you need to resolve a macro or import path.
#[derive(Clone, Debug)]
pub struct ParentScope<'a> {
crate module: Module<'a>,
crate expansion: Mark,
crate legacy: LegacyScope<'a>,
crate derives: Vec<ast::Path>,
}
// Macro namespace is separated into two sub-namespaces, one for bang macros and
// one for attribute-like macros (attributes, derives).
// We ignore resolutions from one sub-namespace when searching names in scope for another.
fn sub_namespace_match(candidate: Option<MacroKind>, requirement: Option<MacroKind>) -> bool {
#[derive(PartialEq)]
enum SubNS { Bang, AttrLike }
let sub_ns = |kind| match kind {
MacroKind::Bang => Some(SubNS::Bang),
MacroKind::Attr | MacroKind::Derive => Some(SubNS::AttrLike),
MacroKind::ProcMacroStub => None,
};
let requirement = requirement.and_then(|kind| sub_ns(kind));
let candidate = candidate.and_then(|kind| sub_ns(kind));
// "No specific sub-namespace" means "matches anything" for both requirements and candidates.
candidate.is_none() || requirement.is_none() || candidate == requirement
}
2018-12-10 05:37:10 +01:00
impl<'a> base::Resolver for Resolver<'a> {
fn next_node_id(&mut self) -> ast::NodeId {
self.session.next_node_id()
}
fn get_module_scope(&mut self, id: ast::NodeId) -> Mark {
2017-03-22 08:39:51 +00:00
let mark = Mark::fresh(Mark::root());
let module = self.module_map[&self.definitions.local_def_id(id)];
self.invocations.insert(mark, self.arenas.alloc_invocation_data(InvocationData {
2016-09-16 08:50:34 +00:00
module: Cell::new(module),
def_index: module.def_id().unwrap().index,
parent_legacy_scope: Cell::new(LegacyScope::Empty),
output_legacy_scope: Cell::new(Some(LegacyScope::Empty)),
2016-09-16 08:50:34 +00:00
}));
mark
}
fn resolve_dollar_crates(&mut self, annotatable: &Annotatable) {
pub struct ResolveDollarCrates<'a, 'b: 'a> {
pub resolver: &'a mut Resolver<'b>,
}
impl<'a> Visitor<'a> for ResolveDollarCrates<'a, '_> {
fn visit_ident(&mut self, ident: Ident) {
if ident.name == keywords::DollarCrate.name() {
let name = match self.resolver.resolve_crate_root(ident).kind {
ModuleKind::Def(_, name) if name != keywords::Invalid.name() => name,
_ => keywords::Crate.name(),
};
ident.span.ctxt().set_dollar_crate_name(name);
}
}
fn visit_mac(&mut self, _: &ast::Mac) {}
}
annotatable.visit_with(&mut ResolveDollarCrates { resolver: self });
}
fn visit_ast_fragment_with_placeholders(&mut self, mark: Mark, fragment: &AstFragment,
derives: &[Mark]) {
2016-10-06 08:04:30 +00:00
let invocation = self.invocations[&mark];
self.collect_def_ids(mark, invocation, fragment);
2016-10-06 08:04:30 +00:00
self.current_module = invocation.module.get();
self.current_module.unresolved_invocations.borrow_mut().remove(&mark);
self.current_module.unresolved_invocations.borrow_mut().extend(derives);
2018-10-17 11:36:19 +02:00
self.invocations.extend(derives.iter().map(|&derive| (derive, invocation)));
2016-10-06 08:04:30 +00:00
let mut visitor = BuildReducedGraphVisitor {
resolver: self,
current_legacy_scope: invocation.parent_legacy_scope.get(),
expansion: mark,
2016-10-06 08:04:30 +00:00
};
fragment.visit_with(&mut visitor);
invocation.output_legacy_scope.set(Some(visitor.current_legacy_scope));
}
2018-02-27 17:11:14 +01:00
fn add_builtin(&mut self, ident: ast::Ident, ext: Lrc<SyntaxExtension>) {
2016-10-28 06:52:45 +00:00
let def_id = DefId {
krate: CrateNum::BuiltinMacros,
index: DefIndex::from_array_index(self.macro_map.len(),
DefIndexAddressSpace::Low),
2016-10-28 06:52:45 +00:00
};
2017-02-23 20:12:33 +10:30
let kind = ext.kind();
2016-10-28 06:52:45 +00:00
self.macro_map.insert(def_id, ext);
let binding = self.arenas.alloc_name_binding(NameBinding {
kind: NameBindingKind::Def(Def::Macro(def_id, kind), false),
ambiguity: None,
span: DUMMY_SP,
vis: ty::Visibility::Public,
expansion: Mark::root(),
});
if self.builtin_macros.insert(ident.name, binding).is_some() {
self.session.span_err(ident.span,
&format!("built-in macro `{}` was already defined", ident));
}
}
2016-11-10 10:11:25 +00:00
fn resolve_imports(&mut self) {
ImportResolver { resolver: self }.resolve_imports()
}
fn resolve_macro_invocation(&mut self, invoc: &Invocation, invoc_id: Mark, force: bool)
-> Result<Option<Lrc<SyntaxExtension>>, Determinacy> {
let (path, kind, derives_in_scope, after_derive) = match invoc.kind {
InvocationKind::Attr { attr: None, .. } =>
return Ok(None),
InvocationKind::Attr { attr: Some(ref attr), ref traits, after_derive, .. } =>
(&attr.path, MacroKind::Attr, traits.clone(), after_derive),
InvocationKind::Bang { ref mac, .. } =>
(&mac.node.path, MacroKind::Bang, Vec::new(), false),
InvocationKind::Derive { ref path, .. } =>
(path, MacroKind::Derive, Vec::new(), false),
};
let parent_scope = self.invoc_parent_scope(invoc_id, derives_in_scope);
let (def, ext) = match self.resolve_macro_to_def(path, kind, &parent_scope, true, force) {
Ok((def, ext)) => (def, ext),
Err(Determinacy::Determined) if kind == MacroKind::Attr => {
// Replace unresolved attributes with used inert attributes for better recovery.
return Ok(Some(Lrc::new(SyntaxExtension::NonMacroAttr { mark_used: true })));
}
Err(determinacy) => return Err(determinacy),
};
if let Def::Macro(def_id, _) = def {
if after_derive {
self.session.span_err(invoc.span(),
"macro attributes must be placed before `#[derive]`");
}
self.macro_defs.insert(invoc.expansion_data.mark, def_id);
let normal_module_def_id =
self.macro_def_scope(invoc.expansion_data.mark).normal_ancestor_id;
self.definitions.add_parent_module_of_macro_def(invoc.expansion_data.mark,
normal_module_def_id);
invoc.expansion_data.mark.set_default_transparency(ext.default_transparency());
}
2017-03-22 08:39:51 +00:00
Ok(Some(ext))
}
fn resolve_macro_path(&mut self, path: &ast::Path, kind: MacroKind, invoc_id: Mark,
derives_in_scope: Vec<ast::Path>, force: bool)
-> Result<Lrc<SyntaxExtension>, Determinacy> {
let parent_scope = self.invoc_parent_scope(invoc_id, derives_in_scope);
Ok(self.resolve_macro_to_def(path, kind, &parent_scope, false, force)?.1)
2017-05-11 10:26:07 +02:00
}
fn check_unused_macros(&self) {
2017-05-15 07:35:19 +02:00
for did in self.unused_macros.iter() {
let id_span = match *self.macro_map[did] {
SyntaxExtension::NormalTT { def_info, .. } |
SyntaxExtension::DeclMacro { def_info, .. } => def_info,
2017-05-15 07:35:19 +02:00
_ => None,
};
if let Some((id, span)) = id_span {
2017-05-11 10:26:07 +02:00
let lint = lint::builtin::UNUSED_MACROS;
rustc: Rearchitect lints to be emitted more eagerly In preparation for incremental compilation this commit refactors the lint handling infrastructure in the compiler to be more "eager" and overall more incremental-friendly. Many passes of the compiler can emit lints at various points but before this commit all lints were buffered in a table to be emitted at the very end of compilation. This commit changes these lints to be emitted immediately during compilation using pre-calculated lint level-related data structures. Linting today is split into two phases, one set of "early" lints run on the `syntax::ast` and a "late" set of lints run on the HIR. This commit moves the "early" lints to running as late as possible in compilation, just before HIR lowering. This notably means that we're catching resolve-related lints just before HIR lowering. The early linting remains a pass very similar to how it was before, maintaining context of the current lint level as it walks the tree. Post-HIR, however, linting is structured as a method on the `TyCtxt` which transitively executes a query to calculate lint levels. Each request to lint on a `TyCtxt` will query the entire crate's 'lint level data structure' and then go from there about whether the lint should be emitted or not. The query depends on the entire HIR crate but should be very quick to calculate (just a quick walk of the HIR) and the red-green system should notice that the lint level data structure rarely changes, and should hopefully preserve incrementality. Overall this resulted in a pretty big change to the test suite now that lints are emitted much earlier in compilation (on-demand vs only at the end). This in turn necessitated the addition of many `#![allow(warnings)]` directives throughout the compile-fail test suite and a number of updates to the UI test suite.
2017-07-26 21:51:09 -07:00
let msg = "unused macro definition";
self.session.buffer_lint(lint, id, span, msg);
2017-05-11 10:26:07 +02:00
} else {
bug!("attempted to create unused macro error, but span not available");
}
}
}
}
2018-12-10 05:37:10 +01:00
impl<'a> Resolver<'a> {
pub fn dummy_parent_scope(&self) -> ParentScope<'a> {
self.invoc_parent_scope(Mark::root(), Vec::new())
}
fn invoc_parent_scope(&self, invoc_id: Mark, derives: Vec<ast::Path>) -> ParentScope<'a> {
let invoc = self.invocations[&invoc_id];
ParentScope {
module: invoc.module.get().nearest_item_scope(),
expansion: invoc_id.parent(),
legacy: invoc.parent_legacy_scope.get(),
derives,
}
}
fn resolve_macro_to_def(
&mut self,
path: &ast::Path,
kind: MacroKind,
parent_scope: &ParentScope<'a>,
trace: bool,
force: bool,
) -> Result<(Def, Lrc<SyntaxExtension>), Determinacy> {
let def = self.resolve_macro_to_def_inner(path, kind, parent_scope, trace, force);
// Report errors and enforce feature gates for the resolved macro.
if def != Err(Determinacy::Undetermined) {
// Do not report duplicated errors on every undetermined resolution.
for segment in &path.segments {
if let Some(args) = &segment.args {
self.session.span_err(args.span(), "generic arguments in macro path");
}
}
}
let def = def?;
match def {
Def::Macro(def_id, macro_kind) => {
self.unused_macros.remove(&def_id);
if macro_kind == MacroKind::ProcMacroStub {
let msg = "can't use a procedural macro from the same crate that defines it";
self.session.span_err(path.span, msg);
return Err(Determinacy::Determined);
}
}
Def::NonMacroAttr(attr_kind) => {
if kind == MacroKind::Attr {
let features = self.session.features_untracked();
if attr_kind == NonMacroAttrKind::Custom {
assert!(path.segments.len() == 1);
let name = path.segments[0].ident.as_str();
if name.starts_with("rustc_") {
if !features.rustc_attrs {
let msg = "unless otherwise specified, attributes with the prefix \
`rustc_` are reserved for internal compiler diagnostics";
feature_err(&self.session.parse_sess, "rustc_attrs", path.span,
GateIssue::Language, &msg).emit();
}
} else if !features.custom_attribute {
let msg = format!("The attribute `{}` is currently unknown to the \
compiler and may have meaning added to it in the \
future", path);
feature_err(&self.session.parse_sess, "custom_attribute", path.span,
GateIssue::Language, &msg).emit();
}
}
} else {
// Not only attributes, but anything in macro namespace can result in
// `Def::NonMacroAttr` definition (e.g., `inline!()`), so we must report
// an error for those cases.
let msg = format!("expected a macro, found {}", def.kind_name());
self.session.span_err(path.span, &msg);
return Err(Determinacy::Determined);
}
rustc: Tweak custom attribute capabilities This commit starts to lay some groundwork for the stabilization of custom attribute invocations and general procedural macros. It applies a number of changes discussed on [internals] as well as a [recent issue][issue], namely: * The path used to specify a custom attribute must be of length one and cannot be a global path. This'll help future-proof us against any ambiguities and give us more time to settle the precise syntax. In the meantime though a bare identifier can be used and imported to invoke a custom attribute macro. A new feature gate, `proc_macro_path_invoc`, was added to gate multi-segment paths and absolute paths. * The set of items which can be annotated by a custom procedural attribute has been restricted. Statements, expressions, and modules are disallowed behind two new feature gates: `proc_macro_expr` and `proc_macro_mod`. * The input to procedural macro attributes has been restricted and adjusted. Today an invocation like `#[foo(bar)]` will receive `(bar)` as the input token stream, but after this PR it will only receive `bar` (the delimiters were removed). Invocations like `#[foo]` are still allowed and will be invoked in the same way as `#[foo()]`. This is a **breaking change** for all nightly users as the syntax coming in to procedural macros will be tweaked slightly. * Procedural macros (`foo!()` style) can only be expanded to item-like items by default. A separate feature gate, `proc_macro_non_items`, is required to expand to items like expressions, statements, etc. Closes #50038 [internals]: https://internals.rust-lang.org/t/help-stabilize-a-subset-of-macros-2-0/7252 [issue]: https://github.com/rust-lang/rust/issues/50038
2018-04-20 07:50:39 -07:00
}
Def::Err => {
return Err(Determinacy::Determined);
}
_ => panic!("expected `Def::Macro` or `Def::NonMacroAttr`"),
rustc: Tweak custom attribute capabilities This commit starts to lay some groundwork for the stabilization of custom attribute invocations and general procedural macros. It applies a number of changes discussed on [internals] as well as a [recent issue][issue], namely: * The path used to specify a custom attribute must be of length one and cannot be a global path. This'll help future-proof us against any ambiguities and give us more time to settle the precise syntax. In the meantime though a bare identifier can be used and imported to invoke a custom attribute macro. A new feature gate, `proc_macro_path_invoc`, was added to gate multi-segment paths and absolute paths. * The set of items which can be annotated by a custom procedural attribute has been restricted. Statements, expressions, and modules are disallowed behind two new feature gates: `proc_macro_expr` and `proc_macro_mod`. * The input to procedural macro attributes has been restricted and adjusted. Today an invocation like `#[foo(bar)]` will receive `(bar)` as the input token stream, but after this PR it will only receive `bar` (the delimiters were removed). Invocations like `#[foo]` are still allowed and will be invoked in the same way as `#[foo()]`. This is a **breaking change** for all nightly users as the syntax coming in to procedural macros will be tweaked slightly. * Procedural macros (`foo!()` style) can only be expanded to item-like items by default. A separate feature gate, `proc_macro_non_items`, is required to expand to items like expressions, statements, etc. Closes #50038 [internals]: https://internals.rust-lang.org/t/help-stabilize-a-subset-of-macros-2-0/7252 [issue]: https://github.com/rust-lang/rust/issues/50038
2018-04-20 07:50:39 -07:00
}
Ok((def, self.get_macro(def)))
}
pub fn resolve_macro_to_def_inner(
&mut self,
path: &ast::Path,
kind: MacroKind,
parent_scope: &ParentScope<'a>,
trace: bool,
force: bool,
) -> Result<Def, Determinacy> {
let path_span = path.span;
let mut path = Segment::from_path(path);
2016-11-27 10:58:46 +00:00
// Possibly apply the macro helper hack
2018-05-14 03:22:52 +03:00
if kind == MacroKind::Bang && path.len() == 1 &&
path[0].ident.span.ctxt().outer().expn_info()
.map_or(false, |info| info.local_inner_macros) {
let root = Ident::new(keywords::DollarCrate.name(), path[0].ident.span);
path.insert(0, Segment::from_ident(root));
}
if path.len() > 1 {
let def = match self.resolve_path(&path, Some(MacroNS), parent_scope,
false, path_span, CrateLint::No) {
PathResult::NonModule(path_res) if path_res.unresolved_segments() == 0 => {
Ok(path_res.base_def())
}
2016-11-27 10:58:46 +00:00
PathResult::Indeterminate if !force => return Err(Determinacy::Undetermined),
PathResult::NonModule(..) | PathResult::Indeterminate | PathResult::Failed(..) => {
Err(Determinacy::Determined)
}
PathResult::Module(..) => unreachable!(),
2016-11-27 10:58:46 +00:00
};
if trace {
parent_scope.module.multi_segment_macro_resolutions.borrow_mut()
.push((path, path_span, kind, parent_scope.clone(), def.ok()));
}
2016-11-27 10:58:46 +00:00
self.prohibit_imported_non_macro_attrs(None, def.ok(), path_span);
def
} else {
let binding = self.early_resolve_ident_in_lexical_scope(
path[0].ident, ScopeSet::Macro(kind), parent_scope, false, force, path_span
);
if let Err(Determinacy::Undetermined) = binding {
return Err(Determinacy::Undetermined);
}
2016-11-10 10:29:36 +00:00
if trace {
parent_scope.module.single_segment_macro_resolutions.borrow_mut()
.push((path[0].ident, kind, parent_scope.clone(), binding.ok()));
}
let def = binding.map(|binding| binding.def());
self.prohibit_imported_non_macro_attrs(binding.ok(), def.ok(), path_span);
def
}
}
2016-09-26 03:17:05 +00:00
// Resolve an identifier in lexical scope.
// This is a variation of `fn resolve_ident_in_lexical_scope` that can be run during
// expansion and import resolution (perhaps they can be merged in the future).
// The function is used for resolving initial segments of macro paths (e.g., `foo` in
// `foo::bar!(); or `foo!();`) and also for import paths on 2018 edition.
crate fn early_resolve_ident_in_lexical_scope(
&mut self,
orig_ident: Ident,
scope_set: ScopeSet,
parent_scope: &ParentScope<'a>,
record_used: bool,
force: bool,
path_span: Span,
) -> Result<&'a NameBinding<'a>, Determinacy> {
// General principles:
// 1. Not controlled (user-defined) names should have higher priority than controlled names
// built into the language or standard library. This way we can add new names into the
// language or standard library without breaking user code.
// 2. "Closed set" below means new names cannot appear after the current resolution attempt.
// Places to search (in order of decreasing priority):
// (Type NS)
// 1. FIXME: Ribs (type parameters), there's no necessary infrastructure yet
// (open set, not controlled).
// 2. Names in modules (both normal `mod`ules and blocks), loop through hygienic parents
// (open, not controlled).
// 3. Extern prelude (closed, not controlled).
// 4. Tool modules (closed, controlled right now, but not in the future).
// 5. Standard library prelude (de-facto closed, controlled).
// 6. Language prelude (closed, controlled).
// (Value NS)
// 1. FIXME: Ribs (local variables), there's no necessary infrastructure yet
// (open set, not controlled).
// 2. Names in modules (both normal `mod`ules and blocks), loop through hygienic parents
// (open, not controlled).
// 3. Standard library prelude (de-facto closed, controlled).
// (Macro NS)
// 1-3. Derive helpers (open, not controlled). All ambiguities with other names
// are currently reported as errors. They should be higher in priority than preludes
// and probably even names in modules according to the "general principles" above. They
// also should be subject to restricted shadowing because are effectively produced by
// derives (you need to resolve the derive first to add helpers into scope), but they
// should be available before the derive is expanded for compatibility.
// It's mess in general, so we are being conservative for now.
// 1-3. `macro_rules` (open, not controlled), loop through legacy scopes. Have higher
// priority than prelude macros, but create ambiguities with macros in modules.
// 1-3. Names in modules (both normal `mod`ules and blocks), loop through hygienic parents
// (open, not controlled). Have higher priority than prelude macros, but create
// ambiguities with `macro_rules`.
// 4. `macro_use` prelude (open, the open part is from macro expansions, not controlled).
// 4a. User-defined prelude from macro-use
// (open, the open part is from macro expansions, not controlled).
// 4b. Standard library prelude is currently implemented as `macro-use` (closed, controlled)
// 5. Language prelude: builtin macros (closed, controlled, except for legacy plugins).
// 6. Language prelude: builtin attributes (closed, controlled).
// 4-6. Legacy plugin helpers (open, not controlled). Similar to derive helpers,
// but introduced by legacy plugins using `register_attribute`. Priority is somewhere
// in prelude, not sure where exactly (creates ambiguities with any other prelude names).
enum WhereToResolve<'a> {
DeriveHelpers,
MacroRules(LegacyScope<'a>),
CrateRoot,
Module(Module<'a>),
MacroUsePrelude,
BuiltinMacros,
BuiltinAttrs,
LegacyPluginHelpers,
ExternPrelude,
ToolPrelude,
StdLibPrelude,
BuiltinTypes,
}
bitflags! {
struct Flags: u8 {
const MACRO_RULES = 1 << 0;
const MODULE = 1 << 1;
const PRELUDE = 1 << 2;
const MISC_SUGGEST_CRATE = 1 << 3;
const MISC_SUGGEST_SELF = 1 << 4;
const MISC_FROM_PRELUDE = 1 << 5;
}
}
assert!(force || !record_used); // `record_used` implies `force`
let mut ident = orig_ident.modern();
// Make sure `self`, `super` etc produce an error when passed to here.
if ident.is_path_segment_keyword() {
return Err(Determinacy::Determined);
}
// This is *the* result, resolution from the scope closest to the resolved identifier.
// However, sometimes this result is "weak" because it comes from a glob import or
// a macro expansion, and in this case it cannot shadow names from outer scopes, e.g.
// mod m { ... } // solution in outer scope
// {
// use prefix::*; // imports another `m` - innermost solution
// // weak, cannot shadow the outer `m`, need to report ambiguity error
// m::mac!();
// }
// So we have to save the innermost solution and continue searching in outer scopes
// to detect potential ambiguities.
let mut innermost_result: Option<(&NameBinding, Flags)> = None;
// Go through all the scopes and try to resolve the name.
let rust_2015 = orig_ident.span.rust_2015();
let (ns, macro_kind, is_import, is_absolute_path) = match scope_set {
ScopeSet::Import(ns) => (ns, None, true, false),
ScopeSet::AbsolutePath(ns) => (ns, None, false, true),
ScopeSet::Macro(macro_kind) => (MacroNS, Some(macro_kind), false, false),
ScopeSet::Module => (TypeNS, None, false, false),
};
let mut where_to_resolve = match ns {
_ if is_absolute_path || is_import && rust_2015 => WhereToResolve::CrateRoot,
TypeNS | ValueNS => WhereToResolve::Module(parent_scope.module),
MacroNS => WhereToResolve::DeriveHelpers,
};
let mut use_prelude = !parent_scope.module.no_implicit_prelude;
let mut determinacy = Determinacy::Determined;
2016-11-10 10:29:36 +00:00
loop {
let result = match where_to_resolve {
WhereToResolve::DeriveHelpers => {
let mut result = Err(Determinacy::Determined);
for derive in &parent_scope.derives {
let parent_scope = ParentScope { derives: Vec::new(), ..*parent_scope };
match self.resolve_macro_to_def(derive, MacroKind::Derive,
&parent_scope, true, force) {
Ok((_, ext)) => {
if let SyntaxExtension::ProcMacroDerive(_, helpers, _) = &*ext {
if helpers.contains(&ident.name) {
let binding =
(Def::NonMacroAttr(NonMacroAttrKind::DeriveHelper),
ty::Visibility::Public, derive.span, Mark::root())
.to_name_binding(self.arenas);
result = Ok((binding, Flags::empty()));
break;
}
}
}
Err(Determinacy::Determined) => {}
Err(Determinacy::Undetermined) =>
result = Err(Determinacy::Undetermined),
}
}
result
}
WhereToResolve::MacroRules(legacy_scope) => match legacy_scope {
LegacyScope::Binding(legacy_binding) if ident == legacy_binding.ident =>
Ok((legacy_binding.binding, Flags::MACRO_RULES)),
LegacyScope::Invocation(invoc) if invoc.output_legacy_scope.get().is_none() =>
Err(Determinacy::Undetermined),
_ => Err(Determinacy::Determined),
}
WhereToResolve::CrateRoot => {
let root_ident = Ident::new(keywords::PathRoot.name(), orig_ident.span);
let root_module = self.resolve_crate_root(root_ident);
let binding = self.resolve_ident_in_module_ext(
ModuleOrUniformRoot::Module(root_module),
orig_ident,
ns,
None,
record_used,
path_span,
);
match binding {
Ok(binding) => Ok((binding, Flags::MODULE | Flags::MISC_SUGGEST_CRATE)),
Err((Determinacy::Undetermined, Weak::No)) =>
return Err(Determinacy::determined(force)),
Err((Determinacy::Undetermined, Weak::Yes)) =>
Err(Determinacy::Undetermined),
Err((Determinacy::Determined, _)) => Err(Determinacy::Determined),
}
}
WhereToResolve::Module(module) => {
let orig_current_module = mem::replace(&mut self.current_module, module);
let binding = self.resolve_ident_in_module_unadjusted_ext(
ModuleOrUniformRoot::Module(module),
ident,
ns,
None,
true,
record_used,
path_span,
);
self.current_module = orig_current_module;
match binding {
Ok(binding) => {
let misc_flags = if ptr::eq(module, self.graph_root) {
Flags::MISC_SUGGEST_CRATE
} else if module.is_normal() {
Flags::MISC_SUGGEST_SELF
} else {
Flags::empty()
};
Ok((binding, Flags::MODULE | misc_flags))
}
Err((Determinacy::Undetermined, Weak::No)) =>
return Err(Determinacy::determined(force)),
Err((Determinacy::Undetermined, Weak::Yes)) =>
Err(Determinacy::Undetermined),
Err((Determinacy::Determined, _)) => Err(Determinacy::Determined),
}
}
WhereToResolve::MacroUsePrelude => {
if use_prelude || rust_2015 {
match self.macro_use_prelude.get(&ident.name).cloned() {
Some(binding) =>
Ok((binding, Flags::PRELUDE | Flags::MISC_FROM_PRELUDE)),
None => Err(Determinacy::determined(
self.graph_root.unresolved_invocations.borrow().is_empty()
))
}
} else {
Err(Determinacy::Determined)
}
}
WhereToResolve::BuiltinMacros => {
match self.builtin_macros.get(&ident.name).cloned() {
Some(binding) => Ok((binding, Flags::PRELUDE)),
None => Err(Determinacy::Determined),
}
}
WhereToResolve::BuiltinAttrs => {
if is_builtin_attr_name(ident.name) {
let binding = (Def::NonMacroAttr(NonMacroAttrKind::Builtin),
ty::Visibility::Public, DUMMY_SP, Mark::root())
.to_name_binding(self.arenas);
Ok((binding, Flags::PRELUDE))
} else {
Err(Determinacy::Determined)
}
}
WhereToResolve::LegacyPluginHelpers => {
if (use_prelude || rust_2015) &&
self.session.plugin_attributes.borrow().iter()
.any(|(name, _)| ident.name == &**name) {
let binding = (Def::NonMacroAttr(NonMacroAttrKind::LegacyPluginHelper),
ty::Visibility::Public, DUMMY_SP, Mark::root())
.to_name_binding(self.arenas);
Ok((binding, Flags::PRELUDE))
} else {
Err(Determinacy::Determined)
}
}
WhereToResolve::ExternPrelude => {
if use_prelude || is_absolute_path {
2018-11-17 21:08:00 +03:00
match self.extern_prelude_get(ident, !record_used) {
Some(binding) => Ok((binding, Flags::PRELUDE)),
None => Err(Determinacy::determined(
self.graph_root.unresolved_invocations.borrow().is_empty()
)),
}
} else {
Err(Determinacy::Determined)
}
}
WhereToResolve::ToolPrelude => {
if use_prelude && is_known_tool(ident.name) {
let binding = (Def::ToolMod, ty::Visibility::Public,
DUMMY_SP, Mark::root()).to_name_binding(self.arenas);
Ok((binding, Flags::PRELUDE))
} else {
Err(Determinacy::Determined)
}
}
WhereToResolve::StdLibPrelude => {
let mut result = Err(Determinacy::Determined);
if use_prelude {
if let Some(prelude) = self.prelude {
if let Ok(binding) = self.resolve_ident_in_module_unadjusted(
ModuleOrUniformRoot::Module(prelude),
ident,
ns,
false,
path_span,
) {
result = Ok((binding, Flags::PRELUDE | Flags::MISC_FROM_PRELUDE));
}
}
}
result
}
WhereToResolve::BuiltinTypes => {
match self.primitive_type_table.primitive_types.get(&ident.name).cloned() {
Some(prim_ty) => {
let binding = (Def::PrimTy(prim_ty), ty::Visibility::Public,
DUMMY_SP, Mark::root()).to_name_binding(self.arenas);
Ok((binding, Flags::PRELUDE))
}
None => Err(Determinacy::Determined)
}
}
};
match result {
Ok((binding, flags)) if sub_namespace_match(binding.macro_kind(), macro_kind) => {
if !record_used {
return Ok(binding);
}
if let Some((innermost_binding, innermost_flags)) = innermost_result {
// Found another solution, if the first one was "weak", report an error.
let (def, innermost_def) = (binding.def(), innermost_binding.def());
if def != innermost_def {
let builtin = Def::NonMacroAttr(NonMacroAttrKind::Builtin);
let derive_helper = Def::NonMacroAttr(NonMacroAttrKind::DeriveHelper);
let legacy_helper =
Def::NonMacroAttr(NonMacroAttrKind::LegacyPluginHelper);
let ambiguity_error_kind = if is_import {
Some(AmbiguityKind::Import)
} else if is_absolute_path {
Some(AmbiguityKind::AbsolutePath)
} else if innermost_def == builtin || def == builtin {
Some(AmbiguityKind::BuiltinAttr)
} else if innermost_def == derive_helper || def == derive_helper {
Some(AmbiguityKind::DeriveHelper)
} else if innermost_def == legacy_helper &&
flags.contains(Flags::PRELUDE) ||
def == legacy_helper &&
innermost_flags.contains(Flags::PRELUDE) {
Some(AmbiguityKind::LegacyHelperVsPrelude)
} else if innermost_flags.contains(Flags::MACRO_RULES) &&
flags.contains(Flags::MODULE) &&
!self.disambiguate_legacy_vs_modern(innermost_binding,
binding) ||
flags.contains(Flags::MACRO_RULES) &&
innermost_flags.contains(Flags::MODULE) &&
!self.disambiguate_legacy_vs_modern(binding,
innermost_binding) {
Some(AmbiguityKind::LegacyVsModern)
} else if innermost_binding.is_glob_import() {
Some(AmbiguityKind::GlobVsOuter)
} else if innermost_binding.may_appear_after(parent_scope.expansion,
binding) {
Some(AmbiguityKind::MoreExpandedVsOuter)
} else {
None
};
if let Some(kind) = ambiguity_error_kind {
let misc = |f: Flags| if f.contains(Flags::MISC_SUGGEST_CRATE) {
AmbiguityErrorMisc::SuggestCrate
} else if f.contains(Flags::MISC_SUGGEST_SELF) {
AmbiguityErrorMisc::SuggestSelf
} else if f.contains(Flags::MISC_FROM_PRELUDE) {
AmbiguityErrorMisc::FromPrelude
} else {
AmbiguityErrorMisc::None
};
self.ambiguity_errors.push(AmbiguityError {
kind,
ident: orig_ident,
b1: innermost_binding,
b2: binding,
misc1: misc(innermost_flags),
misc2: misc(flags),
});
return Ok(innermost_binding);
}
2016-11-27 10:58:46 +00:00
}
} else {
// Found the first solution.
innermost_result = Some((binding, flags));
}
}
Ok(..) | Err(Determinacy::Determined) => {}
Err(Determinacy::Undetermined) => determinacy = Determinacy::Undetermined
2016-11-10 10:29:36 +00:00
}
where_to_resolve = match where_to_resolve {
WhereToResolve::DeriveHelpers =>
WhereToResolve::MacroRules(parent_scope.legacy),
WhereToResolve::MacroRules(legacy_scope) => match legacy_scope {
LegacyScope::Binding(binding) => WhereToResolve::MacroRules(
binding.parent_legacy_scope
),
LegacyScope::Invocation(invoc) => WhereToResolve::MacroRules(
invoc.output_legacy_scope.get().unwrap_or(invoc.parent_legacy_scope.get())
),
LegacyScope::Empty => WhereToResolve::Module(parent_scope.module),
LegacyScope::Uninitialized => unreachable!(),
}
WhereToResolve::CrateRoot if is_import => match ns {
TypeNS | ValueNS => WhereToResolve::Module(parent_scope.module),
MacroNS => WhereToResolve::DeriveHelpers,
}
WhereToResolve::CrateRoot if is_absolute_path => match ns {
TypeNS => {
ident.span.adjust(Mark::root());
WhereToResolve::ExternPrelude
}
ValueNS | MacroNS => break,
}
WhereToResolve::CrateRoot => unreachable!(),
WhereToResolve::Module(module) => {
match self.hygienic_lexical_parent(module, &mut ident.span) {
Some(parent_module) => WhereToResolve::Module(parent_module),
None => {
use_prelude = !module.no_implicit_prelude;
match ns {
TypeNS => WhereToResolve::ExternPrelude,
ValueNS => WhereToResolve::StdLibPrelude,
MacroNS => WhereToResolve::MacroUsePrelude,
}
}
}
}
WhereToResolve::MacroUsePrelude => WhereToResolve::BuiltinMacros,
WhereToResolve::BuiltinMacros => WhereToResolve::BuiltinAttrs,
WhereToResolve::BuiltinAttrs => WhereToResolve::LegacyPluginHelpers,
WhereToResolve::LegacyPluginHelpers => break, // nowhere else to search
WhereToResolve::ExternPrelude if is_absolute_path => break,
WhereToResolve::ExternPrelude => WhereToResolve::ToolPrelude,
WhereToResolve::ToolPrelude => WhereToResolve::StdLibPrelude,
WhereToResolve::StdLibPrelude => match ns {
TypeNS => WhereToResolve::BuiltinTypes,
ValueNS => break, // nowhere else to search
MacroNS => unreachable!(),
}
WhereToResolve::BuiltinTypes => break, // nowhere else to search
};
continue;
}
2016-11-10 10:29:36 +00:00
// The first found solution was the only one, return it.
if let Some((binding, flags)) = innermost_result {
// We get to here only if there's no ambiguity, in ambiguous cases an error will
// be reported anyway, so there's no reason to report an additional feature error.
// The `binding` can actually be introduced by something other than `--extern`,
// but its `Def` should coincide with a crate passed with `--extern`
// (otherwise there would be ambiguity) and we can skip feature error in this case.
'ok: {
2018-12-27 03:38:43 +03:00
if !is_import || !rust_2015 {
break 'ok;
}
if ns == TypeNS && use_prelude && self.extern_prelude_get(ident, true).is_some() {
break 'ok;
}
2018-12-27 03:38:43 +03:00
let root_ident = Ident::new(keywords::PathRoot.name(), orig_ident.span);
let root_module = self.resolve_crate_root(root_ident);
if self.resolve_ident_in_module_ext(ModuleOrUniformRoot::Module(root_module),
orig_ident, ns, None, false, path_span)
.is_ok() {
break 'ok;
}
2018-12-27 03:38:43 +03:00
let msg = "imports can only refer to extern crate names passed with \
`--extern` in macros originating from 2015 edition";
let mut err = self.session.struct_span_err(ident.span, msg);
let what = self.binding_description(binding, ident,
flags.contains(Flags::MISC_FROM_PRELUDE));
let note_msg = format!("this import refers to {what}", what = what);
let label_span = if binding.span.is_dummy() {
err.note(&note_msg);
ident.span
} else {
err.span_note(binding.span, &note_msg);
binding.span
};
err.span_label(label_span, "not an extern crate passed with `--extern`");
err.emit();
}
return Ok(binding);
2016-11-10 10:29:36 +00:00
}
let determinacy = Determinacy::determined(determinacy == Determinacy::Determined || force);
if determinacy == Determinacy::Determined && macro_kind == Some(MacroKind::Attr) {
// For single-segment attributes interpret determinate "no resolution" as a custom
// attribute. (Lexical resolution implies the first segment and attr kind should imply
// the last segment, so we are certainly working with a single-segment attribute here.)
assert!(ns == MacroNS);
let binding = (Def::NonMacroAttr(NonMacroAttrKind::Custom),
ty::Visibility::Public, ident.span, Mark::root())
.to_name_binding(self.arenas);
Ok(binding)
} else {
Err(determinacy)
}
2016-11-10 10:29:36 +00:00
}
pub fn finalize_current_module_macro_resolutions(&mut self) {
let module = self.current_module;
let check_consistency = |this: &mut Self, path: &[Segment], span, kind: MacroKind,
initial_def: Option<Def>, def: Def| {
if let Some(initial_def) = initial_def {
if def != initial_def && def != Def::Err && this.ambiguity_errors.is_empty() {
// Make sure compilation does not succeed if preferred macro resolution
// has changed after the macro had been expanded. In theory all such
// situations should be reported as ambiguity errors, so this is a bug.
if initial_def == Def::NonMacroAttr(NonMacroAttrKind::Custom) {
// Yeah, legacy custom attributes are implemented using forced resolution
// (which is a best effort error recovery tool, basically), so we can't
// promise their resolution won't change later.
let msg = format!("inconsistent resolution for a macro: first {}, then {}",
initial_def.kind_name(), def.kind_name());
this.session.span_err(span, &msg);
} else {
span_bug!(span, "inconsistent resolution for a macro");
}
}
} else {
// It's possible that the macro was unresolved (indeterminate) and silently
// expanded into a dummy fragment for recovery during expansion.
// Now, post-expansion, the resolution may succeed, but we can't change the
// past and need to report an error.
// However, non-speculative `resolve_path` can successfully return private items
// even if speculative `resolve_path` returned nothing previously, so we skip this
// less informative error if the privacy error is reported elsewhere.
if this.privacy_errors.is_empty() {
let msg = format!("cannot determine resolution for the {} `{}`",
2018-11-18 14:41:06 +03:00
kind.descr(), Segment::names_to_string(path));
let msg_note = "import resolution is stuck, try simplifying macro imports";
this.session.struct_span_err(span, &msg).note(msg_note).emit();
}
}
};
let macro_resolutions =
mem::replace(&mut *module.multi_segment_macro_resolutions.borrow_mut(), Vec::new());
for (mut path, path_span, kind, parent_scope, initial_def) in macro_resolutions {
// FIXME: Path resolution will ICE if segment IDs present.
for seg in &mut path { seg.id = None; }
match self.resolve_path(&path, Some(MacroNS), &parent_scope,
true, path_span, CrateLint::No) {
PathResult::NonModule(path_res) if path_res.unresolved_segments() == 0 => {
let def = path_res.base_def();
check_consistency(self, &path, path_span, kind, initial_def, def);
}
path_res @ PathResult::NonModule(..) | path_res @ PathResult::Failed(..) => {
let (span, msg) = if let PathResult::Failed(span, msg, ..) = path_res {
(span, msg)
} else {
(path_span, format!("partially resolved path in {} {}",
kind.article(), kind.descr()))
};
2016-11-27 10:58:46 +00:00
resolve_error(self, span, ResolutionError::FailedToResolve(&msg));
}
PathResult::Module(..) | PathResult::Indeterminate => unreachable!(),
2016-11-27 10:58:46 +00:00
}
}
let macro_resolutions =
mem::replace(&mut *module.single_segment_macro_resolutions.borrow_mut(), Vec::new());
for (ident, kind, parent_scope, initial_binding) in macro_resolutions {
match self.early_resolve_ident_in_lexical_scope(ident, ScopeSet::Macro(kind),
&parent_scope, true, true, ident.span) {
Ok(binding) => {
let initial_def = initial_binding.map(|initial_binding| {
self.record_use(ident, MacroNS, initial_binding, false);
initial_binding.def()
});
let def = binding.def();
2018-11-18 14:41:06 +03:00
let seg = Segment::from_ident(ident);
check_consistency(self, &[seg], ident.span, kind, initial_def, def);
}
Err(..) => {
assert!(initial_binding.is_none());
let bang = if kind == MacroKind::Bang { "!" } else { "" };
let msg =
format!("cannot find {} `{}{}` in this scope", kind.descr(), ident, bang);
let mut err = self.session.struct_span_err(ident.span, &msg);
self.suggest_macro_name(&ident.as_str(), kind, &mut err, ident.span);
err.emit();
}
}
2016-10-31 22:17:15 +00:00
}
let builtin_attrs = mem::replace(&mut *module.builtin_attrs.borrow_mut(), Vec::new());
for (ident, parent_scope) in builtin_attrs {
let _ = self.early_resolve_ident_in_lexical_scope(
ident, ScopeSet::Macro(MacroKind::Attr), &parent_scope, true, true, ident.span
);
}
}
fn prohibit_imported_non_macro_attrs(&self, binding: Option<&'a NameBinding<'a>>,
def: Option<Def>, span: Span) {
if let Some(Def::NonMacroAttr(kind)) = def {
if kind != NonMacroAttrKind::Tool && binding.map_or(true, |b| b.is_import()) {
let msg = format!("cannot use a {} through an import", kind.descr());
let mut err = self.session.struct_span_err(span, &msg);
if let Some(binding) = binding {
err.span_note(binding.span, &format!("the {} imported here", kind.descr()));
}
err.emit();
}
}
}
fn suggest_macro_name(&mut self, name: &str, kind: MacroKind,
err: &mut DiagnosticBuilder<'a>, span: Span) {
// First check if this is a locally-defined bang macro.
let suggestion = if let MacroKind::Bang = kind {
2017-03-22 08:39:51 +00:00
find_best_match_for_name(self.macro_names.iter().map(|ident| &ident.name), name, None)
} else {
None
2017-03-16 01:39:47 +00:00
// Then check global macros.
}.or_else(|| {
let names = self.builtin_macros.iter().chain(self.macro_use_prelude.iter())
.filter_map(|(name, binding)| {
if binding.macro_kind() == Some(kind) { Some(name) } else { None }
});
find_best_match_for_name(names, name, None)
// Then check modules.
}).or_else(|| {
let is_macro = |def| {
if let Def::Macro(_, def_kind) = def {
def_kind == kind
} else {
false
}
};
2018-03-18 16:47:09 +03:00
let ident = Ident::new(Symbol::intern(name), span);
self.lookup_typo_candidate(&[Segment::from_ident(ident)], MacroNS, is_macro, span)
.map(|suggestion| suggestion.candidate)
});
if let Some(suggestion) = suggestion {
if suggestion != name {
if let MacroKind::Bang = kind {
err.span_suggestion_with_applicability(
span,
"you could try the macro",
suggestion.to_string(),
Applicability::MaybeIncorrect
);
} else {
err.span_suggestion_with_applicability(
span,
"try",
suggestion.to_string(),
Applicability::MaybeIncorrect
);
}
} else {
err.help("have you added the `#[macro_use]` on the module/import?");
}
}
}
2017-03-24 23:03:15 +00:00
fn collect_def_ids(&mut self,
mark: Mark,
invocation: &'a InvocationData<'a>,
fragment: &AstFragment) {
let Resolver { ref mut invocations, arenas, graph_root, .. } = *self;
let InvocationData { def_index, .. } = *invocation;
2016-09-16 08:50:34 +00:00
let visit_macro_invoc = &mut |invoc: map::MacroInvocationData| {
invocations.entry(invoc.mark).or_insert_with(|| {
arenas.alloc_invocation_data(InvocationData {
2016-09-16 08:50:34 +00:00
def_index: invoc.def_index,
module: Cell::new(graph_root),
parent_legacy_scope: Cell::new(LegacyScope::Uninitialized),
output_legacy_scope: Cell::new(None),
2016-09-16 08:50:34 +00:00
})
});
};
2017-03-24 23:03:15 +00:00
let mut def_collector = DefCollector::new(&mut self.definitions, mark);
def_collector.visit_macro_invoc = Some(visit_macro_invoc);
def_collector.with_parent(def_index, |def_collector| {
fragment.visit_with(def_collector)
});
}
pub fn define_macro(&mut self,
item: &ast::Item,
expansion: Mark,
current_legacy_scope: &mut LegacyScope<'a>) {
self.local_macro_def_scopes.insert(item.id, self.current_module);
let ident = item.ident;
if ident.name == "macro_rules" {
self.session.span_err(item.span, "user-defined macros may not be named `macro_rules`");
}
let def_id = self.definitions.local_def_id(item.id);
2018-02-27 17:11:14 +01:00
let ext = Lrc::new(macro_rules::compile(&self.session.parse_sess,
2018-02-14 16:11:02 +01:00
&self.session.features_untracked(),
item, hygiene::default_edition()));
self.macro_map.insert(def_id, ext);
let def = match item.node { ast::ItemKind::MacroDef(ref def) => def, _ => unreachable!() };
if def.legacy {
2017-03-22 08:39:51 +00:00
let ident = ident.modern();
self.macro_names.insert(ident);
let def = Def::Macro(def_id, MacroKind::Bang);
let is_macro_export = attr::contains_name(&item.attrs, "macro_export");
let vis = if is_macro_export {
ty::Visibility::Public
} else {
ty::Visibility::Restricted(DefId::local(CRATE_DEF_INDEX))
};
let binding = (def, vis, item.span, expansion).to_name_binding(self.arenas);
self.set_binding_parent_module(binding, self.current_module);
let legacy_binding = self.arenas.alloc_legacy_binding(LegacyBinding {
parent_legacy_scope: *current_legacy_scope, binding, ident
});
*current_legacy_scope = LegacyScope::Binding(legacy_binding);
self.all_macros.insert(ident.name, def);
if is_macro_export {
2018-05-14 03:22:52 +03:00
let module = self.graph_root;
self.define(module, ident, MacroNS,
(def, vis, item.span, expansion, IsMacroExport));
} else {
if !attr::contains_name(&item.attrs, "rustc_doc_only_macro") {
self.check_reserved_macro_name(ident, MacroNS);
}
self.unused_macros.insert(def_id);
}
2017-05-11 10:26:07 +02:00
} else {
let module = self.current_module;
let def = Def::Macro(def_id, MacroKind::Bang);
let vis = self.resolve_visibility(&item.vis);
if vis != ty::Visibility::Public {
self.unused_macros.insert(def_id);
}
self.define(module, ident, MacroNS, (def, vis, item.span, expansion));
}
}
}