// 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::PathRoot.name(), orig_ident.span);
                let root_module = self.resolve_crate_root(root_ident);
                if self.resolve_ident_in_module_ext(ModuleOrUniformRoot::Module(root_module),
                                                    orig_ident, ns, None, false, path_span)
                                                    .is_ok() {
                    break 'ok;
                }

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