about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2019-04-14 17:00:16 +0000
committerbors <bors@rust-lang.org>2019-04-14 17:00:16 +0000
commit9cd61f025b1b92076e69a9ef2d9233325c7d8bdc (patch)
treee06ea1657bc17ae3d7b1ba86bc75013ec0984193 /src
parentd70c5a912edbeca55a84e4185e8fe22918aef8dc (diff)
parentc348bb69d6a7195cc01ce2bcb935e3b6293a2d74 (diff)
downloadrust-9cd61f025b1b92076e69a9ef2d9233325c7d8bdc.tar.gz
rust-9cd61f025b1b92076e69a9ef2d9233325c7d8bdc.zip
Auto merge of #59967 - Centril:rollup-bdqq7ux, r=Centril
Rollup of 7 pull requests

Successful merges:

 - #59856 (update polonius-engine)
 - #59877 (HirIdify hir::Def)
 - #59896 (Remove duplicated redundant spans)
 - #59900 (Remove [mut] syntax in pin docs)
 - #59906 (Make BufWriter use get_mut instead of manipulating inner in Write implementation)
 - #59936 (Fix cross-crate visibility of fictive variant constructors)
 - #59957 (Add missing backtick to Symbol documentation.)

Failed merges:

r? @ghost
Diffstat (limited to 'src')
-rw-r--r--src/libcore/pin.rs28
-rw-r--r--src/librustc/Cargo.toml2
-rw-r--r--src/librustc/hir/def.rs79
-rw-r--r--src/librustc/hir/lowering.rs154
-rw-r--r--src/librustc/hir/map/mod.rs5
-rw-r--r--src/librustc/hir/mod.rs17
-rw-r--r--src/librustc/middle/expr_use_visitor.rs6
-rw-r--r--src/librustc/middle/liveness.rs9
-rw-r--r--src/librustc/middle/mem_categorization.rs8
-rw-r--r--src/librustc/middle/reachable.rs3
-rw-r--r--src/librustc/mir/mod.rs4
-rw-r--r--src/librustc/query/mod.rs4
-rw-r--r--src/librustc/ty/context.rs12
-rw-r--r--src/librustc/ty/mod.rs2
-rw-r--r--src/librustc/ty/print/pretty.rs4
-rw-r--r--src/librustc_metadata/cstore_impl.rs9
-rw-r--r--src/librustc_metadata/decoder.rs15
-rw-r--r--src/librustc_metadata/schema.rs2
-rw-r--r--src/librustc_mir/Cargo.toml2
-rw-r--r--src/librustc_mir/borrow_check/error_reporting.rs2
-rw-r--r--src/librustc_mir/borrow_check/nll/mod.rs2
-rw-r--r--src/librustc_mir/hair/cx/expr.rs9
-rw-r--r--src/librustc_resolve/build_reduced_graph.rs18
-rw-r--r--src/librustc_resolve/error_reporting.rs6
-rw-r--r--src/librustc_resolve/lib.rs17
-rw-r--r--src/librustc_resolve/macros.rs4
-rw-r--r--src/librustc_resolve/resolve_imports.rs12
-rw-r--r--src/librustc_save_analysis/dump_visitor.rs4
-rw-r--r--src/librustc_save_analysis/lib.rs4
-rw-r--r--src/librustc_typeck/check/callee.rs4
-rw-r--r--src/librustc_typeck/check/demand.rs4
-rw-r--r--src/librustc_typeck/check/method/suggest.rs8
-rw-r--r--src/librustc_typeck/check/mod.rs3
-rw-r--r--src/librustc_typeck/check/upvar.rs7
-rw-r--r--src/librustdoc/passes/collect_intra_doc_links.rs4
-rw-r--r--src/libstd/io/buffered.rs4
-rw-r--r--src/libsyntax_pos/symbol.rs2
-rw-r--r--src/test/mir-opt/inline-closure-borrows-arg.rs2
-rw-r--r--src/test/mir-opt/inline-closure.rs2
-rw-r--r--src/test/mir-opt/retag.rs2
-rw-r--r--src/test/ui/issues/issue-59896.rs10
-rw-r--r--src/test/ui/issues/issue-59896.stderr17
-rw-r--r--src/test/ui/rfc-2008-non-exhaustive/variants_fictive_visibility.rs12
43 files changed, 380 insertions, 144 deletions
diff --git a/src/libcore/pin.rs b/src/libcore/pin.rs
index 57bd3ed12b2..d1ebe5ed72a 100644
--- a/src/libcore/pin.rs
+++ b/src/libcore/pin.rs
@@ -158,12 +158,12 @@
 //! is called *even if your type was previously pinned*! It is as if the
 //! compiler automatically called `get_unchecked_mut`.
 //!
-//! This can never cause a problem in safe code because implementing a type that relies on pinning
-//! requires unsafe code, but be aware that deciding to make use of pinning
-//! in your type (for example by implementing some operation on `Pin<&[mut] Self>`)
-//! has consequences for your `Drop` implementation as well: if an element
-//! of your type could have been pinned, you must treat Drop as implicitly taking
-//! `Pin<&mut Self>`.
+//! This can never cause a problem in safe code because implementing a type that
+//! relies on pinning requires unsafe code, but be aware that deciding to make
+//! use of pinning in your type (for example by implementing some operation on
+//! `Pin<&Self>` or `Pin<&mut Self>`) has consequences for your `Drop`
+//! implementation as well: if an element of your type could have been pinned,
+//! you must treat Drop as implicitly taking `Pin<&mut Self>`.
 //!
 //! In particular, if your type is `#[repr(packed)]`, the compiler will automatically
 //! move fields around to be able to drop them. As a consequence, you cannot use
@@ -171,15 +171,19 @@
 //!
 //! # Projections and Structural Pinning
 //!
-//! One interesting question arises when considering the interaction of pinning and
-//! the fields of a struct. When can a struct have a "pinning projection", i.e.,
-//! an operation with type `fn(Pin<&[mut] Struct>) -> Pin<&[mut] Field>`?
-//! In a similar vein, when can a generic wrapper type (such as `Vec<T>`, `Box<T>`, or `RefCell<T>`)
-//! have an operation with type `fn(Pin<&[mut] Wrapper<T>>) -> Pin<&[mut] T>`?
+//! One interesting question arises when considering the interaction of pinning
+//! and the fields of a struct. When can a struct have a "pinning projection",
+//! i.e., an operation with type `fn(Pin<&Struct>) -> Pin<&Field>`?  In a
+//! similar vein, when can a generic wrapper type (such as `Vec<T>`, `Box<T>`,
+//! or `RefCell<T>`) have an operation with type `fn(Pin<&Wrapper<T>>) ->
+//! Pin<&T>`?
+//!
+//! Note: For the entirety of this discussion, the same applies for mutable references as it
+//! does for shared references.
 //!
 //! Having a pinning projection for some field means that pinning is "structural":
 //! when the wrapper is pinned, the field must be considered pinned, too.
-//! After all, the pinning projection lets us get a `Pin<&[mut] Field>`.
+//! After all, the pinning projection lets us get a `Pin<&Field>`.
 //!
 //! However, structural pinning comes with a few extra requirements, so not all
 //! wrappers can be structural and hence not all wrappers can offer pinning projections:
diff --git a/src/librustc/Cargo.toml b/src/librustc/Cargo.toml
index a668ebacabf..2876024beb1 100644
--- a/src/librustc/Cargo.toml
+++ b/src/librustc/Cargo.toml
@@ -19,7 +19,7 @@ lazy_static = "1.0.0"
 num_cpus = "1.0"
 scoped-tls = "1.0"
 log = { version = "0.4", features = ["release_max_level_info", "std"] }
-polonius-engine = "0.6.2"
+polonius-engine = "0.7.0"
 rustc-rayon = "0.1.2"
 rustc-rayon-core = "0.1.2"
 rustc_apfloat = { path = "../librustc_apfloat" }
diff --git a/src/librustc/hir/def.rs b/src/librustc/hir/def.rs
index 3cc23ccdb64..7d173af3112 100644
--- a/src/librustc/hir/def.rs
+++ b/src/librustc/hir/def.rs
@@ -2,10 +2,12 @@ use crate::hir::def_id::DefId;
 use crate::util::nodemap::{NodeMap, DefIdMap};
 use syntax::ast;
 use syntax::ext::base::MacroKind;
+use syntax::ast::NodeId;
 use syntax_pos::Span;
 use rustc_macros::HashStable;
 use crate::hir;
 use crate::ty;
+use std::fmt::Debug;
 
 use self::Namespace::*;
 
@@ -43,7 +45,7 @@ pub enum NonMacroAttrKind {
 }
 
 #[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, HashStable)]
-pub enum Def {
+pub enum Def<Id = hir::HirId> {
     // Type namespace
     Mod(DefId),
     /// `DefId` refers to the struct itself, `Def::Ctor` refers to its constructor if it exists.
@@ -78,8 +80,8 @@ pub enum Def {
     Method(DefId),
     AssociatedConst(DefId),
 
-    Local(ast::NodeId),
-    Upvar(ast::NodeId,  // `NodeId` of closed over local
+    Local(Id),
+    Upvar(Id,           // `HirId` of closed over local
           usize,        // index in the `freevars` list of the closure
           ast::NodeId), // expr node that creates the closure
     Label(ast::NodeId),
@@ -108,22 +110,22 @@ pub enum Def {
 /// ```
 #[derive(Copy, Clone, Debug)]
 pub struct PathResolution {
-    base_def: Def,
+    base_def: Def<NodeId>,
     unresolved_segments: usize,
 }
 
 impl PathResolution {
-    pub fn new(def: Def) -> Self {
+    pub fn new(def: Def<NodeId>) -> Self {
         PathResolution { base_def: def, unresolved_segments: 0 }
     }
 
-    pub fn with_unresolved_segments(def: Def, mut unresolved_segments: usize) -> Self {
+    pub fn with_unresolved_segments(def: Def<NodeId>, mut unresolved_segments: usize) -> Self {
         if def == Def::Err { unresolved_segments = 0 }
         PathResolution { base_def: def, unresolved_segments: unresolved_segments }
     }
 
     #[inline]
-    pub fn base_def(&self) -> Def {
+    pub fn base_def(&self) -> Def<NodeId> {
         self.base_def
     }
 
@@ -215,18 +217,18 @@ pub type DefMap = NodeMap<PathResolution>;
 
 /// This is the replacement export map. It maps a module to all of the exports
 /// within.
-pub type ExportMap = DefIdMap<Vec<Export>>;
+pub type ExportMap<Id> = DefIdMap<Vec<Export<Id>>>;
 
 /// Map used to track the `use` statements within a scope, matching it with all the items in every
 /// namespace.
 pub type ImportMap = NodeMap<PerNS<Option<PathResolution>>>;
 
 #[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
-pub struct Export {
+pub struct Export<Id> {
     /// The name of the target.
     pub ident: ast::Ident,
     /// The definition of the target.
-    pub def: Def,
+    pub def: Def<Id>,
     /// The span of the target definition.
     pub span: Span,
     /// The visibility of the export.
@@ -234,6 +236,17 @@ pub struct Export {
     pub vis: ty::Visibility,
 }
 
+impl<Id> Export<Id> {
+    pub fn map_id<R>(self, map: impl FnMut(Id) -> R) -> Export<R> {
+        Export {
+            ident: self.ident,
+            def: self.def.map_id(map),
+            span: self.span,
+            vis: self.vis,
+        }
+    }
+}
+
 impl CtorKind {
     pub fn from_ast(vdata: &ast::VariantData) -> CtorKind {
         match *vdata {
@@ -264,9 +277,12 @@ impl NonMacroAttrKind {
     }
 }
 
-impl Def {
+impl<Id> Def<Id> {
     /// Return the `DefId` of this `Def` if it has an id, else panic.
-    pub fn def_id(&self) -> DefId {
+    pub fn def_id(&self) -> DefId
+    where
+        Id: Debug,
+    {
         self.opt_def_id().unwrap_or_else(|| {
             bug!("attempted .def_id() on invalid def: {:?}", self)
         })
@@ -358,4 +374,43 @@ impl Def {
             _ => "a",
         }
     }
+
+    pub fn map_id<R>(self, mut map: impl FnMut(Id) -> R) -> Def<R> {
+        match self {
+            Def::Fn(id) => Def::Fn(id),
+            Def::Mod(id) => Def::Mod(id),
+            Def::Static(id, is_mutbl) => Def::Static(id, is_mutbl),
+            Def::Enum(id) => Def::Enum(id),
+            Def::Variant(id) => Def::Variant(id),
+            Def::Ctor(a, b, c) => Def::Ctor(a, b, c),
+            Def::Struct(id) => Def::Struct(id),
+            Def::Existential(id) => Def::Existential(id),
+            Def::TyAlias(id) => Def::TyAlias(id),
+            Def::TraitAlias(id) => Def::TraitAlias(id),
+            Def::AssociatedTy(id) => Def::AssociatedTy(id),
+            Def::AssociatedExistential(id) => Def::AssociatedExistential(id),
+            Def::SelfCtor(id) => Def::SelfCtor(id),
+            Def::Union(id) => Def::Union(id),
+            Def::Trait(id) => Def::Trait(id),
+            Def::ForeignTy(id) => Def::ForeignTy(id),
+            Def::Method(id) => Def::Method(id),
+            Def::Const(id) => Def::Const(id),
+            Def::AssociatedConst(id) => Def::AssociatedConst(id),
+            Def::TyParam(id) => Def::TyParam(id),
+            Def::ConstParam(id) => Def::ConstParam(id),
+            Def::PrimTy(id) => Def::PrimTy(id),
+            Def::Local(id) => Def::Local(map(id)),
+            Def::Upvar(id, index, closure) => Def::Upvar(
+                map(id),
+                index,
+                closure
+            ),
+            Def::Label(id) => Def::Label(id),
+            Def::SelfTy(a, b) => Def::SelfTy(a, b),
+            Def::Macro(id, macro_kind) => Def::Macro(id, macro_kind),
+            Def::ToolMod => Def::ToolMod,
+            Def::NonMacroAttr(attr_kind) => Def::NonMacroAttr(attr_kind),
+            Def::Err => Def::Err,
+        }
+    }
 }
diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs
index 2a255523676..a8269bb1395 100644
--- a/src/librustc/hir/lowering.rs
+++ b/src/librustc/hir/lowering.rs
@@ -401,6 +401,7 @@ impl<'a> LoweringContext<'a> {
         /// declared for every type and trait definition.
         struct MiscCollector<'lcx, 'interner: 'lcx> {
             lctx: &'lcx mut LoweringContext<'interner>,
+            hir_id_owner: Option<NodeId>,
         }
 
         impl MiscCollector<'_, '_> {
@@ -432,9 +433,34 @@ impl<'a> LoweringContext<'a> {
                     }
                 }
             }
+
+            fn with_hir_id_owner<F, T>(&mut self, owner: Option<NodeId>, f: F) -> T
+            where
+                F: FnOnce(&mut Self) -> T,
+            {
+                let old = mem::replace(&mut self.hir_id_owner, owner);
+                let r = f(self);
+                self.hir_id_owner = old;
+                r
+            }
         }
 
         impl<'lcx, 'interner> Visitor<'lcx> for MiscCollector<'lcx, 'interner> {
+            fn visit_pat(&mut self, p: &'lcx Pat) {
+                match p.node {
+                    // Doesn't generate a Hir node
+                    PatKind::Paren(..) => {},
+                    _ => {
+
+                        if let Some(owner) = self.hir_id_owner {
+                            self.lctx.lower_node_id_with_owner(p.id, owner);
+                        }
+                    }
+                };
+
+                visit::walk_pat(self, p)
+            }
+
             fn visit_item(&mut self, item: &'lcx Item) {
                 let hir_id = self.lctx.allocate_hir_id_counter(item.id).hir_id;
 
@@ -461,17 +487,63 @@ impl<'a> LoweringContext<'a> {
                     }
                     _ => {}
                 }
-                visit::walk_item(self, item);
+
+                self.with_hir_id_owner(Some(item.id), |this| {
+                    visit::walk_item(this, item);
+                });
             }
 
             fn visit_trait_item(&mut self, item: &'lcx TraitItem) {
                 self.lctx.allocate_hir_id_counter(item.id);
-                visit::walk_trait_item(self, item);
+
+                match item.node {
+                    TraitItemKind::Method(_, None) => {
+                        // Ignore patterns in trait methods without bodies
+                        self.with_hir_id_owner(None, |this| {
+                            visit::walk_trait_item(this, item)
+                        });
+                    }
+                    _ => self.with_hir_id_owner(Some(item.id), |this| {
+                        visit::walk_trait_item(this, item);
+                    })
+                }
             }
 
             fn visit_impl_item(&mut self, item: &'lcx ImplItem) {
                 self.lctx.allocate_hir_id_counter(item.id);
-                visit::walk_impl_item(self, item);
+                self.with_hir_id_owner(Some(item.id), |this| {
+                    visit::walk_impl_item(this, item);
+                });
+            }
+
+            fn visit_foreign_item(&mut self, i: &'lcx ForeignItem) {
+                // Ignore patterns in foreign items
+                self.with_hir_id_owner(None, |this| {
+                    visit::walk_foreign_item(this, i)
+                });
+            }
+
+            fn visit_ty(&mut self, t: &'lcx Ty) {
+                match t.node {
+                    // Mirrors the case in visit::walk_ty
+                    TyKind::BareFn(ref f) => {
+                        walk_list!(
+                            self,
+                            visit_generic_param,
+                            &f.generic_params
+                        );
+                        // Mirrors visit::walk_fn_decl
+                        for argument in &f.decl.inputs {
+                            // We don't lower the ids of argument patterns
+                            self.with_hir_id_owner(None, |this| {
+                                this.visit_pat(&argument.pat);
+                            });
+                            self.visit_ty(&argument.ty)
+                        }
+                        self.visit_fn_ret_ty(&f.decl.output)
+                    }
+                    _ => visit::walk_ty(self, t),
+                }
             }
         }
 
@@ -565,7 +637,7 @@ impl<'a> LoweringContext<'a> {
         self.lower_node_id(CRATE_NODE_ID);
         debug_assert!(self.node_id_to_hir_id[CRATE_NODE_ID] == hir::CRATE_HIR_ID);
 
-        visit::walk_crate(&mut MiscCollector { lctx: &mut self }, c);
+        visit::walk_crate(&mut MiscCollector { lctx: &mut self, hir_id_owner: None }, c);
         visit::walk_crate(&mut ItemLowerer { lctx: &mut self }, c);
 
         let module = self.lower_mod(&c.module);
@@ -729,7 +801,15 @@ impl<'a> LoweringContext<'a> {
         self.lower_node_id(self.sess.next_node_id())
     }
 
-    fn expect_full_def(&mut self, id: NodeId) -> Def {
+    fn lower_def(&mut self, def: Def<NodeId>) -> Def {
+        def.map_id(|id| {
+            self.lower_node_id_generic(id, |_| {
+                panic!("expected node_id to be lowered already for def {:#?}", def)
+            }).hir_id
+        })
+    }
+
+    fn expect_full_def(&mut self, id: NodeId) -> Def<NodeId> {
         self.resolver.get_resolution(id).map_or(Def::Err, |pr| {
             if pr.unresolved_segments() != 0 {
                 bug!("path not fully resolved: {:?}", pr);
@@ -738,7 +818,7 @@ impl<'a> LoweringContext<'a> {
         })
     }
 
-    fn expect_full_def_from_use(&mut self, id: NodeId) -> impl Iterator<Item = Def> {
+    fn expect_full_def_from_use(&mut self, id: NodeId) -> impl Iterator<Item = Def<NodeId>> {
         self.resolver.get_import(id).present_items().map(|pr| {
             if pr.unresolved_segments() != 0 {
                 bug!("path not fully resolved: {:?}", pr);
@@ -1324,14 +1404,20 @@ impl<'a> LoweringContext<'a> {
                 }
                 return ty;
             }
-            TyKind::ImplicitSelf => hir::TyKind::Path(hir::QPath::Resolved(
-                None,
-                P(hir::Path {
-                    def: self.expect_full_def(t.id),
-                    segments: hir_vec![hir::PathSegment::from_ident(keywords::SelfUpper.ident())],
-                    span: t.span,
-                }),
-            )),
+            TyKind::ImplicitSelf => {
+                let def = self.expect_full_def(t.id);
+                let def = self.lower_def(def);
+                hir::TyKind::Path(hir::QPath::Resolved(
+                    None,
+                    P(hir::Path {
+                        def,
+                        segments: hir_vec![hir::PathSegment::from_ident(
+                            keywords::SelfUpper.ident()
+                        )],
+                        span: t.span,
+                    }),
+                ))
+            },
             TyKind::Array(ref ty, ref length) => {
                 hir::TyKind::Array(self.lower_ty(ty, itctx), self.lower_anon_const(length))
             }
@@ -1755,7 +1841,7 @@ impl<'a> LoweringContext<'a> {
 
         let proj_start = p.segments.len() - resolution.unresolved_segments();
         let path = P(hir::Path {
-            def: resolution.base_def(),
+            def: self.lower_def(resolution.base_def()),
             segments: p.segments[..proj_start]
                 .iter()
                 .enumerate()
@@ -1931,6 +2017,7 @@ impl<'a> LoweringContext<'a> {
 
     fn lower_path(&mut self, id: NodeId, p: &Path, param_mode: ParamMode) -> hir::Path {
         let def = self.expect_full_def(id);
+        let def = self.lower_def(def);
         self.lower_path_extra(def, p, param_mode, None)
     }
 
@@ -2042,7 +2129,7 @@ impl<'a> LoweringContext<'a> {
         hir::PathSegment::new(
             segment.ident,
             Some(id.hir_id),
-            Some(def),
+            Some(self.lower_def(def)),
             generic_args,
             infer_types,
         )
@@ -3174,7 +3261,7 @@ impl<'a> LoweringContext<'a> {
                 let mut defs = self.expect_full_def_from_use(id);
                 // We want to return *something* from this function, so hold onto the first item
                 // for later.
-                let ret_def = defs.next().unwrap_or(Def::Err);
+                let ret_def = self.lower_def(defs.next().unwrap_or(Def::Err));
 
                 // Here, we are looping over namespaces, if they exist for the definition
                 // being imported. We only handle type and value namespaces because we
@@ -3192,6 +3279,7 @@ impl<'a> LoweringContext<'a> {
 
                     self.with_hir_id_owner(new_node_id, |this| {
                         let new_id = this.lower_node_id(new_node_id);
+                        let def = this.lower_def(def);
                         let path =
                             this.lower_path_extra(def, &path, ParamMode::Explicit, None);
                         let item = hir::ItemKind::Use(P(path), hir::UseKind::Single);
@@ -3347,6 +3435,7 @@ impl<'a> LoweringContext<'a> {
                 }
 
                 let def = self.expect_full_def_from_use(id).next().unwrap_or(Def::Err);
+                let def = self.lower_def(def);
                 let path = P(self.lower_path_extra(def, &prefix, ParamMode::Explicit, None));
                 hir::ItemKind::Use(path, hir::UseKind::ListStem)
             }
@@ -3780,7 +3869,7 @@ impl<'a> LoweringContext<'a> {
                         None,
                         P(hir::Path {
                             span: ident.span,
-                            def,
+                            def: self.lower_def(def),
                             segments: hir_vec![hir::PathSegment::from_ident(ident)],
                         }),
                     )),
@@ -4435,7 +4524,7 @@ impl<'a> LoweringContext<'a> {
                 let iter = self.str_to_ident("iter");
 
                 let next_ident = self.str_to_ident("__next");
-                let (next_pat, next_pat_nid) = self.pat_ident_binding_mode(
+                let (next_pat, next_pat_hid) = self.pat_ident_binding_mode(
                     desugared_span,
                     next_ident,
                     hir::BindingAnnotation::Mutable,
@@ -4444,9 +4533,9 @@ impl<'a> LoweringContext<'a> {
                 // `::std::option::Option::Some(val) => next = val`
                 let pat_arm = {
                     let val_ident = self.str_to_ident("val");
-                    let (val_pat, val_pat_nid) = self.pat_ident(pat.span, val_ident);
-                    let val_expr = P(self.expr_ident(pat.span, val_ident, val_pat_nid));
-                    let next_expr = P(self.expr_ident(pat.span, next_ident, next_pat_nid));
+                    let (val_pat, val_pat_hid) = self.pat_ident(pat.span, val_ident);
+                    let val_expr = P(self.expr_ident(pat.span, val_ident, val_pat_hid));
+                    let next_expr = P(self.expr_ident(pat.span, next_ident, next_pat_hid));
                     let assign = P(self.expr(
                         pat.span,
                         hir::ExprKind::Assign(next_expr, val_expr),
@@ -4497,7 +4586,7 @@ impl<'a> LoweringContext<'a> {
                     span: head_sp,
                 };
 
-                let next_expr = P(self.expr_ident(head_sp, next_ident, next_pat_nid));
+                let next_expr = P(self.expr_ident(head_sp, next_ident, next_pat_hid));
 
                 // `let mut __next`
                 let next_let = self.stmt_let_pat(
@@ -4790,6 +4879,7 @@ impl<'a> LoweringContext<'a> {
                     self.lower_node_id(id)
                 };
                 let def = self.expect_full_def(id);
+                let def = self.lower_def(def);
                 hir::VisibilityKind::Restricted {
                     path: P(self.lower_path_extra(
                         def,
@@ -4891,7 +4981,7 @@ impl<'a> LoweringContext<'a> {
         self.expr(span, hir::ExprKind::Call(e, args), ThinVec::new())
     }
 
-    fn expr_ident(&mut self, span: Span, ident: Ident, binding: NodeId) -> hir::Expr {
+    fn expr_ident(&mut self, span: Span, ident: Ident, binding: hir::HirId) -> hir::Expr {
         self.expr_ident_with_attrs(span, ident, binding, ThinVec::new())
     }
 
@@ -4899,7 +4989,7 @@ impl<'a> LoweringContext<'a> {
         &mut self,
         span: Span,
         ident: Ident,
-        binding: NodeId,
+        binding: hir::HirId,
         attrs: ThinVec<Attribute>,
     ) -> hir::Expr {
         let expr_path = hir::ExprKind::Path(hir::QPath::Resolved(
@@ -4994,8 +5084,8 @@ impl<'a> LoweringContext<'a> {
         mutbl: bool,
         ident: Ident,
         ex: P<hir::Expr>,
-    ) -> (hir::Stmt, NodeId) {
-        let (pat, pat_nid) = if mutbl {
+    ) -> (hir::Stmt, hir::HirId) {
+        let (pat, pat_hid) = if mutbl {
             self.pat_ident_binding_mode(sp, ident, hir::BindingAnnotation::Mutable)
         } else {
             self.pat_ident(sp, ident)
@@ -5003,7 +5093,7 @@ impl<'a> LoweringContext<'a> {
 
         (
             self.stmt_let_pat(sp, Some(ex), pat, hir::LocalSource::Normal),
-            pat_nid,
+            pat_hid,
         )
     }
 
@@ -5061,7 +5151,7 @@ impl<'a> LoweringContext<'a> {
         self.pat(span, pt)
     }
 
-    fn pat_ident(&mut self, span: Span, ident: Ident) -> (P<hir::Pat>, NodeId) {
+    fn pat_ident(&mut self, span: Span, ident: Ident) -> (P<hir::Pat>, hir::HirId) {
         self.pat_ident_binding_mode(span, ident, hir::BindingAnnotation::Unannotated)
     }
 
@@ -5070,8 +5160,8 @@ impl<'a> LoweringContext<'a> {
         span: Span,
         ident: Ident,
         bm: hir::BindingAnnotation,
-    ) -> (P<hir::Pat>, NodeId) {
-        let LoweredNodeId { node_id, hir_id } = self.next_id();
+    ) -> (P<hir::Pat>, hir::HirId) {
+        let LoweredNodeId { node_id: _, hir_id } = self.next_id();
 
         (
             P(hir::Pat {
@@ -5079,7 +5169,7 @@ impl<'a> LoweringContext<'a> {
                 node: hir::PatKind::Binding(bm, hir_id, ident.with_span_pos(span), None),
                 span,
             }),
-            node_id
+            hir_id
         )
     }
 
diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs
index c0579ef0f7a..4eef2019e26 100644
--- a/src/librustc/hir/map/mod.rs
+++ b/src/librustc/hir/map/mod.rs
@@ -393,7 +393,7 @@ impl<'hir> Map<'hir> {
             Node::Block(_) |
             Node::Crate => None,
             Node::Local(local) => {
-                Some(Def::Local(self.hir_to_node_id(local.hir_id)))
+                Some(Def::Local(local.hir_id))
             }
             Node::MacroDef(macro_def) => {
                 Some(Def::Macro(self.local_def_id_from_hir_id(macro_def.hir_id),
@@ -402,8 +402,7 @@ impl<'hir> Map<'hir> {
             Node::GenericParam(param) => {
                 Some(match param.kind {
                     GenericParamKind::Lifetime { .. } => {
-                        let node_id = self.hir_to_node_id(param.hir_id);
-                        Def::Local(node_id)
+                        Def::Local(param.hir_id)
                     },
                     GenericParamKind::Type { .. } => Def::TyParam(
                         self.local_def_id_from_hir_id(param.hir_id)),
diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs
index 58a27d3f78e..7ed8c08c923 100644
--- a/src/librustc/hir/mod.rs
+++ b/src/librustc/hir/mod.rs
@@ -2424,16 +2424,23 @@ impl ForeignItemKind {
 
 /// A free variable referred to in a function.
 #[derive(Debug, Copy, Clone, RustcEncodable, RustcDecodable, HashStable)]
-pub struct Freevar {
+pub struct Freevar<Id = HirId> {
     /// The variable being accessed free.
-    pub def: Def,
+    pub def: def::Def<Id>,
 
     // First span where it is accessed (there can be multiple).
     pub span: Span
 }
 
-impl Freevar {
-    pub fn var_id(&self) -> NodeId {
+impl<Id: fmt::Debug + Copy> Freevar<Id> {
+    pub fn map_id<R>(self, map: impl FnMut(Id) -> R) -> Freevar<R> {
+        Freevar {
+            def: self.def.map_id(map),
+            span: self.span,
+        }
+    }
+
+    pub fn var_id(&self) -> Id {
         match self.def {
             Def::Local(id) | Def::Upvar(id, ..) => id,
             _ => bug!("Freevar::var_id: bad def ({:?})", self.def)
@@ -2441,7 +2448,7 @@ impl Freevar {
     }
 }
 
-pub type FreevarMap = NodeMap<Vec<Freevar>>;
+pub type FreevarMap = NodeMap<Vec<Freevar<ast::NodeId>>>;
 
 pub type CaptureModeMap = NodeMap<CaptureClause>;
 
diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs
index 4f630fe9a39..41ff9406d9d 100644
--- a/src/librustc/middle/expr_use_visitor.rs
+++ b/src/librustc/middle/expr_use_visitor.rs
@@ -863,7 +863,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
 
                     // Each match binding is effectively an assignment to the
                     // binding being produced.
-                    let def = Def::Local(mc.tcx.hir().hir_to_node_id(canonical_id));
+                    let def = Def::Local(canonical_id);
                     if let Ok(ref binding_cmt) = mc.cat_def(pat.hir_id, pat.span, pat_ty, def) {
                         delegate.mutate(pat.hir_id, pat.span, binding_cmt, MutateMode::Init);
                     }
@@ -930,7 +930,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
         let closure_def_id = self.tcx().hir().local_def_id_from_hir_id(closure_expr.hir_id);
         self.tcx().with_freevars(closure_expr.hir_id, |freevars| {
             for freevar in freevars {
-                let var_hir_id = self.tcx().hir().node_to_hir_id(freevar.var_id());
+                let var_hir_id = freevar.var_id();
                 let upvar_id = ty::UpvarId {
                     var_path: ty::UpvarPath { hir_id: var_hir_id },
                     closure_expr_id: closure_def_id.to_local(),
@@ -967,7 +967,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
                         -> mc::McResult<mc::cmt_<'tcx>> {
         // Create the cmt for the variable being borrowed, from the
         // caller's perspective
-        let var_hir_id = self.tcx().hir().node_to_hir_id(upvar.var_id());
+        let var_hir_id = upvar.var_id();
         let var_ty = self.mc.node_ty(var_hir_id)?;
         self.mc.cat_def(closure_hir_id, closure_span, var_ty, upvar.def)
     }
diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs
index f5a95d7004b..d167b44d42f 100644
--- a/src/librustc/middle/liveness.rs
+++ b/src/librustc/middle/liveness.rs
@@ -487,8 +487,7 @@ fn visit_expr<'a, 'tcx>(ir: &mut IrMaps<'a, 'tcx>, expr: &'tcx Expr) {
             call_caps.extend(freevars.iter().filter_map(|fv| {
                 if let Def::Local(rv) = fv.def {
                     let fv_ln = ir.add_live_node(FreeVarNode(fv.span));
-                    let var_hid = ir.tcx.hir().node_to_hir_id(rv);
-                    Some(CaptureInfo { ln: fv_ln, var_hid })
+                    Some(CaptureInfo { ln: fv_ln, var_hid: rv })
                 } else {
                     None
                 }
@@ -1347,7 +1346,8 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
     fn access_path(&mut self, hir_id: HirId, path: &hir::Path, succ: LiveNode, acc: u32)
                    -> LiveNode {
         match path.def {
-            Def::Local(nid) => {
+            Def::Local(hid) => {
+              let nid = self.ir.tcx.hir().hir_to_node_id(hid);
               self.access_var(hir_id, nid, succ, acc, path.span)
             }
             _ => succ
@@ -1539,13 +1539,12 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
     fn check_place(&mut self, expr: &'tcx Expr) {
         match expr.node {
             hir::ExprKind::Path(hir::QPath::Resolved(_, ref path)) => {
-                if let Def::Local(nid) = path.def {
+                if let Def::Local(var_hid) = path.def {
                     // Assignment to an immutable variable or argument: only legal
                     // if there is no later assignment. If this local is actually
                     // mutable, then check for a reassignment to flag the mutability
                     // as being used.
                     let ln = self.live_node(expr.hir_id, expr.span);
-                    let var_hid = self.ir.tcx.hir().node_to_hir_id(nid);
                     let var = self.variable(var_hid, expr.span);
                     self.warn_about_dead_assign(expr.span, expr.hir_id, ln, var);
                 }
diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs
index 1a3fef18404..a031037b7a0 100644
--- a/src/librustc/middle/mem_categorization.rs
+++ b/src/librustc/middle/mem_categorization.rs
@@ -734,15 +734,17 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
             }
 
             Def::Upvar(var_id, _, fn_node_id) => {
-                self.cat_upvar(hir_id, span, var_id, fn_node_id)
+                let var_nid = self.tcx.hir().hir_to_node_id(var_id);
+                self.cat_upvar(hir_id, span, var_nid, fn_node_id)
             }
 
             Def::Local(vid) => {
+                let vnid = self.tcx.hir().hir_to_node_id(vid);
                 Ok(cmt_ {
                     hir_id,
                     span,
-                    cat: Categorization::Local(self.tcx.hir().node_to_hir_id(vid)),
-                    mutbl: MutabilityCategory::from_local(self.tcx, self.tables, vid),
+                    cat: Categorization::Local(vid),
+                    mutbl: MutabilityCategory::from_local(self.tcx, self.tables, vnid),
                     ty: expr_ty,
                     note: NoteNone
                 })
diff --git a/src/librustc/middle/reachable.rs b/src/librustc/middle/reachable.rs
index b55e840596b..92266838dd8 100644
--- a/src/librustc/middle/reachable.rs
+++ b/src/librustc/middle/reachable.rs
@@ -103,8 +103,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ReachableContext<'a, 'tcx> {
         };
 
         match def {
-            Some(Def::Local(node_id)) | Some(Def::Upvar(node_id, ..)) => {
-                let hir_id = self.tcx.hir().node_to_hir_id(node_id);
+            Some(Def::Local(hir_id)) | Some(Def::Upvar(hir_id, ..)) => {
                 self.reachable_symbols.insert(hir_id);
             }
             Some(def) => {
diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs
index 3cab7a3812f..3f376fb052a 100644
--- a/src/librustc/mir/mod.rs
+++ b/src/librustc/mir/mod.rs
@@ -2455,7 +2455,7 @@ impl<'tcx> Debug for Rvalue<'tcx> {
 
                             tcx.with_freevars(hir_id, |freevars| {
                                 for (freevar, place) in freevars.iter().zip(places) {
-                                    let var_name = tcx.hir().name(freevar.var_id());
+                                    let var_name = tcx.hir().name_by_hir_id(freevar.var_id());
                                     struct_fmt.field(&var_name.as_str(), place);
                                 }
                             });
@@ -2474,7 +2474,7 @@ impl<'tcx> Debug for Rvalue<'tcx> {
 
                             tcx.with_freevars(hir_id, |freevars| {
                                 for (freevar, place) in freevars.iter().zip(places) {
-                                    let var_name = tcx.hir().name(freevar.var_id());
+                                    let var_name = tcx.hir().name_by_hir_id(freevar.var_id());
                                     struct_fmt.field(&var_name.as_str(), place);
                                 }
                                 struct_fmt.field("$state", &places[freevars.len()]);
diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs
index d0ad2c90668..bc9aaf870ce 100644
--- a/src/librustc/query/mod.rs
+++ b/src/librustc/query/mod.rs
@@ -641,7 +641,7 @@ rustc_queries! {
     }
 
     Other {
-        query module_exports(_: DefId) -> Option<Lrc<Vec<Export>>> {
+        query module_exports(_: DefId) -> Option<Lrc<Vec<Export<hir::HirId>>>> {
             eval_always
         }
     }
@@ -781,7 +781,7 @@ rustc_queries! {
             eval_always
             desc { "fetching what a crate is named" }
         }
-        query item_children(_: DefId) -> Lrc<Vec<Export>> {}
+        query item_children(_: DefId) -> Lrc<Vec<Export<hir::HirId>>> {}
         query extern_mod_stmt_cnum(_: DefId) -> Option<CrateNum> {}
 
         query get_lib_features(_: CrateNum) -> Lrc<LibFeatures> {
diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs
index 7dc4dee3fbf..9bd5b2fdb96 100644
--- a/src/librustc/ty/context.rs
+++ b/src/librustc/ty/context.rs
@@ -1024,7 +1024,7 @@ pub struct GlobalCtxt<'tcx> {
                                        Lrc<StableVec<TraitCandidate>>>>>,
 
     /// Export map produced by name resolution.
-    export_map: FxHashMap<DefId, Lrc<Vec<Export>>>,
+    export_map: FxHashMap<DefId, Lrc<Vec<Export<hir::HirId>>>>,
 
     hir_map: hir_map::Map<'tcx>,
 
@@ -1271,10 +1271,16 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
             types: common_types,
             trait_map,
             export_map: resolutions.export_map.into_iter().map(|(k, v)| {
-                (k, Lrc::new(v))
+                let exports: Vec<_> = v.into_iter().map(|e| {
+                    e.map_id(|id| hir.node_to_hir_id(id))
+                }).collect();
+                (k, Lrc::new(exports))
             }).collect(),
             freevars: resolutions.freevars.into_iter().map(|(k, v)| {
-                (hir.local_def_id(k), Lrc::new(v))
+                let vars: Vec<_> = v.into_iter().map(|e| {
+                    e.map_id(|id| hir.node_to_hir_id(id))
+                }).collect();
+                (hir.local_def_id(k), Lrc::new(vars))
             }).collect(),
             maybe_unused_trait_imports:
                 resolutions.maybe_unused_trait_imports
diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs
index 7d47867cea1..d24395ac9c1 100644
--- a/src/librustc/ty/mod.rs
+++ b/src/librustc/ty/mod.rs
@@ -123,7 +123,7 @@ pub struct Resolutions {
     pub trait_map: TraitMap,
     pub maybe_unused_trait_imports: NodeSet,
     pub maybe_unused_extern_crates: Vec<(NodeId, Span)>,
-    pub export_map: ExportMap,
+    pub export_map: ExportMap<NodeId>,
     pub glob_map: GlobMap,
     /// Extern prelude entries. The value is `true` if the entry was introduced
     /// via `extern crate` item and not `--extern` option or compiler built-in.
diff --git a/src/librustc/ty/print/pretty.rs b/src/librustc/ty/print/pretty.rs
index c9a4961a8e0..b31ba10d523 100644
--- a/src/librustc/ty/print/pretty.rs
+++ b/src/librustc/ty/print/pretty.rs
@@ -592,7 +592,7 @@ pub trait PrettyPrinter<'gcx: 'tcx, 'tcx>:
                         p!(
                             write("{}{}:",
                                     sep,
-                                    self.tcx().hir().name(freevar.var_id())),
+                                    self.tcx().hir().name_by_hir_id(freevar.var_id())),
                             print(upvar_ty));
                         sep = ", ";
                     }
@@ -635,7 +635,7 @@ pub trait PrettyPrinter<'gcx: 'tcx, 'tcx>:
                         p!(
                             write("{}{}:",
                                     sep,
-                                    self.tcx().hir().name(freevar.var_id())),
+                                    self.tcx().hir().name_by_hir_id(freevar.var_id())),
                             print(upvar_ty));
                         sep = ", ";
                     }
diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs
index 995532a00cd..e3bf09299ef 100644
--- a/src/librustc_metadata/cstore_impl.rs
+++ b/src/librustc_metadata/cstore_impl.rs
@@ -11,6 +11,7 @@ use rustc::middle::cstore::{CrateStore, DepKind,
 use rustc::middle::exported_symbols::ExportedSymbol;
 use rustc::middle::stability::DeprecationEntry;
 use rustc::hir::def;
+use rustc::hir;
 use rustc::session::{CrateDisambiguator, Session};
 use rustc::ty::{self, TyCtxt};
 use rustc::ty::query::Providers;
@@ -347,7 +348,7 @@ pub fn provide<'tcx>(providers: &mut Providers<'tcx>) {
             {
                 let visible_parent_map = &mut visible_parent_map;
                 let mut add_child = |bfs_queue: &mut VecDeque<_>,
-                                     child: &def::Export,
+                                     child: &def::Export<hir::HirId>,
                                      parent: DefId| {
                     if child.vis != ty::Visibility::Public {
                         return;
@@ -415,7 +416,11 @@ impl cstore::CStore {
         self.get_crate_data(def.krate).get_item_attrs(def.index, sess)
     }
 
-    pub fn item_children_untracked(&self, def_id: DefId, sess: &Session) -> Vec<def::Export> {
+    pub fn item_children_untracked(
+        &self,
+        def_id: DefId,
+        sess: &Session
+    ) -> Vec<def::Export<hir::HirId>> {
         let mut result = vec![];
         self.get_crate_data(def_id.krate)
             .each_child_of_item(def_id.index, |child| result.push(child), sess);
diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs
index f456a5c1619..5dade8d9438 100644
--- a/src/librustc_metadata/decoder.rs
+++ b/src/librustc_metadata/decoder.rs
@@ -734,7 +734,7 @@ impl<'a, 'tcx> CrateMetadata {
 
     /// Iterates over each child of the given item.
     pub fn each_child_of_item<F>(&self, id: DefIndex, mut callback: F, sess: &Session)
-        where F: FnMut(def::Export)
+        where F: FnMut(def::Export<hir::HirId>)
     {
         if let Some(ref proc_macros) = self.proc_macros {
             /* If we are loading as a proc macro, we want to return the view of this crate
@@ -831,7 +831,18 @@ impl<'a, 'tcx> CrateMetadata {
                             let ctor_def_id = self.get_ctor_def_id(child_index).unwrap_or(def_id);
                             let ctor_kind = self.get_ctor_kind(child_index);
                             let ctor_def = Def::Ctor(ctor_def_id, CtorOf::Variant, ctor_kind);
-                            let vis = self.get_visibility(ctor_def_id.index);
+                            let mut vis = self.get_visibility(ctor_def_id.index);
+                            if ctor_def_id == def_id && vis == ty::Visibility::Public {
+                                // For non-exhaustive variants lower the constructor visibility to
+                                // within the crate. We only need this for fictive constructors,
+                                // for other constructors correct visibilities
+                                // were already encoded in metadata.
+                                let attrs = self.get_item_attrs(def_id.index, sess);
+                                if attr::contains_name(&attrs, "non_exhaustive") {
+                                    let crate_def_id = DefId { index: CRATE_DEF_INDEX, ..def_id };
+                                    vis = ty::Visibility::Restricted(crate_def_id);
+                                }
+                            }
                             callback(def::Export { def: ctor_def, ident, vis, span });
                         }
                         _ => {}
diff --git a/src/librustc_metadata/schema.rs b/src/librustc_metadata/schema.rs
index fe2ea26c327..504c7da7d6b 100644
--- a/src/librustc_metadata/schema.rs
+++ b/src/librustc_metadata/schema.rs
@@ -423,7 +423,7 @@ impl<'a> HashStable<StableHashingContext<'a>> for RenderedConst {
 
 #[derive(RustcEncodable, RustcDecodable)]
 pub struct ModData {
-    pub reexports: LazySeq<def::Export>,
+    pub reexports: LazySeq<def::Export<hir::HirId>>,
 }
 
 impl_stable_hash_for!(struct ModData { reexports });
diff --git a/src/librustc_mir/Cargo.toml b/src/librustc_mir/Cargo.toml
index c32bafa9920..5de5f5e7571 100644
--- a/src/librustc_mir/Cargo.toml
+++ b/src/librustc_mir/Cargo.toml
@@ -15,7 +15,7 @@ either = "1.5.0"
 dot = { path = "../libgraphviz", package = "graphviz" }
 log = "0.4"
 log_settings = "0.1.1"
-polonius-engine = "0.6.2"
+polonius-engine = "0.7.0"
 rustc = { path = "../librustc" }
 rustc_target = { path = "../librustc_target" }
 rustc_data_structures = { path = "../librustc_data_structures" }
diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs
index e6d818152f5..3ab0996d3a1 100644
--- a/src/librustc_mir/borrow_check/error_reporting.rs
+++ b/src/librustc_mir/borrow_check/error_reporting.rs
@@ -1824,7 +1824,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
                         .tcx
                         .with_freevars(hir_id, |fv| fv[field.index()]);
 
-                    self.infcx.tcx.hir().name(freevar.var_id()).to_string()
+                    self.infcx.tcx.hir().name_by_hir_id(freevar.var_id()).to_string()
                 }
                 _ => {
                     // Might need a revision when the fields in trait RFC is implemented
diff --git a/src/librustc_mir/borrow_check/nll/mod.rs b/src/librustc_mir/borrow_check/nll/mod.rs
index 2d3800dd1dd..3e1b93fb417 100644
--- a/src/librustc_mir/borrow_check/nll/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/mod.rs
@@ -173,7 +173,7 @@ pub(in crate::borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>(
 
         if infcx.tcx.sess.opts.debugging_opts.polonius {
             let algorithm = env::var("POLONIUS_ALGORITHM")
-                .unwrap_or_else(|_| String::from("DatafrogOpt"));
+                .unwrap_or_else(|_| String::from("Hybrid"));
             let algorithm = Algorithm::from_str(&algorithm).unwrap();
             debug!("compute_regions: using polonius algorithm {:?}", algorithm);
             Some(Rc::new(Output::compute(
diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs
index 91113dc2271..2c22c5e64c4 100644
--- a/src/librustc_mir/hair/cx/expr.rs
+++ b/src/librustc_mir/hair/cx/expr.rs
@@ -986,14 +986,13 @@ fn convert_var<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
     let temp_lifetime = cx.region_scope_tree.temporary_scope(expr.hir_id.local_id);
 
     match def {
-        Def::Local(id) => ExprKind::VarRef { id: cx.tcx.hir().node_to_hir_id(id) },
+        Def::Local(id) => ExprKind::VarRef { id },
 
-        Def::Upvar(var_id, index, closure_expr_id) => {
+        Def::Upvar(var_hir_id, index, closure_expr_id) => {
             debug!("convert_var(upvar({:?}, {:?}, {:?}))",
-                   var_id,
+                   var_hir_id,
                    index,
                    closure_expr_id);
-            let var_hir_id = cx.tcx.hir().node_to_hir_id(var_id);
             let var_ty = cx.tables().node_type(var_hir_id);
 
             // FIXME free regions in closures are not right
@@ -1195,7 +1194,7 @@ fn capture_freevar<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
                                    freevar: &hir::Freevar,
                                    freevar_ty: Ty<'tcx>)
                                    -> ExprRef<'tcx> {
-    let var_hir_id = cx.tcx.hir().node_to_hir_id(freevar.var_id());
+    let var_hir_id = freevar.var_id();
     let upvar_id = ty::UpvarId {
         var_path: ty::UpvarPath { hir_id: var_hir_id },
         closure_expr_id: cx.tcx.hir().local_def_id_from_hir_id(closure_expr.hir_id).to_local(),
diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs
index 7ce264db755..72dd043f214 100644
--- a/src/librustc_resolve/build_reduced_graph.rs
+++ b/src/librustc_resolve/build_reduced_graph.rs
@@ -12,7 +12,7 @@ use crate::Namespace::{self, TypeNS, ValueNS, MacroNS};
 use crate::{resolve_error, resolve_struct_error, ResolutionError};
 
 use rustc::bug;
-use rustc::hir::def::*;
+use rustc::hir::def::{self, *};
 use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, LOCAL_CRATE, DefId};
 use rustc::ty;
 use rustc::middle::cstore::CrateStore;
@@ -44,6 +44,8 @@ use syntax_pos::{Span, DUMMY_SP};
 
 use log::debug;
 
+type Def = def::Def<NodeId>;
+
 impl<'a> ToNameBinding<'a> for (Module<'a>, ty::Visibility, Span, Mark) {
     fn to_name_binding(self, arenas: &'a ResolverArenas<'a>) -> &'a NameBinding<'a> {
         arenas.alloc_name_binding(NameBinding {
@@ -641,7 +643,11 @@ impl<'a> Resolver<'a> {
     }
 
     /// Builds the reduced graph for a single item in an external crate.
-    fn build_reduced_graph_for_external_crate_def(&mut self, parent: Module<'a>, child: Export) {
+    fn build_reduced_graph_for_external_crate_def(
+        &mut self,
+        parent: Module<'a>,
+        child: Export<ast::NodeId>,
+    ) {
         let Export { ident, def, vis, span } = child;
         // FIXME: We shouldn't create the gensym here, it should come from metadata,
         // but metadata cannot encode gensyms currently, so we create it here.
@@ -684,13 +690,14 @@ impl<'a> Resolver<'a> {
                 self.define(parent, ident, TypeNS, (module, vis, DUMMY_SP, expansion));
 
                 for child in self.cstore.item_children_untracked(def_id, self.session) {
-                    let ns = if let Def::AssociatedTy(..) = child.def { TypeNS } else { ValueNS };
+                    let def = child.def.map_id(|_| panic!("unexpected id"));
+                    let ns = if let Def::AssociatedTy(..) = def { TypeNS } else { ValueNS };
                     self.define(module, child.ident, ns,
-                                (child.def, ty::Visibility::Public, DUMMY_SP, expansion));
+                                (def, ty::Visibility::Public, DUMMY_SP, expansion));
 
                     if self.cstore.associated_item_cloned_untracked(child.def.def_id())
                            .method_has_self_argument {
-                        self.has_self.insert(child.def.def_id());
+                        self.has_self.insert(def.def_id());
                     }
                 }
                 module.populated.set(true);
@@ -777,6 +784,7 @@ impl<'a> Resolver<'a> {
         if module.populated.get() { return }
         let def_id = module.def_id().unwrap();
         for child in self.cstore.item_children_untracked(def_id, self.session) {
+            let child = child.map_id(|_| panic!("unexpected id"));
             self.build_reduced_graph_for_external_crate_def(module, child);
         }
         module.populated.set(true)
diff --git a/src/librustc_resolve/error_reporting.rs b/src/librustc_resolve/error_reporting.rs
index 931bce91d7d..9e3894dab0d 100644
--- a/src/librustc_resolve/error_reporting.rs
+++ b/src/librustc_resolve/error_reporting.rs
@@ -2,14 +2,16 @@ use std::cmp::Reverse;
 
 use errors::{Applicability, DiagnosticBuilder, DiagnosticId};
 use log::debug;
-use rustc::hir::def::{Def, CtorKind, Namespace::*};
+use rustc::hir::def::{self, CtorKind, Namespace::*};
 use rustc::hir::def_id::{CRATE_DEF_INDEX, DefId};
 use rustc::session::{Session, config::nightly_options};
-use syntax::ast::{Expr, ExprKind, Ident};
+use syntax::ast::{self, Expr, ExprKind, Ident};
 use syntax::ext::base::MacroKind;
 use syntax::symbol::{Symbol, keywords};
 use syntax_pos::{BytePos, Span};
 
+type Def = def::Def<ast::NodeId>;
+
 use crate::macros::ParentScope;
 use crate::resolve_imports::{ImportDirective, ImportDirectiveSubclass, ImportResolver};
 use crate::{import_candidate_to_enum_paths, is_self_type, is_self_value, path_names_to_string};
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index b34786d8f12..96aac977297 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -4,6 +4,7 @@
 #![feature(label_break_value)]
 #![feature(nll)]
 #![feature(rustc_diagnostic_macros)]
+#![feature(type_alias_enum_variants)]
 
 #![recursion_limit="256"]
 
@@ -20,7 +21,9 @@ use rustc::hir::{self, PrimTy, Bool, Char, Float, Int, Uint, Str};
 use rustc::middle::cstore::CrateStore;
 use rustc::session::Session;
 use rustc::lint;
-use rustc::hir::def::*;
+use rustc::hir::def::{
+    self, PathResolution, CtorKind, CtorOf, NonMacroAttrKind, DefMap, ImportMap, ExportMap
+};
 use rustc::hir::def::Namespace::*;
 use rustc::hir::def_id::{CRATE_DEF_INDEX, LOCAL_CRATE, DefId};
 use rustc::hir::{Freevar, FreevarMap, TraitCandidate, TraitMap, GlobMap};
@@ -66,6 +69,8 @@ use error_reporting::{find_span_of_binding_until_next_binding, extend_span_to_pr
 use resolve_imports::{ImportDirective, ImportDirectiveSubclass, NameResolution, ImportResolver};
 use macros::{InvocationData, LegacyBinding, ParentScope};
 
+type Def = def::Def<NodeId>;
+
 // N.B., this module needs to be declared first so diagnostics are
 // registered before they are used.
 mod diagnostics;
@@ -1563,7 +1568,7 @@ pub struct Resolver<'a> {
     import_map: ImportMap,
     pub freevars: FreevarMap,
     freevars_seen: NodeMap<NodeMap<usize>>,
-    pub export_map: ExportMap,
+    pub export_map: ExportMap<NodeId>,
     pub trait_map: TraitMap,
 
     /// A map from nodes to anonymous modules.
@@ -1773,7 +1778,7 @@ impl<'a> Resolver<'a> {
             }
         };
         let path = self.resolve_hir_path_cb(&path, is_value, |_, _, _| errored = true);
-        if errored || path.def == Def::Err {
+        if errored || path.def == def::Def::Err {
             Err(())
         } else {
             Ok(path)
@@ -1819,12 +1824,14 @@ impl<'a> Resolver<'a> {
 
         let segments: Vec<_> = segments.iter().map(|seg| {
             let mut hir_seg = hir::PathSegment::from_ident(seg.ident);
-            hir_seg.def = Some(self.def_map.get(&seg.id).map_or(Def::Err, |p| p.base_def()));
+            hir_seg.def = Some(self.def_map.get(&seg.id).map_or(def::Def::Err, |p| {
+                p.base_def().map_id(|_| panic!("unexpected node_id"))
+            }));
             hir_seg
         }).collect();
         hir::Path {
             span,
-            def,
+            def: def.map_id(|_| panic!("unexpected node_id")),
             segments: segments.into(),
         }
     }
diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs
index 21ca8ea369f..64f652d6eeb 100644
--- a/src/librustc_resolve/macros.rs
+++ b/src/librustc_resolve/macros.rs
@@ -8,7 +8,7 @@ use crate::build_reduced_graph::{BuildReducedGraphVisitor, IsMacroExport};
 use crate::resolve_imports::ImportResolver;
 use rustc::hir::def_id::{DefId, CRATE_DEF_INDEX, DefIndex,
                          CrateNum, DefIndexAddressSpace};
-use rustc::hir::def::{Def, NonMacroAttrKind};
+use rustc::hir::def::{self, NonMacroAttrKind};
 use rustc::hir::map::{self, DefCollector};
 use rustc::{ty, lint};
 use rustc::{bug, span_bug};
@@ -33,6 +33,8 @@ use std::cell::Cell;
 use std::{mem, ptr};
 use rustc_data_structures::sync::Lrc;
 
+type Def = def::Def<ast::NodeId>;
+
 #[derive(Clone, Debug)]
 pub struct InvocationData<'a> {
     def_index: DefIndex,
diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs
index 62af6e19603..58e0df1cd7c 100644
--- a/src/librustc_resolve/resolve_imports.rs
+++ b/src/librustc_resolve/resolve_imports.rs
@@ -21,7 +21,7 @@ use rustc::lint::builtin::{
     UNUSED_IMPORTS,
 };
 use rustc::hir::def_id::{CrateNum, DefId};
-use rustc::hir::def::*;
+use rustc::hir::def::{self, PathResolution, Export};
 use rustc::session::DiagnosticMessageId;
 use rustc::util::nodemap::FxHashSet;
 use rustc::{bug, span_bug};
@@ -39,6 +39,8 @@ use log::*;
 use std::cell::{Cell, RefCell};
 use std::{mem, ptr};
 
+type Def = def::Def<NodeId>;
+
 /// Contains data for specific types of import directives.
 #[derive(Clone, Debug)]
 pub enum ImportDirectiveSubclass<'a> {
@@ -1311,15 +1313,15 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
         if !is_redundant.is_empty() &&
             is_redundant.present_items().all(|is_redundant| is_redundant)
         {
+            let mut redundant_spans: Vec<_> = redundant_span.present_items().collect();
+            redundant_spans.sort();
+            redundant_spans.dedup();
             self.session.buffer_lint_with_diagnostic(
                 UNUSED_IMPORTS,
                 directive.id,
                 directive.span,
                 &format!("the item `{}` is imported redundantly", ident),
-                BuiltinLintDiagnostics::RedundantImport(
-                    redundant_span.present_items().collect(),
-                    ident,
-                ),
+                BuiltinLintDiagnostics::RedundantImport(redundant_spans, ident),
             );
         }
     }
diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs
index 7d400252594..a5ddf89d3d4 100644
--- a/src/librustc_save_analysis/dump_visitor.rs
+++ b/src/librustc_save_analysis/dump_visitor.rs
@@ -915,13 +915,13 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> {
         // process collected paths
         for (id, ident, immut) in collector.collected_idents {
             match self.save_ctxt.get_path_def(id) {
-                HirDef::Local(id) => {
+                HirDef::Local(hir_id) => {
                     let mut value = if immut == ast::Mutability::Immutable {
                         self.span.snippet(ident.span)
                     } else {
                         "<mutable>".to_owned()
                     };
-                    let hir_id = self.tcx.hir().node_to_hir_id(id);
+                    let id = self.tcx.hir().hir_to_node_id(hir_id);
                     let typ = self.save_ctxt
                         .tables
                         .node_type_opt(hir_id)
diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs
index d6923b4490d..ce0decaee49 100644
--- a/src/librustc_save_analysis/lib.rs
+++ b/src/librustc_save_analysis/lib.rs
@@ -659,7 +659,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
             Node::Binding(&hir::Pat {
                 node: hir::PatKind::Binding(_, canonical_id, ..),
                 ..
-            }) => HirDef::Local(self.tcx.hir().hir_to_node_id(canonical_id)),
+            }) => HirDef::Local(canonical_id),
 
             _ => HirDef::Err,
         }
@@ -707,7 +707,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
                 Some(Ref {
                     kind: RefKind::Variable,
                     span,
-                    ref_id: id_from_node_id(id, self),
+                    ref_id: id_from_node_id(self.tcx.hir().hir_to_node_id(id), self),
                 })
             }
             HirDef::Trait(def_id) if fn_type(path_seg) => {
diff --git a/src/librustc_typeck/check/callee.rs b/src/librustc_typeck/check/callee.rs
index 15ae39600f6..b8c0baff69b 100644
--- a/src/librustc_typeck/check/callee.rs
+++ b/src/librustc_typeck/check/callee.rs
@@ -350,7 +350,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
 
                     let def_span = match def {
                         Def::Err => None,
-                        Def::Local(id) | Def::Upvar(id, ..) => Some(self.tcx.hir().span(id)),
+                        Def::Local(id) | Def::Upvar(id, ..) => {
+                            Some(self.tcx.hir().span_by_hir_id(id))
+                        },
                         _ => def
                             .opt_def_id()
                             .and_then(|did| self.tcx.hir().span_if_local(did)),
diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs
index 8739147c621..8c1f4aabb1b 100644
--- a/src/librustc_typeck/check/demand.rs
+++ b/src/librustc_typeck/check/demand.rs
@@ -236,12 +236,12 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
     ) -> Option<(Span, &'static str, String)> {
         if let hir::ExprKind::Path(hir::QPath::Resolved(_, ref path)) = expr.node {
             if let hir::def::Def::Local(id) = path.def {
-                let parent = self.tcx.hir().get_parent_node(id);
+                let parent = self.tcx.hir().get_parent_node_by_hir_id(id);
                 if let Some(Node::Expr(hir::Expr {
                     hir_id,
                     node: hir::ExprKind::Closure(_, decl, ..),
                     ..
-                })) = self.tcx.hir().find(parent) {
+                })) = self.tcx.hir().find_by_hir_id(parent) {
                     let parent = self.tcx.hir().get_parent_node_by_hir_id(*hir_id);
                     if let (Some(Node::Expr(hir::Expr {
                         node: hir::ExprKind::MethodCall(path, span, expr),
diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs
index 31b7724d638..ff889c89770 100644
--- a/src/librustc_typeck/check/method/suggest.rs
+++ b/src/librustc_typeck/check/method/suggest.rs
@@ -249,14 +249,14 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                             ExprKind::Path(ref qpath) => {
                                 // local binding
                                 if let &QPath::Resolved(_, ref path) = &qpath {
-                                    if let hir::def::Def::Local(node_id) = path.def {
-                                        let span = tcx.hir().span(node_id);
+                                    if let hir::def::Def::Local(hir_id) = path.def {
+                                        let span = tcx.hir().span_by_hir_id(hir_id);
                                         let snippet = tcx.sess.source_map().span_to_snippet(span)
                                             .unwrap();
                                         let filename = tcx.sess.source_map().span_to_filename(span);
 
-                                        let parent_node = self.tcx.hir().get(
-                                            self.tcx.hir().get_parent_node(node_id),
+                                        let parent_node = self.tcx.hir().get_by_hir_id(
+                                            self.tcx.hir().get_parent_node_by_hir_id(hir_id),
                                         );
                                         let msg = format!(
                                             "you must specify a type for this binding, like `{}`",
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index 313ed19b945..0f076aaa205 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -5397,8 +5397,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         let tcx = self.tcx;
 
         match def {
-            Def::Local(nid) | Def::Upvar(nid, ..) => {
-                let hid = self.tcx.hir().node_to_hir_id(nid);
+            Def::Local(hid) | Def::Upvar(hid, ..) => {
                 let ty = self.local_ty(span, hid).decl_ty;
                 let ty = self.normalize_associated_types_in(span, &ty);
                 self.write_ty(hir_id, ty);
diff --git a/src/librustc_typeck/check/upvar.rs b/src/librustc_typeck/check/upvar.rs
index a76dfdd69ba..dc66c6c93d0 100644
--- a/src/librustc_typeck/check/upvar.rs
+++ b/src/librustc_typeck/check/upvar.rs
@@ -126,7 +126,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
             for freevar in freevars {
                 let upvar_id = ty::UpvarId {
                     var_path: ty::UpvarPath {
-                        hir_id: self.tcx.hir().node_to_hir_id(freevar.var_id()),
+                        hir_id: freevar.var_id(),
                     },
                     closure_expr_id: LocalDefId::from_def_id(closure_def_id),
                 };
@@ -250,8 +250,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
             freevars
                 .iter()
                 .map(|freevar| {
-                    let var_node_id = freevar.var_id();
-                    let var_hir_id = tcx.hir().node_to_hir_id(var_node_id);
+                    let var_hir_id = freevar.var_id();
                     let freevar_ty = self.node_ty(var_hir_id);
                     let upvar_id = ty::UpvarId {
                         var_path: ty::UpvarPath { hir_id: var_hir_id },
@@ -261,7 +260,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
 
                     debug!(
                         "var_id={:?} freevar_ty={:?} capture={:?}",
-                        var_node_id, freevar_ty, capture
+                        var_hir_id, freevar_ty, capture
                     );
 
                     match capture {
diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs
index dbc55b62ef8..a62b3368648 100644
--- a/src/librustdoc/passes/collect_intra_doc_links.rs
+++ b/src/librustdoc/passes/collect_intra_doc_links.rs
@@ -429,12 +429,12 @@ fn macro_resolve(cx: &DocContext<'_>, path_str: &str) -> Option<Def> {
                 // skip proc-macro stubs, they'll cause `get_macro` to crash
             } else {
                 if let SyntaxExtension::DeclMacro { .. } = *resolver.get_macro(def) {
-                    return Some(def);
+                    return Some(def.map_id(|_| panic!("unexpected id")));
                 }
             }
         }
         if let Some(def) = resolver.all_macros.get(&Symbol::intern(path_str)) {
-            return Some(*def);
+            return Some(def.map_id(|_| panic!("unexpected id")));
         }
         None
     })
diff --git a/src/libstd/io/buffered.rs b/src/libstd/io/buffered.rs
index 3370a447fcc..bf406bb9b0b 100644
--- a/src/libstd/io/buffered.rs
+++ b/src/libstd/io/buffered.rs
@@ -601,7 +601,7 @@ impl<W: Write> Write for BufWriter<W> {
         }
         if buf.len() >= self.buf.capacity() {
             self.panicked = true;
-            let r = self.inner.as_mut().unwrap().write(buf);
+            let r = self.get_mut().write(buf);
             self.panicked = false;
             r
         } else {
@@ -616,7 +616,7 @@ impl<W: Write> Write for BufWriter<W> {
         }
         if total_len >= self.buf.capacity() {
             self.panicked = true;
-            let r = self.inner.as_mut().unwrap().write_vectored(bufs);
+            let r = self.get_mut().write_vectored(bufs);
             self.panicked = false;
             r
         } else {
diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs
index 393f52e7de5..d2fb67f8c06 100644
--- a/src/libsyntax_pos/symbol.rs
+++ b/src/libsyntax_pos/symbol.rs
@@ -136,7 +136,7 @@ impl Decodable for Ident {
 }
 
 /// A symbol is an interned or gensymed string. The use of `newtype_index!` means
-/// that `Option<Symbol>` only takes up 4 bytes, because `newtype_index! reserves
+/// that `Option<Symbol>` only takes up 4 bytes, because `newtype_index!` reserves
 /// the last 256 values for tagging purposes.
 ///
 /// Note that `Symbol` cannot directly be a `newtype_index!` because it implements
diff --git a/src/test/mir-opt/inline-closure-borrows-arg.rs b/src/test/mir-opt/inline-closure-borrows-arg.rs
index d09ddce09c5..2c30c7f3651 100644
--- a/src/test/mir-opt/inline-closure-borrows-arg.rs
+++ b/src/test/mir-opt/inline-closure-borrows-arg.rs
@@ -20,7 +20,7 @@ fn foo<T: Copy>(_t: T, q: &i32) -> i32 {
 // ...
 // bb0: {
 //     ...
-//     _3 = [closure@HirId { owner: DefIndex(0:4), local_id: 27 }];
+//     _3 = [closure@HirId { owner: DefIndex(0:4), local_id: 29 }];
 //     ...
 //     _4 = &_3;
 //     ...
diff --git a/src/test/mir-opt/inline-closure.rs b/src/test/mir-opt/inline-closure.rs
index 436a8c20e2b..8116a445467 100644
--- a/src/test/mir-opt/inline-closure.rs
+++ b/src/test/mir-opt/inline-closure.rs
@@ -16,7 +16,7 @@ fn foo<T: Copy>(_t: T, q: i32) -> i32 {
 // ...
 // bb0: {
 //     ...
-//     _3 = [closure@HirId { owner: DefIndex(0:4), local_id: 11 }];
+//     _3 = [closure@HirId { owner: DefIndex(0:4), local_id: 13 }];
 //     ...
 //     _4 = &_3;
 //     ...
diff --git a/src/test/mir-opt/retag.rs b/src/test/mir-opt/retag.rs
index 3b333b5431c..1f8abf10fa5 100644
--- a/src/test/mir-opt/retag.rs
+++ b/src/test/mir-opt/retag.rs
@@ -98,7 +98,7 @@ fn main() {
 // }
 // END rustc.main.EraseRegions.after.mir
 // START rustc.main-{{closure}}.EraseRegions.after.mir
-// fn main::{{closure}}#0(_1: &[closure@HirId { owner: DefIndex(0:7), local_id: 70 }], _2: &i32) -> &i32 {
+// fn main::{{closure}}#0(_1: &[closure@HirId { owner: DefIndex(0:7), local_id: 72 }], _2: &i32) -> &i32 {
 //     ...
 //     bb0: {
 //         Retag([fn entry] _1);
diff --git a/src/test/ui/issues/issue-59896.rs b/src/test/ui/issues/issue-59896.rs
new file mode 100644
index 00000000000..cecf2c5c22b
--- /dev/null
+++ b/src/test/ui/issues/issue-59896.rs
@@ -0,0 +1,10 @@
+#![deny(unused_imports)]
+
+struct S;
+
+fn main() {
+    use S;  //~ ERROR the item `S` is imported redundantly
+
+    let _s = S;
+}
+
diff --git a/src/test/ui/issues/issue-59896.stderr b/src/test/ui/issues/issue-59896.stderr
new file mode 100644
index 00000000000..ef78f27fa69
--- /dev/null
+++ b/src/test/ui/issues/issue-59896.stderr
@@ -0,0 +1,17 @@
+error: the item `S` is imported redundantly
+  --> $DIR/issue-59896.rs:6:9
+   |
+LL | struct S;
+   | --------- the item `S` is already defined here
+...
+LL |     use S;
+   |         ^
+   |
+note: lint level defined here
+  --> $DIR/issue-59896.rs:1:9
+   |
+LL | #![deny(unused_imports)]
+   |         ^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/rfc-2008-non-exhaustive/variants_fictive_visibility.rs b/src/test/ui/rfc-2008-non-exhaustive/variants_fictive_visibility.rs
new file mode 100644
index 00000000000..62f6e4463f9
--- /dev/null
+++ b/src/test/ui/rfc-2008-non-exhaustive/variants_fictive_visibility.rs
@@ -0,0 +1,12 @@
+// compile-pass
+// aux-build:variants.rs
+
+extern crate variants;
+
+const S: u8 = 0;
+
+// OK, `Struct` in value namespace is crate-private, so it's filtered away
+// and there's no conflict with the previously defined `const S`.
+use variants::NonExhaustiveVariants::Struct as S;
+
+fn main() {}