]> git.lizzy.rs Git - rust.git/blobdiff - src/librustc_resolve/lib.rs
Auto merge of #31747 - jseyfried:stop_resolve_after_fail, r=nrc
[rust.git] / src / librustc_resolve / lib.rs
index 5fbe06a868f07f0d420fc5fb088f4e5b01a46673..11c51522b6763e4ab9bc720353cf3e98f72e9cca 100644 (file)
@@ -18,7 +18,6 @@
 #![cfg_attr(not(stage0), deny(warnings))]
 
 #![feature(associated_consts)]
-#![feature(borrow_state)]
 #![feature(rustc_diagnostic_macros)]
 #![feature(rustc_private)]
 #![feature(staged_api)]
@@ -60,9 +59,8 @@
 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::ast::{self, FloatTy};
+use syntax::ast::{CRATE_NODE_ID, Name, NodeId, CrateNum, IntTy, UintTy};
 use syntax::attr::AttrMetaMethods;
 use syntax::codemap::{self, Span, Pos};
 use syntax::errors::DiagnosticBuilder;
@@ -81,8 +79,9 @@
 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::{Pat, PatKind, Path, PrimTy};
+use rustc_front::hir::{PathSegment, PathParameters};
+use rustc_front::hir::HirVec;
 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;
@@ -119,6 +118,12 @@ enum SuggestionType {
     NotFound,
 }
 
+/// Candidates for a name resolution failure
+pub struct SuggestedCandidates {
+    name: String,
+    candidates: Vec<Path>,
+}
+
 pub enum ResolutionError<'a> {
     /// error E0401: can't use type parameters from outer function
     TypeParametersFromOuterFunction,
@@ -129,7 +134,7 @@ pub enum ResolutionError<'a> {
     /// error E0404: is not a trait
     IsNotATrait(&'a str),
     /// error E0405: use of undeclared trait name
-    UndeclaredTraitName(&'a str),
+    UndeclaredTraitName(&'a str, SuggestedCandidates),
     /// error E0406: undeclared associated type
     UndeclaredAssociatedType,
     /// error E0407: method is not a member of trait
@@ -147,7 +152,7 @@ pub enum ResolutionError<'a> {
     /// error E0411: use of `Self` outside of an impl or trait
     SelfUsedOutsideImplOrTrait,
     /// error E0412: use of undeclared
-    UseOfUndeclared(&'a str, &'a str),
+    UseOfUndeclared(&'a str, &'a str, SuggestedCandidates),
     /// error E0413: declaration shadows an enum variant or unit-like struct in scope
     DeclarationShadowsEnumVariantOrUnitLikeStruct(Name),
     /// error E0414: only irrefutable patterns allowed here
@@ -250,12 +255,14 @@ fn resolve_struct_error<'b, 'a: 'b, 'tcx: 'a>(resolver: &'b Resolver<'a, 'tcx>,
         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::UndeclaredTraitName(name, candidates) => {
+            let mut err = struct_span_err!(resolver.session,
+                                           span,
+                                           E0405,
+                                           "trait `{}` is not in scope",
+                                           name);
+            show_candidates(&mut err, span, &candidates);
+            err
         }
         ResolutionError::UndeclaredAssociatedType => {
             struct_span_err!(resolver.session, span, E0406, "undeclared associated type")
@@ -315,13 +322,15 @@ fn resolve_struct_error<'b, 'a: 'b, 'tcx: 'a>(resolver: &'b Resolver<'a, 'tcx>,
                              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::UseOfUndeclared(kind, name, candidates) => {
+            let mut err = struct_span_err!(resolver.session,
+                                           span,
+                                           E0412,
+                                           "{} `{}` is undefined or not in scope",
+                                           kind,
+                                           name);
+            show_candidates(&mut err, span, &candidates);
+            err
         }
         ResolutionError::DeclarationShadowsEnumVariantOrUnitLikeStruct(name) => {
             struct_span_err!(resolver.session,
@@ -439,25 +448,25 @@ fn resolve_struct_error<'b, 'a: 'b, 'tcx: 'a>(resolver: &'b Resolver<'a, 'tcx>,
                                 help_msg = format!("To reference an item from the \
                                                     `{module}` module, use \
                                                     `{module}::{ident}`",
-                                                   module = &*path,
+                                                   module = path,
                                                    ident = ident.node);
                             }
                             ExprMethodCall(ident, _, _) => {
                                 help_msg = format!("To call a function from the \
                                                     `{module}` module, use \
                                                     `{module}::{ident}(..)`",
-                                                   module = &*path,
+                                                   module = path,
                                                    ident = ident.node);
                             }
                             ExprCall(_, _) => {
                                 help_msg = format!("No function corresponds to `{module}(..)`",
-                                                   module = &*path);
+                                                   module = path);
                             }
                             _ => { } // no help available
                         }
                     } else {
                         help_msg = format!("Module `{module}` cannot be the value of an expression",
-                                           module = &*path);
+                                           module = path);
                     }
 
                     if !help_msg.is_empty() {
@@ -578,7 +587,7 @@ fn visit_expr(&mut self, expr: &Expr) {
         self.resolve_expr(expr);
     }
     fn visit_local(&mut self, local: &Local) {
-        execute_callback!(hir_map::Node::NodeLocal(&*local.pat), self);
+        execute_callback!(hir_map::Node::NodeLocal(&local.pat), self);
         self.resolve_local(local);
     }
     fn visit_ty(&mut self, ty: &Ty) {
@@ -799,12 +808,12 @@ pub struct ModuleS<'a> {
     is_public: bool,
     is_extern_crate: bool,
 
-    children: RefCell<HashMap<(Name, Namespace), NameResolution<'a>>>,
-    imports: RefCell<Vec<ImportDirective>>,
+    resolutions: RefCell<HashMap<(Name, Namespace), NameResolution<'a>>>,
+    unresolved_imports: RefCell<Vec<ImportDirective>>,
 
-    // The anonymous children of this node. Anonymous children are pseudo-
-    // modules that are implicitly created around items contained within
-    // blocks.
+    // The module children of this node, including normal modules and anonymous modules.
+    // Anonymous children are pseudo-modules that are implicitly created around items
+    // contained within blocks.
     //
     // For example, if we have this:
     //
@@ -816,7 +825,7 @@ pub struct ModuleS<'a> {
     //
     // There will be an anonymous module created around `g` with the ID of the
     // entry block for `f`.
-    anonymous_children: RefCell<NodeMap<Module<'a>>>,
+    module_children: RefCell<NodeMap<Module<'a>>>,
 
     shadowed_traits: RefCell<Vec<&'a NameBinding<'a>>>,
 
@@ -829,9 +838,6 @@ pub struct ModuleS<'a> {
     // 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.
@@ -841,20 +847,20 @@ pub struct ModuleS<'a> {
 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: def,
             is_public: is_public,
             is_extern_crate: false,
-            children: RefCell::new(HashMap::new()),
-            imports: RefCell::new(Vec::new()),
-            anonymous_children: RefCell::new(NodeMap()),
+            resolutions: RefCell::new(HashMap::new()),
+            unresolved_imports: RefCell::new(Vec::new()),
+            module_children: RefCell::new(NodeMap()),
             shadowed_traits: RefCell::new(Vec::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),
         }
     }
@@ -864,7 +870,7 @@ fn resolve_name(&self, name: Name, ns: Namespace, allow_private_imports: bool)
         let glob_count =
             if allow_private_imports { self.glob_count.get() } else { self.pub_glob_count.get() };
 
-        self.children.borrow().get(&(name, ns)).cloned().unwrap_or_default().result(glob_count)
+        self.resolutions.borrow().get(&(name, ns)).cloned().unwrap_or_default().result(glob_count)
             .and_then(|binding| {
                 let allowed = allow_private_imports || !binding.is_import() || binding.is_public();
                 if allowed { Success(binding) } else { Failed(None) }
@@ -874,7 +880,7 @@ fn resolve_name(&self, name: Name, ns: Namespace, allow_private_imports: bool)
     // Define the name or return the existing binding if there is a collision.
     fn try_define_child(&self, name: Name, ns: Namespace, binding: &'a NameBinding<'a>)
                         -> Result<(), &'a NameBinding<'a>> {
-        let mut children = self.children.borrow_mut();
+        let mut children = self.resolutions.borrow_mut();
         let resolution = children.entry((name, ns)).or_insert_with(Default::default);
 
         // FIXME #31379: We can use methods from imported traits shadowed by non-import items
@@ -890,31 +896,23 @@ fn try_define_child(&self, name: Name, ns: Namespace, binding: &'a NameBinding<'
     }
 
     fn increment_outstanding_references_for(&self, name: Name, ns: Namespace) {
-        let mut children = self.children.borrow_mut();
+        let mut children = self.resolutions.borrow_mut();
         children.entry((name, ns)).or_insert_with(Default::default).outstanding_references += 1;
     }
 
     fn decrement_outstanding_references_for(&self, name: Name, ns: Namespace) {
-        match self.children.borrow_mut().get_mut(&(name, ns)).unwrap().outstanding_references {
+        match self.resolutions.borrow_mut().get_mut(&(name, ns)).unwrap().outstanding_references {
             0 => panic!("No more outstanding references!"),
             ref mut outstanding_references => { *outstanding_references -= 1; }
         }
     }
 
     fn for_each_child<F: FnMut(Name, Namespace, &'a NameBinding<'a>)>(&self, mut f: F) {
-        for (&(name, ns), name_resolution) in self.children.borrow().iter() {
+        for (&(name, ns), name_resolution) in self.resolutions.borrow().iter() {
             name_resolution.binding.map(|binding| f(name, ns, binding));
         }
     }
 
-    fn for_each_local_child<F: FnMut(Name, Namespace, &'a NameBinding<'a>)>(&self, mut f: F) {
-        self.for_each_child(|name, ns, name_binding| {
-            if !name_binding.is_import() && !name_binding.is_extern_crate() {
-                f(name, ns, name_binding)
-            }
-        })
-    }
-
     fn def_id(&self) -> Option<DefId> {
         self.def.as_ref().map(Def::def_id)
     }
@@ -933,15 +931,6 @@ fn is_trait(&self) -> bool {
         }
     }
 
-    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);
     }
@@ -1048,6 +1037,7 @@ fn is_public(&self) -> bool {
 
     fn def_and_lp(&self) -> (Def, LastPrivate) {
         let def = self.def().unwrap();
+        if let Def::Err = def { return (def, LastMod(AllPublic)) }
         (def, LastMod(if self.is_public() { AllPublic } else { DependsOn(def.def_id()) }))
     }
 
@@ -1074,19 +1064,19 @@ fn new() -> PrimitiveTypeTable {
 
         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("f32", TyFloat(FloatTy::F32));
+        table.intern("f64", TyFloat(FloatTy::F64));
+        table.intern("isize", TyInt(IntTy::Is));
+        table.intern("i8", TyInt(IntTy::I8));
+        table.intern("i16", TyInt(IntTy::I16));
+        table.intern("i32", TyInt(IntTy::I32));
+        table.intern("i64", TyInt(IntTy::I64));
         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.intern("usize", TyUint(UintTy::Us));
+        table.intern("u8", TyUint(UintTy::U8));
+        table.intern("u16", TyUint(UintTy::U16));
+        table.intern("u32", TyUint(UintTy::U32));
+        table.intern("u64", TyUint(UintTy::U64));
 
         table
     }
@@ -1299,7 +1289,7 @@ fn resolve_module_path_from_root(&mut self,
                                      span: Span,
                                      lp: LastPrivate)
                                      -> ResolveResult<(Module<'a>, LastPrivate)> {
-        fn search_parent_externals<'a>(needle: Name, module: Module<'a>) -> Option<Module<'a>> {
+        fn search_parent_externals(needle: Name, module: Module) -> Option<Module> {
             match module.resolve_name(needle, TypeNS, false) {
                 Success(binding) if binding.is_extern_crate() => Some(module),
                 _ => match module.parent_link {
@@ -1332,8 +1322,8 @@ fn search_parent_externals<'a>(needle: Name, module: Module<'a>) -> Option<Modul
                         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 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()
@@ -1401,7 +1391,7 @@ fn resolve_module_path(&mut self,
 
         debug!("(resolving module path for import) processing `{}` rooted at `{}`",
                names_to_string(module_path),
-               module_to_string(&*module_));
+               module_to_string(&module_));
 
         // Resolve the module prefix, if any.
         let module_prefix_result = self.resolve_module_prefix(module_, module_path);
@@ -1495,7 +1485,7 @@ fn resolve_item_in_lexical_scope(&mut self,
         debug!("(resolving item in lexical scope) resolving `{}` in namespace {:?} in `{}`",
                name,
                namespace,
-               module_to_string(&*module_));
+               module_to_string(&module_));
 
         // Proceed up the scope chain looking for parent modules.
         let mut search_module = module_;
@@ -1503,7 +1493,7 @@ fn resolve_item_in_lexical_scope(&mut self,
             // Resolve the name in the parent module.
             match self.resolve_name_in_module(search_module, name, namespace, true, record_used) {
                 Failed(Some((span, msg))) => {
-                    resolve_error(self, span, ResolutionError::FailedToResolve(&*msg));
+                    resolve_error(self, span, ResolutionError::FailedToResolve(&msg));
                 }
                 Failed(None) => (), // Continue up the search chain.
                 Indeterminate => {
@@ -1593,7 +1583,7 @@ fn resolve_module_prefix(&mut self,
         // 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));
+                   module_to_string(&containing_module));
             match self.get_nearest_normal_module_parent(containing_module) {
                 None => return Failed(None),
                 Some(new_module) => {
@@ -1604,7 +1594,7 @@ fn resolve_module_prefix(&mut self,
         }
 
         debug!("(resolving module prefix) finished resolving prefix at {}",
-               module_to_string(&*containing_module));
+               module_to_string(&containing_module));
 
         return Success(PrefixFound(containing_module, i));
     }
@@ -1631,30 +1621,13 @@ fn resolve_name_in_module(&mut self,
     }
 
     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));
+        for import in module_.unresolved_imports.borrow().iter() {
+            resolve_error(self, import.span, ResolutionError::UnresolvedImport(None));
+            break;
         }
 
         // Descend into children and anonymous children.
-        build_reduced_graph::populate_module_if_necessary(self, module_);
-
-        module_.for_each_local_child(|_, _, child_node| {
-            match child_node.module() {
-                None => {
-                    // Continue.
-                }
-                Some(child_module) => {
-                    self.report_unresolved_imports(child_module);
-                }
-            }
-        });
-
-        for (_, module_) in module_.anonymous_children.borrow().iter() {
+        for (_, module_) in module_.module_children.borrow().iter() {
             self.report_unresolved_imports(module_);
         }
     }
@@ -1677,32 +1650,14 @@ fn report_unresolved_imports(&mut self, module_: Module<'a>) {
     // 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)
+    fn with_scope<F>(&mut self, id: NodeId, 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);
-
-                if let Success(name_binding) = orig_module.resolve_name(name, TypeNS, false) {
-                    match name_binding.module() {
-                        None => {
-                            debug!("!!! (with scope) didn't find module for `{}` in `{}`",
-                                   name,
-                                   module_to_string(orig_module));
-                        }
-                        Some(module) => {
-                            self.current_module = module;
-                        }
-                    }
-                }
-            }
+        if let Some(module) = orig_module.module_children.borrow().get(&id) {
+            self.current_module = module;
         }
 
         f(self);
@@ -1771,7 +1726,7 @@ fn resolve_item(&mut self, item: &Item) {
             ItemImpl(_, _, ref generics, ref opt_trait_ref, ref self_type, ref impl_items) => {
                 self.resolve_implementation(generics,
                                             opt_trait_ref,
-                                            &**self_type,
+                                            &self_type,
                                             item.id,
                                             impl_items);
             }
@@ -1826,7 +1781,7 @@ fn resolve_item(&mut self, item: &Item) {
             }
 
             ItemMod(_) | ItemForeignMod(_) => {
-                self.with_scope(Some(name), |this| {
+                self.with_scope(item.id, |this| {
                     intravisit::walk_item(this, item);
                 });
             }
@@ -1966,9 +1921,9 @@ fn resolve_function(&mut self, rib_kind: RibKind<'a>, declaration: &FnDecl, bloc
         // 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.resolve_pattern(&argument.pat, ArgumentIrrefutableMode, &mut bindings_list);
 
-            self.visit_ty(&*argument.ty);
+            self.visit_ty(&argument.ty);
 
             debug!("(resolving function) recorded argument");
         }
@@ -1998,7 +1953,7 @@ fn resolve_trait_reference(&mut self,
                 let mut err =
                     resolve_struct_error(self,
                                   trait_path.span,
-                                  ResolutionError::IsNotATrait(&*path_names_to_string(trait_path,
+                                  ResolutionError::IsNotATrait(&path_names_to_string(trait_path,
                                                                                       path_depth)));
 
                 // If it's a typedef, give a note
@@ -2010,10 +1965,28 @@ fn resolve_trait_reference(&mut self,
                 Err(())
             }
         } else {
-            resolve_error(self,
-                          trait_path.span,
-                          ResolutionError::UndeclaredTraitName(&*path_names_to_string(trait_path,
-                                                                                      path_depth)));
+
+            // find possible candidates
+            let trait_name = trait_path.segments.last().unwrap().identifier.name;
+            let candidates =
+                self.lookup_candidates(
+                    trait_name,
+                    TypeNS,
+                    |def| match def {
+                        Def::Trait(_) => true,
+                        _             => false,
+                    },
+                );
+
+            // create error object
+            let name = &path_names_to_string(trait_path, path_depth);
+            let error =
+                ResolutionError::UndeclaredTraitName(
+                    name,
+                    candidates,
+                );
+
+            resolve_error(self, trait_path.span, error);
             Err(())
         }
     }
@@ -2166,7 +2139,7 @@ fn check_trait_item<F>(&self, name: Name, span: Span, err: F)
         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));
+                resolve_error(self, span, err(name, &path_str));
             }
         }
     }
@@ -2179,7 +2152,7 @@ fn resolve_local(&mut self, local: &Local) {
         walk_list!(self, visit_expr, &local.init);
 
         // Resolve the pattern.
-        self.resolve_pattern(&*local.pat, LocalIrrefutableMode, &mut HashMap::new());
+        self.resolve_pattern(&local.pat, LocalIrrefutableMode, &mut HashMap::new());
     }
 
     // build a map from pattern identifiers to binding-info's.
@@ -2205,9 +2178,9 @@ fn check_consistent_bindings(&mut self, arm: &Arm) {
         if arm.pats.is_empty() {
             return;
         }
-        let map_0 = self.binding_mode_map(&*arm.pats[0]);
+        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);
+            let map_i = self.binding_mode_map(&p);
 
             for (&key, &binding_0) in &map_0 {
                 match map_i.get(&key) {
@@ -2242,7 +2215,7 @@ fn resolve_arm(&mut self, arm: &Arm) {
 
         let mut bindings_list = HashMap::new();
         for pattern in &arm.pats {
-            self.resolve_pattern(&**pattern, RefutableMode, &mut bindings_list);
+            self.resolve_pattern(&pattern, RefutableMode, &mut bindings_list);
         }
 
         // This has to happen *after* we determine which
@@ -2250,7 +2223,7 @@ fn resolve_arm(&mut self, arm: &Arm) {
         self.check_consistent_bindings(arm);
 
         walk_list!(self, visit_expr, &arm.guard);
-        self.visit_expr(&*arm.body);
+        self.visit_expr(&arm.body);
 
         if !self.resolved {
             self.value_ribs.pop();
@@ -2262,7 +2235,7 @@ fn resolve_block(&mut self, block: &Block) {
         // Move down in the graph, if there's an anonymous module rooted here.
         let orig_module = self.current_module;
         let anonymous_module =
-            orig_module.anonymous_children.borrow().get(&block.id).map(|module| *module);
+            orig_module.module_children.borrow().get(&block.id).map(|module| *module);
 
         if let Some(anonymous_module) = anonymous_module {
             debug!("(resolving block) found anonymous module, moving down");
@@ -2337,13 +2310,33 @@ fn resolve_type(&mut self, ty: &Ty) {
                                           ty.span,
                                           ResolutionError::SelfUsedOutsideImplOrTrait);
                         } else {
-                            resolve_error(self,
-                                          ty.span,
-                                          ResolutionError::UseOfUndeclared(
-                                                                    kind,
-                                                                    &*path_names_to_string(path,
-                                                                                           0))
-                                         );
+                            let segment = path.segments.last();
+                            let segment = segment.expect("missing name in path");
+                            let type_name = segment.identifier.name;
+
+                            let candidates =
+                                self.lookup_candidates(
+                                    type_name,
+                                    TypeNS,
+                                    |def| match def {
+                                        Def::Trait(_) |
+                                        Def::Enum(_) |
+                                        Def::Struct(_) |
+                                        Def::TyAlias(_) => true,
+                                        _               => false,
+                                    },
+                                );
+
+                            // create error object
+                            let name = &path_names_to_string(path, 0);
+                            let error =
+                                ResolutionError::UseOfUndeclared(
+                                    kind,
+                                    name,
+                                    candidates,
+                                );
+
+                            resolve_error(self, ty.span, error);
                         }
                     }
                 }
@@ -2363,8 +2356,8 @@ fn resolve_pattern(&mut self,
         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
+                PatKind::Ident(binding_mode, ref path1, ref at_rhs) => {
+                    // The meaning of PatKind::Ident 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
@@ -2475,7 +2468,7 @@ fn resolve_pattern(&mut self,
                     }
                 }
 
-                PatEnum(ref path, _) => {
+                PatKind::TupleStruct(ref path, _) | PatKind::Path(ref path) => {
                     // This must be an enum variant, struct or const.
                     let resolution = match self.resolve_possibly_assoc_item(pat_id,
                                                                             None,
@@ -2483,16 +2476,13 @@ fn resolve_pattern(&mut self,
                                                                             ValueNS,
                                                                             false) {
                         // The below shouldn't happen because all
-                        // qualified paths should be in PatQPath.
+                        // qualified paths should be in PatKind::QPath.
                         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"),
+                                                  "resolve_possibly_assoc_item claimed that a path \
+                                                   in PatKind::Path or PatKind::TupleStruct \
+                                                   requires typecheck to resolve, but qualified \
+                                                   paths should be PatKind::QPath"),
                         ResolveAttempt(resolution) => resolution,
                     };
                     if let Some(path_res) = resolution {
@@ -2551,7 +2541,7 @@ fn resolve_pattern(&mut self,
                     intravisit::walk_path(self, path);
                 }
 
-                PatQPath(ref qself, ref path) => {
+                PatKind::QPath(ref qself, ref path) => {
                     // Associated constants only.
                     let resolution = match self.resolve_possibly_assoc_item(pat_id,
                                                                             Some(qself),
@@ -2606,7 +2596,7 @@ fn resolve_pattern(&mut self,
                     intravisit::walk_pat(self, pattern);
                 }
 
-                PatStruct(ref path, _, _) => {
+                PatKind::Struct(ref path, _, _) => {
                     match self.resolve_path(pat_id, path, 0, TypeNS, false) {
                         Some(definition) => {
                             self.record_def(pattern.id, definition);
@@ -2617,7 +2607,7 @@ fn resolve_pattern(&mut self,
                                 self,
                                 path.span,
                                 ResolutionError::DoesNotNameAStruct(
-                                    &*path_names_to_string(path, 0))
+                                    &path_names_to_string(path, 0))
                             );
                             self.record_def(pattern.id, err_path_resolution());
                         }
@@ -2625,7 +2615,7 @@ fn resolve_pattern(&mut self,
                     intravisit::walk_path(self, path);
                 }
 
-                PatLit(_) | PatRange(..) => {
+                PatKind::Lit(_) | PatKind::Range(..) => {
                     intravisit::walk_pat(self, pattern);
                 }
 
@@ -2673,7 +2663,7 @@ fn resolve_bare_identifier_pattern(&mut self,
             Failed(err) => {
                 match err {
                     Some((span, msg)) => {
-                        resolve_error(self, span, ResolutionError::FailedToResolve(&*msg));
+                        resolve_error(self, span, ResolutionError::FailedToResolve(&msg));
                     }
                     None => (),
                 }
@@ -2805,7 +2795,7 @@ fn resolve_identifier(&mut self,
         match self.resolve_item_in_lexical_scope(module, name, namespace, record_used) {
             Success(binding) => binding.def().map(LocalDef::from_def),
             Failed(Some((span, msg))) => {
-                resolve_error(self, span, ResolutionError::FailedToResolve(&*msg));
+                resolve_error(self, span, ResolutionError::FailedToResolve(&msg));
                 None
             }
             _ => None,
@@ -2928,7 +2918,7 @@ fn resolve_module_relative_path(&mut self,
                     }
                 };
 
-                resolve_error(self, span, ResolutionError::FailedToResolve(&*msg));
+                resolve_error(self, span, ResolutionError::FailedToResolve(&msg));
                 return None;
             }
             Indeterminate => return None,
@@ -2983,7 +2973,7 @@ fn resolve_crate_relative_path(&mut self,
                     }
                 };
 
-                resolve_error(self, span, ResolutionError::FailedToResolve(&*msg));
+                resolve_error(self, span, ResolutionError::FailedToResolve(&msg));
                 return None;
             }
 
@@ -3065,8 +3055,8 @@ fn extract_path_and_node_id(t: &Ty,
                                     -> 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),
+                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.
@@ -3184,7 +3174,7 @@ fn find_best_match(&mut self, name: &str) -> SuggestionType {
                     .flat_map(|rib| rib.bindings.keys());
 
         if let Some(found) = find_best_match_for_name(names, name, None) {
-            if name != &*found {
+            if name != found {
                 return SuggestionType::Function(found);
             }
         } SuggestionType::NotFound
@@ -3230,7 +3220,7 @@ fn resolve_expr(&mut self, expr: &Expr) {
 
                         let mut err = resolve_struct_error(self,
                                         expr.span,
-                                        ResolutionError::StructVariantUsedAsFunction(&*path_name));
+                                        ResolutionError::StructVariantUsedAsFunction(&path_name));
 
                         let msg = format!("did you mean to write: `{} {{ /* fields */ }}`?",
                                           path_name);
@@ -3271,7 +3261,7 @@ fn resolve_expr(&mut self, expr: &Expr) {
                         Some(Def::Struct(..)) => {
                             let mut err = resolve_struct_error(self,
                                 expr.span,
-                                ResolutionError::StructVariantUsedAsFunction(&*path_name));
+                                ResolutionError::StructVariantUsedAsFunction(&path_name));
 
                             let msg = format!("did you mean to write: `{} {{ /* fields */ }}`?",
                                               path_name);
@@ -3347,7 +3337,7 @@ fn resolve_expr(&mut self, expr: &Expr) {
                                 resolve_error(self,
                                               expr.span,
                                               ResolutionError::UnresolvedName(
-                                                  &*path_name, &*msg, context));
+                                                  &path_name, &msg, context));
                             }
                         }
                     }
@@ -3368,7 +3358,7 @@ fn resolve_expr(&mut self, expr: &Expr) {
                         resolve_error(self,
                                       path.span,
                                       ResolutionError::DoesNotNameAStruct(
-                                                                &*path_names_to_string(path, 0))
+                                                                &path_names_to_string(path, 0))
                                      );
                         self.record_def(expr.id, err_path_resolution());
                     }
@@ -3501,6 +3491,99 @@ fn add_trait_info(found_traits: &mut Vec<DefId>, trait_def_id: DefId, name: Name
         found_traits
     }
 
+    /// When name resolution fails, this method can be used to look up candidate
+    /// entities with the expected name. It allows filtering them using the
+    /// supplied predicate (which should be used to only accept the types of
+    /// definitions expected e.g. traits). The lookup spans across all crates.
+    ///
+    /// NOTE: The method does not look into imports, but this is not a problem,
+    /// since we report the definitions (thus, the de-aliased imports).
+    fn lookup_candidates<FilterFn>(&mut self,
+                                   lookup_name: Name,
+                                   namespace: Namespace,
+                                   filter_fn: FilterFn) -> SuggestedCandidates
+        where FilterFn: Fn(Def) -> bool {
+
+        let mut lookup_results = Vec::new();
+        let mut worklist = Vec::new();
+        worklist.push((self.graph_root, Vec::new(), false));
+
+        while let Some((in_module,
+                        path_segments,
+                        in_module_is_extern)) = worklist.pop() {
+            build_reduced_graph::populate_module_if_necessary(self, &in_module);
+
+            in_module.for_each_child(|name, ns, name_binding| {
+
+                // avoid imports entirely
+                if name_binding.is_import() { return; }
+
+                // collect results based on the filter function
+                if let Some(def) = name_binding.def() {
+                    if name == lookup_name && ns == namespace && filter_fn(def) {
+                        // create the path
+                        let ident = hir::Ident::from_name(name);
+                        let params = PathParameters::none();
+                        let segment = PathSegment {
+                            identifier: ident,
+                            parameters: params,
+                        };
+                        let span = name_binding.span.unwrap_or(syntax::codemap::DUMMY_SP);
+                        let mut segms = path_segments.clone();
+                        segms.push(segment);
+                        let segms = HirVec::from_vec(segms);
+                        let path = Path {
+                            span: span,
+                            global: true,
+                            segments: segms,
+                        };
+                        // the entity is accessible in the following cases:
+                        // 1. if it's defined in the same crate, it's always
+                        // accessible (since private entities can be made public)
+                        // 2. if it's defined in another crate, it's accessible
+                        // only if both the module is public and the entity is
+                        // declared as public (due to pruning, we don't explore
+                        // outside crate private modules => no need to check this)
+                        if !in_module_is_extern || name_binding.is_public() {
+                            lookup_results.push(path);
+                        }
+                    }
+                }
+
+                // collect submodules to explore
+                if let Some(module) = name_binding.module() {
+                    // form the path
+                    let path_segments = match module.parent_link {
+                        NoParentLink => path_segments.clone(),
+                        ModuleParentLink(_, name) => {
+                            let mut paths = path_segments.clone();
+                            let ident = hir::Ident::from_name(name);
+                            let params = PathParameters::none();
+                            let segm = PathSegment {
+                                identifier: ident,
+                                parameters: params,
+                            };
+                            paths.push(segm);
+                            paths
+                        }
+                        _ => unreachable!(),
+                    };
+
+                    if !in_module_is_extern || name_binding.is_public() {
+                        // add the module to the lookup
+                        let is_extern = in_module_is_extern || module.is_extern_crate;
+                        worklist.push((module, path_segments, is_extern));
+                    }
+                }
+            })
+        }
+
+        SuggestedCandidates {
+            name: lookup_name.as_str().to_string(),
+            candidates: lookup_results,
+        }
+    }
+
     fn record_def(&mut self, node_id: NodeId, resolution: PathResolution) {
         debug!("(recording def) recording {:?} for {}", resolution, node_id);
         assert!(match resolution.last_private {
@@ -3556,11 +3639,72 @@ fn path_names_to_string(path: &Path, depth: usize) -> String {
     names_to_string(&names[..])
 }
 
+/// When an entity with a given name is not available in scope, we search for
+/// entities with that name in all crates. This method allows outputting the
+/// results of this search in a programmer-friendly way
+fn show_candidates(session: &mut DiagnosticBuilder,
+                   span: syntax::codemap::Span,
+                   candidates: &SuggestedCandidates) {
+
+    let paths = &candidates.candidates;
+
+    if paths.len() > 0 {
+        // don't show more than MAX_CANDIDATES results, so
+        // we're consistent with the trait suggestions
+        const MAX_CANDIDATES: usize = 5;
+
+        // we want consistent results across executions, but candidates are produced
+        // by iterating through a hash map, so make sure they are ordered:
+        let mut path_strings: Vec<_> = paths.into_iter()
+                                            .map(|p| path_names_to_string(&p, 0))
+                                            .collect();
+        path_strings.sort();
+
+        // behave differently based on how many candidates we have:
+        if !paths.is_empty() {
+            if paths.len() == 1 {
+                session.fileline_help(
+                    span,
+                    &format!("you can to import it into scope: `use {};`.",
+                        &path_strings[0]),
+                );
+            } else {
+                session.fileline_help(span, "you can import several candidates \
+                    into scope (`use ...;`):");
+                let count = path_strings.len() as isize - MAX_CANDIDATES as isize + 1;
+
+                for (idx, path_string) in path_strings.iter().enumerate() {
+                    if idx == MAX_CANDIDATES - 1 && count > 1 {
+                        session.fileline_help(
+                            span,
+                            &format!("  and {} other candidates", count).to_string(),
+                        );
+                        break;
+                    } else {
+                        session.fileline_help(
+                            span,
+                            &format!("  `{}`", path_string).to_string(),
+                        );
+                    }
+                }
+            }
+        }
+    } else {
+        // nothing found:
+        session.fileline_help(
+            span,
+            &format!("no candidates by the name of `{}` found in your \
+            project; maybe you misspelled the name or forgot to import \
+            an external crate?", candidates.name.to_string()),
+        );
+    };
+}
+
 /// A somewhat inefficient routine to obtain the name of a module.
-fn module_to_string<'a>(module: Module<'a>) -> String {
+fn module_to_string(module: Module) -> String {
     let mut names = Vec::new();
 
-    fn collect_mod<'a>(names: &mut Vec<ast::Name>, module: Module<'a>) {
+    fn collect_mod(names: &mut Vec<ast::Name>, module: Module) {
         match module.parent_link {
             NoParentLink => {}
             ModuleParentLink(ref module, name) => {