]> git.lizzy.rs Git - rust.git/blobdiff - src/librustc_resolve/lib.rs
Auto merge of #53815 - F001:if-let-guard, r=petrochenkov
[rust.git] / src / librustc_resolve / lib.rs
index 9c23aeb41a3437485bedb9c27c4a0032a627296c..0f6a97423091796dc83d97866b4a8d238c99f4bc 100644 (file)
@@ -9,11 +9,12 @@
 // except according to those terms.
 
 #![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/")]
+       html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
+       html_root_url = "https://doc.rust-lang.org/nightly/")]
 
 #![feature(crate_visibility_modifier)]
 #![cfg_attr(not(stage0), feature(nll))]
+#![cfg_attr(not(stage0), feature(infer_outlives_requirements))]
 #![feature(rustc_diagnostic_macros)]
 #![feature(slice_sort_by_cached_key)]
 
@@ -35,7 +36,7 @@
 use self::RibKind::*;
 
 use rustc::hir::map::{Definitions, DefCollector};
-use rustc::hir::{self, PrimTy, TyBool, TyChar, TyFloat, TyInt, TyUint, TyStr};
+use rustc::hir::{self, PrimTy, Bool, Char, Float, Int, Uint, Str};
 use rustc::middle::cstore::CrateStore;
 use rustc::session::Session;
 use rustc::lint;
@@ -49,7 +50,7 @@
 use rustc_metadata::creader::CrateLoader;
 use rustc_metadata::cstore::CStore;
 
-use syntax::codemap::CodeMap;
+use syntax::source_map::SourceMap;
 use syntax::ext::hygiene::{Mark, Transparency, SyntaxContext};
 use syntax::ast::{self, Name, NodeId, Ident, FloatTy, IntTy, UintTy};
 use syntax::ext::base::SyntaxExtension;
@@ -69,7 +70,7 @@
 use syntax::ptr::P;
 
 use syntax_pos::{Span, DUMMY_SP, MultiSpan};
-use errors::{DiagnosticBuilder, DiagnosticId};
+use errors::{Applicability, DiagnosticBuilder, DiagnosticId};
 
 use std::cell::{Cell, RefCell};
 use std::cmp;
@@ -80,7 +81,7 @@
 use rustc_data_structures::sync::Lrc;
 
 use resolve_imports::{ImportDirective, ImportDirectiveSubclass, NameResolution, ImportResolver};
-use macros::{InvocationData, LegacyBinding, LegacyScope, MacroBinding};
+use macros::{InvocationData, LegacyBinding};
 
 // NB: This module needs to be declared first so diagnostics are
 // registered before they are used.
@@ -195,13 +196,13 @@ fn resolve_struct_error<'sess, 'a>(resolver: &'sess Resolver,
                                            "can't use type parameters from outer function");
             err.span_label(span, "use of type variable from outer function");
 
-            let cm = resolver.session.codemap();
+            let cm = resolver.session.source_map();
             match outer_def {
                 Def::SelfTy(_, maybe_impl_defid) => {
                     if let Some(impl_span) = maybe_impl_defid.map_or(None,
                             |def_id| resolver.definitions.opt_span(def_id)) {
                         err.span_label(reduce_impl_span_to_impl_keyword(cm, impl_span),
-                                    "`Self` type implicitely declared here, on the `impl`");
+                                    "`Self` type implicitly declared here, on the `impl`");
                     }
                 },
                 Def::TyParam(typaram_defid) => {
@@ -220,9 +221,12 @@ fn resolve_struct_error<'sess, 'a>(resolver: &'sess Resolver,
             let sugg_msg = "try using a local type parameter instead";
             if let Some((sugg_span, new_snippet)) = cm.generate_local_type_param_snippet(span) {
                 // Suggest the modification to the user
-                err.span_suggestion(sugg_span,
-                                    sugg_msg,
-                                    new_snippet);
+                err.span_suggestion_with_applicability(
+                    sugg_span,
+                    sugg_msg,
+                    new_snippet,
+                    Applicability::MachineApplicable,
+                );
             } else if let Some(sp) = cm.generate_fn_name_span(span) {
                 err.span_label(sp, "try adding a local type parameter in this method instead");
             } else {
@@ -414,8 +418,8 @@ fn resolve_struct_error<'sess, 'a>(resolver: &'sess Resolver,
 ///
 /// Attention: The method used is very fragile since it essentially duplicates the work of the
 /// parser. If you need to use this function or something similar, please consider updating the
-/// codemap functions and this function to something more robust.
-fn reduce_impl_span_to_impl_keyword(cm: &CodeMap, impl_span: Span) -> Span {
+/// source_map functions and this function to something more robust.
+fn reduce_impl_span_to_impl_keyword(cm: &SourceMap, impl_span: Span) -> Span {
     let impl_span = cm.span_until_char(impl_span, '<');
     let impl_span = cm.span_until_whitespace(impl_span);
     impl_span
@@ -539,7 +543,7 @@ fn is_expected(self, def: Def) -> bool {
                 Def::Trait(..) | Def::TyAlias(..) | Def::AssociatedTy(..) |
                 Def::PrimTy(..) | Def::TyParam(..) | Def::SelfTy(..) |
                 Def::Existential(..) |
-                Def::TyForeign(..) => true,
+                Def::ForeignTy(..) => true,
                 _ => false,
             },
             PathSource::Trait(AliasPossibility::No) => match def {
@@ -822,11 +826,12 @@ fn visit_generics(&mut self, generics: &'tcx Generics) {
             .filter_map(|param| match param.kind {
                 GenericParamKind::Lifetime { .. } => None,
                 GenericParamKind::Type { ref default, .. } => {
-                    if found_default || default.is_some() {
-                        found_default = true;
-                        return Some((Ident::with_empty_ctxt(param.ident.name), Def::Err));
+                    found_default |= default.is_some();
+                    if found_default {
+                        Some((Ident::with_empty_ctxt(param.ident.name), Def::Err))
+                    } else {
+                        None
                     }
-                    None
                 }
             }));
 
@@ -1279,23 +1284,23 @@ impl PrimitiveTypeTable {
     fn new() -> PrimitiveTypeTable {
         let mut table = PrimitiveTypeTable { primitive_types: FxHashMap() };
 
-        table.intern("bool", TyBool);
-        table.intern("char", TyChar);
-        table.intern("f32", TyFloat(FloatTy::F32));
-        table.intern("f64", TyFloat(FloatTy::F64));
-        table.intern("isize", TyInt(IntTy::Isize));
-        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("i128", TyInt(IntTy::I128));
-        table.intern("str", TyStr);
-        table.intern("usize", TyUint(UintTy::Usize));
-        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.intern("u128", TyUint(UintTy::U128));
+        table.intern("bool", Bool);
+        table.intern("char", Char);
+        table.intern("f32", Float(FloatTy::F32));
+        table.intern("f64", Float(FloatTy::F64));
+        table.intern("isize", Int(IntTy::Isize));
+        table.intern("i8", Int(IntTy::I8));
+        table.intern("i16", Int(IntTy::I16));
+        table.intern("i32", Int(IntTy::I32));
+        table.intern("i64", Int(IntTy::I64));
+        table.intern("i128", Int(IntTy::I128));
+        table.intern("str", Str);
+        table.intern("usize", Uint(UintTy::Usize));
+        table.intern("u8", Uint(UintTy::U8));
+        table.intern("u16", Uint(UintTy::U16));
+        table.intern("u32", Uint(UintTy::U32));
+        table.intern("u64", Uint(UintTy::U64));
+        table.intern("u128", Uint(UintTy::U128));
         table
     }
 
@@ -1398,24 +1403,19 @@ pub struct Resolver<'a, 'b: 'a> {
     proc_mac_errors: Vec<macros::ProcMacError>,
     /// crate-local macro expanded `macro_export` referred to by a module-relative path
     macro_expanded_macro_export_errors: BTreeSet<(Span, Span)>,
-
-    gated_errors: FxHashSet<Span>,
+    /// macro-expanded `macro_rules` shadowing existing macros
     disallowed_shadowing: Vec<&'a LegacyBinding<'a>>,
 
     arenas: &'a ResolverArenas<'a>,
     dummy_binding: &'a NameBinding<'a>,
-    /// true if `#![feature(use_extern_macros)]`
-    use_extern_macros: bool,
 
     crate_loader: &'a mut CrateLoader<'b>,
     macro_names: FxHashSet<Ident>,
     macro_prelude: FxHashMap<Name, &'a NameBinding<'a>>,
     pub all_macros: FxHashMap<Name, Def>,
-    lexical_macro_resolutions: Vec<(Ident, &'a Cell<LegacyScope<'a>>)>,
     macro_map: FxHashMap<DefId, Lrc<SyntaxExtension>>,
     macro_defs: FxHashMap<Mark, DefId>,
     local_macro_def_scopes: FxHashMap<NodeId, Module<'a>>,
-    macro_exports: Vec<Export>, // FIXME: Remove when `use_extern_macros` is stabilized
     pub whitelisted_legacy_custom_derives: Vec<Name>,
     pub found_unresolved_macro: bool,
 
@@ -1657,8 +1657,6 @@ pub fn new(session: &'a Session,
         invocations.insert(Mark::root(),
                            arenas.alloc_invocation_data(InvocationData::root(graph_root)));
 
-        let features = session.features_untracked();
-
         let mut macro_defs = FxHashMap();
         macro_defs.insert(Mark::root(), root_def_id);
 
@@ -1717,7 +1715,6 @@ pub fn new(session: &'a Session,
             ambiguity_errors: Vec::new(),
             use_injections: Vec::new(),
             proc_mac_errors: Vec::new(),
-            gated_errors: FxHashSet(),
             disallowed_shadowing: Vec::new(),
             macro_expanded_macro_export_errors: BTreeSet::new(),
 
@@ -1729,15 +1726,11 @@ pub fn new(session: &'a Session,
                 vis: ty::Visibility::Public,
             }),
 
-            use_extern_macros: features.use_extern_macros(),
-
             crate_loader,
             macro_names: FxHashSet(),
             macro_prelude: FxHashMap(),
             all_macros: FxHashMap(),
-            lexical_macro_resolutions: Vec::new(),
             macro_map: FxHashMap(),
-            macro_exports: Vec::new(),
             invocations,
             macro_defs,
             local_macro_def_scopes: FxHashMap(),
@@ -1770,9 +1763,7 @@ pub fn arenas() -> ResolverArenas<'a> {
     fn per_ns<F: FnMut(&mut Self, Namespace)>(&mut self, mut f: F) {
         f(self, TypeNS);
         f(self, ValueNS);
-        if self.use_extern_macros {
-            f(self, MacroNS);
-        }
+        f(self, MacroNS);
     }
 
     fn macro_def(&self, mut ctxt: SyntaxContext) -> DefId {
@@ -1833,7 +1824,7 @@ fn record_use(&mut self, ident: Ident, ns: Namespace, binding: &'a NameBinding<'
 
     fn add_to_glob_map(&mut self, id: NodeId, ident: Ident) {
         if self.make_glob_map {
-            self.glob_map.entry(id).or_insert_with(FxHashSet).insert(ident.name);
+            self.glob_map.entry(id).or_default().insert(ident.name);
         }
     }
 
@@ -1914,12 +1905,13 @@ fn resolve_ident_in_lexical_scope(&mut self,
         }
 
         ident.span = ident.span.modern();
+        let mut poisoned = None;
         loop {
-            let (opt_module, poisoned) = if let Some(node_id) = record_used_id {
+            let opt_module = if let Some(node_id) = record_used_id {
                 self.hygienic_lexical_parent_with_compatibility_fallback(module, &mut ident.span,
-                                                                         node_id)
+                                                                         node_id, &mut poisoned)
             } else {
-                (self.hygienic_lexical_parent(module, &mut ident.span), None)
+                self.hygienic_lexical_parent(module, &mut ident.span)
             };
             module = unwrap_or!(opt_module, break);
             let orig_current_module = self.current_module;
@@ -1947,7 +1939,6 @@ fn resolve_ident_in_lexical_scope(&mut self,
                     }
                     return Some(LexicalScopeBinding::Item(binding))
                 }
-                _ if poisoned.is_some() => break,
                 Err(Determined) => continue,
                 Err(Undetermined) =>
                     span_bug!(ident.span, "undetermined resolution during main resolution pass"),
@@ -2012,12 +2003,12 @@ fn hygienic_lexical_parent(&mut self, module: Module<'a>, span: &mut Span)
         None
     }
 
-    fn hygienic_lexical_parent_with_compatibility_fallback(
-        &mut self, module: Module<'a>, span: &mut Span, node_id: NodeId
-    ) -> (Option<Module<'a>>, /* poisoned */ Option<NodeId>)
-    {
+    fn hygienic_lexical_parent_with_compatibility_fallback(&mut self, module: Module<'a>,
+                                                           span: &mut Span, node_id: NodeId,
+                                                           poisoned: &mut Option<NodeId>)
+                                                           -> Option<Module<'a>> {
         if let module @ Some(..) = self.hygienic_lexical_parent(module, span) {
-            return (module, None);
+            return module;
         }
 
         // We need to support the next case under a deprecation warning
@@ -2038,13 +2029,14 @@ fn hygienic_lexical_parent_with_compatibility_fallback(
                 // The macro is a proc macro derive
                 if module.expansion.looks_like_proc_macro_derive() {
                     if parent.expansion.is_descendant_of(span.ctxt().outer()) {
-                        return (module.parent, Some(node_id));
+                        *poisoned = Some(node_id);
+                        return module.parent;
                     }
                 }
             }
         }
 
-        (None, None)
+        None
     }
 
     fn resolve_ident_in_module(&mut self,
@@ -2191,20 +2183,29 @@ fn search_label<P, R>(&self, mut ident: Ident, pred: P) -> Option<R>
 
     fn resolve_item(&mut self, item: &Item) {
         let name = item.ident.name;
-
         debug!("(resolving item) resolving {}", name);
 
-        self.check_proc_macro_attrs(&item.attrs);
-
         match item.node {
-            ItemKind::Enum(_, ref generics) |
             ItemKind::Ty(_, ref generics) |
-            ItemKind::Existential(_, ref generics) |
-            ItemKind::Struct(_, ref generics) |
-            ItemKind::Union(_, ref generics) |
-            ItemKind::Fn(_, _, ref generics, _) => {
+            ItemKind::Fn(_, _, ref generics, _) |
+            ItemKind::Existential(_, ref generics) => {
                 self.with_type_parameter_rib(HasTypeParameters(generics, ItemRibKind),
-                                         |this| visit::walk_item(this, item));
+                                             |this| visit::walk_item(this, item));
+            }
+
+            ItemKind::Enum(_, ref generics) |
+            ItemKind::Struct(_, ref generics) |
+            ItemKind::Union(_, ref generics) => {
+                self.with_type_parameter_rib(HasTypeParameters(generics, ItemRibKind), |this| {
+                    let item_def_id = this.definitions.local_def_id(item.id);
+                    if this.session.features_untracked().self_in_typedefs {
+                        this.with_self_rib(Def::SelfTy(None, Some(item_def_id)), |this| {
+                            visit::walk_item(this, item);
+                        });
+                    } else {
+                        visit::walk_item(this, item);
+                    }
+                });
             }
 
             ItemKind::Impl(.., ref generics, ref opt_trait_ref, ref self_type, ref impl_items) =>
@@ -2223,8 +2224,6 @@ fn resolve_item(&mut self, item: &Item) {
                         walk_list!(this, visit_param_bound, bounds);
 
                         for trait_item in trait_items {
-                            this.check_proc_macro_attrs(&trait_item.attrs);
-
                             let type_parameters = HasTypeParameters(&trait_item.generics,
                                                                     TraitOrImplItemRibKind);
                             this.with_type_parameter_rib(type_parameters, |this| {
@@ -2351,28 +2350,30 @@ fn with_type_parameter_rib<'b, F>(&'b mut self, type_parameters: TypeParameters<
             HasTypeParameters(generics, rib_kind) => {
                 let mut function_type_rib = Rib::new(rib_kind);
                 let mut seen_bindings = FxHashMap();
-                generics.params.iter().for_each(|param| match param.kind {
-                    GenericParamKind::Lifetime { .. } => {}
-                    GenericParamKind::Type { .. } => {
-                        let ident = param.ident.modern();
-                        debug!("with_type_parameter_rib: {}", param.id);
-
-                        if seen_bindings.contains_key(&ident) {
-                            let span = seen_bindings.get(&ident).unwrap();
-                            let err = ResolutionError::NameAlreadyUsedInTypeParameterList(
-                                ident.name,
-                                span,
-                            );
-                            resolve_error(self, param.ident.span, err);
-                        }
-                        seen_bindings.entry(ident).or_insert(param.ident.span);
+                for param in &generics.params {
+                    match param.kind {
+                        GenericParamKind::Lifetime { .. } => {}
+                        GenericParamKind::Type { .. } => {
+                            let ident = param.ident.modern();
+                            debug!("with_type_parameter_rib: {}", param.id);
+
+                            if seen_bindings.contains_key(&ident) {
+                                let span = seen_bindings.get(&ident).unwrap();
+                                let err = ResolutionError::NameAlreadyUsedInTypeParameterList(
+                                    ident.name,
+                                    span,
+                                );
+                                resolve_error(self, param.ident.span, err);
+                            }
+                            seen_bindings.entry(ident).or_insert(param.ident.span);
 
-                    // Plain insert (no renaming).
-                    let def = Def::TyParam(self.definitions.local_def_id(param.id));
-                        function_type_rib.bindings.insert(ident, def);
-                        self.record_def(param.id, PathResolution::new(def));
+                        // Plain insert (no renaming).
+                        let def = Def::TyParam(self.definitions.local_def_id(param.id));
+                            function_type_rib.bindings.insert(ident, def);
+                            self.record_def(param.id, PathResolution::new(def));
+                        }
                     }
-                });
+                }
                 self.ribs[TypeNS].push(function_type_rib);
             }
 
@@ -2494,16 +2495,16 @@ fn resolve_implementation(&mut self,
                     let item_def_id = this.definitions.local_def_id(item_id);
                     this.with_self_rib(Def::SelfTy(trait_id, Some(item_def_id)), |this| {
                         if let Some(trait_ref) = opt_trait_reference.as_ref() {
-                            // Resolve type arguments in trait path
+                            // Resolve type arguments in the trait path.
                             visit::walk_trait_ref(this, trait_ref);
                         }
                         // Resolve the self type.
                         this.visit_ty(self_type);
                         // Resolve the type parameters.
                         this.visit_generics(generics);
+                        // Resolve the items within the impl.
                         this.with_current_self_type(self_type, |this| {
                             for impl_item in impl_items {
-                                this.check_proc_macro_attrs(&impl_item.attrs);
                                 this.resolve_visibility(&impl_item.vis);
 
                                 // We also need a new scope for the impl item type parameters.
@@ -2516,8 +2517,8 @@ fn resolve_implementation(&mut self,
                                             // If this is a trait impl, ensure the const
                                             // exists in trait
                                             this.check_trait_item(impl_item.ident,
-                                                                ValueNS,
-                                                                impl_item.span,
+                                                                  ValueNS,
+                                                                  impl_item.span,
                                                 |n, s| ConstNotMemberOfTrait(n, s));
                                             this.with_constant_rib(|this|
                                                 visit::walk_impl_item(this, impl_item)
@@ -2527,8 +2528,8 @@ fn resolve_implementation(&mut self,
                                             // If this is a trait impl, ensure the method
                                             // exists in trait
                                             this.check_trait_item(impl_item.ident,
-                                                                ValueNS,
-                                                                impl_item.span,
+                                                                  ValueNS,
+                                                                  impl_item.span,
                                                 |n, s| MethodNotMemberOfTrait(n, s));
 
                                             visit::walk_impl_item(this, impl_item);
@@ -2537,8 +2538,8 @@ fn resolve_implementation(&mut self,
                                             // If this is a trait impl, ensure the type
                                             // exists in trait
                                             this.check_trait_item(impl_item.ident,
-                                                                TypeNS,
-                                                                impl_item.span,
+                                                                  TypeNS,
+                                                                  impl_item.span,
                                                 |n, s| TypeNotMemberOfTrait(n, s));
 
                                             this.visit_ty(ty);
@@ -2547,8 +2548,8 @@ fn resolve_implementation(&mut self,
                                             // If this is a trait impl, ensure the type
                                             // exists in trait
                                             this.check_trait_item(impl_item.ident,
-                                                                TypeNS,
-                                                                impl_item.span,
+                                                                  TypeNS,
+                                                                  impl_item.span,
                                                 |n, s| TypeNotMemberOfTrait(n, s));
 
                                             for bound in bounds {
@@ -2700,7 +2701,10 @@ fn resolve_arm(&mut self, arm: &Arm) {
         // This has to happen *after* we determine which pat_idents are variants
         self.check_consistent_bindings(&arm.pats);
 
-        walk_list!(self, visit_expr, &arm.guard);
+        match arm.guard {
+            Some(ast::Guard::If(ref expr)) => self.visit_expr(expr),
+            _ => {}
+        }
         self.visit_expr(&arm.body);
 
         self.ribs[ValueNS].pop();
@@ -2973,7 +2977,12 @@ fn smart_resolve_path_fragment(&mut self,
             if is_self_type(path, ns) {
                 __diagnostic_used!(E0411);
                 err.code(DiagnosticId::Error("E0411".into()));
-                err.span_label(span, "`Self` is only available in traits and impls");
+                let available_in = if this.session.features_untracked().self_in_typedefs {
+                    "impls, traits, and type definitions"
+                } else {
+                    "traits and impls"
+                };
+                err.span_label(span, format!("`Self` is only available in {}", available_in));
                 return (err, Vec::new());
             }
             if is_self_value(path, ns) {
@@ -3001,8 +3010,12 @@ fn smart_resolve_path_fragment(&mut self,
                                         enum_path);
                         err.help(&msg);
                     } else {
-                        err.span_suggestion(span, "you can try using the variant's enum",
-                                            enum_path);
+                        err.span_suggestion_with_applicability(
+                            span,
+                            "you can try using the variant's enum",
+                            enum_path,
+                            Applicability::MachineApplicable,
+                        );
                     }
                 }
             }
@@ -3011,20 +3024,32 @@ fn smart_resolve_path_fragment(&mut self,
                     let self_is_available = this.self_value_is_available(path[0].span, span);
                     match candidate {
                         AssocSuggestion::Field => {
-                            err.span_suggestion(span, "try",
-                                                format!("self.{}", path_str));
+                            err.span_suggestion_with_applicability(
+                                span,
+                                "try",
+                                format!("self.{}", path_str),
+                                Applicability::MachineApplicable,
+                            );
                             if !self_is_available {
                                 err.span_label(span, format!("`self` value is only available in \
                                                                methods with `self` parameter"));
                             }
                         }
                         AssocSuggestion::MethodWithSelf if self_is_available => {
-                            err.span_suggestion(span, "try",
-                                                format!("self.{}", path_str));
+                            err.span_suggestion_with_applicability(
+                                span,
+                                "try",
+                                format!("self.{}", path_str),
+                                Applicability::MachineApplicable,
+                            );
                         }
                         AssocSuggestion::MethodWithSelf | AssocSuggestion::AssocItem => {
-                            err.span_suggestion(span, "try",
-                                                format!("Self::{}", path_str));
+                            err.span_suggestion_with_applicability(
+                                span,
+                                "try",
+                                format!("Self::{}", path_str),
+                                Applicability::MachineApplicable,
+                            );
                         }
                     }
                     return (err, candidates);
@@ -3092,7 +3117,7 @@ fn smart_resolve_path_fragment(&mut self,
                             // parser issue where a struct literal is being used on an expression
                             // where a brace being opened means a block is being started. Look
                             // ahead for the next text to see if `span` is followed by a `{`.
-                            let cm = this.session.codemap();
+                            let cm = this.session.source_map();
                             let mut sp = span;
                             loop {
                                 sp = cm.next_point(sp);
@@ -3219,7 +3244,7 @@ fn type_ascription_suggestion(&self,
                                   err: &mut DiagnosticBuilder,
                                   base_span: Span) {
         debug!("type_ascription_suggetion {:?}", base_span);
-        let cm = self.session.codemap();
+        let cm = self.session.source_map();
         debug!("self.current_type_ascription {:?}", self.current_type_ascription);
         if let Some(sp) = self.current_type_ascription.last() {
             let mut sp = *sp;
@@ -3464,33 +3489,37 @@ fn resolve_path(
             let ns = if is_last { opt_ns.unwrap_or(TypeNS) } else { TypeNS };
             let name = ident.name;
 
-            if i == 0 && ns == TypeNS && name == keywords::SelfValue.name() {
-                let mut ctxt = ident.span.ctxt().modern();
-                module = Some(ModuleOrUniformRoot::Module(
-                    self.resolve_self(&mut ctxt, self.current_module)));
-                continue
-            } else if allow_super && ns == TypeNS && name == keywords::Super.name() {
-                let mut ctxt = ident.span.ctxt().modern();
-                let self_module_parent = match i {
-                    0 => self.resolve_self(&mut ctxt, self.current_module).parent,
-                    _ => match module {
-                        Some(ModuleOrUniformRoot::Module(module)) => module.parent,
-                        _ => None,
-                    },
-                };
-                if let Some(parent) = self_module_parent {
-                    module = Some(ModuleOrUniformRoot::Module(
-                        self.resolve_self(&mut ctxt, parent)));
-                    continue
-                } else {
+            allow_super &= ns == TypeNS &&
+                (name == keywords::SelfValue.name() ||
+                 name == keywords::Super.name());
+
+            if ns == TypeNS {
+                if allow_super && name == keywords::Super.name() {
+                    let mut ctxt = ident.span.ctxt().modern();
+                    let self_module = match i {
+                        0 => Some(self.resolve_self(&mut ctxt, self.current_module)),
+                        _ => match module {
+                            Some(ModuleOrUniformRoot::Module(module)) => Some(module),
+                            _ => None,
+                        },
+                    };
+                    if let Some(self_module) = self_module {
+                        if let Some(parent) = self_module.parent {
+                            module = Some(ModuleOrUniformRoot::Module(
+                                self.resolve_self(&mut ctxt, parent)));
+                            continue;
+                        }
+                    }
                     let msg = "There are too many initial `super`s.".to_string();
                     return PathResult::Failed(ident.span, msg, false);
                 }
-            }
-            allow_super = false;
-
-            if ns == TypeNS {
                 if i == 0 {
+                    if name == keywords::SelfValue.name() {
+                        let mut ctxt = ident.span.ctxt().modern();
+                        module = Some(ModuleOrUniformRoot::Module(
+                            self.resolve_self(&mut ctxt, self.current_module)));
+                        continue;
+                    }
                     if name == keywords::Extern.name() ||
                        name == keywords::CrateRoot.name() &&
                        self.session.features_untracked().extern_absolute_paths &&
@@ -3498,30 +3527,19 @@ fn resolve_path(
                         module = Some(ModuleOrUniformRoot::UniformRoot(name));
                         continue;
                     }
-                }
-                if (i == 0 && name == keywords::CrateRoot.name()) ||
-                   (i == 0 && name == keywords::Crate.name()) ||
-                   (i == 0 && name == keywords::DollarCrate.name()) ||
-                   (i == 1 && name == keywords::Crate.name() &&
-                              path[0].name == keywords::CrateRoot.name()) {
-                    // `::a::b`, `crate::a::b`, `::crate::a::b` or `$crate::a::b`
-                    module = Some(ModuleOrUniformRoot::Module(
-                        self.resolve_crate_root(ident)));
-                    continue
+                    if name == keywords::CrateRoot.name() ||
+                       name == keywords::Crate.name() ||
+                       name == keywords::DollarCrate.name() {
+                        // `::a::b`, `crate::a::b` or `$crate::a::b`
+                        module = Some(ModuleOrUniformRoot::Module(
+                            self.resolve_crate_root(ident)));
+                        continue;
+                    }
                 }
             }
 
             // Report special messages for path segment keywords in wrong positions.
-            if name == keywords::CrateRoot.name() && i != 0 ||
-               name == keywords::DollarCrate.name() && i != 0 ||
-               name == keywords::SelfValue.name() && i != 0 ||
-               name == keywords::SelfType.name() && i != 0 ||
-               name == keywords::Super.name() && i != 0 ||
-               name == keywords::Extern.name() && i != 0 ||
-               // we allow crate::foo and ::crate::foo but nothing else
-               name == keywords::Crate.name() && i > 1 &&
-                    path[0].name != keywords::CrateRoot.name() ||
-               name == keywords::Crate.name() && path.len() == 1 {
+            if ident.is_path_segment_keyword() && i != 0 {
                 let name_str = if name == keywords::CrateRoot.name() {
                     "crate root".to_string()
                 } else {
@@ -3540,7 +3558,7 @@ fn resolve_path(
             } else if opt_ns == Some(MacroNS) {
                 assert!(ns == TypeNS);
                 self.resolve_lexical_macro_path_segment(ident, ns, record_used, record_used,
-                                                        false, path_span).map(MacroBinding::binding)
+                                                        false, path_span).map(|(b, _)| b)
             } else {
                 let record_used_id =
                     if record_used { crate_lint.node_id().or(Some(CRATE_NODE_ID)) } else { None };
@@ -3735,14 +3753,14 @@ fn adjust_local_def(&mut self,
 
                             let seen = self.freevars_seen
                                            .entry(function_id)
-                                           .or_insert_with(|| NodeMap());
+                                           .or_default();
                             if let Some(&index) = seen.get(&node_id) {
                                 def = Def::Upvar(node_id, index, function_id);
                                 continue;
                             }
                             let vec = self.freevars
                                           .entry(function_id)
-                                          .or_insert_with(|| vec![]);
+                                          .or_default();
                             let depth = vec.len();
                             def = Def::Upvar(node_id, depth, function_id);
 
@@ -3910,7 +3928,7 @@ fn lookup_typo_candidate<FilterFn>(&mut self,
                 }
             }
             // Add primitive types to the mix
-            if filter_fn(Def::PrimTy(TyBool)) {
+            if filter_fn(Def::PrimTy(Bool)) {
                 names.extend(
                     self.primitive_type_table.primitive_types.iter().map(|(name, _)| name)
                 )
@@ -4481,6 +4499,42 @@ fn is_accessible_from(&self, vis: ty::Visibility, module: Module<'a>) -> bool {
         vis.is_accessible_from(module.normal_ancestor_id, self)
     }
 
+    fn report_ambiguity_error(
+        &self, name: Name, span: Span, _lexical: bool,
+        def1: Def, is_import1: bool, is_glob1: bool, from_expansion1: bool, span1: Span,
+        def2: Def, is_import2: bool, _is_glob2: bool, _from_expansion2: bool, span2: Span,
+    ) {
+        let participle = |is_import: bool| if is_import { "imported" } else { "defined" };
+        let msg1 = format!("`{}` could refer to the name {} here", name, participle(is_import1));
+        let msg2 =
+            format!("`{}` could also refer to the name {} here", name, participle(is_import2));
+        let note = if from_expansion1 {
+            Some(if let Def::Macro(..) = def1 {
+                format!("macro-expanded {} do not shadow",
+                        if is_import1 { "macro imports" } else { "macros" })
+            } else {
+                format!("macro-expanded {} do not shadow when used in a macro invocation path",
+                        if is_import1 { "imports" } else { "items" })
+            })
+        } else if is_glob1 {
+            Some(format!("consider adding an explicit import of `{}` to disambiguate", name))
+        } else {
+            None
+        };
+
+        let mut err = struct_span_err!(self.session, span, E0659, "`{}` is ambiguous", name);
+        err.span_note(span1, &msg1);
+        match def2 {
+            Def::Macro(..) if span2.is_dummy() =>
+                err.note(&format!("`{}` is also a builtin macro", name)),
+            _ => err.span_note(span2, &msg2),
+        };
+        if let Some(note) = note {
+            err.note(&note);
+        }
+        err.emit();
+    }
+
     fn report_errors(&mut self, krate: &Crate) {
         self.report_shadowing_errors();
         self.report_with_use_injections(krate);
@@ -4490,36 +4544,24 @@ fn report_errors(&mut self, krate: &Crate) {
         for &(span_use, span_def) in &self.macro_expanded_macro_export_errors {
             let msg = "macro-expanded `macro_export` macros from the current crate \
                        cannot be referred to by absolute paths";
-            self.session.struct_span_err(span_use, msg)
-                        .span_note(span_def, "the macro is defined here")
-                        .emit();
+            self.session.buffer_lint_with_diagnostic(
+                lint::builtin::MACRO_EXPANDED_MACRO_EXPORTS_ACCESSED_BY_ABSOLUTE_PATHS,
+                CRATE_NODE_ID, span_use, msg,
+                lint::builtin::BuiltinLintDiagnostics::
+                    MacroExpandedMacroExportsAccessedByAbsolutePaths(span_def),
+            );
         }
 
         for &AmbiguityError { span, name, b1, b2, lexical } in &self.ambiguity_errors {
-            if !reported_spans.insert(span) { continue }
-            let participle = |binding: &NameBinding| {
-                if binding.is_import() { "imported" } else { "defined" }
-            };
-            let msg1 = format!("`{}` could refer to the name {} here", name, participle(b1));
-            let msg2 = format!("`{}` could also refer to the name {} here", name, participle(b2));
-            let note = if b1.expansion == Mark::root() || !lexical && b1.is_glob_import() {
-                format!("consider adding an explicit import of `{}` to disambiguate", name)
-            } else if let Def::Macro(..) = b1.def() {
-                format!("macro-expanded {} do not shadow",
-                        if b1.is_import() { "macro imports" } else { "macros" })
-            } else {
-                format!("macro-expanded {} do not shadow when used in a macro invocation path",
-                        if b1.is_import() { "imports" } else { "items" })
-            };
-
-            let mut err = struct_span_err!(self.session, span, E0659, "`{}` is ambiguous", name);
-            err.span_note(b1.span, &msg1);
-            match b2.def() {
-                Def::Macro(..) if b2.span.is_dummy() =>
-                    err.note(&format!("`{}` is also a builtin macro", name)),
-                _ => err.span_note(b2.span, &msg2),
-            };
-            err.note(&note).emit();
+            if reported_spans.insert(span) {
+                self.report_ambiguity_error(
+                    name, span, lexical,
+                    b1.def(), b1.is_import(), b1.is_glob_import(),
+                    b1.expansion != Mark::root(), b1.span,
+                    b2.def(), b2.is_import(), b2.is_glob_import(),
+                    b2.expansion != Mark::root(), b2.span,
+                );
+            }
         }
 
         for &PrivacyError(span, name, binding) in &self.privacy_errors {
@@ -4539,10 +4581,6 @@ fn report_with_use_injections(&mut self, krate: &Crate) {
     }
 
     fn report_shadowing_errors(&mut self) {
-        for (ident, scope) in replace(&mut self.lexical_macro_resolutions, Vec::new()) {
-            self.resolve_legacy_scope(scope, ident, true);
-        }
-
         let mut reported_errors = FxHashSet();
         for binding in replace(&mut self.disallowed_shadowing, Vec::new()) {
             if self.resolve_legacy_scope(&binding.parent, binding.ident, false).is_some() &&
@@ -4584,7 +4622,7 @@ fn report_conflict<'b>(&mut self,
             false => "defined",
         };
 
-        let (name, span) = (ident.name, self.session.codemap().def_span(new_binding.span));
+        let (name, span) = (ident.name, self.session.source_map().def_span(new_binding.span));
 
         if let Some(s) = self.name_already_seen.get(&name) {
             if s == &span {
@@ -4623,7 +4661,7 @@ fn report_conflict<'b>(&mut self,
 
         err.span_label(span, format!("`{}` re{} here", name, new_participle));
         if !old_binding.span.is_dummy() {
-            err.span_label(self.session.codemap().def_span(old_binding.span),
+            err.span_label(self.session.source_map().def_span(old_binding.span),
                            format!("previous {} of the {} `{}` here", old_noun, old_kind, name));
         }
 
@@ -4635,7 +4673,7 @@ fn report_conflict<'b>(&mut self,
                 old_binding
             };
 
-            let cm = self.session.codemap();
+            let cm = self.session.source_map();
             let rename_msg = "You can use `as` to change the binding name of the import";
 
             if let (Ok(snippet), false) = (cm.span_to_snippet(binding.span),
@@ -4646,15 +4684,16 @@ fn report_conflict<'b>(&mut self,
                     format!("other_{}", name)
                 };
 
-                err.span_suggestion(binding.span,
-                                    rename_msg,
-                                    if snippet.ends_with(';') {
-                                        format!("{} as {};",
-                                                &snippet[..snippet.len()-1],
-                                                suggested_name)
-                                    } else {
-                                        format!("{} as {}", snippet, suggested_name)
-                                    });
+                err.span_suggestion_with_applicability(
+                    binding.span,
+                    rename_msg,
+                    if snippet.ends_with(';') {
+                        format!("{} as {};", &snippet[..snippet.len() - 1], suggested_name)
+                    } else {
+                        format!("{} as {}", snippet, suggested_name)
+                    },
+                    Applicability::MachineApplicable,
+                );
             } else {
                 err.span_label(binding.span, rename_msg);
             }
@@ -4663,36 +4702,6 @@ fn report_conflict<'b>(&mut self,
         err.emit();
         self.name_already_seen.insert(name, span);
     }
-
-    fn check_proc_macro_attrs(&mut self, attrs: &[ast::Attribute]) {
-        if self.use_extern_macros { return; }
-
-        for attr in attrs {
-            if attr.path.segments.len() > 1 {
-                continue
-            }
-            let ident = attr.path.segments[0].ident;
-            let result = self.resolve_lexical_macro_path_segment(ident,
-                                                                 MacroNS,
-                                                                 false,
-                                                                 false,
-                                                                 true,
-                                                                 attr.path.span);
-            if let Ok(binding) = result {
-                if let SyntaxExtension::AttrProcMacro(..) = *binding.binding().get_macro(self) {
-                    attr::mark_known(attr);
-
-                    let msg = "attribute procedural macros are experimental";
-                    let feature = "use_extern_macros";
-
-                    feature_err(&self.session.parse_sess, feature,
-                                attr.span, GateIssue::Language, msg)
-                        .span_label(binding.span(), "procedural macro imported here")
-                        .emit();
-                }
-            }
-        }
-    }
 }
 
 fn is_self_type(path: &[Ident], namespace: Namespace) -> bool {