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

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

            binding.map(|binding| binding.def_ignoring_ambiguity())
        }
    }

    // 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 || self.session.features_untracked().uniform_paths {
                    break 'ok;
                }
                if ns == TypeNS && use_prelude && self.extern_prelude_get(ident, true).is_some() {
                    break 'ok;
                }
                if rust_2015 {
                    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` on stable channel";
                let mut err = feature_err(&self.session.parse_sess, "uniform_paths",
                                          ident.span, GateIssue::Language, 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);
                if binding.span.is_dummy() {
                    err.note(&note_msg);
                } else {
                    err.span_note(binding.span, &note_msg);
                    err.span_label(binding.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 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 vis = ty::Visibility::Invisible; // Doesn't matter for legacy bindings
            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 attr::contains_name(&item.attrs, "macro_export") {
                let module = self.graph_root;
                let vis = ty::Visibility::Public;
                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);
        }
    }
}
