// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use {AmbiguityError, AmbiguityKind, AmbiguityErrorMisc};
use {CrateLint, Resolver, ResolutionError, ScopeSet, Weak};
use {Module, ModuleKind, NameBinding, NameBindingKind, PathResult, Segment, ToNameBinding};
use {is_known_tool, resolve_error};
use ModuleOrUniformRoot;
use Namespace::*;
use build_reduced_graph::{BuildReducedGraphVisitor, IsMacroExport};
use resolve_imports::ImportResolver;
use rustc::hir::def_id::{DefId, CRATE_DEF_INDEX, DefIndex,
                         CrateNum, DefIndexAddressSpace};
use rustc::hir::def::{Def, NonMacroAttrKind};
use rustc::hir::map::{self, DefCollector};
use rustc::{ty, lint};
use syntax::ast::{self, Name, Ident};
use syntax::attr;
use syntax::errors::DiagnosticBuilder;
use syntax::ext::base::{self, Determinacy};
use syntax::ext::base::{MacroKind, SyntaxExtension, Resolver as SyntaxResolver};
use syntax::ext::expand::{AstFragment, Invocation, InvocationKind};
use syntax::ext::hygiene::{self, Mark};
use syntax::ext::tt::macro_rules;
use syntax::feature_gate::{self, feature_err, emit_feature_err, is_builtin_attr_name, GateIssue};
use syntax::feature_gate::EXPLAIN_DERIVE_UNDERSCORE;
use syntax::fold::{self, Folder};
use syntax::parse::parser::PathStyle;
use syntax::parse::token::{self, Token};
use syntax::ptr::P;
use syntax::symbol::{Symbol, keywords};
use syntax::tokenstream::{TokenStream, TokenTree, Delimited, DelimSpan};
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};
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 {
            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)]
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.
    Empty,
    /// Scope introduced by a `macro_rules!` macro definition.
    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
}

impl<'a, 'crateloader: 'a> base::Resolver for Resolver<'a, 'crateloader> {
    fn next_node_id(&mut self) -> ast::NodeId {
        self.session.next_node_id()
    }

    fn get_module_scope(&mut self, id: ast::NodeId) -> Mark {
        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 {
            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)),
        }));
        mark
    }

    fn eliminate_crate_var(&mut self, item: P<ast::Item>) -> P<ast::Item> {
        struct EliminateCrateVar<'b, 'a: 'b, 'crateloader: 'a>(
            &'b mut Resolver<'a, 'crateloader>, Span
        );

        impl<'a, 'b, 'crateloader> Folder for EliminateCrateVar<'a, 'b, 'crateloader> {
            fn fold_path(&mut self, path: ast::Path) -> ast::Path {
                match self.fold_qpath(None, path) {
                    (None, path) => path,
                    _ => unreachable!(),
                }
            }

            fn fold_qpath(&mut self, mut qself: Option<ast::QSelf>, mut path: ast::Path)
                          -> (Option<ast::QSelf>, ast::Path) {
                qself = qself.map(|ast::QSelf { ty, path_span, position }| {
                    ast::QSelf {
                        ty: self.fold_ty(ty),
                        path_span: self.new_span(path_span),
                        position,
                    }
                });

                if path.segments[0].ident.name == keywords::DollarCrate.name() {
                    let module = self.0.resolve_crate_root(path.segments[0].ident);
                    path.segments[0].ident.name = keywords::CrateRoot.name();
                    if !module.is_local() {
                        let span = path.segments[0].ident.span;
                        path.segments.insert(1, match module.kind {
                            ModuleKind::Def(_, name) => ast::PathSegment::from_ident(
                                ast::Ident::with_empty_ctxt(name).with_span_pos(span)
                            ),
                            _ => unreachable!(),
                        });
                        if let Some(qself) = &mut qself {
                            qself.position += 1;
                        }
                    }
                }
                (qself, path)
            }

            fn fold_mac(&mut self, mac: ast::Mac) -> ast::Mac {
                fold::noop_fold_mac(mac, self)
            }
        }

        let ret = EliminateCrateVar(self, item.span).fold_item(item);
        assert!(ret.len() == 1);
        ret.into_iter().next().unwrap()
    }

    fn is_whitelisted_legacy_custom_derive(&self, name: Name) -> bool {
        self.whitelisted_legacy_custom_derives.contains(&name)
    }

    fn visit_ast_fragment_with_placeholders(&mut self, mark: Mark, fragment: &AstFragment,
                                            derives: &[Mark]) {
        let invocation = self.invocations[&mark];
        self.collect_def_ids(mark, invocation, fragment);

        self.current_module = invocation.module.get();
        self.current_module.unresolved_invocations.borrow_mut().remove(&mark);
        self.current_module.unresolved_invocations.borrow_mut().extend(derives);
        self.invocations.extend(derives.iter().map(|&derive| (derive, invocation)));
        let mut visitor = BuildReducedGraphVisitor {
            resolver: self,
            current_legacy_scope: invocation.parent_legacy_scope.get(),
            expansion: mark,
        };
        fragment.visit_with(&mut visitor);
        invocation.output_legacy_scope.set(Some(visitor.current_legacy_scope));
    }

    fn add_builtin(&mut self, ident: ast::Ident, ext: Lrc<SyntaxExtension>) {
        let def_id = DefId {
            krate: CrateNum::BuiltinMacros,
            index: DefIndex::from_array_index(self.macro_map.len(),
                                              DefIndexAddressSpace::Low),
        };
        let kind = ext.kind();
        self.macro_map.insert(def_id, ext);
        let binding = self.arenas.alloc_name_binding(NameBinding {
            kind: NameBindingKind::Def(Def::Macro(def_id, kind), false),
            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));
        }
    }

    fn resolve_imports(&mut self) {
        ImportResolver { resolver: self }.resolve_imports()
    }

    // Resolves attribute and derive legacy macros from `#![plugin(..)]`.
    fn find_legacy_attr_invoc(&mut self, attrs: &mut Vec<ast::Attribute>, allow_derive: bool)
                              -> Option<ast::Attribute> {
        if !allow_derive {
            return None;
        }

        // Check for legacy derives
        for i in 0..attrs.len() {
            let name = attrs[i].name();

            if name == "derive" {
                let result = attrs[i].parse_list(&self.session.parse_sess, |parser| {
                    parser.parse_path_allowing_meta(PathStyle::Mod)
                });

                let mut traits = match result {
                    Ok(traits) => traits,
                    Err(mut e) => {
                        e.cancel();
                        continue
                    }
                };

                for j in 0..traits.len() {
                    if traits[j].segments.len() > 1 {
                        continue
                    }
                    let trait_name = traits[j].segments[0].ident.name;
                    let legacy_name = Symbol::intern(&format!("derive_{}", trait_name));
                    if !self.builtin_macros.contains_key(&legacy_name) {
                        continue
                    }
                    let span = traits.remove(j).span;
                    self.gate_legacy_custom_derive(legacy_name, span);
                    if traits.is_empty() {
                        attrs.remove(i);
                    } else {
                        let mut tokens = Vec::with_capacity(traits.len() - 1);
                        for (j, path) in traits.iter().enumerate() {
                            if j > 0 {
                                tokens.push(TokenTree::Token(attrs[i].span, Token::Comma).into());
                            }
                            tokens.reserve((path.segments.len() * 2).saturating_sub(1));
                            for (k, segment) in path.segments.iter().enumerate() {
                                if k > 0 {
                                    tokens.push(TokenTree::Token(path.span, Token::ModSep).into());
                                }
                                let tok = Token::from_ast_ident(segment.ident);
                                tokens.push(TokenTree::Token(path.span, tok).into());
                            }
                        }
                        let delim_span = DelimSpan::from_single(attrs[i].span);
                        attrs[i].tokens = TokenTree::Delimited(delim_span, Delimited {
                            delim: token::Paren,
                            tts: TokenStream::concat(tokens).into(),
                        }).into();
                    }
                    return Some(ast::Attribute {
                        path: ast::Path::from_ident(Ident::new(legacy_name, span)),
                        tokens: TokenStream::empty(),
                        id: attr::mk_attr_id(),
                        style: ast::AttrStyle::Outer,
                        is_sugared_doc: false,
                        span,
                    });
                }
            }
        }

        None
    }

    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) = self.resolve_macro_to_def(path, kind, &parent_scope, true, force)?;

        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());
            invoc.expansion_data.mark.set_is_builtin(def_id.krate == CrateNum::BuiltinMacros);
        }

        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)
    }

    fn check_unused_macros(&self) {
        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,
                _ => None,
            };
            if let Some((id, span)) = id_span {
                let lint = lint::builtin::UNUSED_MACROS;
                let msg = "unused macro definition";
                self.session.buffer_lint(lint, id, span, msg);
            } else {
                bug!("attempted to create unused macro error, but span not available");
            }
        }
    }
}

impl<'a, 'cl> Resolver<'a, 'cl> {
    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.name.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 name.starts_with("derive_") {
                            if !features.custom_derive {
                                feature_err(&self.session.parse_sess, "custom_derive", path.span,
                                            GateIssue::Language, EXPLAIN_DERIVE_UNDERSCORE).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);
                }
            }
            Def::Err => {
                return Err(Determinacy::Determined);
            }
            _ => panic!("expected `Def::Macro` or `Def::NonMacroAttr`"),
        }

        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);

        // Possibly apply the macro helper hack
        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())
                }
                PathResult::Indeterminate if !force => return Err(Determinacy::Undetermined),
                PathResult::NonModule(..) | PathResult::Indeterminate | PathResult::Failed(..) => {
                    self.found_unresolved_macro = true;
                    Err(Determinacy::Determined)
                }
                PathResult::Module(..) => unreachable!(),
            };

            if trace {
                parent_scope.module.multi_segment_macro_resolutions.borrow_mut()
                    .push((path, path_span, kind, parent_scope.clone(), def.ok()));
            }

            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
            );
            match binding {
                Ok(..) => {}
                Err(Determinacy::Determined) => self.found_unresolved_macro = true,
                Err(Determinacy::Undetermined) => return Err(Determinacy::Undetermined),
            }

            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_ignoring_ambiguity());
            self.prohibit_imported_non_macro_attrs(binding.ok(), def.ok(), path_span);
            def
        }
    }

    // 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;
        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::CrateRoot.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 {
                        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);
                            }
                        }
                    } else {
                        // Found the first solution.
                        innermost_result = Some((binding, flags));
                    }
                }
                Ok(..) | Err(Determinacy::Determined) => {}
                Err(Determinacy::Undetermined) => determinacy = Determinacy::Undetermined
            }

            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;
        }

        // 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: {
                if !is_import || !rust_2015 {
                    break 'ok;
                }
                if ns == TypeNS && use_prelude && self.extern_prelude_get(ident, true).is_some() {
                    break 'ok;
                }
                let root_ident = Ident::new(keywords::CrateRoot.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;
                }

                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);
        }

        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)
        }
    }

    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, 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.
                    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 {} `{}`",
                                        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()))
                    };
                    resolve_error(self, span, ResolutionError::FailedToResolve(&msg));
                }
                PathResult::Module(..) | PathResult::Indeterminate => unreachable!(),
            }
        }

        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_ignoring_ambiguity()
                    });
                    let def = binding.def_ignoring_ambiguity();
                    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();
                }
            }
        }

        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 {
            find_best_match_for_name(self.macro_names.iter().map(|ident| &ident.name), name, None)
        } else {
            None
        // 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
                }
            };
            let ident = Ident::new(Symbol::intern(name), span);
            self.lookup_typo_candidate(&[Segment::from_ident(ident)], MacroNS, is_macro, span)
        });

        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?");
            }
        }
    }

    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;

        let visit_macro_invoc = &mut |invoc: map::MacroInvocationData| {
            invocations.entry(invoc.mark).or_insert_with(|| {
                arenas.alloc_invocation_data(InvocationData {
                    def_index: invoc.def_index,
                    module: Cell::new(graph_root),
                    parent_legacy_scope: Cell::new(LegacyScope::Uninitialized),
                    output_legacy_scope: Cell::new(None),
                })
            });
        };

        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);
        let ext = Lrc::new(macro_rules::compile(&self.session.parse_sess,
                                               &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 {
            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 {
                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);
            }
        } 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));
        }
    }

    fn gate_legacy_custom_derive(&mut self, name: Symbol, span: Span) {
        if !self.session.features_untracked().custom_derive {
            let sess = &self.session.parse_sess;
            let explain = feature_gate::EXPLAIN_CUSTOM_DERIVE;
            emit_feature_err(sess, "custom_derive", span, GateIssue::Language, explain);
        } else if !self.is_whitelisted_legacy_custom_derive(name) {
            self.session.span_warn(span, feature_gate::EXPLAIN_DEPR_CUSTOM_DERIVE);
        }
    }
}
