// Copyright 2012-2015 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.

#![crate_name = "rustc_resolve"]
#![unstable(feature = "rustc_private", issue = "27812")]
#![crate_type = "dylib"]
#![crate_type = "rlib"]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
      html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
      html_root_url = "https://doc.rust-lang.org/nightly/")]

#![feature(associated_consts)]
#![feature(borrow_state)]
#![feature(rustc_diagnostic_macros)]
#![feature(rustc_private)]
#![feature(staged_api)]

#[macro_use]
extern crate log;
#[macro_use]
extern crate syntax;
extern crate arena;
#[macro_use]
#[no_link]
extern crate rustc_bitflags;
extern crate rustc_front;
extern crate rustc;

use self::PatternBindingMode::*;
use self::Namespace::*;
use self::NamespaceResult::*;
use self::ResolveResult::*;
use self::FallbackSuggestion::*;
use self::TypeParameters::*;
use self::RibKind::*;
use self::UseLexicalScopeFlag::*;
use self::ModulePrefixResult::*;
use self::AssocItemResolveResult::*;
use self::NameSearchType::*;
use self::BareIdentifierPatternResolution::*;
use self::ParentLink::*;
use self::FallbackChecks::*;

use rustc::front::map as hir_map;
use rustc::session::Session;
use rustc::lint;
use rustc::middle::cstore::{CrateStore, DefLike, DlDef};
use rustc::middle::def::*;
use rustc::middle::def_id::DefId;
use rustc::middle::pat_util::pat_bindings;
use rustc::middle::privacy::*;
use rustc::middle::subst::{ParamSpace, FnSpace, TypeSpace};
use rustc::middle::ty::{Freevar, FreevarMap, TraitMap, GlobMap};
use rustc::util::nodemap::{NodeMap, DefIdSet, FnvHashMap};

use syntax::ast;
use syntax::ast::{CRATE_NODE_ID, Name, NodeId, CrateNum, TyIs, TyI8, TyI16, TyI32, TyI64};
use syntax::ast::{TyUs, TyU8, TyU16, TyU32, TyU64, TyF64, TyF32};
use syntax::attr::AttrMetaMethods;
use syntax::codemap::{self, Span, Pos};
use syntax::errors::DiagnosticBuilder;
use syntax::parse::token::{self, special_names, special_idents};
use syntax::util::lev_distance::find_best_match_for_name;

use rustc_front::intravisit::{self, FnKind, Visitor};
use rustc_front::hir;
use rustc_front::hir::{Arm, BindByRef, BindByValue, BindingMode, Block};
use rustc_front::hir::Crate;
use rustc_front::hir::{Expr, ExprAgain, ExprBreak, ExprCall, ExprField};
use rustc_front::hir::{ExprLoop, ExprWhile, ExprMethodCall};
use rustc_front::hir::{ExprPath, ExprStruct, FnDecl};
use rustc_front::hir::{ForeignItemFn, ForeignItemStatic, Generics};
use rustc_front::hir::{ImplItem, Item, ItemConst, ItemEnum, ItemExternCrate};
use rustc_front::hir::{ItemFn, ItemForeignMod, ItemImpl, ItemMod, ItemStatic, ItemDefaultImpl};
use rustc_front::hir::{ItemStruct, ItemTrait, ItemTy, ItemUse};
use rustc_front::hir::Local;
use rustc_front::hir::{Pat, PatEnum, PatIdent, PatLit, PatQPath};
use rustc_front::hir::{PatRange, PatStruct, Path, PrimTy};
use rustc_front::hir::{TraitRef, Ty, TyBool, TyChar, TyFloat, TyInt};
use rustc_front::hir::{TyRptr, TyStr, TyUint, TyPath, TyPtr};
use rustc_front::util::walk_pat;

use std::collections::{HashMap, HashSet};
use std::cell::{Cell, RefCell};
use std::fmt;
use std::mem::replace;
use std::rc::Rc;

use resolve_imports::{Target, ImportDirective, ImportResolutionPerNamespace};
use resolve_imports::Shadowable;

// NB: This module needs to be declared first so diagnostics are
// registered before they are used.
pub mod diagnostics;

mod check_unused;
mod build_reduced_graph;
mod resolve_imports;

// Perform the callback, not walking deeper if the return is true
macro_rules! execute_callback {
    ($node: expr, $walker: expr) => (
        if let Some(ref callback) = $walker.callback {
            if callback($node, &mut $walker.resolved) {
                return;
            }
        }
    )
}

enum SuggestionType {
    Macro(String),
    Function(token::InternedString),
    NotFound,
}

pub enum ResolutionError<'a> {
    /// error E0260: name conflicts with an extern crate
    NameConflictsWithExternCrate(Name),
    /// error E0401: can't use type parameters from outer function
    TypeParametersFromOuterFunction,
    /// error E0402: cannot use an outer type parameter in this context
    OuterTypeParameterContext,
    /// error E0403: the name is already used for a type parameter in this type parameter list
    NameAlreadyUsedInTypeParameterList(Name),
    /// error E0404: is not a trait
    IsNotATrait(&'a str),
    /// error E0405: use of undeclared trait name
    UndeclaredTraitName(&'a str),
    /// error E0406: undeclared associated type
    UndeclaredAssociatedType,
    /// error E0407: method is not a member of trait
    MethodNotMemberOfTrait(Name, &'a str),
    /// error E0437: type is not a member of trait
    TypeNotMemberOfTrait(Name, &'a str),
    /// error E0438: const is not a member of trait
    ConstNotMemberOfTrait(Name, &'a str),
    /// error E0408: variable `{}` from pattern #1 is not bound in pattern
    VariableNotBoundInPattern(Name, usize),
    /// error E0409: variable is bound with different mode in pattern #{} than in pattern #1
    VariableBoundWithDifferentMode(Name, usize),
    /// error E0410: variable from pattern is not bound in pattern #1
    VariableNotBoundInParentPattern(Name, usize),
    /// error E0411: use of `Self` outside of an impl or trait
    SelfUsedOutsideImplOrTrait,
    /// error E0412: use of undeclared
    UseOfUndeclared(&'a str, &'a str),
    /// error E0413: declaration shadows an enum variant or unit-like struct in scope
    DeclarationShadowsEnumVariantOrUnitLikeStruct(Name),
    /// error E0414: only irrefutable patterns allowed here
    OnlyIrrefutablePatternsAllowedHere(DefId, Name),
    /// error E0415: identifier is bound more than once in this parameter list
    IdentifierBoundMoreThanOnceInParameterList(&'a str),
    /// error E0416: identifier is bound more than once in the same pattern
    IdentifierBoundMoreThanOnceInSamePattern(&'a str),
    /// error E0417: static variables cannot be referenced in a pattern
    StaticVariableReference,
    /// error E0418: is not an enum variant, struct or const
    NotAnEnumVariantStructOrConst(&'a str),
    /// error E0419: unresolved enum variant, struct or const
    UnresolvedEnumVariantStructOrConst(&'a str),
    /// error E0420: is not an associated const
    NotAnAssociatedConst(&'a str),
    /// error E0421: unresolved associated const
    UnresolvedAssociatedConst(&'a str),
    /// error E0422: does not name a struct
    DoesNotNameAStruct(&'a str),
    /// error E0423: is a struct variant name, but this expression uses it like a function name
    StructVariantUsedAsFunction(&'a str),
    /// error E0424: `self` is not available in a static method
    SelfNotAvailableInStaticMethod,
    /// error E0425: unresolved name
    UnresolvedName(&'a str, &'a str, UnresolvedNameContext),
    /// error E0426: use of undeclared label
    UndeclaredLabel(&'a str),
    /// error E0427: cannot use `ref` binding mode with ...
    CannotUseRefBindingModeWith(&'a str),
    /// error E0428: duplicate definition
    DuplicateDefinition(&'a str, Name),
    /// error E0429: `self` imports are only allowed within a { } list
    SelfImportsOnlyAllowedWithin,
    /// error E0430: `self` import can only appear once in the list
    SelfImportCanOnlyAppearOnceInTheList,
    /// error E0431: `self` import can only appear in an import list with a non-empty prefix
    SelfImportOnlyInImportListWithNonEmptyPrefix,
    /// error E0432: unresolved import
    UnresolvedImport(Option<(&'a str, &'a str)>),
    /// error E0433: failed to resolve
    FailedToResolve(&'a str),
    /// error E0434: can't capture dynamic environment in a fn item
    CannotCaptureDynamicEnvironmentInFnItem,
    /// error E0435: attempt to use a non-constant value in a constant
    AttemptToUseNonConstantValueInConstant,
}

/// Context of where `ResolutionError::UnresolvedName` arose.
#[derive(Clone, PartialEq, Eq, Debug)]
pub enum UnresolvedNameContext {
    /// `PathIsMod(id)` indicates that a given path, used in
    /// expression context, actually resolved to a module rather than
    /// a value. The `id` attached to the variant is the node id of
    /// the erroneous path expression.
    PathIsMod(ast::NodeId),

    /// `Other` means we have no extra information about the context
    /// of the unresolved name error. (Maybe we could eliminate all
    /// such cases; but for now, this is an information-free default.)
    Other,
}

fn resolve_error<'b, 'a: 'b, 'tcx: 'a>(resolver: &'b Resolver<'a, 'tcx>,
                                       span: syntax::codemap::Span,
                                       resolution_error: ResolutionError<'b>) {
    resolve_struct_error(resolver, span, resolution_error).emit();
}

fn resolve_struct_error<'b, 'a: 'b, 'tcx: 'a>(resolver: &'b Resolver<'a, 'tcx>,
                                              span: syntax::codemap::Span,
                                              resolution_error: ResolutionError<'b>)
                                              -> DiagnosticBuilder<'a> {
    if !resolver.emit_errors {
        return resolver.session.diagnostic().struct_dummy();
    }

    match resolution_error {
        ResolutionError::NameConflictsWithExternCrate(name) => {
            struct_span_err!(resolver.session,
                             span,
                             E0260,
                             "the name `{}` conflicts with an external crate \
                             that has been imported into this module",
                             name)
        }
        ResolutionError::TypeParametersFromOuterFunction => {
            struct_span_err!(resolver.session,
                             span,
                             E0401,
                             "can't use type parameters from outer function; try using a local \
                              type parameter instead")
        }
        ResolutionError::OuterTypeParameterContext => {
            struct_span_err!(resolver.session,
                             span,
                             E0402,
                             "cannot use an outer type parameter in this context")
        }
        ResolutionError::NameAlreadyUsedInTypeParameterList(name) => {
            struct_span_err!(resolver.session,
                             span,
                             E0403,
                             "the name `{}` is already used for a type parameter in this type \
                              parameter list",
                             name)
        }
        ResolutionError::IsNotATrait(name) => {
            struct_span_err!(resolver.session, span, E0404, "`{}` is not a trait", name)
        }
        ResolutionError::UndeclaredTraitName(name) => {
            struct_span_err!(resolver.session,
                             span,
                             E0405,
                             "use of undeclared trait name `{}`",
                             name)
        }
        ResolutionError::UndeclaredAssociatedType => {
            struct_span_err!(resolver.session, span, E0406, "undeclared associated type")
        }
        ResolutionError::MethodNotMemberOfTrait(method, trait_) => {
            struct_span_err!(resolver.session,
                             span,
                             E0407,
                             "method `{}` is not a member of trait `{}`",
                             method,
                             trait_)
        }
        ResolutionError::TypeNotMemberOfTrait(type_, trait_) => {
            struct_span_err!(resolver.session,
                             span,
                             E0437,
                             "type `{}` is not a member of trait `{}`",
                             type_,
                             trait_)
        }
        ResolutionError::ConstNotMemberOfTrait(const_, trait_) => {
            struct_span_err!(resolver.session,
                             span,
                             E0438,
                             "const `{}` is not a member of trait `{}`",
                             const_,
                             trait_)
        }
        ResolutionError::VariableNotBoundInPattern(variable_name, pattern_number) => {
            struct_span_err!(resolver.session,
                             span,
                             E0408,
                             "variable `{}` from pattern #1 is not bound in pattern #{}",
                             variable_name,
                             pattern_number)
        }
        ResolutionError::VariableBoundWithDifferentMode(variable_name, pattern_number) => {
            struct_span_err!(resolver.session,
                             span,
                             E0409,
                             "variable `{}` is bound with different mode in pattern #{} than in \
                              pattern #1",
                             variable_name,
                             pattern_number)
        }
        ResolutionError::VariableNotBoundInParentPattern(variable_name, pattern_number) => {
            struct_span_err!(resolver.session,
                             span,
                             E0410,
                             "variable `{}` from pattern #{} is not bound in pattern #1",
                             variable_name,
                             pattern_number)
        }
        ResolutionError::SelfUsedOutsideImplOrTrait => {
            struct_span_err!(resolver.session,
                             span,
                             E0411,
                             "use of `Self` outside of an impl or trait")
        }
        ResolutionError::UseOfUndeclared(kind, name) => {
            struct_span_err!(resolver.session,
                             span,
                             E0412,
                             "use of undeclared {} `{}`",
                             kind,
                             name)
        }
        ResolutionError::DeclarationShadowsEnumVariantOrUnitLikeStruct(name) => {
            struct_span_err!(resolver.session,
                             span,
                             E0413,
                             "declaration of `{}` shadows an enum variant \
                              or unit-like struct in scope",
                             name)
        }
        ResolutionError::OnlyIrrefutablePatternsAllowedHere(did, name) => {
            let mut err = struct_span_err!(resolver.session,
                                           span,
                                           E0414,
                                           "only irrefutable patterns allowed here");
            err.span_note(span,
                          "there already is a constant in scope sharing the same \
                           name as this pattern");
            if let Some(sp) = resolver.ast_map.span_if_local(did) {
                err.span_note(sp, "constant defined here");
            }
            if let Some(directive) = resolver.current_module
                                             .import_resolutions
                                             .borrow()
                                             .get(&name) {
                let item = resolver.ast_map.expect_item(directive.value_ns.id);
                err.span_note(item.span, "constant imported here");
            }
            err
        }
        ResolutionError::IdentifierBoundMoreThanOnceInParameterList(identifier) => {
            struct_span_err!(resolver.session,
                             span,
                             E0415,
                             "identifier `{}` is bound more than once in this parameter list",
                             identifier)
        }
        ResolutionError::IdentifierBoundMoreThanOnceInSamePattern(identifier) => {
            struct_span_err!(resolver.session,
                             span,
                             E0416,
                             "identifier `{}` is bound more than once in the same pattern",
                             identifier)
        }
        ResolutionError::StaticVariableReference => {
            struct_span_err!(resolver.session,
                             span,
                             E0417,
                             "static variables cannot be referenced in a pattern, use a \
                              `const` instead")
        }
        ResolutionError::NotAnEnumVariantStructOrConst(name) => {
            struct_span_err!(resolver.session,
                             span,
                             E0418,
                             "`{}` is not an enum variant, struct or const",
                             name)
        }
        ResolutionError::UnresolvedEnumVariantStructOrConst(name) => {
            struct_span_err!(resolver.session,
                             span,
                             E0419,
                             "unresolved enum variant, struct or const `{}`",
                             name)
        }
        ResolutionError::NotAnAssociatedConst(name) => {
            struct_span_err!(resolver.session,
                             span,
                             E0420,
                             "`{}` is not an associated const",
                             name)
        }
        ResolutionError::UnresolvedAssociatedConst(name) => {
            struct_span_err!(resolver.session,
                             span,
                             E0421,
                             "unresolved associated const `{}`",
                             name)
        }
        ResolutionError::DoesNotNameAStruct(name) => {
            struct_span_err!(resolver.session,
                             span,
                             E0422,
                             "`{}` does not name a structure",
                             name)
        }
        ResolutionError::StructVariantUsedAsFunction(path_name) => {
            struct_span_err!(resolver.session,
                             span,
                             E0423,
                             "`{}` is the name of a struct or struct variant, but this expression \
                             uses it like a function name",
                             path_name)
        }
        ResolutionError::SelfNotAvailableInStaticMethod => {
            struct_span_err!(resolver.session,
                             span,
                             E0424,
                             "`self` is not available in a static method. Maybe a `self` \
                             argument is missing?")
        }
        ResolutionError::UnresolvedName(path, msg, context) => {
            let mut err = struct_span_err!(resolver.session,
                                           span,
                                           E0425,
                                           "unresolved name `{}`{}",
                                           path,
                                           msg);

            match context {
                UnresolvedNameContext::Other => { } // no help available
                UnresolvedNameContext::PathIsMod(id) => {
                    let mut help_msg = String::new();
                    let parent_id = resolver.ast_map.get_parent_node(id);
                    if let Some(hir_map::Node::NodeExpr(e)) = resolver.ast_map.find(parent_id) {
                        match e.node {
                            ExprField(_, ident) => {
                                help_msg = format!("To reference an item from the \
                                                    `{module}` module, use \
                                                    `{module}::{ident}`",
                                                   module = &*path,
                                                   ident = ident.node);
                            }
                            ExprMethodCall(ident, _, _) => {
                                help_msg = format!("To call a function from the \
                                                    `{module}` module, use \
                                                    `{module}::{ident}(..)`",
                                                   module = &*path,
                                                   ident = ident.node);
                            }
                            ExprCall(_, _) => {
                                help_msg = format!("No function corresponds to `{module}(..)`",
                                                   module = &*path);
                            }
                            _ => { } // no help available
                        }
                    } else {
                        help_msg = format!("Module `{module}` cannot be the value of an expression",
                                           module = &*path);
                    }

                    if !help_msg.is_empty() {
                        err.fileline_help(span, &help_msg);
                    }
                }
            }
            err
        }
        ResolutionError::UndeclaredLabel(name) => {
            struct_span_err!(resolver.session,
                             span,
                             E0426,
                             "use of undeclared label `{}`",
                             name)
        }
        ResolutionError::CannotUseRefBindingModeWith(descr) => {
            struct_span_err!(resolver.session,
                             span,
                             E0427,
                             "cannot use `ref` binding mode with {}",
                             descr)
        }
        ResolutionError::DuplicateDefinition(namespace, name) => {
            struct_span_err!(resolver.session,
                             span,
                             E0428,
                             "duplicate definition of {} `{}`",
                             namespace,
                             name)
        }
        ResolutionError::SelfImportsOnlyAllowedWithin => {
            struct_span_err!(resolver.session,
                             span,
                             E0429,
                             "{}",
                             "`self` imports are only allowed within a { } list")
        }
        ResolutionError::SelfImportCanOnlyAppearOnceInTheList => {
            struct_span_err!(resolver.session,
                             span,
                             E0430,
                             "`self` import can only appear once in the list")
        }
        ResolutionError::SelfImportOnlyInImportListWithNonEmptyPrefix => {
            struct_span_err!(resolver.session,
                             span,
                             E0431,
                             "`self` import can only appear in an import list with a \
                              non-empty prefix")
        }
        ResolutionError::UnresolvedImport(name) => {
            let msg = match name {
                Some((n, p)) => format!("unresolved import `{}`{}", n, p),
                None => "unresolved import".to_owned(),
            };
            struct_span_err!(resolver.session, span, E0432, "{}", msg)
        }
        ResolutionError::FailedToResolve(msg) => {
            struct_span_err!(resolver.session, span, E0433, "failed to resolve. {}", msg)
        }
        ResolutionError::CannotCaptureDynamicEnvironmentInFnItem => {
            struct_span_err!(resolver.session,
                             span,
                             E0434,
                             "{}",
                             "can't capture dynamic environment in a fn item; use the || { ... } \
                              closure form instead")
        }
        ResolutionError::AttemptToUseNonConstantValueInConstant => {
            struct_span_err!(resolver.session,
                             span,
                             E0435,
                             "attempt to use a non-constant value in a constant")
        }
    }
}

#[derive(Copy, Clone)]
struct BindingInfo {
    span: Span,
    binding_mode: BindingMode,
}

// Map from the name in a pattern to its binding mode.
type BindingMap = HashMap<Name, BindingInfo>;

#[derive(Copy, Clone, PartialEq)]
enum PatternBindingMode {
    RefutableMode,
    LocalIrrefutableMode,
    ArgumentIrrefutableMode,
}

#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
pub enum Namespace {
    TypeNS,
    ValueNS,
}

/// A NamespaceResult represents the result of resolving an import in
/// a particular namespace. The result is either definitely-resolved,
/// definitely- unresolved, or unknown.
#[derive(Clone)]
enum NamespaceResult<'a> {
    /// Means that resolve hasn't gathered enough information yet to determine
    /// whether the name is bound in this namespace. (That is, it hasn't
    /// resolved all `use` directives yet.)
    UnknownResult,
    /// Means that resolve has determined that the name is definitely
    /// not bound in the namespace.
    UnboundResult,
    /// Means that resolve has determined that the name is bound in the Module
    /// argument, and specified by the NameBinding argument.
    BoundResult(Module<'a>, NameBinding<'a>),
}

impl<'a> NamespaceResult<'a> {
    fn is_unknown(&self) -> bool {
        match *self {
            UnknownResult => true,
            _ => false,
        }
    }
    fn is_unbound(&self) -> bool {
        match *self {
            UnboundResult => true,
            _ => false,
        }
    }
}

impl<'a, 'v, 'tcx> Visitor<'v> for Resolver<'a, 'tcx> {
    fn visit_nested_item(&mut self, item: hir::ItemId) {
        self.visit_item(self.ast_map.expect_item(item.id))
    }
    fn visit_item(&mut self, item: &Item) {
        execute_callback!(hir_map::Node::NodeItem(item), self);
        self.resolve_item(item);
    }
    fn visit_arm(&mut self, arm: &Arm) {
        self.resolve_arm(arm);
    }
    fn visit_block(&mut self, block: &Block) {
        execute_callback!(hir_map::Node::NodeBlock(block), self);
        self.resolve_block(block);
    }
    fn visit_expr(&mut self, expr: &Expr) {
        execute_callback!(hir_map::Node::NodeExpr(expr), self);
        self.resolve_expr(expr);
    }
    fn visit_local(&mut self, local: &Local) {
        execute_callback!(hir_map::Node::NodeLocal(&*local.pat), self);
        self.resolve_local(local);
    }
    fn visit_ty(&mut self, ty: &Ty) {
        self.resolve_type(ty);
    }
    fn visit_generics(&mut self, generics: &Generics) {
        self.resolve_generics(generics);
    }
    fn visit_poly_trait_ref(&mut self, tref: &hir::PolyTraitRef, m: &hir::TraitBoundModifier) {
        match self.resolve_trait_reference(tref.trait_ref.ref_id, &tref.trait_ref.path, 0) {
            Ok(def) => self.record_def(tref.trait_ref.ref_id, def),
            Err(_) => {
                // error already reported
                self.record_def(tref.trait_ref.ref_id, err_path_resolution())
            }
        }
        intravisit::walk_poly_trait_ref(self, tref, m);
    }
    fn visit_variant(&mut self,
                     variant: &hir::Variant,
                     generics: &Generics,
                     item_id: ast::NodeId) {
        execute_callback!(hir_map::Node::NodeVariant(variant), self);
        if let Some(ref dis_expr) = variant.node.disr_expr {
            // resolve the discriminator expr as a constant
            self.with_constant_rib(|this| {
                this.visit_expr(dis_expr);
            });
        }

        // `intravisit::walk_variant` without the discriminant expression.
        self.visit_variant_data(&variant.node.data,
                                variant.node.name,
                                generics,
                                item_id,
                                variant.span);
    }
    fn visit_foreign_item(&mut self, foreign_item: &hir::ForeignItem) {
        execute_callback!(hir_map::Node::NodeForeignItem(foreign_item), self);
        let type_parameters = match foreign_item.node {
            ForeignItemFn(_, ref generics) => {
                HasTypeParameters(generics, FnSpace, ItemRibKind)
            }
            ForeignItemStatic(..) => NoTypeParameters,
        };
        self.with_type_parameter_rib(type_parameters, |this| {
            intravisit::walk_foreign_item(this, foreign_item);
        });
    }
    fn visit_fn(&mut self,
                function_kind: FnKind<'v>,
                declaration: &'v FnDecl,
                block: &'v Block,
                _: Span,
                node_id: NodeId) {
        let rib_kind = match function_kind {
            FnKind::ItemFn(_, generics, _, _, _, _) => {
                self.visit_generics(generics);
                ItemRibKind
            }
            FnKind::Method(_, sig, _) => {
                self.visit_generics(&sig.generics);
                self.visit_explicit_self(&sig.explicit_self);
                MethodRibKind
            }
            FnKind::Closure => ClosureRibKind(node_id),
        };
        self.resolve_function(rib_kind, declaration, block);
    }
}

type ErrorMessage = Option<(Span, String)>;

enum ResolveResult<T> {
    Failed(ErrorMessage), // Failed to resolve the name, optional helpful error message.
    Indeterminate, // Couldn't determine due to unresolved globs.
    Success(T), // Successfully resolved the import.
}

impl<T> ResolveResult<T> {
    fn success(&self) -> bool {
        match *self {
            Success(_) => true,
            _ => false,
        }
    }
}

enum FallbackSuggestion {
    NoSuggestion,
    Field,
    Method,
    TraitItem,
    StaticMethod(String),
    TraitMethod(String),
}

#[derive(Copy, Clone)]
enum TypeParameters<'a> {
    NoTypeParameters,
    HasTypeParameters(// Type parameters.
                      &'a Generics,

                      // Identifies the things that these parameters
                      // were declared on (type, fn, etc)
                      ParamSpace,

                      // The kind of the rib used for type parameters.
                      RibKind),
}

// The rib kind controls the translation of local
// definitions (`DefLocal`) to upvars (`DefUpvar`).
#[derive(Copy, Clone, Debug)]
enum RibKind {
    // No translation needs to be applied.
    NormalRibKind,

    // We passed through a closure scope at the given node ID.
    // Translate upvars as appropriate.
    ClosureRibKind(NodeId /* func id */),

    // We passed through an impl or trait and are now in one of its
    // methods. Allow references to ty params that impl or trait
    // binds. Disallow any other upvars (including other ty params that are
    // upvars).
    MethodRibKind,

    // We passed through an item scope. Disallow upvars.
    ItemRibKind,

    // We're in a constant item. Can't refer to dynamic stuff.
    ConstantItemRibKind,
}

#[derive(Copy, Clone)]
enum UseLexicalScopeFlag {
    DontUseLexicalScope,
    UseLexicalScope,
}

enum ModulePrefixResult<'a> {
    NoPrefixFound,
    PrefixFound(Module<'a>, usize),
}

#[derive(Copy, Clone)]
enum AssocItemResolveResult {
    /// Syntax such as `<T>::item`, which can't be resolved until type
    /// checking.
    TypecheckRequired,
    /// We should have been able to resolve the associated item.
    ResolveAttempt(Option<PathResolution>),
}

#[derive(Copy, Clone, PartialEq)]
enum NameSearchType {
    /// We're doing a name search in order to resolve a `use` directive.
    ImportSearch,

    /// We're doing a name search in order to resolve a path type, a path
    /// expression, or a path pattern.
    PathSearch,
}

#[derive(Copy, Clone)]
enum BareIdentifierPatternResolution {
    FoundStructOrEnumVariant(Def, LastPrivate),
    FoundConst(Def, LastPrivate, Name),
    BareIdentifierPatternUnresolved,
}

/// One local scope.
#[derive(Debug)]
struct Rib {
    bindings: HashMap<Name, DefLike>,
    kind: RibKind,
}

impl Rib {
    fn new(kind: RibKind) -> Rib {
        Rib {
            bindings: HashMap::new(),
            kind: kind,
        }
    }
}

/// A definition along with the index of the rib it was found on
struct LocalDef {
    ribs: Option<(Namespace, usize)>,
    def: Def,
}

impl LocalDef {
    fn from_def(def: Def) -> Self {
        LocalDef {
            ribs: None,
            def: def,
        }
    }
}

/// The link from a module up to its nearest parent node.
#[derive(Clone,Debug)]
enum ParentLink<'a> {
    NoParentLink,
    ModuleParentLink(Module<'a>, Name),
    BlockParentLink(Module<'a>, NodeId),
}

/// One node in the tree of modules.
pub struct ModuleS<'a> {
    parent_link: ParentLink<'a>,
    def: Cell<Option<Def>>,
    is_public: bool,

    children: RefCell<HashMap<Name, NameBindings<'a>>>,
    imports: RefCell<Vec<ImportDirective>>,

    // The external module children of this node that were declared with
    // `extern crate`.
    external_module_children: RefCell<HashMap<Name, Module<'a>>>,

    // The anonymous children of this node. Anonymous children are pseudo-
    // modules that are implicitly created around items contained within
    // blocks.
    //
    // For example, if we have this:
    //
    //  fn f() {
    //      fn g() {
    //          ...
    //      }
    //  }
    //
    // There will be an anonymous module created around `g` with the ID of the
    // entry block for `f`.
    anonymous_children: RefCell<NodeMap<Module<'a>>>,

    // The status of resolving each import in this module.
    import_resolutions: RefCell<HashMap<Name, ImportResolutionPerNamespace<'a>>>,

    // The number of unresolved globs that this module exports.
    glob_count: Cell<usize>,

    // The number of unresolved pub imports (both regular and globs) in this module
    pub_count: Cell<usize>,

    // The number of unresolved pub glob imports in this module
    pub_glob_count: Cell<usize>,

    // The index of the import we're resolving.
    resolved_import_count: Cell<usize>,

    // Whether this module is populated. If not populated, any attempt to
    // access the children must be preceded with a
    // `populate_module_if_necessary` call.
    populated: Cell<bool>,
}

pub type Module<'a> = &'a ModuleS<'a>;

impl<'a> ModuleS<'a> {
    fn new(parent_link: ParentLink<'a>, def: Option<Def>, external: bool, is_public: bool) -> Self {
        ModuleS {
            parent_link: parent_link,
            def: Cell::new(def),
            is_public: is_public,
            children: RefCell::new(HashMap::new()),
            imports: RefCell::new(Vec::new()),
            external_module_children: RefCell::new(HashMap::new()),
            anonymous_children: RefCell::new(NodeMap()),
            import_resolutions: RefCell::new(HashMap::new()),
            glob_count: Cell::new(0),
            pub_count: Cell::new(0),
            pub_glob_count: Cell::new(0),
            resolved_import_count: Cell::new(0),
            populated: Cell::new(!external),
        }
    }

    fn def_id(&self) -> Option<DefId> {
        self.def.get().as_ref().map(Def::def_id)
    }

    fn is_normal(&self) -> bool {
        match self.def.get() {
            Some(DefMod(_)) | Some(DefForeignMod(_)) => true,
            _ => false,
        }
    }

    fn is_trait(&self) -> bool {
        match self.def.get() {
            Some(DefTrait(_)) => true,
            _ => false,
        }
    }

    fn all_imports_resolved(&self) -> bool {
        if self.imports.borrow_state() == ::std::cell::BorrowState::Writing {
            // it is currently being resolved ! so nope
            false
        } else {
            self.imports.borrow().len() == self.resolved_import_count.get()
        }
    }

    pub fn inc_glob_count(&self) {
        self.glob_count.set(self.glob_count.get() + 1);
    }
    pub fn dec_glob_count(&self) {
        assert!(self.glob_count.get() > 0);
        self.glob_count.set(self.glob_count.get() - 1);
    }
    pub fn inc_pub_count(&self) {
        self.pub_count.set(self.pub_count.get() + 1);
    }
    pub fn dec_pub_count(&self) {
        assert!(self.pub_count.get() > 0);
        self.pub_count.set(self.pub_count.get() - 1);
    }
    pub fn inc_pub_glob_count(&self) {
        self.pub_glob_count.set(self.pub_glob_count.get() + 1);
    }
    pub fn dec_pub_glob_count(&self) {
        assert!(self.pub_glob_count.get() > 0);
        self.pub_glob_count.set(self.pub_glob_count.get() - 1);
    }
}

impl<'a> fmt::Debug for ModuleS<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f,
               "{:?}, {}",
               self.def,
               if self.is_public {
                   "public"
               } else {
                   "private"
               })
    }
}

bitflags! {
    #[derive(Debug)]
    flags DefModifiers: u8 {
        // Enum variants are always considered `PUBLIC`, this is needed for `use Enum::Variant`
        // or `use Enum::*` to work on private enums.
        const PUBLIC     = 1 << 0,
        const IMPORTABLE = 1 << 1,
        // Variants are considered `PUBLIC`, but some of them live in private enums.
        // We need to track them to prohibit reexports like `pub use PrivEnum::Variant`.
        const PRIVATE_VARIANT = 1 << 2,
    }
}

// Records a possibly-private value, type, or module definition.
#[derive(Debug)]
struct NsDef<'a> {
    modifiers: DefModifiers, // see note in ImportResolutionPerNamespace about how to use this
    def_or_module: DefOrModule<'a>,
    span: Option<Span>,
}

#[derive(Debug)]
enum DefOrModule<'a> {
    Def(Def),
    Module(Module<'a>),
}

impl<'a> NsDef<'a> {
    fn create_from_module(module: Module<'a>, span: Option<Span>) -> Self {
        let modifiers = if module.is_public {
            DefModifiers::PUBLIC
        } else {
            DefModifiers::empty()
        } | DefModifiers::IMPORTABLE;

        NsDef { modifiers: modifiers, def_or_module: DefOrModule::Module(module), span: span }
    }

    fn create_from_def(def: Def, modifiers: DefModifiers, span: Option<Span>) -> Self {
        NsDef { modifiers: modifiers, def_or_module: DefOrModule::Def(def), span: span }
    }

    fn module(&self) -> Option<Module<'a>> {
        match self.def_or_module {
            DefOrModule::Module(ref module) => Some(module),
            DefOrModule::Def(_) => None,
        }
    }

    fn def(&self) -> Option<Def> {
        match self.def_or_module {
            DefOrModule::Def(def) => Some(def),
            DefOrModule::Module(ref module) => module.def.get(),
        }
    }
}

// Records at most one definition that a name in a namespace is bound to
#[derive(Clone,Debug)]
pub struct NameBinding<'a>(Rc<RefCell<Option<NsDef<'a>>>>);

impl<'a> NameBinding<'a> {
    fn new() -> Self {
        NameBinding(Rc::new(RefCell::new(None)))
    }

    fn create_from_module(module: Module<'a>) -> Self {
        NameBinding(Rc::new(RefCell::new(Some(NsDef::create_from_module(module, None)))))
    }

    fn set(&self, ns_def: NsDef<'a>) {
        *self.0.borrow_mut() = Some(ns_def);
    }

    fn set_modifiers(&self, modifiers: DefModifiers) {
        if let Some(ref mut ns_def) = *self.0.borrow_mut() {
            ns_def.modifiers = modifiers
        }
    }

    fn borrow(&self) -> ::std::cell::Ref<Option<NsDef<'a>>> {
        self.0.borrow()
    }

    // Lifted versions of the NsDef methods and fields
    fn def(&self) -> Option<Def> {
        self.borrow().as_ref().and_then(NsDef::def)
    }
    fn module(&self) -> Option<Module<'a>> {
        self.borrow().as_ref().and_then(NsDef::module)
    }
    fn span(&self) -> Option<Span> {
        self.borrow().as_ref().and_then(|def| def.span)
    }
    fn modifiers(&self) -> Option<DefModifiers> {
        self.borrow().as_ref().and_then(|def| Some(def.modifiers))
    }

    fn defined(&self) -> bool {
        self.borrow().is_some()
    }

    fn defined_with(&self, modifiers: DefModifiers) -> bool {
        self.modifiers().map(|m| m.contains(modifiers)).unwrap_or(false)
    }

    fn is_public(&self) -> bool {
        self.defined_with(DefModifiers::PUBLIC)
    }

    fn def_and_lp(&self) -> (Def, LastPrivate) {
        let def = self.def().unwrap();
        (def, LastMod(if self.is_public() { AllPublic } else { DependsOn(def.def_id()) }))
    }
}

// Records the definitions (at most one for each namespace) that a name is
// bound to.
#[derive(Clone,Debug)]
pub struct NameBindings<'a> {
    type_ns: NameBinding<'a>, // < Meaning in type namespace.
    value_ns: NameBinding<'a>, // < Meaning in value namespace.
}

impl<'a> ::std::ops::Index<Namespace> for NameBindings<'a> {
    type Output = NameBinding<'a>;
    fn index(&self, namespace: Namespace) -> &NameBinding<'a> {
        match namespace { TypeNS => &self.type_ns, ValueNS => &self.value_ns }
    }
}

impl<'a> NameBindings<'a> {
    fn new() -> Self {
        NameBindings {
            type_ns: NameBinding::new(),
            value_ns: NameBinding::new(),
        }
    }

    /// Creates a new module in this set of name bindings.
    fn define_module(&self, module: Module<'a>, sp: Span) {
        self.type_ns.set(NsDef::create_from_module(module, Some(sp)));
    }

    /// Records a type definition.
    fn define_type(&self, def: Def, sp: Span, modifiers: DefModifiers) {
        debug!("defining type for def {:?} with modifiers {:?}", def, modifiers);
        self.type_ns.set(NsDef::create_from_def(def, modifiers, Some(sp)));
    }

    /// Records a value definition.
    fn define_value(&self, def: Def, sp: Span, modifiers: DefModifiers) {
        debug!("defining value for def {:?} with modifiers {:?}", def, modifiers);
        self.value_ns.set(NsDef::create_from_def(def, modifiers, Some(sp)));
    }
}

/// Interns the names of the primitive types.
struct PrimitiveTypeTable {
    primitive_types: HashMap<Name, PrimTy>,
}

impl PrimitiveTypeTable {
    fn new() -> PrimitiveTypeTable {
        let mut table = PrimitiveTypeTable { primitive_types: HashMap::new() };

        table.intern("bool", TyBool);
        table.intern("char", TyChar);
        table.intern("f32", TyFloat(TyF32));
        table.intern("f64", TyFloat(TyF64));
        table.intern("isize", TyInt(TyIs));
        table.intern("i8", TyInt(TyI8));
        table.intern("i16", TyInt(TyI16));
        table.intern("i32", TyInt(TyI32));
        table.intern("i64", TyInt(TyI64));
        table.intern("str", TyStr);
        table.intern("usize", TyUint(TyUs));
        table.intern("u8", TyUint(TyU8));
        table.intern("u16", TyUint(TyU16));
        table.intern("u32", TyUint(TyU32));
        table.intern("u64", TyUint(TyU64));

        table
    }

    fn intern(&mut self, string: &str, primitive_type: PrimTy) {
        self.primitive_types.insert(token::intern(string), primitive_type);
    }
}

/// The main resolver class.
pub struct Resolver<'a, 'tcx: 'a> {
    session: &'a Session,

    ast_map: &'a hir_map::Map<'tcx>,

    graph_root: Module<'a>,

    trait_item_map: FnvHashMap<(Name, DefId), DefId>,

    structs: FnvHashMap<DefId, Vec<Name>>,

    // The number of imports that are currently unresolved.
    unresolved_imports: usize,

    // The module that represents the current item scope.
    current_module: Module<'a>,

    // The current set of local scopes, for values.
    // FIXME #4948: Reuse ribs to avoid allocation.
    value_ribs: Vec<Rib>,

    // The current set of local scopes, for types.
    type_ribs: Vec<Rib>,

    // The current set of local scopes, for labels.
    label_ribs: Vec<Rib>,

    // The trait that the current context can refer to.
    current_trait_ref: Option<(DefId, TraitRef)>,

    // The current self type if inside an impl (used for better errors).
    current_self_type: Option<Ty>,

    // The idents for the primitive types.
    primitive_type_table: PrimitiveTypeTable,

    def_map: RefCell<DefMap>,
    freevars: FreevarMap,
    freevars_seen: NodeMap<NodeMap<usize>>,
    export_map: ExportMap,
    trait_map: TraitMap,
    external_exports: ExternalExports,

    // Whether or not to print error messages. Can be set to true
    // when getting additional info for error message suggestions,
    // so as to avoid printing duplicate errors
    emit_errors: bool,

    make_glob_map: bool,
    // Maps imports to the names of items actually imported (this actually maps
    // all imports, but only glob imports are actually interesting).
    glob_map: GlobMap,

    used_imports: HashSet<(NodeId, Namespace)>,
    used_crates: HashSet<CrateNum>,

    // Callback function for intercepting walks
    callback: Option<Box<Fn(hir_map::Node, &mut bool) -> bool>>,
    // The intention is that the callback modifies this flag.
    // Once set, the resolver falls out of the walk, preserving the ribs.
    resolved: bool,

    arenas: &'a ResolverArenas<'a>,
}

pub struct ResolverArenas<'a> {
    modules: arena::TypedArena<ModuleS<'a>>,
}

#[derive(PartialEq)]
enum FallbackChecks {
    Everything,
    OnlyTraitAndStatics,
}

impl<'a, 'tcx> Resolver<'a, 'tcx> {
    fn new(session: &'a Session,
           ast_map: &'a hir_map::Map<'tcx>,
           make_glob_map: MakeGlobMap,
           arenas: &'a ResolverArenas<'a>)
           -> Resolver<'a, 'tcx> {
        let root_def_id = ast_map.local_def_id(CRATE_NODE_ID);
        let graph_root = ModuleS::new(NoParentLink, Some(DefMod(root_def_id)), false, true);
        let graph_root = arenas.modules.alloc(graph_root);

        Resolver {
            session: session,

            ast_map: ast_map,

            // The outermost module has def ID 0; this is not reflected in the
            // AST.
            graph_root: graph_root,

            trait_item_map: FnvHashMap(),
            structs: FnvHashMap(),

            unresolved_imports: 0,

            current_module: graph_root,
            value_ribs: Vec::new(),
            type_ribs: Vec::new(),
            label_ribs: Vec::new(),

            current_trait_ref: None,
            current_self_type: None,

            primitive_type_table: PrimitiveTypeTable::new(),

            def_map: RefCell::new(NodeMap()),
            freevars: NodeMap(),
            freevars_seen: NodeMap(),
            export_map: NodeMap(),
            trait_map: NodeMap(),
            used_imports: HashSet::new(),
            used_crates: HashSet::new(),
            external_exports: DefIdSet(),

            emit_errors: true,
            make_glob_map: make_glob_map == MakeGlobMap::Yes,
            glob_map: HashMap::new(),

            callback: None,
            resolved: false,

            arenas: arenas,
        }
    }

    fn arenas() -> ResolverArenas<'a> {
        ResolverArenas {
            modules: arena::TypedArena::new(),
        }
    }

    fn new_module(&self,
                  parent_link: ParentLink<'a>,
                  def: Option<Def>,
                  external: bool,
                  is_public: bool) -> Module<'a> {
        self.arenas.modules.alloc(ModuleS::new(parent_link, def, external, is_public))
    }

    #[inline]
    fn record_import_use(&mut self, import_id: NodeId, name: Name) {
        if !self.make_glob_map {
            return;
        }
        if self.glob_map.contains_key(&import_id) {
            self.glob_map.get_mut(&import_id).unwrap().insert(name);
            return;
        }

        let mut new_set = HashSet::new();
        new_set.insert(name);
        self.glob_map.insert(import_id, new_set);
    }

    fn get_trait_name(&self, did: DefId) -> Name {
        if let Some(node_id) = self.ast_map.as_local_node_id(did) {
            self.ast_map.expect_item(node_id).name
        } else {
            self.session.cstore.item_name(did)
        }
    }

    /// Check that an external crate doesn't collide with items or other external crates.
    fn check_for_conflicts_for_external_crate(&self, module: Module<'a>, name: Name, span: Span) {
        if module.external_module_children.borrow().contains_key(&name) {
            span_err!(self.session,
                      span,
                      E0259,
                      "an external crate named `{}` has already been imported into this module",
                      name);
        }
        match module.children.borrow().get(&name) {
            Some(name_bindings) if name_bindings.type_ns.defined() => {
                resolve_error(self,
                              name_bindings.type_ns.span().unwrap_or(codemap::DUMMY_SP),
                              ResolutionError::NameConflictsWithExternCrate(name));
            }
            _ => {},
        }
    }

    /// Checks that the names of items don't collide with external crates.
    fn check_for_conflicts_between_external_crates_and_items(&self,
                                                             module: Module<'a>,
                                                             name: Name,
                                                             span: Span) {
        if module.external_module_children.borrow().contains_key(&name) {
            resolve_error(self, span, ResolutionError::NameConflictsWithExternCrate(name));
        }
    }

    /// Resolves the given module path from the given root `module_`.
    fn resolve_module_path_from_root(&mut self,
                                     module_: Module<'a>,
                                     module_path: &[Name],
                                     index: usize,
                                     span: Span,
                                     name_search_type: NameSearchType,
                                     lp: LastPrivate)
                                     -> ResolveResult<(Module<'a>, LastPrivate)> {
        fn search_parent_externals<'a>(needle: Name, module: Module<'a>)
                                       -> Option<Module<'a>> {
            match module.external_module_children.borrow().get(&needle) {
                Some(_) => Some(module),
                None => match module.parent_link {
                    ModuleParentLink(ref parent, _) => {
                        search_parent_externals(needle, parent)
                    }
                    _ => None,
                },
            }
        }

        let mut search_module = module_;
        let mut index = index;
        let module_path_len = module_path.len();
        let mut closest_private = lp;

        // Resolve the module part of the path. This does not involve looking
        // upward though scope chains; we simply resolve names directly in
        // modules as we go.
        while index < module_path_len {
            let name = module_path[index];
            match self.resolve_name_in_module(search_module,
                                              name,
                                              TypeNS,
                                              name_search_type,
                                              false) {
                Failed(None) => {
                    let segment_name = name.as_str();
                    let module_name = module_to_string(search_module);
                    let mut span = span;
                    let msg = if "???" == &module_name[..] {
                        span.hi = span.lo + Pos::from_usize(segment_name.len());

                        match search_parent_externals(name, &self.current_module) {
                            Some(module) => {
                                let path_str = names_to_string(module_path);
                                let target_mod_str = module_to_string(&*module);
                                let current_mod_str = module_to_string(&*self.current_module);

                                let prefix = if target_mod_str == current_mod_str {
                                    "self::".to_string()
                                } else {
                                    format!("{}::", target_mod_str)
                                };

                                format!("Did you mean `{}{}`?", prefix, path_str)
                            }
                            None => format!("Maybe a missing `extern crate {}`?", segment_name),
                        }
                    } else {
                        format!("Could not find `{}` in `{}`", segment_name, module_name)
                    };

                    return Failed(Some((span, msg)));
                }
                Failed(err) => return Failed(err),
                Indeterminate => {
                    debug!("(resolving module path for import) module resolution is \
                            indeterminate: {}",
                           name);
                    return Indeterminate;
                }
                Success((target, used_proxy)) => {
                    // Check to see whether there are type bindings, and, if
                    // so, whether there is a module within.
                    if let Some(module_def) = target.binding.module() {
                        // track extern crates for unused_extern_crate lint
                        if let Some(did) = module_def.def_id() {
                            self.used_crates.insert(did.krate);
                        }

                        search_module = module_def;

                        // Keep track of the closest private module used
                        // when resolving this import chain.
                        if !used_proxy && !search_module.is_public {
                            if let Some(did) = search_module.def_id() {
                                closest_private = LastMod(DependsOn(did));
                            }
                        }
                    } else {
                        let msg = format!("Not a module `{}`", name);
                        return Failed(Some((span, msg)));
                    }
                }
            }

            index += 1;
        }

        return Success((search_module, closest_private));
    }

    /// Attempts to resolve the module part of an import directive or path
    /// rooted at the given module.
    ///
    /// On success, returns the resolved module, and the closest *private*
    /// module found to the destination when resolving this path.
    fn resolve_module_path(&mut self,
                           module_: Module<'a>,
                           module_path: &[Name],
                           use_lexical_scope: UseLexicalScopeFlag,
                           span: Span,
                           name_search_type: NameSearchType)
                           -> ResolveResult<(Module<'a>, LastPrivate)> {
        let module_path_len = module_path.len();
        assert!(module_path_len > 0);

        debug!("(resolving module path for import) processing `{}` rooted at `{}`",
               names_to_string(module_path),
               module_to_string(&*module_));

        // Resolve the module prefix, if any.
        let module_prefix_result = self.resolve_module_prefix(module_, module_path);

        let search_module;
        let start_index;
        let last_private;
        match module_prefix_result {
            Failed(None) => {
                let mpath = names_to_string(module_path);
                let mpath = &mpath[..];
                match mpath.rfind(':') {
                    Some(idx) => {
                        let msg = format!("Could not find `{}` in `{}`",
                                          // idx +- 1 to account for the
                                          // colons on either side
                                          &mpath[idx + 1..],
                                          &mpath[..idx - 1]);
                        return Failed(Some((span, msg)));
                    }
                    None => {
                        return Failed(None);
                    }
                }
            }
            Failed(err) => return Failed(err),
            Indeterminate => {
                debug!("(resolving module path for import) indeterminate; bailing");
                return Indeterminate;
            }
            Success(NoPrefixFound) => {
                // There was no prefix, so we're considering the first element
                // of the path. How we handle this depends on whether we were
                // instructed to use lexical scope or not.
                match use_lexical_scope {
                    DontUseLexicalScope => {
                        // This is a crate-relative path. We will start the
                        // resolution process at index zero.
                        search_module = self.graph_root;
                        start_index = 0;
                        last_private = LastMod(AllPublic);
                    }
                    UseLexicalScope => {
                        // This is not a crate-relative path. We resolve the
                        // first component of the path in the current lexical
                        // scope and then proceed to resolve below that.
                        match self.resolve_module_in_lexical_scope(module_, module_path[0]) {
                            Failed(err) => return Failed(err),
                            Indeterminate => {
                                debug!("(resolving module path for import) indeterminate; bailing");
                                return Indeterminate;
                            }
                            Success(containing_module) => {
                                search_module = containing_module;
                                start_index = 1;
                                last_private = LastMod(AllPublic);
                            }
                        }
                    }
                }
            }
            Success(PrefixFound(ref containing_module, index)) => {
                search_module = containing_module;
                start_index = index;
                last_private = LastMod(DependsOn(containing_module.def_id()
                                                                  .unwrap()));
            }
        }

        self.resolve_module_path_from_root(search_module,
                                           module_path,
                                           start_index,
                                           span,
                                           name_search_type,
                                           last_private)
    }

    /// Invariant: This must only be called during main resolution, not during
    /// import resolution.
    fn resolve_item_in_lexical_scope(&mut self,
                                     module_: Module<'a>,
                                     name: Name,
                                     namespace: Namespace,
                                     record_used: bool)
                                     -> ResolveResult<(Target<'a>, bool)> {
        debug!("(resolving item in lexical scope) resolving `{}` in namespace {:?} in `{}`",
               name,
               namespace,
               module_to_string(&*module_));

        // The current module node is handled specially. First, check for
        // its immediate children.
        build_reduced_graph::populate_module_if_necessary(self, &module_);

        match module_.children.borrow().get(&name) {
            Some(name_bindings) if name_bindings[namespace].defined() => {
                debug!("top name bindings succeeded");
                return Success((Target::new(module_,
                                            name_bindings[namespace].clone(),
                                            Shadowable::Never),
                                false));
            }
            Some(_) | None => {
                // Not found; continue.
            }
        }

        // Now check for its import directives. We don't have to have resolved
        // all its imports in the usual way; this is because chains of
        // adjacent import statements are processed as though they mutated the
        // current scope.
        if let Some(import_resolution) = module_.import_resolutions.borrow().get(&name) {
            match import_resolution[namespace].target.clone() {
                None => {
                    // Not found; continue.
                    debug!("(resolving item in lexical scope) found import resolution, but not \
                            in namespace {:?}",
                           namespace);
                }
                Some(target) => {
                    debug!("(resolving item in lexical scope) using import resolution");
                    // track used imports and extern crates as well
                    let id = import_resolution[namespace].id;
                    if record_used {
                        self.used_imports.insert((id, namespace));
                        self.record_import_use(id, name);
                        if let Some(DefId{krate: kid, ..}) = target.target_module.def_id() {
                            self.used_crates.insert(kid);
                        }
                    }
                    return Success((target, false));
                }
            }
        }

        // Search for external modules.
        if namespace == TypeNS {
            let children = module_.external_module_children.borrow();
            if let Some(module) = children.get(&name) {
                let name_binding = NameBinding::create_from_module(module);
                debug!("lower name bindings succeeded");
                return Success((Target::new(module_, name_binding, Shadowable::Never),
                                false));
            }
        }

        // Finally, proceed up the scope chain looking for parent modules.
        let mut search_module = module_;
        loop {
            // Go to the next parent.
            match search_module.parent_link {
                NoParentLink => {
                    // No more parents. This module was unresolved.
                    debug!("(resolving item in lexical scope) unresolved module");
                    return Failed(None);
                }
                ModuleParentLink(parent_module_node, _) => {
                    if search_module.is_normal() {
                        // We stop the search here.
                        debug!("(resolving item in lexical scope) unresolved module: not \
                                searching through module parents");
                            return Failed(None);
                    } else {
                        search_module = parent_module_node;
                    }
                }
                BlockParentLink(parent_module_node, _) => {
                    search_module = parent_module_node;
                }
            }

            // Resolve the name in the parent module.
            match self.resolve_name_in_module(search_module,
                                              name,
                                              namespace,
                                              PathSearch,
                                              true) {
                Failed(Some((span, msg))) => {
                    resolve_error(self, span, ResolutionError::FailedToResolve(&*msg));
                }
                Failed(None) => (), // Continue up the search chain.
                Indeterminate => {
                    // We couldn't see through the higher scope because of an
                    // unresolved import higher up. Bail.

                    debug!("(resolving item in lexical scope) indeterminate higher scope; bailing");
                    return Indeterminate;
                }
                Success((target, used_reexport)) => {
                    // We found the module.
                    debug!("(resolving item in lexical scope) found name in module, done");
                    return Success((target, used_reexport));
                }
            }
        }
    }

    /// Resolves a module name in the current lexical scope.
    fn resolve_module_in_lexical_scope(&mut self,
                                       module_: Module<'a>,
                                       name: Name)
                                       -> ResolveResult<Module<'a>> {
        // If this module is an anonymous module, resolve the item in the
        // lexical scope. Otherwise, resolve the item from the crate root.
        let resolve_result = self.resolve_item_in_lexical_scope(module_, name, TypeNS, true);
        match resolve_result {
            Success((target, _)) => {
                if let Some(module_def) = target.binding.module() {
                    return Success(module_def)
                } else {
                    debug!("!!! (resolving module in lexical scope) module \
                            wasn't actually a module!");
                    return Failed(None);
                }
            }
            Indeterminate => {
                debug!("(resolving module in lexical scope) indeterminate; bailing");
                return Indeterminate;
            }
            Failed(err) => {
                debug!("(resolving module in lexical scope) failed to resolve");
                return Failed(err);
            }
        }
    }

    /// Returns the nearest normal module parent of the given module.
    fn get_nearest_normal_module_parent(&mut self, module_: Module<'a>) -> Option<Module<'a>> {
        let mut module_ = module_;
        loop {
            match module_.parent_link {
                NoParentLink => return None,
                ModuleParentLink(new_module, _) |
                BlockParentLink(new_module, _) => {
                    let new_module = new_module;
                    if new_module.is_normal() {
                        return Some(new_module);
                    }
                    module_ = new_module;
                }
            }
        }
    }

    /// Returns the nearest normal module parent of the given module, or the
    /// module itself if it is a normal module.
    fn get_nearest_normal_module_parent_or_self(&mut self, module_: Module<'a>) -> Module<'a> {
        if module_.is_normal() {
            return module_;
        }
        match self.get_nearest_normal_module_parent(module_) {
            None => module_,
            Some(new_module) => new_module,
        }
    }

    /// Resolves a "module prefix". A module prefix is one or both of (a) `self::`;
    /// (b) some chain of `super::`.
    /// grammar: (SELF MOD_SEP ) ? (SUPER MOD_SEP) *
    fn resolve_module_prefix(&mut self,
                             module_: Module<'a>,
                             module_path: &[Name])
                             -> ResolveResult<ModulePrefixResult<'a>> {
        // Start at the current module if we see `self` or `super`, or at the
        // top of the crate otherwise.
        let mut i = match &*module_path[0].as_str() {
            "self" => 1,
            "super" => 0,
            _ => return Success(NoPrefixFound),
        };
        let mut containing_module = self.get_nearest_normal_module_parent_or_self(module_);

        // Now loop through all the `super`s we find.
        while i < module_path.len() && "super" == module_path[i].as_str() {
            debug!("(resolving module prefix) resolving `super` at {}",
                   module_to_string(&*containing_module));
            match self.get_nearest_normal_module_parent(containing_module) {
                None => return Failed(None),
                Some(new_module) => {
                    containing_module = new_module;
                    i += 1;
                }
            }
        }

        debug!("(resolving module prefix) finished resolving prefix at {}",
               module_to_string(&*containing_module));

        return Success(PrefixFound(containing_module, i));
    }

    /// Attempts to resolve the supplied name in the given module for the
    /// given namespace. If successful, returns the target corresponding to
    /// the name.
    ///
    /// The boolean returned on success is an indicator of whether this lookup
    /// passed through a public re-export proxy.
    fn resolve_name_in_module(&mut self,
                              module_: Module<'a>,
                              name: Name,
                              namespace: Namespace,
                              name_search_type: NameSearchType,
                              allow_private_imports: bool)
                              -> ResolveResult<(Target<'a>, bool)> {
        debug!("(resolving name in module) resolving `{}` in `{}`",
               name,
               module_to_string(&*module_));

        // First, check the direct children of the module.
        build_reduced_graph::populate_module_if_necessary(self, &module_);

        let children = module_.children.borrow();
        match children.get(&name) {
            Some(name_bindings) if name_bindings[namespace].defined() => {
                debug!("(resolving name in module) found node as child");
                return Success((Target::new(module_,
                                            name_bindings[namespace].clone(),
                                            Shadowable::Never),
                                false));
            }
            Some(_) | None => {
                // Continue.
            }
        }

        // Next, check the module's imports if necessary.

        // If this is a search of all imports, we should be done with glob
        // resolution at this point.
        if name_search_type == PathSearch {
            assert_eq!(module_.glob_count.get(), 0);
        }

        // Check the list of resolved imports.
        let children = module_.import_resolutions.borrow();
        match children.get(&name) {
            Some(import_resolution) if allow_private_imports ||
                                       import_resolution[namespace].is_public => {

                if import_resolution[namespace].is_public &&
                   import_resolution.outstanding_references != 0 {
                    debug!("(resolving name in module) import unresolved; bailing out");
                    return Indeterminate;
                }
                match import_resolution[namespace].target.clone() {
                    None => {
                        debug!("(resolving name in module) name found, but not in namespace {:?}",
                               namespace);
                    }
                    Some(target) => {
                        debug!("(resolving name in module) resolved to import");
                        // track used imports and extern crates as well
                        let id = import_resolution[namespace].id;
                        self.used_imports.insert((id, namespace));
                        self.record_import_use(id, name);
                        if let Some(DefId{krate: kid, ..}) = target.target_module.def_id() {
                            self.used_crates.insert(kid);
                        }
                        return Success((target, true));
                    }
                }
            }
            Some(..) | None => {} // Continue.
        }

        // Finally, search through external children.
        if namespace == TypeNS {
            let children = module_.external_module_children.borrow();
            if let Some(module) = children.get(&name) {
                let name_binding = NameBinding::create_from_module(module);
                return Success((Target::new(module_, name_binding, Shadowable::Never),
                                false));
            }
        }

        // We're out of luck.
        debug!("(resolving name in module) failed to resolve `{}`", name);
        return Failed(None);
    }

    fn report_unresolved_imports(&mut self, module_: Module<'a>) {
        let index = module_.resolved_import_count.get();
        let imports = module_.imports.borrow();
        let import_count = imports.len();
        if index != import_count {
            resolve_error(self,
                          (*imports)[index].span,
                          ResolutionError::UnresolvedImport(None));
        }

        // Descend into children and anonymous children.
        build_reduced_graph::populate_module_if_necessary(self, &module_);

        for (_, child_node) in module_.children.borrow().iter() {
            match child_node.type_ns.module() {
                None => {
                    // Continue.
                }
                Some(child_module) => {
                    self.report_unresolved_imports(child_module);
                }
            }
        }

        for (_, module_) in module_.anonymous_children.borrow().iter() {
            self.report_unresolved_imports(module_);
        }
    }

    // AST resolution
    //
    // We maintain a list of value ribs and type ribs.
    //
    // Simultaneously, we keep track of the current position in the module
    // graph in the `current_module` pointer. When we go to resolve a name in
    // the value or type namespaces, we first look through all the ribs and
    // then query the module graph. When we resolve a name in the module
    // namespace, we can skip all the ribs (since nested modules are not
    // allowed within blocks in Rust) and jump straight to the current module
    // graph node.
    //
    // Named implementations are handled separately. When we find a method
    // call, we consult the module node to find all of the implementations in
    // scope. This information is lazily cached in the module node. We then
    // generate a fake "implementation scope" containing all the
    // implementations thus found, for compatibility with old resolve pass.

    fn with_scope<F>(&mut self, name: Option<Name>, f: F)
        where F: FnOnce(&mut Resolver)
    {
        let orig_module = self.current_module;

        // Move down in the graph.
        match name {
            None => {
                // Nothing to do.
            }
            Some(name) => {
                build_reduced_graph::populate_module_if_necessary(self, &orig_module);

                match orig_module.children.borrow().get(&name) {
                    None => {
                        debug!("!!! (with scope) didn't find `{}` in `{}`",
                               name,
                               module_to_string(&*orig_module));
                    }
                    Some(name_bindings) => {
                        match name_bindings.type_ns.module() {
                            None => {
                                debug!("!!! (with scope) didn't find module for `{}` in `{}`",
                                       name,
                                       module_to_string(&*orig_module));
                            }
                            Some(module_) => {
                                self.current_module = module_;
                            }
                        }
                    }
                }
            }
        }

        f(self);

        self.current_module = orig_module;
    }

    /// Searches the current set of local scopes for labels.
    /// Stops after meeting a closure.
    fn search_label(&self, name: Name) -> Option<DefLike> {
        for rib in self.label_ribs.iter().rev() {
            match rib.kind {
                NormalRibKind => {
                    // Continue
                }
                _ => {
                    // Do not resolve labels across function boundary
                    return None;
                }
            }
            let result = rib.bindings.get(&name).cloned();
            if result.is_some() {
                return result;
            }
        }
        None
    }

    fn resolve_crate(&mut self, krate: &hir::Crate) {
        debug!("(resolving crate) starting");

        intravisit::walk_crate(self, krate);
    }

    fn check_if_primitive_type_name(&self, name: Name, span: Span) {
        if let Some(_) = self.primitive_type_table.primitive_types.get(&name) {
            span_err!(self.session,
                      span,
                      E0317,
                      "user-defined types or type parameters cannot shadow the primitive types");
        }
    }

    fn resolve_item(&mut self, item: &Item) {
        let name = item.name;

        debug!("(resolving item) resolving {}", name);

        match item.node {
            ItemEnum(_, ref generics) |
            ItemTy(_, ref generics) |
            ItemStruct(_, ref generics) => {
                self.check_if_primitive_type_name(name, item.span);

                self.with_type_parameter_rib(HasTypeParameters(generics, TypeSpace, ItemRibKind),
                                             |this| intravisit::walk_item(this, item));
            }
            ItemFn(_, _, _, _, ref generics, _) => {
                self.with_type_parameter_rib(HasTypeParameters(generics, FnSpace, ItemRibKind),
                                             |this| intravisit::walk_item(this, item));
            }

            ItemDefaultImpl(_, ref trait_ref) => {
                self.with_optional_trait_ref(Some(trait_ref), |_, _| {});
            }
            ItemImpl(_, _, ref generics, ref opt_trait_ref, ref self_type, ref impl_items) => {
                self.resolve_implementation(generics,
                                            opt_trait_ref,
                                            &**self_type,
                                            item.id,
                                            impl_items);
            }

            ItemTrait(_, ref generics, ref bounds, ref trait_items) => {
                self.check_if_primitive_type_name(name, item.span);

                // Create a new rib for the trait-wide type parameters.
                self.with_type_parameter_rib(HasTypeParameters(generics,
                                                               TypeSpace,
                                                               ItemRibKind),
                                             |this| {
                    let local_def_id = this.ast_map.local_def_id(item.id);
                    this.with_self_rib(DefSelfTy(Some(local_def_id), None), |this| {
                        this.visit_generics(generics);
                        walk_list!(this, visit_ty_param_bound, bounds);

                        for trait_item in trait_items {
                            match trait_item.node {
                                hir::ConstTraitItem(_, ref default) => {
                                    // Only impose the restrictions of
                                    // ConstRibKind if there's an actual constant
                                    // expression in a provided default.
                                    if default.is_some() {
                                        this.with_constant_rib(|this| {
                                            intravisit::walk_trait_item(this, trait_item)
                                        });
                                    } else {
                                        intravisit::walk_trait_item(this, trait_item)
                                    }
                                }
                                hir::MethodTraitItem(ref sig, _) => {
                                    let type_parameters =
                                        HasTypeParameters(&sig.generics,
                                                          FnSpace,
                                                          MethodRibKind);
                                    this.with_type_parameter_rib(type_parameters, |this| {
                                        intravisit::walk_trait_item(this, trait_item)
                                    });
                                }
                                hir::TypeTraitItem(..) => {
                                    this.check_if_primitive_type_name(trait_item.name,
                                                                      trait_item.span);
                                    this.with_type_parameter_rib(NoTypeParameters, |this| {
                                        intravisit::walk_trait_item(this, trait_item)
                                    });
                                }
                            };
                        }
                    });
                });
            }

            ItemMod(_) | ItemForeignMod(_) => {
                self.with_scope(Some(name), |this| {
                    intravisit::walk_item(this, item);
                });
            }

            ItemConst(..) | ItemStatic(..) => {
                self.with_constant_rib(|this| {
                    intravisit::walk_item(this, item);
                });
            }

            ItemUse(ref view_path) => {
                // check for imports shadowing primitive types
                let check_rename = |this: &Self, id, name| {
                    match this.def_map.borrow().get(&id).map(|d| d.full_def()) {
                        Some(DefTy(..)) | Some(DefStruct(..)) | Some(DefTrait(..)) | None => {
                            this.check_if_primitive_type_name(name, item.span);
                        }
                        _ => {}
                    }
                };

                match view_path.node {
                    hir::ViewPathSimple(name, _) => {
                        check_rename(self, item.id, name);
                    }
                    hir::ViewPathList(ref prefix, ref items) => {
                        for item in items {
                            if let Some(name) = item.node.rename() {
                                check_rename(self, item.node.id(), name);
                            }
                        }

                        // Resolve prefix of an import with empty braces (issue #28388)
                        if items.is_empty() && !prefix.segments.is_empty() {
                            match self.resolve_crate_relative_path(prefix.span,
                                                                   &prefix.segments,
                                                                   TypeNS) {
                                Some((def, lp)) =>
                                    self.record_def(item.id, PathResolution::new(def, lp, 0)),
                                None => {
                                    resolve_error(self,
                                                  prefix.span,
                                                  ResolutionError::FailedToResolve(
                                                      &path_names_to_string(prefix, 0)));
                                    self.record_def(item.id, err_path_resolution());
                                }
                            }
                        }
                    }
                    _ => {}
                }
            }

            ItemExternCrate(_) => {
                // do nothing, these are just around to be encoded
            }
        }
    }

    fn with_type_parameter_rib<F>(&mut self, type_parameters: TypeParameters, f: F)
        where F: FnOnce(&mut Resolver)
    {
        match type_parameters {
            HasTypeParameters(generics, space, rib_kind) => {
                let mut function_type_rib = Rib::new(rib_kind);
                let mut seen_bindings = HashSet::new();
                for (index, type_parameter) in generics.ty_params.iter().enumerate() {
                    let name = type_parameter.name;
                    debug!("with_type_parameter_rib: {}", type_parameter.id);

                    if seen_bindings.contains(&name) {
                        resolve_error(self,
                                      type_parameter.span,
                                      ResolutionError::NameAlreadyUsedInTypeParameterList(name));
                    }
                    seen_bindings.insert(name);

                    // plain insert (no renaming)
                    function_type_rib.bindings
                                     .insert(name,
                                             DlDef(DefTyParam(space,
                                                              index as u32,
                                                              self.ast_map
                                                                  .local_def_id(type_parameter.id),
                                                              name)));
                }
                self.type_ribs.push(function_type_rib);
            }

            NoTypeParameters => {
                // Nothing to do.
            }
        }

        f(self);

        match type_parameters {
            HasTypeParameters(..) => {
                if !self.resolved {
                    self.type_ribs.pop();
                }
            }
            NoTypeParameters => {}
        }
    }

    fn with_label_rib<F>(&mut self, f: F)
        where F: FnOnce(&mut Resolver)
    {
        self.label_ribs.push(Rib::new(NormalRibKind));
        f(self);
        if !self.resolved {
            self.label_ribs.pop();
        }
    }

    fn with_constant_rib<F>(&mut self, f: F)
        where F: FnOnce(&mut Resolver)
    {
        self.value_ribs.push(Rib::new(ConstantItemRibKind));
        self.type_ribs.push(Rib::new(ConstantItemRibKind));
        f(self);
        if !self.resolved {
            self.type_ribs.pop();
            self.value_ribs.pop();
        }
    }

    fn resolve_function(&mut self, rib_kind: RibKind, declaration: &FnDecl, block: &Block) {
        // Create a value rib for the function.
        self.value_ribs.push(Rib::new(rib_kind));

        // Create a label rib for the function.
        self.label_ribs.push(Rib::new(rib_kind));

        // Add each argument to the rib.
        let mut bindings_list = HashMap::new();
        for argument in &declaration.inputs {
            self.resolve_pattern(&*argument.pat, ArgumentIrrefutableMode, &mut bindings_list);

            self.visit_ty(&*argument.ty);

            debug!("(resolving function) recorded argument");
        }
        intravisit::walk_fn_ret_ty(self, &declaration.output);

        // Resolve the function body.
        self.visit_block(block);

        debug!("(resolving function) leaving function");

        if !self.resolved {
            self.label_ribs.pop();
            self.value_ribs.pop();
        }
    }

    fn resolve_trait_reference(&mut self,
                               id: NodeId,
                               trait_path: &Path,
                               path_depth: usize)
                               -> Result<PathResolution, ()> {
        if let Some(path_res) = self.resolve_path(id, trait_path, path_depth, TypeNS, true) {
            if let DefTrait(_) = path_res.base_def {
                debug!("(resolving trait) found trait def: {:?}", path_res);
                Ok(path_res)
            } else {
                let mut err =
                    resolve_struct_error(self,
                                  trait_path.span,
                                  ResolutionError::IsNotATrait(&*path_names_to_string(trait_path,
                                                                                      path_depth)));

                // If it's a typedef, give a note
                if let DefTy(..) = path_res.base_def {
                    err.span_note(trait_path.span,
                                  "`type` aliases cannot be used for traits");
                }
                err.emit();
                Err(())
            }
        } else {
            resolve_error(self,
                          trait_path.span,
                          ResolutionError::UndeclaredTraitName(&*path_names_to_string(trait_path,
                                                                                      path_depth)));
            Err(())
        }
    }

    fn resolve_generics(&mut self, generics: &Generics) {
        for type_parameter in generics.ty_params.iter() {
            self.check_if_primitive_type_name(type_parameter.name, type_parameter.span);
        }
        for predicate in &generics.where_clause.predicates {
            match predicate {
                &hir::WherePredicate::BoundPredicate(_) |
                &hir::WherePredicate::RegionPredicate(_) => {}
                &hir::WherePredicate::EqPredicate(ref eq_pred) => {
                    let path_res = self.resolve_path(eq_pred.id, &eq_pred.path, 0, TypeNS, true);
                    if let Some(PathResolution { base_def: DefTyParam(..), .. }) = path_res {
                        self.record_def(eq_pred.id, path_res.unwrap());
                    } else {
                        resolve_error(self,
                                      eq_pred.span,
                                      ResolutionError::UndeclaredAssociatedType);
                        self.record_def(eq_pred.id, err_path_resolution());
                    }
                }
            }
        }
        intravisit::walk_generics(self, generics);
    }

    fn with_current_self_type<T, F>(&mut self, self_type: &Ty, f: F) -> T
        where F: FnOnce(&mut Resolver) -> T
    {
        // Handle nested impls (inside fn bodies)
        let previous_value = replace(&mut self.current_self_type, Some(self_type.clone()));
        let result = f(self);
        self.current_self_type = previous_value;
        result
    }

    fn with_optional_trait_ref<T, F>(&mut self, opt_trait_ref: Option<&TraitRef>, f: F) -> T
        where F: FnOnce(&mut Resolver, Option<DefId>) -> T
    {
        let mut new_val = None;
        let mut new_id = None;
        if let Some(trait_ref) = opt_trait_ref {
            if let Ok(path_res) = self.resolve_trait_reference(trait_ref.ref_id,
                                                               &trait_ref.path,
                                                               0) {
                assert!(path_res.depth == 0);
                self.record_def(trait_ref.ref_id, path_res);
                new_val = Some((path_res.base_def.def_id(), trait_ref.clone()));
                new_id = Some(path_res.base_def.def_id());
            } else {
                self.record_def(trait_ref.ref_id, err_path_resolution());
            }
            intravisit::walk_trait_ref(self, trait_ref);
        }
        let original_trait_ref = replace(&mut self.current_trait_ref, new_val);
        let result = f(self, new_id);
        self.current_trait_ref = original_trait_ref;
        result
    }

    fn with_self_rib<F>(&mut self, self_def: Def, f: F)
        where F: FnOnce(&mut Resolver)
    {
        let mut self_type_rib = Rib::new(NormalRibKind);

        // plain insert (no renaming, types are not currently hygienic....)
        let name = special_names::type_self;
        self_type_rib.bindings.insert(name, DlDef(self_def));
        self.type_ribs.push(self_type_rib);
        f(self);
        if !self.resolved {
            self.type_ribs.pop();
        }
    }

    fn resolve_implementation(&mut self,
                              generics: &Generics,
                              opt_trait_reference: &Option<TraitRef>,
                              self_type: &Ty,
                              item_id: NodeId,
                              impl_items: &[ImplItem]) {
        // If applicable, create a rib for the type parameters.
        self.with_type_parameter_rib(HasTypeParameters(generics,
                                                       TypeSpace,
                                                       ItemRibKind),
                                     |this| {
            // Resolve the type parameters.
            this.visit_generics(generics);

            // Resolve the trait reference, if necessary.
            this.with_optional_trait_ref(opt_trait_reference.as_ref(), |this, trait_id| {
                // Resolve the self type.
                this.visit_ty(self_type);

                this.with_self_rib(DefSelfTy(trait_id, Some((item_id, self_type.id))), |this| {
                    this.with_current_self_type(self_type, |this| {
                        for impl_item in impl_items {
                            match impl_item.node {
                                hir::ImplItemKind::Const(..) => {
                                    // If this is a trait impl, ensure the const
                                    // exists in trait
                                    this.check_trait_item(impl_item.name,
                                                          impl_item.span,
                                        |n, s| ResolutionError::ConstNotMemberOfTrait(n, s));
                                    this.with_constant_rib(|this| {
                                        intravisit::walk_impl_item(this, impl_item);
                                    });
                                }
                                hir::ImplItemKind::Method(ref sig, _) => {
                                    // If this is a trait impl, ensure the method
                                    // exists in trait
                                    this.check_trait_item(impl_item.name,
                                                          impl_item.span,
                                        |n, s| ResolutionError::MethodNotMemberOfTrait(n, s));

                                    // We also need a new scope for the method-
                                    // specific type parameters.
                                    let type_parameters =
                                        HasTypeParameters(&sig.generics,
                                                          FnSpace,
                                                          MethodRibKind);
                                    this.with_type_parameter_rib(type_parameters, |this| {
                                        intravisit::walk_impl_item(this, impl_item);
                                    });
                                }
                                hir::ImplItemKind::Type(ref ty) => {
                                    // If this is a trait impl, ensure the type
                                    // exists in trait
                                    this.check_trait_item(impl_item.name,
                                                          impl_item.span,
                                        |n, s| ResolutionError::TypeNotMemberOfTrait(n, s));

                                    this.visit_ty(ty);
                                }
                            }
                        }
                    });
                });
            });
        });
    }

    fn check_trait_item<F>(&self, name: Name, span: Span, err: F)
        where F: FnOnce(Name, &str) -> ResolutionError
    {
        // If there is a TraitRef in scope for an impl, then the method must be in the
        // trait.
        if let Some((did, ref trait_ref)) = self.current_trait_ref {
            if !self.trait_item_map.contains_key(&(name, did)) {
                let path_str = path_names_to_string(&trait_ref.path, 0);
                resolve_error(self, span, err(name, &*path_str));
            }
        }
    }

    fn resolve_local(&mut self, local: &Local) {
        // Resolve the type.
        walk_list!(self, visit_ty, &local.ty);

        // Resolve the initializer.
        walk_list!(self, visit_expr, &local.init);

        // Resolve the pattern.
        self.resolve_pattern(&*local.pat, LocalIrrefutableMode, &mut HashMap::new());
    }

    // build a map from pattern identifiers to binding-info's.
    // this is done hygienically. This could arise for a macro
    // that expands into an or-pattern where one 'x' was from the
    // user and one 'x' came from the macro.
    fn binding_mode_map(&mut self, pat: &Pat) -> BindingMap {
        let mut result = HashMap::new();
        pat_bindings(&self.def_map, pat, |binding_mode, _id, sp, path1| {
            let name = path1.node;
            result.insert(name,
                          BindingInfo {
                              span: sp,
                              binding_mode: binding_mode,
                          });
        });
        return result;
    }

    // check that all of the arms in an or-pattern have exactly the
    // same set of bindings, with the same binding modes for each.
    fn check_consistent_bindings(&mut self, arm: &Arm) {
        if arm.pats.is_empty() {
            return;
        }
        let map_0 = self.binding_mode_map(&*arm.pats[0]);
        for (i, p) in arm.pats.iter().enumerate() {
            let map_i = self.binding_mode_map(&**p);

            for (&key, &binding_0) in &map_0 {
                match map_i.get(&key) {
                    None => {
                        resolve_error(self,
                                      p.span,
                                      ResolutionError::VariableNotBoundInPattern(key, i + 1));
                    }
                    Some(binding_i) => {
                        if binding_0.binding_mode != binding_i.binding_mode {
                            resolve_error(self,
                                          binding_i.span,
                                          ResolutionError::VariableBoundWithDifferentMode(key,
                                                                                          i + 1));
                        }
                    }
                }
            }

            for (&key, &binding) in &map_i {
                if !map_0.contains_key(&key) {
                    resolve_error(self,
                                  binding.span,
                                  ResolutionError::VariableNotBoundInParentPattern(key, i + 1));
                }
            }
        }
    }

    fn resolve_arm(&mut self, arm: &Arm) {
        self.value_ribs.push(Rib::new(NormalRibKind));

        let mut bindings_list = HashMap::new();
        for pattern in &arm.pats {
            self.resolve_pattern(&**pattern, RefutableMode, &mut bindings_list);
        }

        // This has to happen *after* we determine which
        // pat_idents are variants
        self.check_consistent_bindings(arm);

        walk_list!(self, visit_expr, &arm.guard);
        self.visit_expr(&*arm.body);

        if !self.resolved {
            self.value_ribs.pop();
        }
    }

    fn resolve_block(&mut self, block: &Block) {
        debug!("(resolving block) entering block");
        self.value_ribs.push(Rib::new(NormalRibKind));

        // Move down in the graph, if there's an anonymous module rooted here.
        let orig_module = self.current_module;
        match orig_module.anonymous_children.borrow().get(&block.id) {
            None => {
                // Nothing to do.
            }
            Some(anonymous_module) => {
                debug!("(resolving block) found anonymous module, moving down");
                self.current_module = anonymous_module;
            }
        }

        // Check for imports appearing after non-item statements.
        let mut found_non_item = false;
        for statement in &block.stmts {
            if let hir::StmtDecl(ref declaration, _) = statement.node {
                if let hir::DeclItem(i) = declaration.node {
                    let i = self.ast_map.expect_item(i.id);
                    match i.node {
                        ItemExternCrate(_) | ItemUse(_) if found_non_item => {
                            span_err!(self.session,
                                      i.span,
                                      E0154,
                                      "imports are not allowed after non-item statements");
                        }
                        _ => {}
                    }
                } else {
                    found_non_item = true
                }
            } else {
                found_non_item = true;
            }
        }

        // Descend into the block.
        intravisit::walk_block(self, block);

        // Move back up.
        if !self.resolved {
            self.current_module = orig_module;
            self.value_ribs.pop();
        }
        debug!("(resolving block) leaving block");
    }

    fn resolve_type(&mut self, ty: &Ty) {
        match ty.node {
            TyPath(ref maybe_qself, ref path) => {
                let resolution = match self.resolve_possibly_assoc_item(ty.id,
                                                                        maybe_qself.as_ref(),
                                                                        path,
                                                                        TypeNS,
                                                                        true) {
                    // `<T>::a::b::c` is resolved by typeck alone.
                    TypecheckRequired => {
                        // Resolve embedded types.
                        intravisit::walk_ty(self, ty);
                        return;
                    }
                    ResolveAttempt(resolution) => resolution,
                };

                // This is a path in the type namespace. Walk through scopes
                // looking for it.
                match resolution {
                    Some(def) => {
                        // Write the result into the def map.
                        debug!("(resolving type) writing resolution for `{}` (id {}) = {:?}",
                               path_names_to_string(path, 0),
                               ty.id,
                               def);
                        self.record_def(ty.id, def);
                    }
                    None => {
                        self.record_def(ty.id, err_path_resolution());

                        // Keep reporting some errors even if they're ignored above.
                        self.resolve_path(ty.id, path, 0, TypeNS, true);

                        let kind = if maybe_qself.is_some() {
                            "associated type"
                        } else {
                            "type name"
                        };

                        let self_type_name = special_idents::type_self.name;
                        let is_invalid_self_type_name = path.segments.len() > 0 &&
                                                        maybe_qself.is_none() &&
                                                        path.segments[0].identifier.name ==
                                                        self_type_name;
                        if is_invalid_self_type_name {
                            resolve_error(self,
                                          ty.span,
                                          ResolutionError::SelfUsedOutsideImplOrTrait);
                        } else {
                            resolve_error(self,
                                          ty.span,
                                          ResolutionError::UseOfUndeclared(
                                                                    kind,
                                                                    &*path_names_to_string(path,
                                                                                           0))
                                         );
                        }
                    }
                }
            }
            _ => {}
        }
        // Resolve embedded types.
        intravisit::walk_ty(self, ty);
    }

    fn resolve_pattern(&mut self,
                       pattern: &Pat,
                       mode: PatternBindingMode,
                       // Maps idents to the node ID for the (outermost)
                       // pattern that binds them
                       bindings_list: &mut HashMap<Name, NodeId>) {
        let pat_id = pattern.id;
        walk_pat(pattern, |pattern| {
            match pattern.node {
                PatIdent(binding_mode, ref path1, ref at_rhs) => {
                    // The meaning of PatIdent with no type parameters
                    // depends on whether an enum variant or unit-like struct
                    // with that name is in scope. The probing lookup has to
                    // be careful not to emit spurious errors. Only matching
                    // patterns (match) can match nullary variants or
                    // unit-like structs. For binding patterns (let
                    // and the LHS of @-patterns), matching such a value is
                    // simply disallowed (since it's rarely what you want).
                    let const_ok = mode == RefutableMode && at_rhs.is_none();

                    let ident = path1.node;
                    let renamed = ident.name;

                    match self.resolve_bare_identifier_pattern(ident.unhygienic_name,
                                                               pattern.span) {
                        FoundStructOrEnumVariant(def, lp) if const_ok => {
                            debug!("(resolving pattern) resolving `{}` to struct or enum variant",
                                   renamed);

                            self.enforce_default_binding_mode(pattern,
                                                              binding_mode,
                                                              "an enum variant");
                            self.record_def(pattern.id,
                                            PathResolution {
                                                base_def: def,
                                                last_private: lp,
                                                depth: 0,
                                            });
                        }
                        FoundStructOrEnumVariant(..) => {
                            resolve_error(
                                self,
                                pattern.span,
                                ResolutionError::DeclarationShadowsEnumVariantOrUnitLikeStruct(
                                    renamed)
                            );
                            self.record_def(pattern.id, err_path_resolution());
                        }
                        FoundConst(def, lp, _) if const_ok => {
                            debug!("(resolving pattern) resolving `{}` to constant", renamed);

                            self.enforce_default_binding_mode(pattern, binding_mode, "a constant");
                            self.record_def(pattern.id,
                                            PathResolution {
                                                base_def: def,
                                                last_private: lp,
                                                depth: 0,
                                            });
                        }
                        FoundConst(def, _, name) => {
                            resolve_error(
                                self,
                                pattern.span,
                                ResolutionError::OnlyIrrefutablePatternsAllowedHere(def.def_id(),
                                                                                    name)
                            );
                            self.record_def(pattern.id, err_path_resolution());
                        }
                        BareIdentifierPatternUnresolved => {
                            debug!("(resolving pattern) binding `{}`", renamed);

                            let def_id = self.ast_map.local_def_id(pattern.id);
                            let def = DefLocal(def_id, pattern.id);

                            // Record the definition so that later passes
                            // will be able to distinguish variants from
                            // locals in patterns.

                            self.record_def(pattern.id,
                                            PathResolution {
                                                base_def: def,
                                                last_private: LastMod(AllPublic),
                                                depth: 0,
                                            });

                            // Add the binding to the local ribs, if it
                            // doesn't already exist in the bindings list. (We
                            // must not add it if it's in the bindings list
                            // because that breaks the assumptions later
                            // passes make about or-patterns.)
                            if !bindings_list.contains_key(&renamed) {
                                let this = &mut *self;
                                let last_rib = this.value_ribs.last_mut().unwrap();
                                last_rib.bindings.insert(renamed, DlDef(def));
                                bindings_list.insert(renamed, pat_id);
                            } else if mode == ArgumentIrrefutableMode &&
                               bindings_list.contains_key(&renamed) {
                                // Forbid duplicate bindings in the same
                                // parameter list.
                                resolve_error(
                                    self,
                                    pattern.span,
                                    ResolutionError::IdentifierBoundMoreThanOnceInParameterList(
                                        &ident.name.as_str())
                                );
                            } else if bindings_list.get(&renamed) == Some(&pat_id) {
                                // Then this is a duplicate variable in the
                                // same disjunction, which is an error.
                                resolve_error(
                                    self,
                                    pattern.span,
                                    ResolutionError::IdentifierBoundMoreThanOnceInSamePattern(
                                        &ident.name.as_str())
                                );
                            }
                            // Else, not bound in the same pattern: do
                            // nothing.
                        }
                    }
                }

                PatEnum(ref path, _) => {
                    // This must be an enum variant, struct or const.
                    let resolution = match self.resolve_possibly_assoc_item(pat_id,
                                                                            None,
                                                                            path,
                                                                            ValueNS,
                                                                            false) {
                        // The below shouldn't happen because all
                        // qualified paths should be in PatQPath.
                        TypecheckRequired =>
                            self.session.span_bug(path.span,
                                                  "resolve_possibly_assoc_item claimed
                                     \
                                                   that a path in PatEnum requires typecheck
                                     \
                                                   to resolve, but qualified paths should be
                                     \
                                                   PatQPath"),
                        ResolveAttempt(resolution) => resolution,
                    };
                    if let Some(path_res) = resolution {
                        match path_res.base_def {
                            DefVariant(..) | DefStruct(..) | DefConst(..) => {
                                self.record_def(pattern.id, path_res);
                            }
                            DefStatic(..) => {
                                resolve_error(&self,
                                              path.span,
                                              ResolutionError::StaticVariableReference);
                                self.record_def(pattern.id, err_path_resolution());
                            }
                            _ => {
                                // If anything ends up here entirely resolved,
                                // it's an error. If anything ends up here
                                // partially resolved, that's OK, because it may
                                // be a `T::CONST` that typeck will resolve.
                                if path_res.depth == 0 {
                                    resolve_error(
                                        self,
                                        path.span,
                                        ResolutionError::NotAnEnumVariantStructOrConst(
                                            &path.segments
                                                 .last()
                                                 .unwrap()
                                                 .identifier
                                                 .name
                                                 .as_str())
                                    );
                                    self.record_def(pattern.id, err_path_resolution());
                                } else {
                                    let const_name = path.segments
                                                         .last()
                                                         .unwrap()
                                                         .identifier
                                                         .name;
                                    let traits = self.get_traits_containing_item(const_name);
                                    self.trait_map.insert(pattern.id, traits);
                                    self.record_def(pattern.id, path_res);
                                }
                            }
                        }
                    } else {
                        resolve_error(
                            self,
                            path.span,
                            ResolutionError::UnresolvedEnumVariantStructOrConst(
                                &path.segments.last().unwrap().identifier.name.as_str())
                        );
                        self.record_def(pattern.id, err_path_resolution());
                    }
                    intravisit::walk_path(self, path);
                }

                PatQPath(ref qself, ref path) => {
                    // Associated constants only.
                    let resolution = match self.resolve_possibly_assoc_item(pat_id,
                                                                            Some(qself),
                                                                            path,
                                                                            ValueNS,
                                                                            false) {
                        TypecheckRequired => {
                            // All `<T>::CONST` should end up here, and will
                            // require use of the trait map to resolve
                            // during typechecking.
                            let const_name = path.segments
                                                 .last()
                                                 .unwrap()
                                                 .identifier
                                                 .name;
                            let traits = self.get_traits_containing_item(const_name);
                            self.trait_map.insert(pattern.id, traits);
                            intravisit::walk_pat(self, pattern);
                            return true;
                        }
                        ResolveAttempt(resolution) => resolution,
                    };
                    if let Some(path_res) = resolution {
                        match path_res.base_def {
                            // All `<T as Trait>::CONST` should end up here, and
                            // have the trait already selected.
                            DefAssociatedConst(..) => {
                                self.record_def(pattern.id, path_res);
                            }
                            _ => {
                                resolve_error(
                                    self,
                                    path.span,
                                    ResolutionError::NotAnAssociatedConst(
                                        &path.segments.last().unwrap().identifier.name.as_str()
                                    )
                                );
                                self.record_def(pattern.id, err_path_resolution());
                            }
                        }
                    } else {
                        resolve_error(self,
                                      path.span,
                                      ResolutionError::UnresolvedAssociatedConst(&path.segments
                                                                                      .last()
                                                                                      .unwrap()
                                                                                      .identifier
                                                                                      .name
                                                                                      .as_str()));
                        self.record_def(pattern.id, err_path_resolution());
                    }
                    intravisit::walk_pat(self, pattern);
                }

                PatStruct(ref path, _, _) => {
                    match self.resolve_path(pat_id, path, 0, TypeNS, false) {
                        Some(definition) => {
                            self.record_def(pattern.id, definition);
                        }
                        result => {
                            debug!("(resolving pattern) didn't find struct def: {:?}", result);
                            resolve_error(
                                self,
                                path.span,
                                ResolutionError::DoesNotNameAStruct(
                                    &*path_names_to_string(path, 0))
                            );
                            self.record_def(pattern.id, err_path_resolution());
                        }
                    }
                    intravisit::walk_path(self, path);
                }

                PatLit(_) | PatRange(..) => {
                    intravisit::walk_pat(self, pattern);
                }

                _ => {
                    // Nothing to do.
                }
            }
            true
        });
    }

    fn resolve_bare_identifier_pattern(&mut self,
                                       name: Name,
                                       span: Span)
                                       -> BareIdentifierPatternResolution {
        let module = self.current_module;
        match self.resolve_item_in_lexical_scope(module, name, ValueNS, true) {
            Success((target, _)) => {
                debug!("(resolve bare identifier pattern) succeeded in finding {} at {:?}",
                       name,
                       target.binding.borrow());
                match target.binding.def() {
                    None => {
                        panic!("resolved name in the value namespace to a set of name bindings \
                                with no def?!");
                    }
                    // For the two success cases, this lookup can be
                    // considered as not having a private component because
                    // the lookup happened only within the current module.
                    Some(def @ DefVariant(..)) | Some(def @ DefStruct(..)) => {
                        return FoundStructOrEnumVariant(def, LastMod(AllPublic));
                    }
                    Some(def @ DefConst(..)) | Some(def @ DefAssociatedConst(..)) => {
                        return FoundConst(def, LastMod(AllPublic), name);
                    }
                    Some(DefStatic(..)) => {
                        resolve_error(self, span, ResolutionError::StaticVariableReference);
                        return BareIdentifierPatternUnresolved;
                    }
                    _ => return BareIdentifierPatternUnresolved
                }
            }

            Indeterminate => {
                panic!("unexpected indeterminate result");
            }
            Failed(err) => {
                match err {
                    Some((span, msg)) => {
                        resolve_error(self, span, ResolutionError::FailedToResolve(&*msg));
                    }
                    None => (),
                }

                debug!("(resolve bare identifier pattern) failed to find {}", name);
                return BareIdentifierPatternUnresolved;
            }
        }
    }

    /// Handles paths that may refer to associated items
    fn resolve_possibly_assoc_item(&mut self,
                                   id: NodeId,
                                   maybe_qself: Option<&hir::QSelf>,
                                   path: &Path,
                                   namespace: Namespace,
                                   check_ribs: bool)
                                   -> AssocItemResolveResult {
        let max_assoc_types;

        match maybe_qself {
            Some(qself) => {
                if qself.position == 0 {
                    return TypecheckRequired;
                }
                max_assoc_types = path.segments.len() - qself.position;
                // Make sure the trait is valid.
                let _ = self.resolve_trait_reference(id, path, max_assoc_types);
            }
            None => {
                max_assoc_types = path.segments.len();
            }
        }

        let mut resolution = self.with_no_errors(|this| {
            this.resolve_path(id, path, 0, namespace, check_ribs)
        });
        for depth in 1..max_assoc_types {
            if resolution.is_some() {
                break;
            }
            self.with_no_errors(|this| {
                resolution = this.resolve_path(id, path, depth, TypeNS, true);
            });
        }
        if let Some(DefMod(_)) = resolution.map(|r| r.base_def) {
            // A module is not a valid type or value.
            resolution = None;
        }
        ResolveAttempt(resolution)
    }

    /// If `check_ribs` is true, checks the local definitions first; i.e.
    /// doesn't skip straight to the containing module.
    /// Skips `path_depth` trailing segments, which is also reflected in the
    /// returned value. See `middle::def::PathResolution` for more info.
    pub fn resolve_path(&mut self,
                        id: NodeId,
                        path: &Path,
                        path_depth: usize,
                        namespace: Namespace,
                        check_ribs: bool)
                        -> Option<PathResolution> {
        let span = path.span;
        let segments = &path.segments[..path.segments.len() - path_depth];

        let mk_res = |(def, lp)| PathResolution::new(def, lp, path_depth);

        if path.global {
            let def = self.resolve_crate_relative_path(span, segments, namespace);
            return def.map(mk_res);
        }

        // Try to find a path to an item in a module.
        let last_ident = segments.last().unwrap().identifier;
        if segments.len() <= 1 {
            let unqualified_def = self.resolve_identifier(last_ident, namespace, check_ribs, true);
            return unqualified_def.and_then(|def| self.adjust_local_def(def, span))
                                  .map(|def| {
                                      PathResolution::new(def, LastMod(AllPublic), path_depth)
                                  });
        }

        let unqualified_def = self.resolve_identifier(last_ident, namespace, check_ribs, false);
        let def = self.resolve_module_relative_path(span, segments, namespace);
        match (def, unqualified_def) {
            (Some((ref d, _)), Some(ref ud)) if *d == ud.def => {
                self.session
                    .add_lint(lint::builtin::UNUSED_QUALIFICATIONS,
                              id,
                              span,
                              "unnecessary qualification".to_string());
            }
            _ => {}
        }

        def.map(mk_res)
    }

    // Resolve a single identifier
    fn resolve_identifier(&mut self,
                          identifier: hir::Ident,
                          namespace: Namespace,
                          check_ribs: bool,
                          record_used: bool)
                          -> Option<LocalDef> {
        // First, check to see whether the name is a primitive type.
        if namespace == TypeNS {
            if let Some(&prim_ty) = self.primitive_type_table
                                        .primitive_types
                                        .get(&identifier.unhygienic_name) {
                return Some(LocalDef::from_def(DefPrimTy(prim_ty)));
            }
        }

        if check_ribs {
            if let Some(def) = self.resolve_identifier_in_local_ribs(identifier, namespace) {
                return Some(def);
            }
        }

        let name = identifier.unhygienic_name;
        self.resolve_item_by_name_in_lexical_scope(name, namespace, record_used)
            .map(LocalDef::from_def)
    }

    // Resolve a local definition, potentially adjusting for closures.
    fn adjust_local_def(&mut self, local_def: LocalDef, span: Span) -> Option<Def> {
        let ribs = match local_def.ribs {
            Some((TypeNS, i)) => &self.type_ribs[i + 1..],
            Some((ValueNS, i)) => &self.value_ribs[i + 1..],
            _ => &[] as &[_],
        };
        let mut def = local_def.def;
        match def {
            DefUpvar(..) => {
                self.session.span_bug(span, &format!("unexpected {:?} in bindings", def))
            }
            DefLocal(_, node_id) => {
                for rib in ribs {
                    match rib.kind {
                        NormalRibKind => {
                            // Nothing to do. Continue.
                        }
                        ClosureRibKind(function_id) => {
                            let prev_def = def;
                            let node_def_id = self.ast_map.local_def_id(node_id);

                            let seen = self.freevars_seen
                                           .entry(function_id)
                                           .or_insert_with(|| NodeMap());
                            if let Some(&index) = seen.get(&node_id) {
                                def = DefUpvar(node_def_id, node_id, index, function_id);
                                continue;
                            }
                            let vec = self.freevars
                                          .entry(function_id)
                                          .or_insert_with(|| vec![]);
                            let depth = vec.len();
                            vec.push(Freevar {
                                def: prev_def,
                                span: span,
                            });

                            def = DefUpvar(node_def_id, node_id, depth, function_id);
                            seen.insert(node_id, depth);
                        }
                        ItemRibKind | MethodRibKind => {
                            // This was an attempt to access an upvar inside a
                            // named function item. This is not allowed, so we
                            // report an error.
                            resolve_error(self,
                                          span,
                                          ResolutionError::CannotCaptureDynamicEnvironmentInFnItem);
                            return None;
                        }
                        ConstantItemRibKind => {
                            // Still doesn't deal with upvars
                            resolve_error(self,
                                          span,
                                          ResolutionError::AttemptToUseNonConstantValueInConstant);
                            return None;
                        }
                    }
                }
            }
            DefTyParam(..) | DefSelfTy(..) => {
                for rib in ribs {
                    match rib.kind {
                        NormalRibKind | MethodRibKind | ClosureRibKind(..) => {
                            // Nothing to do. Continue.
                        }
                        ItemRibKind => {
                            // This was an attempt to use a type parameter outside
                            // its scope.

                            resolve_error(self,
                                          span,
                                          ResolutionError::TypeParametersFromOuterFunction);
                            return None;
                        }
                        ConstantItemRibKind => {
                            // see #9186
                            resolve_error(self, span, ResolutionError::OuterTypeParameterContext);
                            return None;
                        }
                    }
                }
            }
            _ => {}
        }
        return Some(def);
    }

    // resolve a "module-relative" path, e.g. a::b::c
    fn resolve_module_relative_path(&mut self,
                                    span: Span,
                                    segments: &[hir::PathSegment],
                                    namespace: Namespace)
                                    -> Option<(Def, LastPrivate)> {
        let module_path = segments.split_last()
                                  .unwrap()
                                  .1
                                  .iter()
                                  .map(|ps| ps.identifier.name)
                                  .collect::<Vec<_>>();

        let containing_module;
        let last_private;
        let current_module = self.current_module;
        match self.resolve_module_path(current_module,
                                       &module_path[..],
                                       UseLexicalScope,
                                       span,
                                       PathSearch) {
            Failed(err) => {
                let (span, msg) = match err {
                    Some((span, msg)) => (span, msg),
                    None => {
                        let msg = format!("Use of undeclared type or module `{}`",
                                          names_to_string(&module_path));
                        (span, msg)
                    }
                };

                resolve_error(self, span, ResolutionError::FailedToResolve(&*msg));
                return None;
            }
            Indeterminate => panic!("indeterminate unexpected"),
            Success((resulting_module, resulting_last_private)) => {
                containing_module = resulting_module;
                last_private = resulting_last_private;
            }
        }

        let name = segments.last().unwrap().identifier.name;
        let def = match self.resolve_name_in_module(containing_module,
                                                    name,
                                                    namespace,
                                                    NameSearchType::PathSearch,
                                                    false) {
            Success((Target { binding, .. }, _)) => {
                let (def, lp) = binding.def_and_lp();
                (def, last_private.or(lp))
            }
            _ => return None,
        };
        if let Some(DefId{krate: kid, ..}) = containing_module.def_id() {
            self.used_crates.insert(kid);
        }
        return Some(def);
    }

    /// Invariant: This must be called only during main resolution, not during
    /// import resolution.
    fn resolve_crate_relative_path(&mut self,
                                   span: Span,
                                   segments: &[hir::PathSegment],
                                   namespace: Namespace)
                                   -> Option<(Def, LastPrivate)> {
        let module_path = segments.split_last()
                                  .unwrap()
                                  .1
                                  .iter()
                                  .map(|ps| ps.identifier.name)
                                  .collect::<Vec<_>>();

        let root_module = self.graph_root;

        let containing_module;
        let last_private;
        match self.resolve_module_path_from_root(root_module,
                                                 &module_path[..],
                                                 0,
                                                 span,
                                                 PathSearch,
                                                 LastMod(AllPublic)) {
            Failed(err) => {
                let (span, msg) = match err {
                    Some((span, msg)) => (span, msg),
                    None => {
                        let msg = format!("Use of undeclared module `::{}`",
                                          names_to_string(&module_path[..]));
                        (span, msg)
                    }
                };

                resolve_error(self, span, ResolutionError::FailedToResolve(&*msg));
                return None;
            }

            Indeterminate => {
                panic!("indeterminate unexpected");
            }

            Success((resulting_module, resulting_last_private)) => {
                containing_module = resulting_module;
                last_private = resulting_last_private;
            }
        }

        let name = segments.last().unwrap().identifier.name;
        match self.resolve_name_in_module(containing_module,
                                          name,
                                          namespace,
                                          NameSearchType::PathSearch,
                                          false) {
            Success((Target { binding, .. }, _)) => {
                let (def, lp) = binding.def_and_lp();
                Some((def, last_private.or(lp)))
            }
            _ => None,
        }
    }

    fn resolve_identifier_in_local_ribs(&mut self,
                                        ident: hir::Ident,
                                        namespace: Namespace)
                                        -> Option<LocalDef> {
        // Check the local set of ribs.
        let (name, ribs) = match namespace {
            ValueNS => (ident.name, &self.value_ribs),
            TypeNS => (ident.unhygienic_name, &self.type_ribs),
        };

        for (i, rib) in ribs.iter().enumerate().rev() {
            if let Some(def_like) = rib.bindings.get(&name).cloned() {
                match def_like {
                    DlDef(def) => {
                        debug!("(resolving path in local ribs) resolved `{}` to {:?} at {}",
                               name,
                               def,
                               i);
                        return Some(LocalDef {
                            ribs: Some((namespace, i)),
                            def: def,
                        });
                    }
                    def_like => {
                        debug!("(resolving path in local ribs) resolved `{}` to pseudo-def {:?}",
                               name,
                               def_like);
                        return None;
                    }
                }
            }
        }

        None
    }

    fn resolve_item_by_name_in_lexical_scope(&mut self,
                                             name: Name,
                                             namespace: Namespace,
                                             record_used: bool)
                                             -> Option<Def> {
        // Check the items.
        let module = self.current_module;
        match self.resolve_item_in_lexical_scope(module, name, namespace, record_used) {
            Success((target, _)) => {
                match target.binding.def() {
                    None => {
                        // This can happen if we were looking for a type and
                        // found a module instead. Modules don't have defs.
                        debug!("(resolving item path by identifier in lexical scope) failed to \
                                resolve {} after success...",
                               name);
                        None
                    }
                    Some(def) => {
                        debug!("(resolving item path in lexical scope) resolved `{}` to item",
                               name);
                        // This lookup is "all public" because it only searched
                        // for one identifier in the current module (couldn't
                        // have passed through reexports or anything like that.
                        Some(def)
                    }
                }
            }
            Indeterminate => {
                panic!("unexpected indeterminate result");
            }
            Failed(err) => {
                debug!("(resolving item path by identifier in lexical scope) failed to resolve {}",
                       name);

                if let Some((span, msg)) = err {
                    resolve_error(self, span, ResolutionError::FailedToResolve(&*msg))
                }

                None
            }
        }
    }

    fn with_no_errors<T, F>(&mut self, f: F) -> T
        where F: FnOnce(&mut Resolver) -> T
    {
        self.emit_errors = false;
        let rs = f(self);
        self.emit_errors = true;
        rs
    }

    fn find_fallback_in_self_type(&mut self, name: Name) -> FallbackSuggestion {
        fn extract_path_and_node_id(t: &Ty,
                                    allow: FallbackChecks)
                                    -> Option<(Path, NodeId, FallbackChecks)> {
            match t.node {
                TyPath(None, ref path) => Some((path.clone(), t.id, allow)),
                TyPtr(ref mut_ty) => extract_path_and_node_id(&*mut_ty.ty, OnlyTraitAndStatics),
                TyRptr(_, ref mut_ty) => extract_path_and_node_id(&*mut_ty.ty, allow),
                // This doesn't handle the remaining `Ty` variants as they are not
                // that commonly the self_type, it might be interesting to provide
                // support for those in future.
                _ => None,
            }
        }

        fn get_module<'a, 'tcx>(this: &mut Resolver<'a, 'tcx>,
                                span: Span,
                                name_path: &[ast::Name])
                                -> Option<Module<'a>> {
            let root = this.current_module;
            let last_name = name_path.last().unwrap();

            if name_path.len() == 1 {
                match this.primitive_type_table.primitive_types.get(last_name) {
                    Some(_) => None,
                    None => {
                        match this.current_module.children.borrow().get(last_name) {
                            Some(child) => child.type_ns.module(),
                            None => None,
                        }
                    }
                }
            } else {
                match this.resolve_module_path(root,
                                               &name_path[..],
                                               UseLexicalScope,
                                               span,
                                               PathSearch) {
                    Success((module, _)) => Some(module),
                    _ => None,
                }
            }
        }

        fn is_static_method(this: &Resolver, did: DefId) -> bool {
            if let Some(node_id) = this.ast_map.as_local_node_id(did) {
                let sig = match this.ast_map.get(node_id) {
                    hir_map::NodeTraitItem(trait_item) => match trait_item.node {
                        hir::MethodTraitItem(ref sig, _) => sig,
                        _ => return false,
                    },
                    hir_map::NodeImplItem(impl_item) => match impl_item.node {
                        hir::ImplItemKind::Method(ref sig, _) => sig,
                        _ => return false,
                    },
                    _ => return false,
                };
                sig.explicit_self.node == hir::SelfStatic
            } else {
                this.session.cstore.is_static_method(did)
            }
        }

        let (path, node_id, allowed) = match self.current_self_type {
            Some(ref ty) => match extract_path_and_node_id(ty, Everything) {
                Some(x) => x,
                None => return NoSuggestion,
            },
            None => return NoSuggestion,
        };

        if allowed == Everything {
            // Look for a field with the same name in the current self_type.
            match self.def_map.borrow().get(&node_id).map(|d| d.full_def()) {
                Some(DefTy(did, _)) |
                Some(DefStruct(did)) |
                Some(DefVariant(_, did, _)) => match self.structs.get(&did) {
                    None => {}
                    Some(fields) => {
                        if fields.iter().any(|&field_name| name == field_name) {
                            return Field;
                        }
                    }
                },
                _ => {} // Self type didn't resolve properly
            }
        }

        let name_path = path.segments.iter().map(|seg| seg.identifier.name).collect::<Vec<_>>();

        // Look for a method in the current self type's impl module.
        if let Some(module) = get_module(self, path.span, &name_path) {
            if let Some(binding) = module.children.borrow().get(&name) {
                if let Some(DefMethod(did)) = binding.value_ns.def() {
                    if is_static_method(self, did) {
                        return StaticMethod(path_names_to_string(&path, 0));
                    }
                    if self.current_trait_ref.is_some() {
                        return TraitItem;
                    } else if allowed == Everything {
                        return Method;
                    }
                }
            }
        }

        // Look for a method in the current trait.
        if let Some((trait_did, ref trait_ref)) = self.current_trait_ref {
            if let Some(&did) = self.trait_item_map.get(&(name, trait_did)) {
                if is_static_method(self, did) {
                    return TraitMethod(path_names_to_string(&trait_ref.path, 0));
                } else {
                    return TraitItem;
                }
            }
        }

        NoSuggestion
    }

    fn find_best_match(&mut self, name: &str) -> SuggestionType {
        if let Some(macro_name) = self.session.available_macros
                                  .borrow().iter().find(|n| n.as_str() == name) {
            return SuggestionType::Macro(format!("{}!", macro_name));
        }

        let names = self.value_ribs
                    .iter()
                    .rev()
                    .flat_map(|rib| rib.bindings.keys());

        if let Some(found) = find_best_match_for_name(names, name, None) {
            if name != &*found {
                return SuggestionType::Function(found);
            }
        } SuggestionType::NotFound
    }

    fn resolve_expr(&mut self, expr: &Expr) {
        // First, record candidate traits for this expression if it could
        // result in the invocation of a method call.

        self.record_candidate_traits_for_expr_if_necessary(expr);

        // Next, resolve the node.
        match expr.node {
            ExprPath(ref maybe_qself, ref path) => {
                let resolution = match self.resolve_possibly_assoc_item(expr.id,
                                                                        maybe_qself.as_ref(),
                                                                        path,
                                                                        ValueNS,
                                                                        true) {
                    // `<T>::a::b::c` is resolved by typeck alone.
                    TypecheckRequired => {
                        let method_name = path.segments.last().unwrap().identifier.name;
                        let traits = self.get_traits_containing_item(method_name);
                        self.trait_map.insert(expr.id, traits);
                        intravisit::walk_expr(self, expr);
                        return;
                    }
                    ResolveAttempt(resolution) => resolution,
                };

                // This is a local path in the value namespace. Walk through
                // scopes looking for it.
                if let Some(path_res) = resolution {
                    // Check if struct variant
                    if let DefVariant(_, _, true) = path_res.base_def {
                        let path_name = path_names_to_string(path, 0);

                        let mut err = resolve_struct_error(self,
                                        expr.span,
                                        ResolutionError::StructVariantUsedAsFunction(&*path_name));

                        let msg = format!("did you mean to write: `{} {{ /* fields */ }}`?",
                                          path_name);
                        if self.emit_errors {
                            err.fileline_help(expr.span, &msg);
                        } else {
                            err.span_help(expr.span, &msg);
                        }
                        err.emit();
                        self.record_def(expr.id, err_path_resolution());
                    } else {
                        // Write the result into the def map.
                        debug!("(resolving expr) resolved `{}`",
                               path_names_to_string(path, 0));

                        // Partial resolutions will need the set of traits in scope,
                        // so they can be completed during typeck.
                        if path_res.depth != 0 {
                            let method_name = path.segments.last().unwrap().identifier.name;
                            let traits = self.get_traits_containing_item(method_name);
                            self.trait_map.insert(expr.id, traits);
                        }

                        self.record_def(expr.id, path_res);
                    }
                } else {
                    // Be helpful if the name refers to a struct
                    // (The pattern matching def_tys where the id is in self.structs
                    // matches on regular structs while excluding tuple- and enum-like
                    // structs, which wouldn't result in this error.)
                    let path_name = path_names_to_string(path, 0);
                    let type_res = self.with_no_errors(|this| {
                        this.resolve_path(expr.id, path, 0, TypeNS, false)
                    });

                    self.record_def(expr.id, err_path_resolution());
                    match type_res.map(|r| r.base_def) {
                        Some(DefTy(struct_id, _)) if self.structs.contains_key(&struct_id) => {
                            let mut err = resolve_struct_error(self,
                                expr.span,
                                ResolutionError::StructVariantUsedAsFunction(&*path_name));

                            let msg = format!("did you mean to write: `{} {{ /* fields */ }}`?",
                                              path_name);
                            if self.emit_errors {
                                err.fileline_help(expr.span, &msg);
                            } else {
                                err.span_help(expr.span, &msg);
                            }
                            err.emit();
                        }
                        _ => {
                            // Keep reporting some errors even if they're ignored above.
                            self.resolve_path(expr.id, path, 0, ValueNS, true);

                            let mut method_scope = false;
                            self.value_ribs.iter().rev().all(|rib| {
                                method_scope = match rib.kind {
                                    MethodRibKind => true,
                                    ItemRibKind | ConstantItemRibKind => false,
                                    _ => return true, // Keep advancing
                                };
                                false // Stop advancing
                            });

                            if method_scope && special_names::self_.as_str() == &path_name[..] {
                                resolve_error(self,
                                              expr.span,
                                              ResolutionError::SelfNotAvailableInStaticMethod);
                            } else {
                                let last_name = path.segments.last().unwrap().identifier.name;
                                let mut msg = match self.find_fallback_in_self_type(last_name) {
                                    NoSuggestion => {
                                        // limit search to 5 to reduce the number
                                        // of stupid suggestions
                                        match self.find_best_match(&path_name) {
                                            SuggestionType::Macro(s) => {
                                                format!("the macro `{}`", s)
                                            }
                                            SuggestionType::Function(s) => format!("`{}`", s),
                                            SuggestionType::NotFound => "".to_string(),
                                        }
                                    }
                                    Field => format!("`self.{}`", path_name),
                                    Method |
                                    TraitItem => format!("to call `self.{}`", path_name),
                                    TraitMethod(path_str) |
                                    StaticMethod(path_str) =>
                                        format!("to call `{}::{}`", path_str, path_name),
                                };

                                let mut context =  UnresolvedNameContext::Other;
                                if !msg.is_empty() {
                                    msg = format!(". Did you mean {}?", msg);
                                } else {
                                    // we check if this a module and if so, we display a help
                                    // message
                                    let name_path = path.segments.iter()
                                                        .map(|seg| seg.identifier.name)
                                                        .collect::<Vec<_>>();
                                    let current_module = self.current_module;

                                    match self.resolve_module_path(current_module,
                                                   &name_path[..],
                                                   UseLexicalScope,
                                                   expr.span,
                                                   PathSearch) {
                                        Success(_) => {
                                            context = UnresolvedNameContext::PathIsMod(expr.id);
                                        },
                                        _ => {},
                                    };
                                }

                                resolve_error(self,
                                              expr.span,
                                              ResolutionError::UnresolvedName(
                                                  &*path_name, &*msg, context));
                            }
                        }
                    }
                }

                intravisit::walk_expr(self, expr);
            }

            ExprStruct(ref path, _, _) => {
                // Resolve the path to the structure it goes to. We don't
                // check to ensure that the path is actually a structure; that
                // is checked later during typeck.
                match self.resolve_path(expr.id, path, 0, TypeNS, false) {
                    Some(definition) => self.record_def(expr.id, definition),
                    None => {
                        debug!("(resolving expression) didn't find struct def",);

                        resolve_error(self,
                                      path.span,
                                      ResolutionError::DoesNotNameAStruct(
                                                                &*path_names_to_string(path, 0))
                                     );
                        self.record_def(expr.id, err_path_resolution());
                    }
                }

                intravisit::walk_expr(self, expr);
            }

            ExprLoop(_, Some(label)) | ExprWhile(_, _, Some(label)) => {
                self.with_label_rib(|this| {
                    let def_like = DlDef(DefLabel(expr.id));

                    {
                        let rib = this.label_ribs.last_mut().unwrap();
                        rib.bindings.insert(label.name, def_like);
                    }

                    intravisit::walk_expr(this, expr);
                })
            }

            ExprBreak(Some(label)) | ExprAgain(Some(label)) => {
                match self.search_label(label.node.name) {
                    None => {
                        self.record_def(expr.id, err_path_resolution());
                        resolve_error(self,
                                      label.span,
                                      ResolutionError::UndeclaredLabel(&label.node.name.as_str()))
                    }
                    Some(DlDef(def @ DefLabel(_))) => {
                        // Since this def is a label, it is never read.
                        self.record_def(expr.id,
                                        PathResolution {
                                            base_def: def,
                                            last_private: LastMod(AllPublic),
                                            depth: 0,
                                        })
                    }
                    Some(_) => {
                        self.session.span_bug(expr.span, "label wasn't mapped to a label def!")
                    }
                }
            }

            _ => {
                intravisit::walk_expr(self, expr);
            }
        }
    }

    fn record_candidate_traits_for_expr_if_necessary(&mut self, expr: &Expr) {
        match expr.node {
            ExprField(_, name) => {
                // FIXME(#6890): Even though you can't treat a method like a
                // field, we need to add any trait methods we find that match
                // the field name so that we can do some nice error reporting
                // later on in typeck.
                let traits = self.get_traits_containing_item(name.node);
                self.trait_map.insert(expr.id, traits);
            }
            ExprMethodCall(name, _, _) => {
                debug!("(recording candidate traits for expr) recording traits for {}",
                       expr.id);
                let traits = self.get_traits_containing_item(name.node);
                self.trait_map.insert(expr.id, traits);
            }
            _ => {
                // Nothing to do.
            }
        }
    }

    fn get_traits_containing_item(&mut self, name: Name) -> Vec<DefId> {
        debug!("(getting traits containing item) looking for '{}'", name);

        fn add_trait_info(found_traits: &mut Vec<DefId>, trait_def_id: DefId, name: Name) {
            debug!("(adding trait info) found trait {:?} for method '{}'",
                   trait_def_id,
                   name);
            found_traits.push(trait_def_id);
        }

        let mut found_traits = Vec::new();
        let mut search_module = self.current_module;
        loop {
            // Look for the current trait.
            match self.current_trait_ref {
                Some((trait_def_id, _)) => {
                    if self.trait_item_map.contains_key(&(name, trait_def_id)) {
                        add_trait_info(&mut found_traits, trait_def_id, name);
                    }
                }
                None => {} // Nothing to do.
            }

            // Look for trait children.
            build_reduced_graph::populate_module_if_necessary(self, &search_module);

            {
                for (_, child_names) in search_module.children.borrow().iter() {
                    let def = match child_names.type_ns.def() {
                        Some(def) => def,
                        None => continue,
                    };
                    let trait_def_id = match def {
                        DefTrait(trait_def_id) => trait_def_id,
                        _ => continue,
                    };
                    if self.trait_item_map.contains_key(&(name, trait_def_id)) {
                        add_trait_info(&mut found_traits, trait_def_id, name);
                    }
                }
            }

            // Look for imports.
            for (_, import) in search_module.import_resolutions.borrow().iter() {
                let target = match import.type_ns.target {
                    None => continue,
                    Some(ref target) => target,
                };
                let did = match target.binding.def() {
                    Some(DefTrait(trait_def_id)) => trait_def_id,
                    Some(..) | None => continue,
                };
                if self.trait_item_map.contains_key(&(name, did)) {
                    add_trait_info(&mut found_traits, did, name);
                    let id = import.type_ns.id;
                    self.used_imports.insert((id, TypeNS));
                    let trait_name = self.get_trait_name(did);
                    self.record_import_use(id, trait_name);
                    if let Some(DefId{krate: kid, ..}) = target.target_module.def_id() {
                        self.used_crates.insert(kid);
                    }
                }
            }

            match search_module.parent_link {
                NoParentLink | ModuleParentLink(..) => break,
                BlockParentLink(parent_module, _) => {
                    search_module = parent_module;
                }
            }
        }

        found_traits
    }

    fn record_def(&mut self, node_id: NodeId, resolution: PathResolution) {
        debug!("(recording def) recording {:?} for {}", resolution, node_id);
        assert!(match resolution.last_private {
                    LastImport{..} => false,
                    _ => true,
                },
                "Import should only be used for `use` directives");

        if let Some(prev_res) = self.def_map.borrow_mut().insert(node_id, resolution) {
            let span = self.ast_map.opt_span(node_id).unwrap_or(codemap::DUMMY_SP);
            self.session.span_bug(span,
                                  &format!("path resolved multiple times ({:?} before, {:?} now)",
                                           prev_res,
                                           resolution));
        }
    }

    fn enforce_default_binding_mode(&mut self,
                                    pat: &Pat,
                                    pat_binding_mode: BindingMode,
                                    descr: &str) {
        match pat_binding_mode {
            BindByValue(_) => {}
            BindByRef(..) => {
                resolve_error(self,
                              pat.span,
                              ResolutionError::CannotUseRefBindingModeWith(descr));
            }
        }
    }

    //
    // Diagnostics
    //
    // Diagnostics are not particularly efficient, because they're rarely
    // hit.
    //

    #[allow(dead_code)]   // useful for debugging
    fn dump_module(&mut self, module_: Module<'a>) {
        debug!("Dump of module `{}`:", module_to_string(&*module_));

        debug!("Children:");
        build_reduced_graph::populate_module_if_necessary(self, &module_);
        for (&name, _) in module_.children.borrow().iter() {
            debug!("* {}", name);
        }

        debug!("Import resolutions:");
        let import_resolutions = module_.import_resolutions.borrow();
        for (&name, import_resolution) in import_resolutions.iter() {
            let value_repr;
            match import_resolution.value_ns.target {
                None => {
                    value_repr = "".to_string();
                }
                Some(_) => {
                    value_repr = " value:?".to_string();
                    // FIXME #4954
                }
            }

            let type_repr;
            match import_resolution.type_ns.target {
                None => {
                    type_repr = "".to_string();
                }
                Some(_) => {
                    type_repr = " type:?".to_string();
                    // FIXME #4954
                }
            }

            debug!("* {}:{}{}", name, value_repr, type_repr);
        }
    }
}


fn names_to_string(names: &[Name]) -> String {
    let mut first = true;
    let mut result = String::new();
    for name in names {
        if first {
            first = false
        } else {
            result.push_str("::")
        }
        result.push_str(&name.as_str());
    }
    result
}

fn path_names_to_string(path: &Path, depth: usize) -> String {
    let names: Vec<ast::Name> = path.segments[..path.segments.len() - depth]
                                    .iter()
                                    .map(|seg| seg.identifier.name)
                                    .collect();
    names_to_string(&names[..])
}

/// A somewhat inefficient routine to obtain the name of a module.
fn module_to_string<'a>(module: Module<'a>) -> String {
    let mut names = Vec::new();

    fn collect_mod<'a>(names: &mut Vec<ast::Name>, module: Module<'a>) {
        match module.parent_link {
            NoParentLink => {}
            ModuleParentLink(ref module, name) => {
                names.push(name);
                collect_mod(names, module);
            }
            BlockParentLink(ref module, _) => {
                // danger, shouldn't be ident?
                names.push(special_idents::opaque.name);
                collect_mod(names, module);
            }
        }
    }
    collect_mod(&mut names, module);

    if names.is_empty() {
        return "???".to_string();
    }
    names_to_string(&names.into_iter().rev().collect::<Vec<ast::Name>>())
}

fn err_path_resolution() -> PathResolution {
    PathResolution {
        base_def: DefErr,
        last_private: LastMod(AllPublic),
        depth: 0,
    }
}


pub struct CrateMap {
    pub def_map: RefCell<DefMap>,
    pub freevars: FreevarMap,
    pub export_map: ExportMap,
    pub trait_map: TraitMap,
    pub external_exports: ExternalExports,
    pub glob_map: Option<GlobMap>,
}

#[derive(PartialEq,Copy, Clone)]
pub enum MakeGlobMap {
    Yes,
    No,
}

/// Entry point to crate resolution.
pub fn resolve_crate<'a, 'tcx>(session: &'a Session,
                               ast_map: &'a hir_map::Map<'tcx>,
                               make_glob_map: MakeGlobMap)
                               -> CrateMap {
    let krate = ast_map.krate();
    let arenas = Resolver::arenas();
    let mut resolver = create_resolver(session, ast_map, krate, make_glob_map, &arenas, None);

    resolver.resolve_crate(krate);

    check_unused::check_crate(&mut resolver, krate);

    CrateMap {
        def_map: resolver.def_map,
        freevars: resolver.freevars,
        export_map: resolver.export_map,
        trait_map: resolver.trait_map,
        external_exports: resolver.external_exports,
        glob_map: if resolver.make_glob_map {
            Some(resolver.glob_map)
        } else {
            None
        },
    }
}

/// Builds a name resolution walker to be used within this module,
/// or used externally, with an optional callback function.
///
/// The callback takes a &mut bool which allows callbacks to end a
/// walk when set to true, passing through the rest of the walk, while
/// preserving the ribs + current module. This allows resolve_path
/// calls to be made with the correct scope info. The node in the
/// callback corresponds to the current node in the walk.
pub fn create_resolver<'a, 'tcx>(session: &'a Session,
                                 ast_map: &'a hir_map::Map<'tcx>,
                                 krate: &'a Crate,
                                 make_glob_map: MakeGlobMap,
                                 arenas: &'a ResolverArenas<'a>,
                                 callback: Option<Box<Fn(hir_map::Node, &mut bool) -> bool>>)
                                 -> Resolver<'a, 'tcx> {
    let mut resolver = Resolver::new(session, ast_map, make_glob_map, arenas);

    resolver.callback = callback;

    build_reduced_graph::build_reduced_graph(&mut resolver, krate);
    session.abort_if_errors();

    resolve_imports::resolve_imports(&mut resolver);
    session.abort_if_errors();

    resolver
}

__build_diagnostic_array! { librustc_resolve, DIAGNOSTICS }
