about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock30
-rw-r--r--appveyor.yml5
-rw-r--r--src/bootstrap/doc.rs2
m---------src/doc/edition-guide0
-rw-r--r--src/libcore/benches/iter.rs32
-rw-r--r--src/libcore/iter/adapters/mod.rs37
-rw-r--r--src/libcore/mem.rs8
-rw-r--r--src/libcore/pin.rs2
-rw-r--r--src/libcore/str/mod.rs6
-rw-r--r--src/librustc/Cargo.toml4
-rw-r--r--src/librustc/hir/intravisit.rs3
-rw-r--r--src/librustc/hir/lowering.rs67
-rw-r--r--src/librustc/hir/map/collector.rs4
-rw-r--r--src/librustc/hir/map/mod.rs6
-rw-r--r--src/librustc/hir/mod.rs13
-rw-r--r--src/librustc/hir/print.rs10
-rw-r--r--src/librustc/ich/impls_hir.rs14
-rw-r--r--src/librustc/ich/impls_mir.rs6
-rw-r--r--src/librustc/lint/context.rs15
-rw-r--r--src/librustc/lint/mod.rs20
-rw-r--r--src/librustc/middle/dead.rs117
-rw-r--r--src/librustc/middle/reachable.rs2
-rw-r--r--src/librustc/middle/resolve_lifetime.rs8
-rw-r--r--src/librustc/middle/stability.rs8
-rw-r--r--src/librustc/mir/mod.rs32
-rw-r--r--src/librustc/mir/tcx.rs6
-rw-r--r--src/librustc/mir/visit.rs6
-rw-r--r--src/librustc/session/mod.rs30
-rw-r--r--src/librustc/traits/specialize/mod.rs4
-rw-r--r--src/librustc/ty/context.rs33
-rw-r--r--src/librustc/ty/layout.rs22
-rw-r--r--src/librustc/ty/query/job.rs5
-rw-r--r--src/librustc_codegen_ssa/mir/analyze.rs5
-rw-r--r--src/librustc_codegen_ssa/mir/block.rs14
-rw-r--r--src/librustc_codegen_ssa/mir/operand.rs2
-rw-r--r--src/librustc_codegen_ssa/mir/place.rs12
-rw-r--r--src/librustc_codegen_ssa/mir/rvalue.rs2
-rw-r--r--src/librustc_codegen_ssa/mir/statement.rs2
-rw-r--r--src/librustc_codegen_utils/symbol_names_test.rs11
-rw-r--r--src/librustc_data_structures/Cargo.toml6
-rw-r--r--src/librustc_data_structures/jobserver.rs156
-rw-r--r--src/librustc_data_structures/lib.rs1
-rw-r--r--src/librustc_driver/Cargo.toml2
-rw-r--r--src/librustc_driver/driver.rs4
-rw-r--r--src/librustc_incremental/assert_dep_graph.rs18
-rw-r--r--src/librustc_incremental/persist/dirty_clean.rs18
-rw-r--r--src/librustc_lint/builtin.rs41
-rw-r--r--src/librustc_metadata/encoder.rs4
-rw-r--r--src/librustc_mir/borrow_check/borrow_set.rs2
-rw-r--r--src/librustc_mir/borrow_check/error_reporting.rs49
-rw-r--r--src/librustc_mir/borrow_check/mod.rs46
-rw-r--r--src/librustc_mir/borrow_check/move_errors.rs2
-rw-r--r--src/librustc_mir/borrow_check/mutability_errors.rs35
-rw-r--r--src/librustc_mir/borrow_check/nll/constraint_generation.rs4
-rw-r--r--src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs29
-rw-r--r--src/librustc_mir/borrow_check/nll/invalidation.rs4
-rw-r--r--src/librustc_mir/borrow_check/nll/type_check/mod.rs18
-rw-r--r--src/librustc_mir/borrow_check/path_utils.rs8
-rw-r--r--src/librustc_mir/borrow_check/place_ext.rs14
-rw-r--r--src/librustc_mir/borrow_check/places_conflict.rs26
-rw-r--r--src/librustc_mir/borrow_check/prefixes.rs13
-rw-r--r--src/librustc_mir/borrow_check/used_muts.rs6
-rw-r--r--src/librustc_mir/build/expr/as_operand.rs2
-rw-r--r--src/librustc_mir/build/expr/as_place.rs20
-rw-r--r--src/librustc_mir/build/expr/as_rvalue.rs27
-rw-r--r--src/librustc_mir/build/expr/as_temp.rs4
-rw-r--r--src/librustc_mir/build/expr/into.rs2
-rw-r--r--src/librustc_mir/build/expr/stmt.rs17
-rw-r--r--src/librustc_mir/build/matches/mod.rs10
-rw-r--r--src/librustc_mir/build/misc.rs2
-rw-r--r--src/librustc_mir/build/mod.rs6
-rw-r--r--src/librustc_mir/build/scope.rs4
-rw-r--r--src/librustc_mir/dataflow/drop_flag_effects.rs2
-rw-r--r--src/librustc_mir/dataflow/impls/borrowed_locals.rs6
-rw-r--r--src/librustc_mir/dataflow/impls/borrows.rs6
-rw-r--r--src/librustc_mir/dataflow/impls/mod.rs3
-rw-r--r--src/librustc_mir/dataflow/move_paths/builder.rs14
-rw-r--r--src/librustc_mir/dataflow/move_paths/mod.rs8
-rw-r--r--src/librustc_mir/hair/cx/expr.rs2
-rw-r--r--src/librustc_mir/hair/pattern/check_match.rs16
-rw-r--r--src/librustc_mir/hair/pattern/mod.rs3
-rw-r--r--src/librustc_mir/interpret/operand.rs5
-rw-r--r--src/librustc_mir/interpret/place.rs10
-rw-r--r--src/librustc_mir/interpret/terminator.rs8
-rw-r--r--src/librustc_mir/lints.rs12
-rw-r--r--src/librustc_mir/monomorphize/collector.rs2
-rw-r--r--src/librustc_mir/shim.rs54
-rw-r--r--src/librustc_mir/transform/add_moves_for_packed_drops.rs4
-rw-r--r--src/librustc_mir/transform/add_retag.rs8
-rw-r--r--src/librustc_mir/transform/check_unsafety.rs22
-rw-r--r--src/librustc_mir/transform/const_prop.rs18
-rw-r--r--src/librustc_mir/transform/copy_prop.rs24
-rw-r--r--src/librustc_mir/transform/elaborate_drops.rs6
-rw-r--r--src/librustc_mir/transform/generator.rs20
-rw-r--r--src/librustc_mir/transform/inline.rs16
-rw-r--r--src/librustc_mir/transform/instcombine.rs4
-rw-r--r--src/librustc_mir/transform/lower_128bit.rs4
-rw-r--r--src/librustc_mir/transform/promote_consts.rs14
-rw-r--r--src/librustc_mir/transform/qualify_consts.rs36
-rw-r--r--src/librustc_mir/transform/qualify_min_const_fn.rs7
-rw-r--r--src/librustc_mir/transform/remove_noop_landing_pads.rs2
-rw-r--r--src/librustc_mir/transform/rustc_peek.rs4
-rw-r--r--src/librustc_mir/transform/uniform_array_move_out.rs22
-rw-r--r--src/librustc_mir/util/elaborate_drops.rs39
-rw-r--r--src/librustc_mir/util/graphviz.rs10
-rw-r--r--src/librustc_mir/util/pretty.rs2
-rw-r--r--src/librustc_privacy/lib.rs85
-rw-r--r--src/librustc_traits/lowering/mod.rs12
-rw-r--r--src/librustc_typeck/astconv.rs7
-rw-r--r--src/librustc_typeck/check/_match.rs6
-rw-r--r--src/librustc_typeck/check/mod.rs32
-rw-r--r--src/librustc_typeck/check/wfcheck.rs31
-rw-r--r--src/librustc_typeck/check/writeback.rs2
-rw-r--r--src/librustc_typeck/check_unused.rs19
-rw-r--r--src/librustc_typeck/coherence/inherent_impls_overlap.rs8
-rw-r--r--src/librustc_typeck/collect.rs48
-rw-r--r--src/librustc_typeck/lib.rs4
-rw-r--r--src/librustc_typeck/variance/constraints.rs25
-rw-r--r--src/librustc_typeck/variance/solve.rs2
-rw-r--r--src/librustc_typeck/variance/terms.rs31
-rw-r--r--src/librustdoc/clean/auto_trait.rs1
-rw-r--r--src/librustdoc/clean/blanket_impl.rs1
-rw-r--r--src/librustdoc/clean/mod.rs16
-rw-r--r--src/librustdoc/passes/collect_intra_doc_links.rs4
-rw-r--r--src/librustdoc/passes/mod.rs10
-rw-r--r--src/libtest/lib.rs39
-rw-r--r--src/test/ui-fulldeps/auxiliary/lint_tool_test.rs6
-rw-r--r--src/tools/tidy/src/deps.rs12
-rw-r--r--src/tools/tidy/src/features.rs2
-rw-r--r--src/tools/tidy/src/lib.rs3
130 files changed, 1130 insertions, 894 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 381322bc421..4fe81951170 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -2358,8 +2358,8 @@ dependencies = [
  "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "polonius-engine 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-rayon 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-rayon-core 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-rayon 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-rayon-core 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc_apfloat 0.0.0",
  "rustc_data_structures 0.0.0",
  "rustc_errors 0.0.0",
@@ -2409,8 +2409,8 @@ dependencies = [
  "rustc-ap-rustc_cratesio_shim 373.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-ap-serialize 373.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-rayon 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-rayon-core 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-rayon 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-rayon-core 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "stable_deref_trait 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -2508,23 +2508,23 @@ dependencies = [
 
 [[package]]
 name = "rustc-rayon"
-version = "0.1.1"
+version = "0.1.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
+ "crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-rayon-core 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-rayon-core 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "rustc-rayon-core"
-version = "0.1.1"
+version = "0.1.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)",
  "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -2672,11 +2672,13 @@ dependencies = [
  "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "ena 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "graphviz 0.0.0",
+ "jobserver 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-rayon 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-rayon-core 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-rayon 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-rayon-core 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc_cratesio_shim 0.0.0",
  "serialize 0.0.0",
  "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2692,7 +2694,7 @@ dependencies = [
  "graphviz 0.0.0",
  "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc 0.0.0",
- "rustc-rayon 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-rayon 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc_allocator 0.0.0",
  "rustc_borrowck 0.0.0",
  "rustc_codegen_utils 0.0.0",
@@ -2758,7 +2760,7 @@ version = "0.0.0"
 dependencies = [
  "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc 0.0.0",
- "rustc-rayon 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-rayon 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc_allocator 0.0.0",
  "rustc_borrowck 0.0.0",
  "rustc_codegen_utils 0.0.0",
@@ -4190,8 +4192,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum rustc-ap-syntax_pos 373.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8e4f88a1213562373cee9de5a1d77bbf16dd706030304af041c9733492fcc952"
 "checksum rustc-demangle 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "82ae957aa1b3055d8e086486723c0ccd3d7b8fa190ae8fa2e35543b6171c810e"
 "checksum rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7540fc8b0c49f096ee9c961cda096467dce8084bec6bdca2fc83895fd9b28cb8"
-"checksum rustc-rayon 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c6d5a683c6ba4ed37959097e88d71c9e8e26659a3cb5be8b389078e7ad45306"
-"checksum rustc-rayon-core 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "40f06724db71e18d68b3b946fdf890ca8c921d9edccc1404fdfdb537b0d12649"
+"checksum rustc-rayon 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8d98c51d9cbbe810c8b6693236d3412d8cd60513ff27a3e1b6af483dca0af544"
+"checksum rustc-rayon-core 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "526e7b6d2707a5b9bec3927d424ad70fa3cfc68e0ac1b75e46cdbbc95adc5108"
 "checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda"
 "checksum rustc_tools_util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b3c5a95edfa0c893236ae4778bb7c4752760e4c0d245e19b5eff33c5aa5eb9dc"
 "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
diff --git a/appveyor.yml b/appveyor.yml
index 3a0cb8b4fce..d70ad54b1c8 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -5,11 +5,6 @@ environment:
   # server goes down presumably. See #43333 for more info
   CARGO_HTTP_CHECK_REVOKE: false
 
-  # Execute the builds on GCE instead of Hyper-V. Those builders have a 3-4
-  # minute startup overhead, but AppVeyor support recommended this as a
-  # possible solution for #58160 (spurious 259 exit codes)
-  appveyor_build_worker_cloud: gce
-
   matrix:
   # 32/64 bit MSVC tests
   - MSYS_BITS: 64
diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs
index 40f0e5ede8b..e0ad0422a6c 100644
--- a/src/bootstrap/doc.rs
+++ b/src/bootstrap/doc.rs
@@ -60,7 +60,7 @@ macro_rules! book {
 // NOTE: When adding a book here, make sure to ALSO build the book by
 // adding a build step in `src/bootstrap/builder.rs`!
 book!(
-    EditionGuide, "src/doc/edition-guide", "edition-guide", RustbookVersion::MdBook1;
+    EditionGuide, "src/doc/edition-guide", "edition-guide", RustbookVersion::MdBook2;
     EmbeddedBook, "src/doc/embedded-book", "embedded-book", RustbookVersion::MdBook2;
     Nomicon, "src/doc/nomicon", "nomicon", RustbookVersion::MdBook1;
     Reference, "src/doc/reference", "reference", RustbookVersion::MdBook1;
diff --git a/src/doc/edition-guide b/src/doc/edition-guide
-Subproject 419edb885ec1a98c0747b3907003d79e3e6b93a
+Subproject 5f3cc2a5618700efcde3bc00799744f21fa9ad2
diff --git a/src/libcore/benches/iter.rs b/src/libcore/benches/iter.rs
index fe852e42b5c..1dd2bd3ee78 100644
--- a/src/libcore/benches/iter.rs
+++ b/src/libcore/benches/iter.rs
@@ -185,13 +185,13 @@ bench_sums! {
 bench_sums! {
     bench_filter_sum,
     bench_filter_ref_sum,
-    (0i64..1000000).filter(|x| x % 2 == 0)
+    (0i64..1000000).filter(|x| x % 3 == 0)
 }
 
 bench_sums! {
     bench_filter_chain_sum,
     bench_filter_chain_ref_sum,
-    (0i64..1000000).chain(0..1000000).filter(|x| x % 2 == 0)
+    (0i64..1000000).chain(0..1000000).filter(|x| x % 3 == 0)
 }
 
 bench_sums! {
@@ -306,3 +306,31 @@ fn bench_skip_then_zip(b: &mut Bencher) {
         assert_eq!(s, 2009900);
     });
 }
+
+#[bench]
+fn bench_filter_count(b: &mut Bencher) {
+    b.iter(|| {
+        (0i64..1000000).map(black_box).filter(|x| x % 3 == 0).count()
+    })
+}
+
+#[bench]
+fn bench_filter_ref_count(b: &mut Bencher) {
+    b.iter(|| {
+        (0i64..1000000).map(black_box).by_ref().filter(|x| x % 3 == 0).count()
+    })
+}
+
+#[bench]
+fn bench_filter_chain_count(b: &mut Bencher) {
+    b.iter(|| {
+        (0i64..1000000).chain(0..1000000).map(black_box).filter(|x| x % 3 == 0).count()
+    })
+}
+
+#[bench]
+fn bench_filter_chain_ref_count(b: &mut Bencher) {
+    b.iter(|| {
+        (0i64..1000000).chain(0..1000000).map(black_box).by_ref().filter(|x| x % 3 == 0).count()
+    })
+}
diff --git a/src/libcore/iter/adapters/mod.rs b/src/libcore/iter/adapters/mod.rs
index bca1b76dbb9..d4ad22c16bb 100644
--- a/src/libcore/iter/adapters/mod.rs
+++ b/src/libcore/iter/adapters/mod.rs
@@ -681,12 +681,7 @@ impl<I: Iterator, P> Iterator for Filter<I, P> where P: FnMut(&I::Item) -> bool
 
     #[inline]
     fn next(&mut self) -> Option<I::Item> {
-        for x in &mut self.iter {
-            if (self.predicate)(&x) {
-                return Some(x);
-            }
-        }
-        None
+        self.try_for_each(Err).err()
     }
 
     #[inline]
@@ -707,12 +702,9 @@ impl<I: Iterator, P> Iterator for Filter<I, P> where P: FnMut(&I::Item) -> bool
     // Using the branchless version will also simplify the LLVM byte code, thus
     // leaving more budget for LLVM optimizations.
     #[inline]
-    fn count(mut self) -> usize {
-        let mut count = 0;
-        for x in &mut self.iter {
-            count += (self.predicate)(&x) as usize;
-        }
-        count
+    fn count(self) -> usize {
+        let mut predicate = self.predicate;
+        self.iter.map(|x| predicate(&x) as usize).sum()
     }
 
     #[inline]
@@ -746,12 +738,7 @@ impl<I: DoubleEndedIterator, P> DoubleEndedIterator for Filter<I, P>
 {
     #[inline]
     fn next_back(&mut self) -> Option<I::Item> {
-        for x in self.iter.by_ref().rev() {
-            if (self.predicate)(&x) {
-                return Some(x);
-            }
-        }
-        None
+        self.try_rfold((), |_, x| Err(x)).err()
     }
 
     #[inline]
@@ -820,12 +807,7 @@ impl<B, I: Iterator, F> Iterator for FilterMap<I, F>
 
     #[inline]
     fn next(&mut self) -> Option<B> {
-        for x in self.iter.by_ref() {
-            if let Some(y) = (self.f)(x) {
-                return Some(y);
-            }
-        }
-        None
+        self.try_for_each(Err).err()
     }
 
     #[inline]
@@ -863,12 +845,7 @@ impl<B, I: DoubleEndedIterator, F> DoubleEndedIterator for FilterMap<I, F>
 {
     #[inline]
     fn next_back(&mut self) -> Option<B> {
-        for x in self.iter.by_ref().rev() {
-            if let Some(y) = (self.f)(x) {
-                return Some(y);
-            }
-        }
-        None
+        self.try_rfold((), |_, x| Err(x)).err()
     }
 
     #[inline]
diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs
index f41d293e80a..94f342e7e8e 100644
--- a/src/libcore/mem.rs
+++ b/src/libcore/mem.rs
@@ -900,10 +900,16 @@ pub fn discriminant<T>(v: &T) -> Discriminant<T> {
     }
 }
 
+// FIXME: Reference `MaybeUninit` from these docs, once that is stable.
 /// A wrapper to inhibit compiler from automatically calling `T`’s destructor.
 ///
 /// This wrapper is 0-cost.
 ///
+/// `ManuallyDrop<T>` is subject to the same layout optimizations as `T`.
+/// As a consequence, it has *no effect* on the assumptions that the compiler makes
+/// about all values being initialized at their type.  In particular, initializing
+/// a `ManuallyDrop<&mut T>` with [`mem::zeroed`] is undefined behavior.
+///
 /// # Examples
 ///
 /// This wrapper helps with explicitly documenting the drop order dependencies between fields of
@@ -935,6 +941,8 @@ pub fn discriminant<T>(v: &T) -> Discriminant<T> {
 ///     }
 /// }
 /// ```
+///
+/// [`mem::zeroed`]: fn.zeroed.html
 #[stable(feature = "manually_drop", since = "1.20.0")]
 #[lang = "manually_drop"]
 #[derive(Copy, Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
diff --git a/src/libcore/pin.rs b/src/libcore/pin.rs
index f9f20dcea9e..835357b4e01 100644
--- a/src/libcore/pin.rs
+++ b/src/libcore/pin.rs
@@ -215,7 +215,7 @@
 //!     had a method `fn get_pin_mut(self: Pin<&mut Self>) -> Pin<&mut T>`.
 //!     Then we could do the following:
 //!     ```compile_fail
-//!     fn exploit_ref_cell<T>(rc: Pin<&mut RefCell<T>) {
+//!     fn exploit_ref_cell<T>(rc: Pin<&mut RefCell<T>>) {
 //!         { let p = rc.as_mut().get_pin_mut(); } // Here we get pinned access to the `T`.
 //!         let rc_shr: &RefCell<T> = rc.into_ref().get_ref();
 //!         let b = rc_shr.borrow_mut();
diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs
index 8b51d846514..53334adadb8 100644
--- a/src/libcore/str/mod.rs
+++ b/src/libcore/str/mod.rs
@@ -3965,7 +3965,7 @@ impl str {
         me.make_ascii_lowercase()
     }
 
-    /// Return an iterator that escapes each char in `s` with [`char::escape_debug`].
+    /// Return an iterator that escapes each char in `self` with [`char::escape_debug`].
     ///
     /// Note: only extended grapheme codepoints that begin the string will be
     /// escaped.
@@ -4013,7 +4013,7 @@ impl str {
         }
     }
 
-    /// Return an iterator that escapes each char in `s` with [`char::escape_default`].
+    /// Return an iterator that escapes each char in `self` with [`char::escape_default`].
     ///
     /// [`char::escape_default`]: ../std/primitive.char.html#method.escape_default
     ///
@@ -4051,7 +4051,7 @@ impl str {
         EscapeDefault { inner: self.chars().flat_map(CharEscapeDefault) }
     }
 
-    /// Return an iterator that escapes each char in `s` with [`char::escape_unicode`].
+    /// Return an iterator that escapes each char in `self` with [`char::escape_unicode`].
     ///
     /// [`char::escape_unicode`]: ../std/primitive.char.html#method.escape_unicode
     ///
diff --git a/src/librustc/Cargo.toml b/src/librustc/Cargo.toml
index e3557132a12..26a27ea88e2 100644
--- a/src/librustc/Cargo.toml
+++ b/src/librustc/Cargo.toml
@@ -20,8 +20,8 @@ num_cpus = "1.0"
 scoped-tls = "1.0"
 log = { version = "0.4", features = ["release_max_level_info", "std"] }
 polonius-engine = "0.6.2"
-rustc-rayon = "0.1.1"
-rustc-rayon-core = "0.1.1"
+rustc-rayon = "0.1.2"
+rustc-rayon-core = "0.1.2"
 rustc_apfloat = { path = "../librustc_apfloat" }
 rustc_target = { path = "../librustc_target" }
 rustc_data_structures = { path = "../librustc_data_structures" }
diff --git a/src/librustc/hir/intravisit.rs b/src/librustc/hir/intravisit.rs
index 8e4b9a5e8e6..0aeac8cc440 100644
--- a/src/librustc/hir/intravisit.rs
+++ b/src/librustc/hir/intravisit.rs
@@ -878,7 +878,6 @@ pub fn walk_trait_item_ref<'v, V: Visitor<'v>>(visitor: &mut V, trait_item_ref:
 pub fn walk_impl_item<'v, V: Visitor<'v>>(visitor: &mut V, impl_item: &'v ImplItem) {
     // N.B., deliberately force a compilation error if/when new fields are added.
     let ImplItem {
-        id: _,
         hir_id: _,
         ident,
         ref vis,
@@ -1106,7 +1105,7 @@ pub fn walk_arm<'v, V: Visitor<'v>>(visitor: &mut V, arm: &'v Arm) {
 }
 
 pub fn walk_vis<'v, V: Visitor<'v>>(visitor: &mut V, vis: &'v Visibility) {
-    if let VisibilityKind::Restricted { ref path, id: _, hir_id } = vis.node {
+    if let VisibilityKind::Restricted { ref path, hir_id } = vis.node {
         visitor.visit_id(hir_id);
         visitor.visit_path(path, hir_id)
     }
diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs
index 19bb7f41e1b..a97ea7da7f1 100644
--- a/src/librustc/hir/lowering.rs
+++ b/src/librustc/hir/lowering.rs
@@ -1151,10 +1151,9 @@ impl<'a> LoweringContext<'a> {
 
     fn lower_ty_binding(&mut self, b: &TypeBinding,
                         itctx: ImplTraitContext<'_>) -> hir::TypeBinding {
-        let LoweredNodeId { node_id, hir_id } = self.lower_node_id(b.id);
+        let LoweredNodeId { node_id: _, hir_id } = self.lower_node_id(b.id);
 
         hir::TypeBinding {
-            id: node_id,
             hir_id,
             ident: b.ident,
             ty: self.lower_ty(&b.ty, itctx),
@@ -1982,14 +1981,13 @@ impl<'a> LoweringContext<'a> {
                     let LoweredNodeId { node_id: _, hir_id } = this.next_id();
                     hir::Ty { node: hir::TyKind::Tup(tys), hir_id, span }
                 };
-                let LoweredNodeId { node_id, hir_id } = this.next_id();
+                let LoweredNodeId { node_id: _, hir_id } = this.next_id();
 
                 (
                     hir::GenericArgs {
                         args: hir_vec![GenericArg::Type(mk_tup(this, inputs, span))],
                         bindings: hir_vec![
                             hir::TypeBinding {
-                                id: node_id,
                                 hir_id,
                                 ident: Ident::from_str(FN_OUTPUT_NAME),
                                 ty: output
@@ -2008,7 +2006,7 @@ impl<'a> LoweringContext<'a> {
     }
 
     fn lower_local(&mut self, l: &Local) -> (hir::Local, SmallVec<[hir::ItemId; 1]>) {
-        let LoweredNodeId { node_id, hir_id } = self.lower_node_id(l.id);
+        let LoweredNodeId { node_id: _, hir_id } = self.lower_node_id(l.id);
         let mut ids = SmallVec::<[hir::ItemId; 1]>::new();
         if self.sess.features_untracked().impl_trait_in_bindings {
             if let Some(ref ty) = l.ty {
@@ -2018,7 +2016,6 @@ impl<'a> LoweringContext<'a> {
         }
         let parent_def_id = DefId::local(self.current_hir_id_owner.last().unwrap().0);
         (hir::Local {
-            id: node_id,
             hir_id,
             ty: l.ty
                 .as_ref()
@@ -2045,9 +2042,8 @@ impl<'a> LoweringContext<'a> {
     }
 
     fn lower_arg(&mut self, arg: &Arg) -> hir::Arg {
-        let LoweredNodeId { node_id, hir_id } = self.lower_node_id(arg.id);
+        let LoweredNodeId { node_id: _, hir_id } = self.lower_node_id(arg.id);
         hir::Arg {
-            id: node_id,
             hir_id,
             pat: self.lower_pat(&arg.pat),
         }
@@ -2327,13 +2323,12 @@ impl<'a> LoweringContext<'a> {
             };
 
             // "<Output = T>"
-            let LoweredNodeId { node_id, hir_id } = this.next_id();
+            let LoweredNodeId { node_id: _, hir_id } = this.next_id();
             let future_params = P(hir::GenericArgs {
                 args: hir_vec![],
                 bindings: hir_vec![hir::TypeBinding {
                     ident: Ident::from_str(FN_OUTPUT_NAME),
                     ty: output_ty,
-                    id: node_id,
                     hir_id,
                     span,
                 }],
@@ -2343,13 +2338,12 @@ impl<'a> LoweringContext<'a> {
             let future_path =
                 this.std_path(span, &["future", "Future"], Some(future_params), false);
 
-            let LoweredNodeId { node_id, hir_id } = this.next_id();
+            let LoweredNodeId { node_id: _, hir_id } = this.next_id();
             let mut bounds = vec![
                 hir::GenericBound::Trait(
                     hir::PolyTraitRef {
                         trait_ref: hir::TraitRef {
                             path: future_path,
-                            ref_id: node_id,
                             hir_ref_id: hir_id,
                         },
                         bound_generic_params: hir_vec![],
@@ -2719,10 +2713,9 @@ impl<'a> LoweringContext<'a> {
             hir::QPath::Resolved(None, path) => path.and_then(|path| path),
             qpath => bug!("lower_trait_ref: unexpected QPath `{:?}`", qpath),
         };
-        let LoweredNodeId { node_id, hir_id } = self.lower_node_id(p.ref_id);
+        let LoweredNodeId { node_id: _, hir_id } = self.lower_node_id(p.ref_id);
         hir::TraitRef {
             path,
-            ref_id: node_id,
             hir_ref_id: hir_id,
         }
     }
@@ -2768,10 +2761,9 @@ impl<'a> LoweringContext<'a> {
     }
 
     fn lower_field(&mut self, f: &Field) -> hir::Field {
-        let LoweredNodeId { node_id, hir_id } = self.next_id();
+        let LoweredNodeId { node_id: _, hir_id } = self.next_id();
 
         hir::Field {
-            id: node_id,
             hir_id,
             ident: f.ident,
             expr: P(self.lower_expr(&f.expr)),
@@ -3123,12 +3115,11 @@ impl<'a> LoweringContext<'a> {
                             hir::VisibilityKind::Public => hir::VisibilityKind::Public,
                             hir::VisibilityKind::Crate(sugar) => hir::VisibilityKind::Crate(sugar),
                             hir::VisibilityKind::Inherited => hir::VisibilityKind::Inherited,
-                            hir::VisibilityKind::Restricted { ref path, id: _, hir_id: _ } => {
+                            hir::VisibilityKind::Restricted { ref path, hir_id: _ } => {
                                 let id = this.next_id();
                                 let path = this.renumber_segment_ids(path);
                                 hir::VisibilityKind::Restricted {
                                     path,
-                                    id: id.node_id,
                                     hir_id: id.hir_id,
                                 }
                             }
@@ -3230,12 +3221,11 @@ impl<'a> LoweringContext<'a> {
                             hir::VisibilityKind::Public => hir::VisibilityKind::Public,
                             hir::VisibilityKind::Crate(sugar) => hir::VisibilityKind::Crate(sugar),
                             hir::VisibilityKind::Inherited => hir::VisibilityKind::Inherited,
-                            hir::VisibilityKind::Restricted { ref path, id: _, hir_id: _ } => {
+                            hir::VisibilityKind::Restricted { ref path, hir_id: _ } => {
                                 let id = this.next_id();
                                 let path = this.renumber_segment_ids(path);
                                 hir::VisibilityKind::Restricted {
                                     path: path,
-                                    id: id.node_id,
                                     hir_id: id.hir_id,
                                 }
                             }
@@ -3353,7 +3343,6 @@ impl<'a> LoweringContext<'a> {
         };
 
         hir::TraitItem {
-            id: node_id,
             hir_id,
             ident: i.ident,
             attrs: self.lower_attrs(&i.attrs),
@@ -3429,7 +3418,6 @@ impl<'a> LoweringContext<'a> {
         };
 
         hir::ImplItem {
-            id: node_id,
             hir_id,
             ident: i.ident,
             attrs: self.lower_attrs(&i.attrs),
@@ -3813,9 +3801,8 @@ impl<'a> LoweringContext<'a> {
 
     fn lower_anon_const(&mut self, c: &AnonConst) -> hir::AnonConst {
         self.with_new_scopes(|this| {
-            let LoweredNodeId { node_id, hir_id } = this.lower_node_id(c.id);
+            let LoweredNodeId { node_id: _, hir_id } = this.lower_node_id(c.id);
             hir::AnonConst {
-                id: node_id,
                 hir_id,
                 body: this.lower_body(None, |this| this.lower_expr(&c.value)),
             }
@@ -4427,9 +4414,8 @@ impl<'a> LoweringContext<'a> {
                         ThinVec::new(),
                     ))
                 };
-                let LoweredNodeId { node_id, hir_id } = self.next_id();
+                let LoweredNodeId { node_id: _, hir_id } = self.next_id();
                 let match_stmt = hir::Stmt {
-                    id: node_id,
                     hir_id,
                     node: hir::StmtKind::Expr(match_expr),
                     span: head_sp,
@@ -4456,9 +4442,8 @@ impl<'a> LoweringContext<'a> {
 
                 let body_block = self.with_loop_scope(e.id, |this| this.lower_block(body, false));
                 let body_expr = P(self.expr_block(body_block, ThinVec::new()));
-                let LoweredNodeId { node_id, hir_id } = self.next_id();
+                let LoweredNodeId { node_id: _, hir_id } = self.next_id();
                 let body_stmt = hir::Stmt {
-                    id: node_id,
                     hir_id,
                     node: hir::StmtKind::Expr(body_expr),
                     span: body.span,
@@ -4639,10 +4624,9 @@ impl<'a> LoweringContext<'a> {
                 let mut ids: SmallVec<[hir::Stmt; 1]> = item_ids
                     .into_iter()
                     .map(|item_id| {
-                        let LoweredNodeId { node_id, hir_id } = self.next_id();
+                        let LoweredNodeId { node_id: _, hir_id } = self.next_id();
 
                         hir::Stmt {
-                            id: node_id,
                             hir_id,
                             node: hir::StmtKind::Item(item_id),
                             span: s.span,
@@ -4650,10 +4634,9 @@ impl<'a> LoweringContext<'a> {
                     })
                     .collect();
                 ids.push({
-                    let LoweredNodeId { node_id, hir_id } = self.lower_node_id(s.id);
+                    let LoweredNodeId { node_id: _, hir_id } = self.lower_node_id(s.id);
 
                     hir::Stmt {
-                        id: node_id,
                         hir_id,
                         node: hir::StmtKind::Local(P(l)),
                         span: s.span,
@@ -4667,12 +4650,11 @@ impl<'a> LoweringContext<'a> {
                 return self.lower_item_id(it)
                     .into_iter()
                     .map(|item_id| {
-                        let LoweredNodeId { node_id, hir_id } = id.take()
+                        let LoweredNodeId { node_id: _, hir_id } = id.take()
                           .map(|id| self.lower_node_id(id))
                           .unwrap_or_else(|| self.next_id());
 
                         hir::Stmt {
-                            id: node_id,
                             hir_id,
                             node: hir::StmtKind::Item(item_id),
                             span: s.span,
@@ -4681,20 +4663,18 @@ impl<'a> LoweringContext<'a> {
                     .collect();
             }
             StmtKind::Expr(ref e) => {
-                let LoweredNodeId { node_id, hir_id } = self.lower_node_id(s.id);
+                let LoweredNodeId { node_id: _, hir_id } = self.lower_node_id(s.id);
 
                 hir::Stmt {
-                    id: node_id,
                     hir_id,
                     node: hir::StmtKind::Expr(P(self.lower_expr(e))),
                     span: s.span,
                 }
             },
             StmtKind::Semi(ref e) => {
-                let LoweredNodeId { node_id, hir_id } = self.lower_node_id(s.id);
+                let LoweredNodeId { node_id: _, hir_id } = self.lower_node_id(s.id);
 
                 hir::Stmt {
-                    id: node_id,
                     hir_id,
                     node: hir::StmtKind::Semi(P(self.lower_expr(e))),
                     span: s.span,
@@ -4739,7 +4719,6 @@ impl<'a> LoweringContext<'a> {
                         ParamMode::Explicit,
                         explicit_owner,
                     )),
-                    id: lowered_id.node_id,
                     hir_id: lowered_id.hir_id,
                 }
             },
@@ -4809,10 +4788,9 @@ impl<'a> LoweringContext<'a> {
     }
 
     fn field(&mut self, ident: Ident, expr: P<hir::Expr>, span: Span) -> hir::Field {
-        let LoweredNodeId { node_id, hir_id } = self.next_id();
+        let LoweredNodeId { node_id: _, hir_id } = self.next_id();
 
         hir::Field {
-            id: node_id,
             hir_id,
             ident,
             span,
@@ -4912,22 +4890,20 @@ impl<'a> LoweringContext<'a> {
         pat: P<hir::Pat>,
         source: hir::LocalSource,
     ) -> hir::Stmt {
-        let LoweredNodeId { node_id, hir_id } = self.next_id();
+        let LoweredNodeId { node_id: _, hir_id } = self.next_id();
 
         let local = hir::Local {
             pat,
             ty: None,
             init: ex,
-            id: node_id,
             hir_id,
             span: sp,
             attrs: ThinVec::new(),
             source,
         };
 
-        let LoweredNodeId { node_id, hir_id } = self.next_id();
+        let LoweredNodeId { node_id: _, hir_id } = self.next_id();
         hir::Stmt {
-            id: node_id,
             hir_id,
             node: hir::StmtKind::Local(P(local)),
             span: sp
@@ -5075,7 +5051,6 @@ impl<'a> LoweringContext<'a> {
                             bound_generic_params: hir::HirVec::new(),
                             trait_ref: hir::TraitRef {
                                 path: path.and_then(|path| path),
-                                ref_id: id.node_id,
                                 hir_ref_id: id.hir_id,
                             },
                             span,
diff --git a/src/librustc/hir/map/collector.rs b/src/librustc/hir/map/collector.rs
index 588b986aad2..0425d5a5023 100644
--- a/src/librustc/hir/map/collector.rs
+++ b/src/librustc/hir/map/collector.rs
@@ -386,7 +386,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
 
     fn visit_trait_item(&mut self, ti: &'hir TraitItem) {
         debug_assert_eq!(ti.hir_id.owner,
-                         self.definitions.opt_def_index(ti.id).unwrap());
+                         self.definitions.opt_def_index(self.hir_to_node_id[&ti.hir_id]).unwrap());
         self.with_dep_node_owner(ti.hir_id.owner, ti, |this| {
             this.insert(ti.span, ti.hir_id, Node::TraitItem(ti));
 
@@ -398,7 +398,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
 
     fn visit_impl_item(&mut self, ii: &'hir ImplItem) {
         debug_assert_eq!(ii.hir_id.owner,
-                         self.definitions.opt_def_index(ii.id).unwrap());
+                         self.definitions.opt_def_index(self.hir_to_node_id[&ii.hir_id]).unwrap());
         self.with_dep_node_owner(ii.hir_id.owner, ii, |this| {
             this.insert(ii.span, ii.hir_id, Node::ImplItem(ii));
 
diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs
index 41e48e46ea5..66e814f0660 100644
--- a/src/librustc/hir/map/mod.rs
+++ b/src/librustc/hir/map/mod.rs
@@ -349,7 +349,7 @@ impl<'hir> Map<'hir> {
                 }
             }
             Node::TraitItem(item) => {
-                let def_id = self.local_def_id(item.id);
+                let def_id = self.local_def_id_from_hir_id(item.hir_id);
                 match item.node {
                     TraitItemKind::Const(..) => Some(Def::AssociatedConst(def_id)),
                     TraitItemKind::Method(..) => Some(Def::Method(def_id)),
@@ -357,7 +357,7 @@ impl<'hir> Map<'hir> {
                 }
             }
             Node::ImplItem(item) => {
-                let def_id = self.local_def_id(item.id);
+                let def_id = self.local_def_id_from_hir_id(item.hir_id);
                 match item.node {
                     ImplItemKind::Const(..) => Some(Def::AssociatedConst(def_id)),
                     ImplItemKind::Method(..) => Some(Def::Method(def_id)),
@@ -387,7 +387,7 @@ impl<'hir> Map<'hir> {
             Node::Block(_) |
             Node::Crate => None,
             Node::Local(local) => {
-                Some(Def::Local(local.id))
+                Some(Def::Local(self.hir_to_node_id(local.hir_id)))
             }
             Node::MacroDef(macro_def) => {
                 Some(Def::Macro(self.local_def_id_from_hir_id(macro_def.hir_id),
diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs
index d8169d05dd4..3ba4efba918 100644
--- a/src/librustc/hir/mod.rs
+++ b/src/librustc/hir/mod.rs
@@ -1162,7 +1162,6 @@ impl UnOp {
 /// A statement.
 #[derive(Clone, RustcEncodable, RustcDecodable)]
 pub struct Stmt {
-    pub id: NodeId,
     pub hir_id: HirId,
     pub node: StmtKind,
     pub span: Span,
@@ -1170,7 +1169,7 @@ pub struct Stmt {
 
 impl fmt::Debug for Stmt {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(f, "stmt({}: {})", self.id,
+        write!(f, "stmt({}: {})", self.hir_id,
                print::to_string(print::NO_ANN, |s| s.print_stmt(self)))
     }
 }
@@ -1208,7 +1207,6 @@ pub struct Local {
     pub ty: Option<P<Ty>>,
     /// Initializer expression to set the value, if any.
     pub init: Option<P<Expr>>,
-    pub id: NodeId,
     pub hir_id: HirId,
     pub span: Span,
     pub attrs: ThinVec<Attribute>,
@@ -1231,7 +1229,6 @@ pub enum Guard {
 
 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
 pub struct Field {
-    pub id: NodeId,
     pub hir_id: HirId,
     pub ident: Ident,
     pub expr: P<Expr>,
@@ -1325,7 +1322,6 @@ impl BodyOwnerKind {
 /// explicit discriminant values for enum variants.
 #[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Debug)]
 pub struct AnonConst {
-    pub id: NodeId,
     pub hir_id: HirId,
     pub body: BodyId,
 }
@@ -1672,7 +1668,6 @@ pub struct TraitItemId {
 /// signature) or provided (meaning it has a default implementation).
 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
 pub struct TraitItem {
-    pub id: NodeId,
     pub ident: Ident,
     pub hir_id: HirId,
     pub attrs: HirVec<Attribute>,
@@ -1715,7 +1710,6 @@ pub struct ImplItemId {
 /// Represents anything within an `impl` block
 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
 pub struct ImplItem {
-    pub id: NodeId,
     pub ident: Ident,
     pub hir_id: HirId,
     pub vis: Visibility,
@@ -1743,7 +1737,6 @@ pub enum ImplItemKind {
 // Bind a type to an associated type: `A=Foo`.
 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
 pub struct TypeBinding {
-    pub id: NodeId,
     pub hir_id: HirId,
     pub ident: Ident,
     pub ty: P<Ty>,
@@ -1859,7 +1852,6 @@ pub struct InlineAsm {
 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
 pub struct Arg {
     pub pat: P<Pat>,
-    pub id: NodeId,
     pub hir_id: HirId,
 }
 
@@ -2070,7 +2062,6 @@ pub enum UseKind {
 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
 pub struct TraitRef {
     pub path: Path,
-    pub ref_id: NodeId,
     pub hir_ref_id: HirId,
 }
 
@@ -2105,7 +2096,7 @@ pub type Visibility = Spanned<VisibilityKind>;
 pub enum VisibilityKind {
     Public,
     Crate(CrateSugar),
-    Restricted { path: P<Path>, id: NodeId, hir_id: HirId },
+    Restricted { path: P<Path>, hir_id: HirId },
     Inherited,
 }
 
diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs
index dab4b9c824d..28e9403e9db 100644
--- a/src/librustc/hir/print.rs
+++ b/src/librustc/hir/print.rs
@@ -25,7 +25,7 @@ pub enum AnnNode<'a> {
     Name(&'a ast::Name),
     Block(&'a hir::Block),
     Item(&'a hir::Item),
-    SubItem(ast::NodeId),
+    SubItem(hir::HirId),
     Expr(&'a hir::Expr),
     Pat(&'a hir::Pat),
 }
@@ -927,7 +927,7 @@ impl<'a> State<'a> {
     }
 
     pub fn print_trait_item(&mut self, ti: &hir::TraitItem) -> io::Result<()> {
-        self.ann.pre(self, AnnNode::SubItem(ti.id))?;
+        self.ann.pre(self, AnnNode::SubItem(ti.hir_id))?;
         self.hardbreak_if_not_bol()?;
         self.maybe_print_comment(ti.span.lo())?;
         self.print_outer_attributes(&ti.attrs)?;
@@ -959,11 +959,11 @@ impl<'a> State<'a> {
                                            default.as_ref().map(|ty| &**ty))?;
             }
         }
-        self.ann.post(self, AnnNode::SubItem(ti.id))
+        self.ann.post(self, AnnNode::SubItem(ti.hir_id))
     }
 
     pub fn print_impl_item(&mut self, ii: &hir::ImplItem) -> io::Result<()> {
-        self.ann.pre(self, AnnNode::SubItem(ii.id))?;
+        self.ann.pre(self, AnnNode::SubItem(ii.hir_id))?;
         self.hardbreak_if_not_bol()?;
         self.maybe_print_comment(ii.span.lo())?;
         self.print_outer_attributes(&ii.attrs)?;
@@ -989,7 +989,7 @@ impl<'a> State<'a> {
                 self.print_associated_type(ii.ident, Some(bounds), None)?;
             }
         }
-        self.ann.post(self, AnnNode::SubItem(ii.id))
+        self.ann.post(self, AnnNode::SubItem(ii.hir_id))
     }
 
     pub fn print_stmt(&mut self, st: &hir::Stmt) -> io::Result<()> {
diff --git a/src/librustc/ich/impls_hir.rs b/src/librustc/ich/impls_hir.rs
index 77582278690..af1cce5e354 100644
--- a/src/librustc/ich/impls_hir.rs
+++ b/src/librustc/ich/impls_hir.rs
@@ -294,7 +294,6 @@ impl_stable_hash_for!(struct hir::MethodSig {
 });
 
 impl_stable_hash_for!(struct hir::TypeBinding {
-    id,
     hir_id,
     ident -> (ident.name),
     ty,
@@ -386,8 +385,7 @@ impl_stable_hash_for!(enum hir::ImplicitSelfKind {
 });
 
 impl_stable_hash_for!(struct hir::TraitRef {
-    // Don't hash the ref_id. It is tracked via the thing it is used to access
-    ref_id -> _,
+    // Don't hash the hir_ref_id. It is tracked via the thing it is used to access
     hir_ref_id -> _,
     path,
 });
@@ -495,7 +493,6 @@ impl_stable_hash_for!(enum hir::UnOp {
 });
 
 impl_stable_hash_for!(struct hir::Stmt {
-    id,
     hir_id,
     node,
     span,
@@ -506,7 +503,6 @@ impl_stable_hash_for!(struct hir::Local {
     pat,
     ty,
     init,
-    id,
     hir_id,
     span,
     attrs,
@@ -525,7 +521,6 @@ impl_stable_hash_for!(enum hir::Guard {
 });
 
 impl_stable_hash_for!(struct hir::Field {
-    id -> _,
     hir_id -> _,
     ident,
     expr,
@@ -549,7 +544,6 @@ impl_stable_hash_for!(enum hir::UnsafeSource {
 });
 
 impl_stable_hash_for!(struct hir::AnonConst {
-    id,
     hir_id,
     body
 });
@@ -673,7 +667,6 @@ impl<'a> HashStable<StableHashingContext<'a>> for hir::TraitItem {
                                           hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
         let hir::TraitItem {
-            id: _,
             hir_id: _,
             ident,
             ref attrs,
@@ -708,7 +701,6 @@ impl<'a> HashStable<StableHashingContext<'a>> for hir::ImplItem {
                                           hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
         let hir::ImplItem {
-            id: _,
             hir_id: _,
             ident,
             ref vis,
@@ -756,9 +748,8 @@ impl<'a> HashStable<StableHashingContext<'a>> for hir::VisibilityKind {
             hir::VisibilityKind::Crate(sugar) => {
                 sugar.hash_stable(hcx, hasher);
             }
-            hir::VisibilityKind::Restricted { ref path, id, hir_id } => {
+            hir::VisibilityKind::Restricted { ref path, hir_id } => {
                 hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| {
-                    id.hash_stable(hcx, hasher);
                     hir_id.hash_stable(hcx, hasher);
                 });
                 path.hash_stable(hcx, hasher);
@@ -962,7 +953,6 @@ impl_stable_hash_for!(enum hir::StmtKind {
 
 impl_stable_hash_for!(struct hir::Arg {
     pat,
-    id,
     hir_id
 });
 
diff --git a/src/librustc/ich/impls_mir.rs b/src/librustc/ich/impls_mir.rs
index ddc091b7187..41b78ee5096 100644
--- a/src/librustc/ich/impls_mir.rs
+++ b/src/librustc/ich/impls_mir.rs
@@ -209,13 +209,13 @@ impl<'a, 'gcx> HashStable<StableHashingContext<'a>> for mir::Place<'gcx> {
                                           hasher: &mut StableHasher<W>) {
         mem::discriminant(self).hash_stable(hcx, hasher);
         match *self {
-            mir::Place::Local(ref local) => {
+            mir::Place::Base(mir::PlaceBase::Local(ref local)) => {
                 local.hash_stable(hcx, hasher);
             }
-            mir::Place::Static(ref statik) => {
+            mir::Place::Base(mir::PlaceBase::Static(ref statik)) => {
                 statik.hash_stable(hcx, hasher);
             }
-            mir::Place::Promoted(ref promoted) => {
+            mir::Place::Base(mir::PlaceBase::Promoted(ref promoted)) => {
                 promoted.hash_stable(hcx, hasher);
             }
             mir::Place::Projection(ref place_projection) => {
diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs
index dda314429fc..9761ee31353 100644
--- a/src/librustc/lint/context.rs
+++ b/src/librustc/lint/context.rs
@@ -729,8 +729,7 @@ impl<'a, 'tcx> LintContext<'tcx> for LateContext<'a, 'tcx> {
         match span {
             Some(s) => self.tcx.struct_span_lint_hir(lint, hir_id, s, msg),
             None => {
-                let node_id = self.tcx.hir().hir_to_node_id(hir_id); // FIXME(@ljedrz): remove later
-                self.tcx.struct_lint_node(lint, node_id, msg)
+                self.tcx.struct_lint_node(lint, hir_id, msg)
             },
         }
     }
@@ -793,11 +792,11 @@ impl<'a, 'tcx> LateContext<'a, 'tcx> {
         run_lints!(self, exit_lint_attrs, attrs);
     }
 
-    fn with_param_env<F>(&mut self, id: ast::NodeId, f: F)
+    fn with_param_env<F>(&mut self, id: hir::HirId, f: F)
         where F: FnOnce(&mut Self),
     {
         let old_param_env = self.param_env;
-        self.param_env = self.tcx.param_env(self.tcx.hir().local_def_id(id));
+        self.param_env = self.tcx.param_env(self.tcx.hir().local_def_id_from_hir_id(id));
         f(self);
         self.param_env = old_param_env;
     }
@@ -841,7 +840,7 @@ impl<'a, 'tcx> hir_visit::Visitor<'tcx> for LateContext<'a, 'tcx> {
         let generics = self.generics.take();
         self.generics = it.node.generics();
         self.with_lint_attrs(it.hir_id, &it.attrs, |cx| {
-            cx.with_param_env(it.id, |cx| {
+            cx.with_param_env(it.hir_id, |cx| {
                 run_lints!(cx, check_item, it);
                 hir_visit::walk_item(cx, it);
                 run_lints!(cx, check_item_post, it);
@@ -852,7 +851,7 @@ impl<'a, 'tcx> hir_visit::Visitor<'tcx> for LateContext<'a, 'tcx> {
 
     fn visit_foreign_item(&mut self, it: &'tcx hir::ForeignItem) {
         self.with_lint_attrs(it.hir_id, &it.attrs, |cx| {
-            cx.with_param_env(it.id, |cx| {
+            cx.with_param_env(it.hir_id, |cx| {
                 run_lints!(cx, check_foreign_item, it);
                 hir_visit::walk_foreign_item(cx, it);
                 run_lints!(cx, check_foreign_item_post, it);
@@ -983,7 +982,7 @@ impl<'a, 'tcx> hir_visit::Visitor<'tcx> for LateContext<'a, 'tcx> {
         let generics = self.generics.take();
         self.generics = Some(&trait_item.generics);
         self.with_lint_attrs(trait_item.hir_id, &trait_item.attrs, |cx| {
-            cx.with_param_env(trait_item.id, |cx| {
+            cx.with_param_env(trait_item.hir_id, |cx| {
                 run_lints!(cx, check_trait_item, trait_item);
                 hir_visit::walk_trait_item(cx, trait_item);
                 run_lints!(cx, check_trait_item_post, trait_item);
@@ -996,7 +995,7 @@ impl<'a, 'tcx> hir_visit::Visitor<'tcx> for LateContext<'a, 'tcx> {
         let generics = self.generics.take();
         self.generics = Some(&impl_item.generics);
         self.with_lint_attrs(impl_item.hir_id, &impl_item.attrs, |cx| {
-            cx.with_param_env(impl_item.id, |cx| {
+            cx.with_param_env(impl_item.hir_id, |cx| {
                 run_lints!(cx, check_impl_item, impl_item);
                 hir_visit::walk_impl_item(cx, impl_item);
                 run_lints!(cx, check_impl_item_post, impl_item);
diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs
index dd003e44bea..496ff568b31 100644
--- a/src/librustc/lint/mod.rs
+++ b/src/librustc/lint/mod.rs
@@ -132,14 +132,22 @@ macro_rules! declare_lint {
 
 #[macro_export]
 macro_rules! declare_tool_lint {
-    ($vis: vis $tool: ident ::$NAME: ident, $Level: ident, $desc: expr) => (
-        declare_tool_lint!{$vis $tool::$NAME, $Level, $desc, false}
+    (
+        $(#[$attr:meta])* $vis:vis $tool:ident ::$NAME:ident, $Level: ident, $desc: expr
+    ) => (
+        declare_tool_lint!{$(#[$attr])* $vis $tool::$NAME, $Level, $desc, false}
     );
-    ($vis: vis $tool: ident ::$NAME: ident, $Level: ident, $desc: expr,
-     report_in_external_macro: $rep: expr) => (
-         declare_tool_lint!{$vis $tool::$NAME, $Level, $desc, $rep}
+    (
+        $(#[$attr:meta])* $vis:vis $tool:ident ::$NAME:ident, $Level:ident, $desc:expr,
+        report_in_external_macro: $rep:expr
+    ) => (
+         declare_tool_lint!{$(#[$attr])* $vis $tool::$NAME, $Level, $desc, $rep}
     );
-    ($vis: vis $tool: ident ::$NAME: ident, $Level: ident, $desc: expr, $external: expr) => (
+    (
+        $(#[$attr:meta])* $vis:vis $tool:ident ::$NAME:ident, $Level:ident, $desc:expr,
+        $external:expr
+    ) => (
+        $(#[$attr])*
         $vis static $NAME: &$crate::lint::Lint = &$crate::lint::Lint {
             name: &concat!(stringify!($tool), "::", stringify!($NAME)),
             default_level: $crate::lint::$Level,
diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs
index 201a779ee18..3b607127d86 100644
--- a/src/librustc/middle/dead.rs
+++ b/src/librustc/middle/dead.rs
@@ -26,8 +26,8 @@ use syntax_pos;
 // function, then we should explore its block to check for codes that
 // may need to be marked as live.
 fn should_explore<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                            node_id: ast::NodeId) -> bool {
-    match tcx.hir().find(node_id) {
+                            hir_id: hir::HirId) -> bool {
+    match tcx.hir().find_by_hir_id(hir_id) {
         Some(Node::Item(..)) |
         Some(Node::ImplItem(..)) |
         Some(Node::ForeignItem(..)) |
@@ -39,33 +39,33 @@ fn should_explore<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 }
 
 struct MarkSymbolVisitor<'a, 'tcx: 'a> {
-    worklist: Vec<ast::NodeId>,
+    worklist: Vec<hir::HirId>,
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     tables: &'a ty::TypeckTables<'tcx>,
-    live_symbols: FxHashSet<ast::NodeId>,
+    live_symbols: FxHashSet<hir::HirId>,
     repr_has_repr_c: bool,
     in_pat: bool,
     inherited_pub_visibility: bool,
     ignore_variant_stack: Vec<DefId>,
     // maps from tuple struct constructors to tuple struct items
-    struct_constructors: FxHashMap<ast::NodeId, ast::NodeId>,
+    struct_constructors: FxHashMap<hir::HirId, hir::HirId>,
 }
 
 impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
     fn check_def_id(&mut self, def_id: DefId) {
-        if let Some(node_id) = self.tcx.hir().as_local_node_id(def_id) {
-            if should_explore(self.tcx, node_id) ||
-               self.struct_constructors.contains_key(&node_id) {
-                self.worklist.push(node_id);
+        if let Some(hir_id) = self.tcx.hir().as_local_hir_id(def_id) {
+            if should_explore(self.tcx, hir_id) ||
+               self.struct_constructors.contains_key(&hir_id) {
+                self.worklist.push(hir_id);
             }
-            self.live_symbols.insert(node_id);
+            self.live_symbols.insert(hir_id);
         }
     }
 
     fn insert_def_id(&mut self, def_id: DefId) {
-        if let Some(node_id) = self.tcx.hir().as_local_node_id(def_id) {
-            debug_assert!(!should_explore(self.tcx, node_id));
-            self.live_symbols.insert(node_id);
+        if let Some(hir_id) = self.tcx.hir().as_local_hir_id(def_id) {
+            debug_assert!(!should_explore(self.tcx, hir_id));
+            self.live_symbols.insert(hir_id);
         }
     }
 
@@ -136,7 +136,7 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
             // tuple struct constructor function
             let id = self.struct_constructors.get(&id).cloned().unwrap_or(id);
 
-            if let Some(node) = self.tcx.hir().find(id) {
+            if let Some(node) = self.tcx.hir().find_by_hir_id(id) {
                 self.live_symbols.insert(id);
                 self.visit_node(node);
             }
@@ -217,7 +217,7 @@ impl<'a, 'tcx> Visitor<'tcx> for MarkSymbolVisitor<'a, 'tcx> {
         let live_fields = def.fields().iter().filter(|f| {
             has_repr_c || inherited_pub_visibility || f.vis.node.is_pub()
         });
-        self.live_symbols.extend(live_fields.map(|f| f.id));
+        self.live_symbols.extend(live_fields.map(|f| f.hir_id));
 
         intravisit::walk_struct_def(self, def);
     }
@@ -285,7 +285,7 @@ impl<'a, 'tcx> Visitor<'tcx> for MarkSymbolVisitor<'a, 'tcx> {
 }
 
 fn has_allow_dead_code_or_lang_attr(tcx: TyCtxt<'_, '_, '_>,
-                                    id: ast::NodeId,
+                                    id: hir::HirId,
                                     attrs: &[ast::Attribute]) -> bool {
     if attr::contains_name(attrs, "lang") {
         return true;
@@ -306,7 +306,7 @@ fn has_allow_dead_code_or_lang_attr(tcx: TyCtxt<'_, '_, '_>,
         return true;
     }
 
-    let def_id = tcx.hir().local_def_id(id);
+    let def_id = tcx.hir().local_def_id_from_hir_id(id);
     let cg_attrs = tcx.codegen_fn_attrs(def_id);
 
     // #[used], #[no_mangle], #[export_name], etc also keeps the item alive
@@ -333,25 +333,25 @@ fn has_allow_dead_code_or_lang_attr(tcx: TyCtxt<'_, '_, '_>,
 //   2) We are not sure to be live or not
 //     * Implementation of a trait method
 struct LifeSeeder<'k, 'tcx: 'k> {
-    worklist: Vec<ast::NodeId>,
+    worklist: Vec<hir::HirId>,
     krate: &'k hir::Crate,
     tcx: TyCtxt<'k, 'tcx, 'tcx>,
     // see `MarkSymbolVisitor::struct_constructors`
-    struct_constructors: FxHashMap<ast::NodeId, ast::NodeId>,
+    struct_constructors: FxHashMap<hir::HirId, hir::HirId>,
 }
 
 impl<'v, 'k, 'tcx> ItemLikeVisitor<'v> for LifeSeeder<'k, 'tcx> {
     fn visit_item(&mut self, item: &hir::Item) {
         let allow_dead_code = has_allow_dead_code_or_lang_attr(self.tcx,
-                                                               item.id,
+                                                               item.hir_id,
                                                                &item.attrs);
         if allow_dead_code {
-            self.worklist.push(item.id);
+            self.worklist.push(item.hir_id);
         }
         match item.node {
             hir::ItemKind::Enum(ref enum_def, _) if allow_dead_code => {
                 self.worklist.extend(enum_def.variants.iter()
-                                                      .map(|variant| variant.node.data.id()));
+                                                      .map(|variant| variant.node.data.hir_id()));
             }
             hir::ItemKind::Trait(.., ref trait_item_refs) => {
                 for trait_item_ref in trait_item_refs {
@@ -360,9 +360,9 @@ impl<'v, 'k, 'tcx> ItemLikeVisitor<'v> for LifeSeeder<'k, 'tcx> {
                         hir::TraitItemKind::Const(_, Some(_)) |
                         hir::TraitItemKind::Method(_, hir::TraitMethod::Provided(_)) => {
                             if has_allow_dead_code_or_lang_attr(self.tcx,
-                                                                trait_item.id,
+                                                                trait_item.hir_id,
                                                                 &trait_item.attrs) {
-                                self.worklist.push(trait_item.id);
+                                self.worklist.push(trait_item.hir_id);
                             }
                         }
                         _ => {}
@@ -374,14 +374,14 @@ impl<'v, 'k, 'tcx> ItemLikeVisitor<'v> for LifeSeeder<'k, 'tcx> {
                     let impl_item = self.krate.impl_item(impl_item_ref.id);
                     if opt_trait.is_some() ||
                             has_allow_dead_code_or_lang_attr(self.tcx,
-                                                             impl_item.id,
+                                                             impl_item.hir_id,
                                                              &impl_item.attrs) {
-                        self.worklist.push(impl_item_ref.id.node_id);
+                        self.worklist.push(self.tcx.hir().node_to_hir_id(impl_item_ref.id.node_id));
                     }
                 }
             }
             hir::ItemKind::Struct(ref variant_data, _) => {
-                self.struct_constructors.insert(variant_data.id(), item.id);
+                self.struct_constructors.insert(variant_data.hir_id(), item.hir_id);
             }
             _ => ()
         }
@@ -400,16 +400,16 @@ fn create_and_seed_worklist<'a, 'tcx>(
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     access_levels: &privacy::AccessLevels,
     krate: &hir::Crate,
-) -> (Vec<ast::NodeId>, FxHashMap<ast::NodeId, ast::NodeId>) {
+) -> (Vec<hir::HirId>, FxHashMap<hir::HirId, hir::HirId>) {
     let worklist = access_levels.map.iter().filter_map(|(&id, level)| {
         if level >= &privacy::AccessLevel::Reachable {
-            Some(id)
+            Some(tcx.hir().node_to_hir_id(id))
         } else {
             None
         }
     }).chain(
         // Seed entry point
-        tcx.entry_fn(LOCAL_CRATE).map(|(def_id, _)| tcx.hir().as_local_node_id(def_id).unwrap())
+        tcx.entry_fn(LOCAL_CRATE).map(|(def_id, _)| tcx.hir().as_local_hir_id(def_id).unwrap())
     ).collect::<Vec<_>>();
 
     // Seed implemented trait items
@@ -427,7 +427,7 @@ fn create_and_seed_worklist<'a, 'tcx>(
 fn find_live<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                        access_levels: &privacy::AccessLevels,
                        krate: &hir::Crate)
-                       -> FxHashSet<ast::NodeId> {
+                       -> FxHashSet<hir::HirId> {
     let (worklist, struct_constructors) = create_and_seed_worklist(tcx, access_levels, krate);
     let mut symbol_visitor = MarkSymbolVisitor {
         worklist,
@@ -446,7 +446,7 @@ fn find_live<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
 struct DeadVisitor<'a, 'tcx: 'a> {
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
-    live_symbols: FxHashSet<ast::NodeId>,
+    live_symbols: FxHashSet<hir::HirId>,
 }
 
 impl<'a, 'tcx> DeadVisitor<'a, 'tcx> {
@@ -461,33 +461,33 @@ impl<'a, 'tcx> DeadVisitor<'a, 'tcx> {
             | hir::ItemKind::Union(..) => true,
             _ => false
         };
-        should_warn && !self.symbol_is_live(item.id)
+        should_warn && !self.symbol_is_live(item.hir_id)
     }
 
     fn should_warn_about_field(&mut self, field: &hir::StructField) -> bool {
         let field_type = self.tcx.type_of(self.tcx.hir().local_def_id(field.id));
         !field.is_positional()
-            && !self.symbol_is_live(field.id)
+            && !self.symbol_is_live(field.hir_id)
             && !field_type.is_phantom_data()
-            && !has_allow_dead_code_or_lang_attr(self.tcx, field.id, &field.attrs)
+            && !has_allow_dead_code_or_lang_attr(self.tcx, field.hir_id, &field.attrs)
     }
 
     fn should_warn_about_variant(&mut self, variant: &hir::VariantKind) -> bool {
-        !self.symbol_is_live(variant.data.id())
+        !self.symbol_is_live(variant.data.hir_id())
             && !has_allow_dead_code_or_lang_attr(self.tcx,
-                                                 variant.data.id(),
+                                                 variant.data.hir_id(),
                                                  &variant.attrs)
     }
 
     fn should_warn_about_foreign_item(&mut self, fi: &hir::ForeignItem) -> bool {
-        !self.symbol_is_live(fi.id)
-            && !has_allow_dead_code_or_lang_attr(self.tcx, fi.id, &fi.attrs)
+        !self.symbol_is_live(fi.hir_id)
+            && !has_allow_dead_code_or_lang_attr(self.tcx, fi.hir_id, &fi.attrs)
     }
 
-    // id := node id of an item's definition.
+    // id := HIR id of an item's definition.
     fn symbol_is_live(
         &mut self,
-        id: ast::NodeId,
+        id: hir::HirId,
     ) -> bool {
         if self.live_symbols.contains(&id) {
             return true;
@@ -496,12 +496,12 @@ impl<'a, 'tcx> DeadVisitor<'a, 'tcx> {
         // This is done to handle the case where, for example, the static
         // method of a private type is used, but the type itself is never
         // called directly.
-        let def_id = self.tcx.hir().local_def_id(id);
+        let def_id = self.tcx.hir().local_def_id_from_hir_id(id);
         let inherent_impls = self.tcx.inherent_impls(def_id);
         for &impl_did in inherent_impls.iter() {
             for &item_did in &self.tcx.associated_item_def_ids(impl_did)[..] {
-                if let Some(item_node_id) = self.tcx.hir().as_local_node_id(item_did) {
-                    if self.live_symbols.contains(&item_node_id) {
+                if let Some(item_hir_id) = self.tcx.hir().as_local_hir_id(item_did) {
+                    if self.live_symbols.contains(&item_hir_id) {
                         return true;
                     }
                 }
@@ -511,18 +511,18 @@ impl<'a, 'tcx> DeadVisitor<'a, 'tcx> {
     }
 
     fn warn_dead_code(&mut self,
-                      id: ast::NodeId,
+                      id: hir::HirId,
                       span: syntax_pos::Span,
                       name: ast::Name,
                       node_type: &str,
                       participle: &str) {
         if !name.as_str().starts_with("_") {
             self.tcx
-                .lint_node(lint::builtin::DEAD_CODE,
-                           id,
-                           span,
-                           &format!("{} is never {}: `{}`",
-                                    node_type, participle, name));
+                .lint_hir(lint::builtin::DEAD_CODE,
+                          id,
+                          span,
+                          &format!("{} is never {}: `{}`",
+                                   node_type, participle, name));
         }
     }
 }
@@ -555,7 +555,7 @@ impl<'a, 'tcx> Visitor<'tcx> for DeadVisitor<'a, 'tcx> {
                 _ => "used"
             };
             self.warn_dead_code(
-                item.id,
+                item.hir_id,
                 span,
                 item.ident.name,
                 item.node.descriptive_variant(),
@@ -572,7 +572,7 @@ impl<'a, 'tcx> Visitor<'tcx> for DeadVisitor<'a, 'tcx> {
                      g: &'tcx hir::Generics,
                      id: hir::HirId) {
         if self.should_warn_about_variant(&variant.node) {
-            self.warn_dead_code(variant.node.data.id(), variant.span, variant.node.ident.name,
+            self.warn_dead_code(variant.node.data.hir_id(), variant.span, variant.node.ident.name,
                                 "variant", "constructed");
         } else {
             intravisit::walk_variant(self, variant, g, id);
@@ -581,7 +581,7 @@ impl<'a, 'tcx> Visitor<'tcx> for DeadVisitor<'a, 'tcx> {
 
     fn visit_foreign_item(&mut self, fi: &'tcx hir::ForeignItem) {
         if self.should_warn_about_foreign_item(fi) {
-            self.warn_dead_code(fi.id, fi.span, fi.ident.name,
+            self.warn_dead_code(fi.hir_id, fi.span, fi.ident.name,
                                 fi.node.descriptive_variant(), "used");
         }
         intravisit::walk_foreign_item(self, fi);
@@ -589,7 +589,7 @@ impl<'a, 'tcx> Visitor<'tcx> for DeadVisitor<'a, 'tcx> {
 
     fn visit_struct_field(&mut self, field: &'tcx hir::StructField) {
         if self.should_warn_about_field(&field) {
-            self.warn_dead_code(field.id, field.span, field.ident.name, "field", "used");
+            self.warn_dead_code(field.hir_id, field.span, field.ident.name, "field", "used");
         }
         intravisit::walk_struct_field(self, field);
     }
@@ -597,8 +597,8 @@ impl<'a, 'tcx> Visitor<'tcx> for DeadVisitor<'a, 'tcx> {
     fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem) {
         match impl_item.node {
             hir::ImplItemKind::Const(_, body_id) => {
-                if !self.symbol_is_live(impl_item.id) {
-                    self.warn_dead_code(impl_item.id,
+                if !self.symbol_is_live(impl_item.hir_id) {
+                    self.warn_dead_code(impl_item.hir_id,
                                         impl_item.span,
                                         impl_item.ident.name,
                                         "associated const",
@@ -607,9 +607,10 @@ impl<'a, 'tcx> Visitor<'tcx> for DeadVisitor<'a, 'tcx> {
                 self.visit_nested_body(body_id)
             }
             hir::ImplItemKind::Method(_, body_id) => {
-                if !self.symbol_is_live(impl_item.id) {
+                if !self.symbol_is_live(impl_item.hir_id) {
                     let span = self.tcx.sess.source_map().def_span(impl_item.span);
-                    self.warn_dead_code(impl_item.id, span, impl_item.ident.name, "method", "used");
+                    self.warn_dead_code(impl_item.hir_id, span, impl_item.ident.name, "method",
+                        "used");
                 }
                 self.visit_nested_body(body_id)
             }
diff --git a/src/librustc/middle/reachable.rs b/src/librustc/middle/reachable.rs
index 0562fddb2b5..cffbc2eaa40 100644
--- a/src/librustc/middle/reachable.rs
+++ b/src/librustc/middle/reachable.rs
@@ -48,7 +48,7 @@ fn method_might_be_inlined<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                      impl_item: &hir::ImplItem,
                                      impl_src: DefId) -> bool {
     let codegen_fn_attrs = tcx.codegen_fn_attrs(impl_item.hir_id.owner_def_id());
-    let generics = tcx.generics_of(tcx.hir().local_def_id(impl_item.id));
+    let generics = tcx.generics_of(tcx.hir().local_def_id_from_hir_id(impl_item.hir_id));
     if codegen_fn_attrs.requests_inline() || generics.requires_monomorphization(tcx) {
         return true
     }
diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs
index 832391d4416..dd44e19bc7d 100644
--- a/src/librustc/middle/resolve_lifetime.rs
+++ b/src/librustc/middle/resolve_lifetime.rs
@@ -781,7 +781,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
             Method(ref sig, _) => {
                 let tcx = self.tcx;
                 self.visit_early_late(
-                    Some(tcx.hir().get_parent(trait_item.id)),
+                    Some(tcx.hir().get_parent_item(trait_item.hir_id)),
                     &sig.decl,
                     &trait_item.generics,
                     |this| intravisit::walk_trait_item(this, trait_item),
@@ -833,7 +833,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
             Method(ref sig, _) => {
                 let tcx = self.tcx;
                 self.visit_early_late(
-                    Some(tcx.hir().get_parent(impl_item.id)),
+                    Some(tcx.hir().get_parent_item(impl_item.hir_id)),
                     &sig.decl,
                     &impl_item.generics,
                     |this| intravisit::walk_impl_item(this, impl_item),
@@ -1685,7 +1685,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
     /// ordering is not important there.
     fn visit_early_late<F>(
         &mut self,
-        parent_id: Option<ast::NodeId>,
+        parent_id: Option<hir::HirId>,
         decl: &'tcx hir::FnDecl,
         generics: &'tcx hir::Generics,
         walk: F,
@@ -1697,7 +1697,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
         // Find the start of nested early scopes, e.g., in methods.
         let mut index = 0;
         if let Some(parent_id) = parent_id {
-            let parent = self.tcx.hir().expect_item(parent_id);
+            let parent = self.tcx.hir().expect_item_by_hir_id(parent_id);
             if sub_items_have_self_param(&parent.node) {
                 index += 1; // Self comes before lifetimes
             }
diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs
index f85b8060544..3c1b49e2dde 100644
--- a/src/librustc/middle/stability.rs
+++ b/src/librustc/middle/stability.rs
@@ -13,7 +13,6 @@ use crate::middle::privacy::AccessLevels;
 use crate::session::{DiagnosticMessageId, Session};
 use syntax::symbol::Symbol;
 use syntax_pos::{Span, MultiSpan};
-use syntax::ast;
 use syntax::ast::Attribute;
 use syntax::errors::Applicability;
 use syntax::feature_gate::{GateIssue, emit_feature_err};
@@ -356,7 +355,8 @@ impl<'a, 'tcx> Visitor<'tcx> for MissingStabilityAnnotations<'a, 'tcx> {
     }
 
     fn visit_impl_item(&mut self, ii: &'tcx hir::ImplItem) {
-        let impl_def_id = self.tcx.hir().local_def_id(self.tcx.hir().get_parent(ii.id));
+        let impl_def_id = self.tcx.hir().local_def_id_from_hir_id(
+            self.tcx.hir().get_parent_item(ii.hir_id));
         if self.tcx.impl_trait_ref(impl_def_id).is_none() {
             self.check_missing_stability(ii.hir_id, ii.span, "item");
         }
@@ -922,8 +922,8 @@ fn unnecessary_stable_feature_lint<'a, 'tcx>(
     feature: Symbol,
     since: Symbol
 ) {
-    tcx.lint_node(lint::builtin::STABLE_FEATURES,
-        ast::CRATE_NODE_ID,
+    tcx.lint_hir(lint::builtin::STABLE_FEATURES,
+        hir::CRATE_HIR_ID,
         span,
         &format!("the feature `{}` has been stable since {} and no longer requires \
                   an attribute to enable", feature, since));
diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs
index bfc74979af4..b6f5ff25c8f 100644
--- a/src/librustc/mir/mod.rs
+++ b/src/librustc/mir/mod.rs
@@ -1896,6 +1896,14 @@ impl<'tcx> Debug for Statement<'tcx> {
 /// changing or disturbing program state.
 #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
 pub enum Place<'tcx> {
+    Base(PlaceBase<'tcx>),
+
+    /// projection out of a place (access a field, deref a pointer, etc)
+    Projection(Box<PlaceProjection<'tcx>>),
+}
+
+#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
+pub enum PlaceBase<'tcx> {
     /// local variable
     Local(Local),
 
@@ -1904,9 +1912,6 @@ pub enum Place<'tcx> {
 
     /// Constant code promoted to an injected static
     Promoted(Box<(Promoted, Ty<'tcx>)>),
-
-    /// projection out of a place (access a field, deref a pointer, etc)
-    Projection(Box<PlaceProjection<'tcx>>),
 }
 
 /// The `DefId` of a static, along with its normalized type (which is
@@ -1994,6 +1999,8 @@ newtype_index! {
 }
 
 impl<'tcx> Place<'tcx> {
+    pub const RETURN_PLACE: Place<'tcx> = Place::Base(PlaceBase::Local(RETURN_PLACE));
+
     pub fn field(self, f: Field, ty: Ty<'tcx>) -> Place<'tcx> {
         self.elem(ProjectionElem::Field(f, ty))
     }
@@ -2020,9 +2027,9 @@ impl<'tcx> Place<'tcx> {
     // FIXME: can we safely swap the semantics of `fn base_local` below in here instead?
     pub fn local(&self) -> Option<Local> {
         match self {
-            Place::Local(local) |
+            Place::Base(PlaceBase::Local(local)) |
             Place::Projection(box Projection {
-                base: Place::Local(local),
+                base: Place::Base(PlaceBase::Local(local)),
                 elem: ProjectionElem::Deref,
             }) => Some(*local),
             _ => None,
@@ -2032,9 +2039,9 @@ impl<'tcx> Place<'tcx> {
     /// Finds the innermost `Local` from this `Place`.
     pub fn base_local(&self) -> Option<Local> {
         match self {
-            Place::Local(local) => Some(*local),
+            Place::Base(PlaceBase::Local(local)) => Some(*local),
             Place::Projection(box Projection { base, elem: _ }) => base.base_local(),
-            Place::Promoted(..) | Place::Static(..) => None,
+            Place::Base(PlaceBase::Promoted(..)) | Place::Base(PlaceBase::Static(..)) => None,
         }
     }
 }
@@ -2044,14 +2051,19 @@ impl<'tcx> Debug for Place<'tcx> {
         use self::Place::*;
 
         match *self {
-            Local(id) => write!(fmt, "{:?}", id),
-            Static(box self::Static { def_id, ty }) => write!(
+            Base(PlaceBase::Local(id)) => write!(fmt, "{:?}", id),
+            Base(PlaceBase::Static(box self::Static { def_id, ty })) => write!(
                 fmt,
                 "({}: {:?})",
                 ty::tls::with(|tcx| tcx.item_path_str(def_id)),
                 ty
             ),
-            Promoted(ref promoted) => write!(fmt, "({:?}: {:?})", promoted.0, promoted.1),
+            Base(PlaceBase::Promoted(ref promoted)) => write!(
+                fmt,
+                "({:?}: {:?})",
+                promoted.0,
+                promoted.1
+            ),
             Projection(ref data) => match data.elem {
                 ProjectionElem::Downcast(ref adt_def, index) => {
                     write!(fmt, "({:?} as {})", data.base, adt_def.variants[index].ident)
diff --git a/src/librustc/mir/tcx.rs b/src/librustc/mir/tcx.rs
index dbf911851bf..a6f153eaf64 100644
--- a/src/librustc/mir/tcx.rs
+++ b/src/librustc/mir/tcx.rs
@@ -158,10 +158,10 @@ impl<'tcx> Place<'tcx> {
         where D: HasLocalDecls<'tcx>
     {
         match *self {
-            Place::Local(index) =>
+            Place::Base(PlaceBase::Local(index)) =>
                 PlaceTy::Ty { ty: local_decls.local_decls()[index].ty },
-            Place::Promoted(ref data) => PlaceTy::Ty { ty: data.1 },
-            Place::Static(ref data) =>
+            Place::Base(PlaceBase::Promoted(ref data)) => PlaceTy::Ty { ty: data.1 },
+            Place::Base(PlaceBase::Static(ref data)) =>
                 PlaceTy::Ty { ty: data.ty },
             Place::Projection(ref proj) =>
                 proj.base.ty(local_decls, tcx).projection_ty(tcx, &proj.elem),
diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs
index 4f31cebca08..28e816f1343 100644
--- a/src/librustc/mir/visit.rs
+++ b/src/librustc/mir/visit.rs
@@ -733,13 +733,13 @@ macro_rules! make_mir_visitor {
                             context: PlaceContext<'tcx>,
                             location: Location) {
                 match place {
-                    Place::Local(local) => {
+                    Place::Base(PlaceBase::Local(local)) => {
                         self.visit_local(local, context, location);
                     }
-                    Place::Static(static_) => {
+                    Place::Base(PlaceBase::Static(static_)) => {
                         self.visit_static(static_, context, location);
                     }
-                    Place::Promoted(promoted) => {
+                    Place::Base(PlaceBase::Promoted(promoted)) => {
                         self.visit_ty(& $($mutability)? promoted.1, TyContext::Location(location));
                     },
                     Place::Projection(proj) => {
diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs
index 5b9b70edc68..3cff5ec2309 100644
--- a/src/librustc/session/mod.rs
+++ b/src/librustc/session/mod.rs
@@ -34,7 +34,8 @@ use crate::util::profiling::SelfProfiler;
 
 use rustc_target::spec::{PanicStrategy, RelroLevel, Target, TargetTriple};
 use rustc_data_structures::flock;
-use jobserver::Client;
+use rustc_data_structures::jobserver;
+use ::jobserver::Client;
 
 use std;
 use std::cell::{self, Cell, RefCell};
@@ -1230,32 +1231,7 @@ pub fn build_session_(
         optimization_fuel,
         print_fuel_crate,
         print_fuel,
-        // Note that this is unsafe because it may misinterpret file descriptors
-        // on Unix as jobserver file descriptors. We hopefully execute this near
-        // the beginning of the process though to ensure we don't get false
-        // positives, or in other words we try to execute this before we open
-        // any file descriptors ourselves.
-        //
-        // Pick a "reasonable maximum" if we don't otherwise have
-        // a jobserver in our environment, capping out at 32 so we
-        // don't take everything down by hogging the process run queue.
-        // The fixed number is used to have deterministic compilation
-        // across machines.
-        //
-        // Also note that we stick this in a global because there could be
-        // multiple `Session` instances in this process, and the jobserver is
-        // per-process.
-        jobserver: unsafe {
-            static mut GLOBAL_JOBSERVER: *mut Client = 0 as *mut _;
-            static INIT: std::sync::Once = std::sync::ONCE_INIT;
-            INIT.call_once(|| {
-                let client = Client::from_env().unwrap_or_else(|| {
-                    Client::new(32).expect("failed to create jobserver")
-                });
-                GLOBAL_JOBSERVER = Box::into_raw(Box::new(client));
-            });
-            (*GLOBAL_JOBSERVER).clone()
-        },
+        jobserver: jobserver::client(),
         has_global_allocator: Once::new(),
         has_panic_handler: Once::new(),
         driver_lint_caps,
diff --git a/src/librustc/traits/specialize/mod.rs b/src/librustc/traits/specialize/mod.rs
index 1d84f22acd9..a2924cb993f 100644
--- a/src/librustc/traits/specialize/mod.rs
+++ b/src/librustc/traits/specialize/mod.rs
@@ -334,9 +334,9 @@ pub(super) fn specialization_graph_provider<'a, 'tcx>(
                         FutureCompatOverlapErrorKind::Issue33140 =>
                             lint::builtin::ORDER_DEPENDENT_TRAIT_OBJECTS,
                     };
-                    tcx.struct_span_lint_node(
+                    tcx.struct_span_lint_hir(
                         lint,
-                        tcx.hir().as_local_node_id(impl_def_id).unwrap(),
+                        tcx.hir().as_local_hir_id(impl_def_id).unwrap(),
                         impl_span,
                         &msg)
                 } else {
diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs
index d02c9fc174c..1983dfbd4b7 100644
--- a/src/librustc/ty/context.rs
+++ b/src/librustc/ty/context.rs
@@ -65,7 +65,7 @@ use std::sync::mpsc;
 use std::sync::Arc;
 use std::marker::PhantomData;
 use rustc_target::spec::abi;
-use syntax::ast::{self, NodeId};
+use syntax::ast;
 use syntax::attr;
 use syntax::source_map::MultiSpan;
 use syntax::edition::Edition;
@@ -2836,14 +2836,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
         self.struct_span_lint_hir(lint, hir_id, span.into(), msg).emit()
     }
 
-    pub fn lint_node<S: Into<MultiSpan>>(self,
-                                         lint: &'static Lint,
-                                         id: NodeId,
-                                         span: S,
-                                         msg: &str) {
-        self.struct_span_lint_node(lint, id, span.into(), msg).emit()
-    }
-
     pub fn lint_hir_note<S: Into<MultiSpan>>(self,
                                              lint: &'static Lint,
                                              hir_id: HirId,
@@ -2866,7 +2858,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
         err.emit()
     }
 
-    pub fn lint_level_at_node(self, lint: &'static Lint, mut id: NodeId)
+    pub fn lint_level_at_node(self, lint: &'static Lint, mut id: hir::HirId)
         -> (lint::Level, lint::LintSource)
     {
         // Right now we insert a `with_ignore` node in the dep graph here to
@@ -2880,11 +2872,10 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
         self.dep_graph.with_ignore(|| {
             let sets = self.lint_levels(LOCAL_CRATE);
             loop {
-                let hir_id = self.hir().definitions().node_to_hir_id(id);
-                if let Some(pair) = sets.level_and_source(lint, hir_id, self.sess) {
+                if let Some(pair) = sets.level_and_source(lint, id, self.sess) {
                     return pair
                 }
-                let next = self.hir().get_parent_node(id);
+                let next = self.hir().get_parent_node_by_hir_id(id);
                 if next == id {
                     bug!("lint traversal reached the root of the crate");
                 }
@@ -2900,23 +2891,11 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
                                                     msg: &str)
         -> DiagnosticBuilder<'tcx>
     {
-        let node_id = self.hir().hir_to_node_id(hir_id);
-        let (level, src) = self.lint_level_at_node(lint, node_id);
-        lint::struct_lint_level(self.sess, lint, level, src, Some(span.into()), msg)
-    }
-
-    pub fn struct_span_lint_node<S: Into<MultiSpan>>(self,
-                                                     lint: &'static Lint,
-                                                     id: NodeId,
-                                                     span: S,
-                                                     msg: &str)
-        -> DiagnosticBuilder<'tcx>
-    {
-        let (level, src) = self.lint_level_at_node(lint, id);
+        let (level, src) = self.lint_level_at_node(lint, hir_id);
         lint::struct_lint_level(self.sess, lint, level, src, Some(span.into()), msg)
     }
 
-    pub fn struct_lint_node(self, lint: &'static Lint, id: NodeId, msg: &str)
+    pub fn struct_lint_node(self, lint: &'static Lint, id: HirId, msg: &str)
         -> DiagnosticBuilder<'tcx>
     {
         let (level, src) = self.lint_level_at_node(lint, id);
diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs
index 6c507c0015d..7d2b21b9aec 100644
--- a/src/librustc/ty/layout.rs
+++ b/src/librustc/ty/layout.rs
@@ -1176,14 +1176,20 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
 
     /// This is invoked by the `layout_raw` query to record the final
     /// layout of each type.
-    #[inline]
+    #[inline(always)]
     fn record_layout_for_printing(&self, layout: TyLayout<'tcx>) {
-        // If we are running with `-Zprint-type-sizes`, record layouts for
-        // dumping later. Ignore layouts that are done with non-empty
-        // environments or non-monomorphic layouts, as the user only wants
-        // to see the stuff resulting from the final codegen session.
+        // If we are running with `-Zprint-type-sizes`, maybe record layouts
+        // for dumping later.
+        if self.tcx.sess.opts.debugging_opts.print_type_sizes {
+            self.record_layout_for_printing_outlined(layout)
+        }
+    }
+
+    fn record_layout_for_printing_outlined(&self, layout: TyLayout<'tcx>) {
+        // Ignore layouts that are done with non-empty environments or
+        // non-monomorphic layouts, as the user only wants to see the stuff
+        // resulting from the final codegen session.
         if
-            !self.tcx.sess.opts.debugging_opts.print_type_sizes ||
             layout.ty.has_param_types() ||
             layout.ty.has_self_ty() ||
             !self.param_env.caller_bounds.is_empty()
@@ -1191,10 +1197,6 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
             return;
         }
 
-        self.record_layout_for_printing_outlined(layout)
-    }
-
-    fn record_layout_for_printing_outlined(&self, layout: TyLayout<'tcx>) {
         // (delay format until we actually need it)
         let record = |kind, packed, opt_discr_size, variants| {
             let type_desc = format!("{:?}", layout.ty);
diff --git a/src/librustc/ty/query/job.rs b/src/librustc/ty/query/job.rs
index 22211468412..8e68c9fa304 100644
--- a/src/librustc/ty/query/job.rs
+++ b/src/librustc/ty/query/job.rs
@@ -7,6 +7,7 @@ use std::{fmt, ptr};
 use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::sync::{Lock, LockGuard, Lrc, Weak};
 use rustc_data_structures::OnDrop;
+use rustc_data_structures::jobserver;
 use syntax_pos::Span;
 
 use crate::ty::tls;
@@ -198,7 +199,11 @@ impl<'tcx> QueryLatch<'tcx> {
             // we have to be in the `wait` call. This is ensured by the deadlock handler
             // getting the self.info lock.
             rayon_core::mark_blocked();
+            jobserver::release_thread();
             waiter.condvar.wait(&mut info);
+            // Release the lock before we potentially block in `acquire_thread`
+            mem::drop(info);
+            jobserver::acquire_thread();
         }
     }
 
diff --git a/src/librustc_codegen_ssa/mir/analyze.rs b/src/librustc_codegen_ssa/mir/analyze.rs
index 9fe2e58bc20..facae9a9797 100644
--- a/src/librustc_codegen_ssa/mir/analyze.rs
+++ b/src/librustc_codegen_ssa/mir/analyze.rs
@@ -103,7 +103,7 @@ impl<'mir, 'a: 'mir, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> Visitor<'tcx>
                     location: Location) {
         debug!("visit_assign(block={:?}, place={:?}, rvalue={:?})", block, place, rvalue);
 
-        if let mir::Place::Local(index) = *place {
+        if let mir::Place::Base(mir::PlaceBase::Local(index)) = *place {
             self.assign(index, location);
             if !self.fx.rvalue_creates_operand(rvalue) {
                 self.not_ssa(index);
@@ -245,7 +245,8 @@ impl<'mir, 'a: 'mir, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> Visitor<'tcx>
             }
 
             PlaceContext::MutatingUse(MutatingUseContext::Drop) => {
-                let ty = mir::Place::Local(local).ty(self.fx.mir, self.fx.cx.tcx());
+                let ty = mir::Place::Base(mir::PlaceBase::Local(local)).ty(self.fx.mir,
+                                                                           self.fx.cx.tcx());
                 let ty = self.fx.monomorphize(&ty.to_ty(self.fx.cx.tcx()));
 
                 // Only need the place if we're actually dropping it.
diff --git a/src/librustc_codegen_ssa/mir/block.rs b/src/librustc_codegen_ssa/mir/block.rs
index 627380ee38f..02086c7730c 100644
--- a/src/librustc_codegen_ssa/mir/block.rs
+++ b/src/librustc_codegen_ssa/mir/block.rs
@@ -249,7 +249,7 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
 
             PassMode::Direct(_) | PassMode::Pair(..) => {
                 let op =
-                    self.codegen_consume(&mut bx, &mir::Place::Local(mir::RETURN_PLACE));
+                    self.codegen_consume(&mut bx, &mir::Place::RETURN_PLACE);
                 if let Ref(llval, _, align) = op.val {
                     bx.load(llval, align)
                 } else {
@@ -615,8 +615,12 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                         // The shuffle array argument is usually not an explicit constant,
                         // but specified directly in the code. This means it gets promoted
                         // and we can then extract the value by evaluating the promoted.
-                        mir::Operand::Copy(mir::Place::Promoted(box(index, ty))) |
-                        mir::Operand::Move(mir::Place::Promoted(box(index, ty))) => {
+                        mir::Operand::Copy(
+                            mir::Place::Base(mir::PlaceBase::Promoted(box(index, ty)))
+                        ) |
+                        mir::Operand::Move(
+                            mir::Place::Base(mir::PlaceBase::Promoted(box(index, ty)))
+                        ) => {
                             let param_env = ty::ParamEnv::reveal_all();
                             let cid = mir::interpret::GlobalId {
                                 instance: self.instance,
@@ -1106,7 +1110,7 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         if fn_ret.is_ignore() {
             return ReturnDest::Nothing;
         }
-        let dest = if let mir::Place::Local(index) = *dest {
+        let dest = if let mir::Place::Base(mir::PlaceBase::Local(index)) = *dest {
             match self.locals[index] {
                 LocalRef::Place(dest) => dest,
                 LocalRef::UnsizedPlace(_) => bug!("return type must be sized"),
@@ -1161,7 +1165,7 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         src: &mir::Operand<'tcx>,
         dst: &mir::Place<'tcx>
     ) {
-        if let mir::Place::Local(index) = *dst {
+        if let mir::Place::Base(mir::PlaceBase::Local(index)) = *dst {
             match self.locals[index] {
                 LocalRef::Place(place) => self.codegen_transmute_into(bx, src, place),
                 LocalRef::UnsizedPlace(_) => bug!("transmute must not involve unsized locals"),
diff --git a/src/librustc_codegen_ssa/mir/operand.rs b/src/librustc_codegen_ssa/mir/operand.rs
index 0e8cdc83b48..0a6549851f4 100644
--- a/src/librustc_codegen_ssa/mir/operand.rs
+++ b/src/librustc_codegen_ssa/mir/operand.rs
@@ -378,7 +378,7 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
 
         // watch out for locals that do not have an
         // alloca; they are handled somewhat differently
-        if let mir::Place::Local(index) = *place {
+        if let mir::Place::Base(mir::PlaceBase::Local(index)) = *place {
             match self.locals[index] {
                 LocalRef::Operand(Some(o)) => {
                     return Some(o);
diff --git a/src/librustc_codegen_ssa/mir/place.rs b/src/librustc_codegen_ssa/mir/place.rs
index 1edcbfead2c..0408ccf039f 100644
--- a/src/librustc_codegen_ssa/mir/place.rs
+++ b/src/librustc_codegen_ssa/mir/place.rs
@@ -392,7 +392,7 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         let cx = self.cx;
         let tcx = self.cx.tcx();
 
-        if let mir::Place::Local(index) = *place {
+        if let mir::Place::Base(mir::PlaceBase::Local(index)) = *place {
             match self.locals[index] {
                 LocalRef::Place(place) => {
                     return place;
@@ -407,8 +407,8 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         }
 
         let result = match *place {
-            mir::Place::Local(_) => bug!(), // handled above
-            mir::Place::Promoted(box (index, ty)) => {
+            mir::Place::Base(mir::PlaceBase::Local(_)) => bug!(), // handled above
+            mir::Place::Base(mir::PlaceBase::Promoted(box (index, ty))) => {
                 let param_env = ty::ParamEnv::reveal_all();
                 let cid = mir::interpret::GlobalId {
                     instance: self.instance,
@@ -435,7 +435,7 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                     }
                 }
             }
-            mir::Place::Static(box mir::Static { def_id, ty }) => {
+            mir::Place::Base(mir::PlaceBase::Static(box mir::Static { def_id, ty })) => {
                 // NB: The layout of a static may be unsized as is the case when working
                 // with a static that is an extern_type.
                 let layout = cx.layout_of(self.monomorphize(&ty));
@@ -457,7 +457,9 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                         cg_base.project_field(bx, field.index())
                     }
                     mir::ProjectionElem::Index(index) => {
-                        let index = &mir::Operand::Copy(mir::Place::Local(index));
+                        let index = &mir::Operand::Copy(
+                            mir::Place::Base(mir::PlaceBase::Local(index))
+                        );
                         let index = self.codegen_operand(bx, index);
                         let llindex = index.immediate();
                         cg_base.project_index(bx, llindex)
diff --git a/src/librustc_codegen_ssa/mir/rvalue.rs b/src/librustc_codegen_ssa/mir/rvalue.rs
index 25a7754d118..b0c667a965d 100644
--- a/src/librustc_codegen_ssa/mir/rvalue.rs
+++ b/src/librustc_codegen_ssa/mir/rvalue.rs
@@ -534,7 +534,7 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
     ) -> Bx::Value {
         // ZST are passed as operands and require special handling
         // because codegen_place() panics if Local is operand.
-        if let mir::Place::Local(index) = *place {
+        if let mir::Place::Base(mir::PlaceBase::Local(index)) = *place {
             if let LocalRef::Operand(Some(op)) = self.locals[index] {
                 if let ty::Array(_, n) = op.layout.ty.sty {
                     let n = n.unwrap_usize(bx.cx().tcx());
diff --git a/src/librustc_codegen_ssa/mir/statement.rs b/src/librustc_codegen_ssa/mir/statement.rs
index a1bd919c433..97729e8aeb3 100644
--- a/src/librustc_codegen_ssa/mir/statement.rs
+++ b/src/librustc_codegen_ssa/mir/statement.rs
@@ -17,7 +17,7 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         self.set_debug_loc(&mut bx, statement.source_info);
         match statement.kind {
             mir::StatementKind::Assign(ref place, ref rvalue) => {
-                if let mir::Place::Local(index) = *place {
+                if let mir::Place::Base(mir::PlaceBase::Local(index)) = *place {
                     match self.locals[index] {
                         LocalRef::Place(cg_dest) => {
                             self.codegen_rvalue(bx, cg_dest, rvalue)
diff --git a/src/librustc_codegen_utils/symbol_names_test.rs b/src/librustc_codegen_utils/symbol_names_test.rs
index a11eb4da66a..c4952681546 100644
--- a/src/librustc_codegen_utils/symbol_names_test.rs
+++ b/src/librustc_codegen_utils/symbol_names_test.rs
@@ -6,7 +6,6 @@
 
 use rustc::hir;
 use rustc::ty::TyCtxt;
-use syntax::ast;
 
 use rustc_mir::monomorphize::Instance;
 
@@ -33,9 +32,9 @@ struct SymbolNamesTest<'a, 'tcx:'a> {
 
 impl<'a, 'tcx> SymbolNamesTest<'a, 'tcx> {
     fn process_attrs(&mut self,
-                     node_id: ast::NodeId) {
+                     hir_id: hir::HirId) {
         let tcx = self.tcx;
-        let def_id = tcx.hir().local_def_id(node_id);
+        let def_id = tcx.hir().local_def_id_from_hir_id(hir_id);
         for attr in tcx.get_attrs(def_id).iter() {
             if attr.check_name(SYMBOL_NAME) {
                 // for now, can only use on monomorphic names
@@ -56,14 +55,14 @@ impl<'a, 'tcx> SymbolNamesTest<'a, 'tcx> {
 
 impl<'a, 'tcx> hir::itemlikevisit::ItemLikeVisitor<'tcx> for SymbolNamesTest<'a, 'tcx> {
     fn visit_item(&mut self, item: &'tcx hir::Item) {
-        self.process_attrs(item.id);
+        self.process_attrs(item.hir_id);
     }
 
     fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem) {
-        self.process_attrs(trait_item.id);
+        self.process_attrs(trait_item.hir_id);
     }
 
     fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem) {
-        self.process_attrs(impl_item.id);
+        self.process_attrs(impl_item.hir_id);
     }
 }
diff --git a/src/librustc_data_structures/Cargo.toml b/src/librustc_data_structures/Cargo.toml
index 6aa262715ec..6002bf69b70 100644
--- a/src/librustc_data_structures/Cargo.toml
+++ b/src/librustc_data_structures/Cargo.toml
@@ -12,13 +12,15 @@ crate-type = ["dylib"]
 [dependencies]
 ena = "0.11"
 log = "0.4"
+jobserver_crate = { version = "0.1", package = "jobserver" }
+lazy_static = "1"
 rustc_cratesio_shim = { path = "../librustc_cratesio_shim" }
 serialize = { path = "../libserialize" }
 graphviz = { path = "../libgraphviz" }
 cfg-if = "0.1.2"
 stable_deref_trait = "1.0.0"
-rayon = { version = "0.1.1", package = "rustc-rayon" }
-rayon-core = { version = "0.1.1", package = "rustc-rayon-core" }
+rayon = { version = "0.1.2", package = "rustc-rayon" }
+rayon-core = { version = "0.1.2", package = "rustc-rayon-core" }
 rustc-hash = "1.0.1"
 smallvec = { version = "0.6.7", features = ["union", "may_dangle"] }
 
diff --git a/src/librustc_data_structures/jobserver.rs b/src/librustc_data_structures/jobserver.rs
new file mode 100644
index 00000000000..48ac8125a0d
--- /dev/null
+++ b/src/librustc_data_structures/jobserver.rs
@@ -0,0 +1,156 @@
+use jobserver_crate::{Client, HelperThread, Acquired};
+use lazy_static::lazy_static;
+use std::sync::{Condvar, Arc, Mutex};
+use std::mem;
+
+#[derive(Default)]
+struct LockedProxyData {
+    /// The number of free thread tokens, this may include the implicit token given to the process
+    free: usize,
+
+    /// The number of threads waiting for a token
+    waiters: usize,
+
+    /// The number of tokens we requested from the server
+    requested: usize,
+
+    /// Stored tokens which will be dropped when we no longer need them
+    tokens: Vec<Acquired>,
+}
+
+impl LockedProxyData {
+    fn request_token(&mut self, thread: &Mutex<HelperThread>) {
+        self.requested += 1;
+        thread.lock().unwrap().request_token();
+    }
+
+    fn release_token(&mut self, cond_var: &Condvar) {
+        if self.waiters > 0 {
+            self.free += 1;
+            cond_var.notify_one();
+        } else {
+            if self.tokens.is_empty() {
+                // We are returning the implicit token
+                self.free += 1;
+            } else {
+                // Return a real token to the server
+                self.tokens.pop().unwrap();
+            }
+        }
+    }
+
+    fn take_token(&mut self, thread: &Mutex<HelperThread>) -> bool {
+        if self.free > 0 {
+            self.free -= 1;
+            self.waiters -= 1;
+
+            // We stole some token reqested by someone else
+            // Request another one
+            if self.requested + self.free < self.waiters {
+                self.request_token(thread);
+            }
+
+            true
+        } else {
+            false
+        }
+    }
+
+    fn new_requested_token(&mut self, token: Acquired, cond_var: &Condvar) {
+        self.requested -= 1;
+
+        // Does anything need this token?
+        if self.waiters > 0 {
+            self.free += 1;
+            self.tokens.push(token);
+            cond_var.notify_one();
+        } else {
+            // Otherwise we'll just drop it
+            mem::drop(token);
+        }
+    }
+}
+
+#[derive(Default)]
+struct ProxyData {
+    lock: Mutex<LockedProxyData>,
+    cond_var: Condvar,
+}
+
+/// A helper type which makes managing jobserver tokens easier.
+/// It also allows you to treat the implicit token given to the process
+/// in the same manner as requested tokens.
+struct Proxy {
+    thread: Mutex<HelperThread>,
+    data: Arc<ProxyData>,
+}
+
+lazy_static! {
+    // We can only call `from_env` once per process
+
+    // Note that this is unsafe because it may misinterpret file descriptors
+    // on Unix as jobserver file descriptors. We hopefully execute this near
+    // the beginning of the process though to ensure we don't get false
+    // positives, or in other words we try to execute this before we open
+    // any file descriptors ourselves.
+    //
+    // Pick a "reasonable maximum" if we don't otherwise have
+    // a jobserver in our environment, capping out at 32 so we
+    // don't take everything down by hogging the process run queue.
+    // The fixed number is used to have deterministic compilation
+    // across machines.
+    //
+    // Also note that we stick this in a global because there could be
+    // multiple rustc instances in this process, and the jobserver is
+    // per-process.
+    static ref GLOBAL_CLIENT: Client = unsafe {
+        Client::from_env().unwrap_or_else(|| {
+            Client::new(32).expect("failed to create jobserver")
+        })
+    };
+
+    static ref GLOBAL_PROXY: Proxy = {
+        let data = Arc::new(ProxyData::default());
+
+        Proxy {
+            data: data.clone(),
+            thread: Mutex::new(client().into_helper_thread(move |token| {
+                data.lock.lock().unwrap().new_requested_token(token.unwrap(), &data.cond_var);
+            }).unwrap()),
+        }
+    };
+}
+
+pub fn client() -> Client {
+    GLOBAL_CLIENT.clone()
+}
+
+pub fn acquire_thread() {
+    GLOBAL_PROXY.acquire_token();
+}
+
+pub fn release_thread() {
+    GLOBAL_PROXY.release_token();
+}
+
+impl Proxy {
+    fn release_token(&self) {
+        self.data.lock.lock().unwrap().release_token(&self.data.cond_var);
+    }
+
+    fn acquire_token(&self) {
+        let mut data = self.data.lock.lock().unwrap();
+        data.waiters += 1;
+        if data.take_token(&self.thread) {
+            return;
+        }
+        // Request a token for us
+        data.request_token(&self.thread);
+        loop {
+            data = self.data.cond_var.wait(data).unwrap();
+            if data.take_token(&self.thread) {
+                return;
+            }
+        }
+    }
+}
diff --git a/src/librustc_data_structures/lib.rs b/src/librustc_data_structures/lib.rs
index 2bfb1b24a81..09482340b1a 100644
--- a/src/librustc_data_structures/lib.rs
+++ b/src/librustc_data_structures/lib.rs
@@ -77,6 +77,7 @@ pub mod fx;
 pub mod graph;
 pub mod indexed_vec;
 pub mod interner;
+pub mod jobserver;
 pub mod obligation_forest;
 pub mod owning_ref;
 pub mod ptr_key;
diff --git a/src/librustc_driver/Cargo.toml b/src/librustc_driver/Cargo.toml
index 0b379ef662d..a77e497af7b 100644
--- a/src/librustc_driver/Cargo.toml
+++ b/src/librustc_driver/Cargo.toml
@@ -13,7 +13,7 @@ arena = { path = "../libarena" }
 graphviz = { path = "../libgraphviz" }
 log = "0.4"
 env_logger = { version = "0.5", default-features = false }
-rustc-rayon = "0.1.1"
+rustc-rayon = "0.1.2"
 scoped-tls = "1.0"
 rustc = { path = "../librustc" }
 rustc_allocator = { path = "../librustc_allocator" }
diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs
index f87a809e6c6..858a5602e7b 100644
--- a/src/librustc_driver/driver.rs
+++ b/src/librustc_driver/driver.rs
@@ -17,6 +17,8 @@ use rustc_allocator as allocator;
 use rustc_borrowck as borrowck;
 use rustc_codegen_utils::codegen_backend::CodegenBackend;
 use rustc_data_structures::sync::{self, Lock};
+#[cfg(parallel_compiler)]
+use rustc_data_structures::jobserver;
 use rustc_incremental;
 use rustc_metadata::creader::CrateLoader;
 use rustc_metadata::cstore::{self, CStore};
@@ -72,6 +74,8 @@ pub fn spawn_thread_pool<F: FnOnce(config::Options) -> R + sync::Send, R: sync::
     let gcx_ptr = &Lock::new(0);
 
     let config = ThreadPoolBuilder::new()
+        .acquire_thread_handler(jobserver::acquire_thread)
+        .release_thread_handler(jobserver::release_thread)
         .num_threads(Session::threads_from_count(opts.debugging_opts.threads))
         .deadlock_handler(|| unsafe { ty::query::handle_deadlock() })
         .stack_size(::STACK_SIZE);
diff --git a/src/librustc_incremental/assert_dep_graph.rs b/src/librustc_incremental/assert_dep_graph.rs
index fe44e0cbe61..1f69d617c83 100644
--- a/src/librustc_incremental/assert_dep_graph.rs
+++ b/src/librustc_incremental/assert_dep_graph.rs
@@ -69,7 +69,7 @@ pub fn assert_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
             let mut visitor = IfThisChanged { tcx,
                                             if_this_changed: vec![],
                                             then_this_would_need: vec![] };
-            visitor.process_attrs(ast::CRATE_NODE_ID, &tcx.hir().krate().attrs);
+            visitor.process_attrs(hir::CRATE_HIR_ID, &tcx.hir().krate().attrs);
             tcx.hir().krate().visit_all_item_likes(&mut visitor.as_deep_visitor());
             (visitor.if_this_changed, visitor.then_this_would_need)
         };
@@ -87,7 +87,7 @@ pub fn assert_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
 }
 
 type Sources = Vec<(Span, DefId, DepNode)>;
-type Targets = Vec<(Span, ast::Name, ast::NodeId, DepNode)>;
+type Targets = Vec<(Span, ast::Name, hir::HirId, DepNode)>;
 
 struct IfThisChanged<'a, 'tcx:'a> {
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
@@ -110,8 +110,8 @@ impl<'a, 'tcx> IfThisChanged<'a, 'tcx> {
         value
     }
 
-    fn process_attrs(&mut self, node_id: ast::NodeId, attrs: &[ast::Attribute]) {
-        let def_id = self.tcx.hir().local_def_id(node_id);
+    fn process_attrs(&mut self, hir_id: hir::HirId, attrs: &[ast::Attribute]) {
+        let def_id = self.tcx.hir().local_def_id_from_hir_id(hir_id);
         let def_path_hash = self.tcx.def_path_hash(def_id);
         for attr in attrs {
             if attr.check_name(ATTR_IF_THIS_CHANGED) {
@@ -151,7 +151,7 @@ impl<'a, 'tcx> IfThisChanged<'a, 'tcx> {
                 };
                 self.then_this_would_need.push((attr.span,
                                                 dep_node_interned.unwrap(),
-                                                node_id,
+                                                hir_id,
                                                 dep_node));
             }
         }
@@ -164,22 +164,22 @@ impl<'a, 'tcx> Visitor<'tcx> for IfThisChanged<'a, 'tcx> {
     }
 
     fn visit_item(&mut self, item: &'tcx hir::Item) {
-        self.process_attrs(item.id, &item.attrs);
+        self.process_attrs(item.hir_id, &item.attrs);
         intravisit::walk_item(self, item);
     }
 
     fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem) {
-        self.process_attrs(trait_item.id, &trait_item.attrs);
+        self.process_attrs(trait_item.hir_id, &trait_item.attrs);
         intravisit::walk_trait_item(self, trait_item);
     }
 
     fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem) {
-        self.process_attrs(impl_item.id, &impl_item.attrs);
+        self.process_attrs(impl_item.hir_id, &impl_item.attrs);
         intravisit::walk_impl_item(self, impl_item);
     }
 
     fn visit_struct_field(&mut self, s: &'tcx hir::StructField) {
-        self.process_attrs(s.id, &s.attrs);
+        self.process_attrs(s.hir_id, &s.attrs);
         intravisit::walk_struct_field(self, s);
     }
 }
diff --git a/src/librustc_incremental/persist/dirty_clean.rs b/src/librustc_incremental/persist/dirty_clean.rs
index c13a3533032..2794b6c556f 100644
--- a/src/librustc_incremental/persist/dirty_clean.rs
+++ b/src/librustc_incremental/persist/dirty_clean.rs
@@ -241,7 +241,7 @@ pub struct DirtyCleanVisitor<'a, 'tcx:'a> {
 impl<'a, 'tcx> DirtyCleanVisitor<'a, 'tcx> {
 
     /// Possibly "deserialize" the attribute into a clean/dirty assertion
-    fn assertion_maybe(&mut self, item_id: ast::NodeId, attr: &Attribute)
+    fn assertion_maybe(&mut self, item_id: hir::HirId, attr: &Attribute)
         -> Option<Assertion>
     {
         let is_clean = if attr.check_name(ATTR_DIRTY) {
@@ -269,7 +269,7 @@ impl<'a, 'tcx> DirtyCleanVisitor<'a, 'tcx> {
     }
 
     /// Gets the "auto" assertion on pre-validated attr, along with the `except` labels.
-    fn assertion_auto(&mut self, item_id: ast::NodeId, attr: &Attribute, is_clean: bool)
+    fn assertion_auto(&mut self, item_id: hir::HirId, attr: &Attribute, is_clean: bool)
         -> Assertion
     {
         let (name, mut auto) = self.auto_labels(item_id, attr);
@@ -321,8 +321,8 @@ impl<'a, 'tcx> DirtyCleanVisitor<'a, 'tcx> {
 
     /// Return all DepNode labels that should be asserted for this item.
     /// index=0 is the "name" used for error messages
-    fn auto_labels(&mut self, item_id: ast::NodeId, attr: &Attribute) -> (&'static str, Labels) {
-        let node = self.tcx.hir().get(item_id);
+    fn auto_labels(&mut self, item_id: hir::HirId, attr: &Attribute) -> (&'static str, Labels) {
+        let node = self.tcx.hir().get_by_hir_id(item_id);
         let (name, labels) = match node {
             HirNode::Item(item) => {
                 match item.node {
@@ -499,8 +499,8 @@ impl<'a, 'tcx> DirtyCleanVisitor<'a, 'tcx> {
         }
     }
 
-    fn check_item(&mut self, item_id: ast::NodeId, item_span: Span) {
-        let def_id = self.tcx.hir().local_def_id(item_id);
+    fn check_item(&mut self, item_id: hir::HirId, item_span: Span) {
+        let def_id = self.tcx.hir().local_def_id_from_hir_id(item_id);
         for attr in self.tcx.get_attrs(def_id).iter() {
             let assertion = match self.assertion_maybe(item_id, attr) {
                 Some(a) => a,
@@ -519,15 +519,15 @@ impl<'a, 'tcx> DirtyCleanVisitor<'a, 'tcx> {
 
 impl<'a, 'tcx> ItemLikeVisitor<'tcx> for DirtyCleanVisitor<'a, 'tcx> {
     fn visit_item(&mut self, item: &'tcx hir::Item) {
-        self.check_item(item.id, item.span);
+        self.check_item(item.hir_id, item.span);
     }
 
     fn visit_trait_item(&mut self, item: &hir::TraitItem) {
-        self.check_item(item.id, item.span);
+        self.check_item(item.hir_id, item.span);
     }
 
     fn visit_impl_item(&mut self, item: &hir::ImplItem) {
-        self.check_item(item.id, item.span);
+        self.check_item(item.hir_id, item.span);
     }
 }
 
diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs
index ac10b6403bd..4d484a64f47 100644
--- a/src/librustc_lint/builtin.rs
+++ b/src/librustc_lint/builtin.rs
@@ -324,7 +324,7 @@ pub struct MissingDoc {
     doc_hidden_stack: Vec<bool>,
 
     /// Private traits or trait items that leaked through. Don't check their methods.
-    private_traits: FxHashSet<ast::NodeId>,
+    private_traits: FxHashSet<hir::HirId>,
 }
 
 fn has_doc(attr: &ast::Attribute) -> bool {
@@ -361,7 +361,7 @@ impl MissingDoc {
 
     fn check_missing_docs_attrs(&self,
                                 cx: &LateContext<'_, '_>,
-                                id: Option<ast::NodeId>,
+                                id: Option<hir::HirId>,
                                 attrs: &[ast::Attribute],
                                 sp: Span,
                                 desc: &'static str) {
@@ -380,7 +380,8 @@ impl MissingDoc {
         // It's an option so the crate root can also use this function (it doesn't
         // have a NodeId).
         if let Some(id) = id {
-            if !cx.access_levels.is_exported(id) {
+            let node_id = cx.tcx.hir().hir_to_node_id(id);
+            if !cx.access_levels.is_exported(node_id) {
                 return;
             }
         }
@@ -444,9 +445,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDoc {
             hir::ItemKind::Trait(.., ref trait_item_refs) => {
                 // Issue #11592, traits are always considered exported, even when private.
                 if let hir::VisibilityKind::Inherited = it.vis.node {
-                    self.private_traits.insert(it.id);
+                    self.private_traits.insert(it.hir_id);
                     for trait_item_ref in trait_item_refs {
-                        self.private_traits.insert(trait_item_ref.id.node_id);
+                        let hir_id = cx.tcx.hir().node_to_hir_id(trait_item_ref.id.node_id);
+                        self.private_traits.insert(hir_id);
                     }
                     return;
                 }
@@ -462,7 +464,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDoc {
                         Some(Node::Item(item)) => {
                             if let hir::VisibilityKind::Inherited = item.vis.node {
                                 for impl_item_ref in impl_item_refs {
-                                    self.private_traits.insert(impl_item_ref.id.node_id);
+                                    let hir_id = cx.tcx.hir().node_to_hir_id(
+                                        impl_item_ref.id.node_id);
+                                    self.private_traits.insert(hir_id);
                                 }
                             }
                         }
@@ -476,11 +480,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDoc {
             _ => return,
         };
 
-        self.check_missing_docs_attrs(cx, Some(it.id), &it.attrs, it.span, desc);
+        self.check_missing_docs_attrs(cx, Some(it.hir_id), &it.attrs, it.span, desc);
     }
 
     fn check_trait_item(&mut self, cx: &LateContext<'_, '_>, trait_item: &hir::TraitItem) {
-        if self.private_traits.contains(&trait_item.id) {
+        if self.private_traits.contains(&trait_item.hir_id) {
             return;
         }
 
@@ -491,7 +495,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDoc {
         };
 
         self.check_missing_docs_attrs(cx,
-                                      Some(trait_item.id),
+                                      Some(trait_item.hir_id),
                                       &trait_item.attrs,
                                       trait_item.span,
                                       desc);
@@ -510,7 +514,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDoc {
             hir::ImplItemKind::Existential(_) => "an associated existential type",
         };
         self.check_missing_docs_attrs(cx,
-                                      Some(impl_item.id),
+                                      Some(impl_item.hir_id),
                                       &impl_item.attrs,
                                       impl_item.span,
                                       desc);
@@ -519,7 +523,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDoc {
     fn check_struct_field(&mut self, cx: &LateContext<'_, '_>, sf: &hir::StructField) {
         if !sf.is_positional() {
             self.check_missing_docs_attrs(cx,
-                                          Some(sf.id),
+                                          Some(sf.hir_id),
                                           &sf.attrs,
                                           sf.span,
                                           "a struct field")
@@ -528,7 +532,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDoc {
 
     fn check_variant(&mut self, cx: &LateContext<'_, '_>, v: &hir::Variant, _: &hir::Generics) {
         self.check_missing_docs_attrs(cx,
-                                      Some(v.node.data.id()),
+                                      Some(v.node.data.hir_id()),
                                       &v.node.attrs,
                                       v.span,
                                       "a variant");
@@ -1108,11 +1112,12 @@ impl LintPass for UnreachablePub {
 }
 
 impl UnreachablePub {
-    fn perform_lint(&self, cx: &LateContext<'_, '_>, what: &str, id: ast::NodeId,
+    fn perform_lint(&self, cx: &LateContext<'_, '_>, what: &str, id: hir::HirId,
                     vis: &hir::Visibility, span: Span, exportable: bool) {
         let mut applicability = Applicability::MachineApplicable;
+        let node_id = cx.tcx.hir().hir_to_node_id(id);
         match vis.node {
-            hir::VisibilityKind::Public if !cx.access_levels.is_reachable(id) => {
+            hir::VisibilityKind::Public if !cx.access_levels.is_reachable(node_id) => {
                 if span.ctxt().outer().expn_info().is_some() {
                     applicability = Applicability::MaybeIncorrect;
                 }
@@ -1144,20 +1149,20 @@ impl UnreachablePub {
 
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnreachablePub {
     fn check_item(&mut self, cx: &LateContext<'_, '_>, item: &hir::Item) {
-        self.perform_lint(cx, "item", item.id, &item.vis, item.span, true);
+        self.perform_lint(cx, "item", item.hir_id, &item.vis, item.span, true);
     }
 
     fn check_foreign_item(&mut self, cx: &LateContext<'_, '_>, foreign_item: &hir::ForeignItem) {
-        self.perform_lint(cx, "item", foreign_item.id, &foreign_item.vis,
+        self.perform_lint(cx, "item", foreign_item.hir_id, &foreign_item.vis,
                           foreign_item.span, true);
     }
 
     fn check_struct_field(&mut self, cx: &LateContext<'_, '_>, field: &hir::StructField) {
-        self.perform_lint(cx, "field", field.id, &field.vis, field.span, false);
+        self.perform_lint(cx, "field", field.hir_id, &field.vis, field.span, false);
     }
 
     fn check_impl_item(&mut self, cx: &LateContext<'_, '_>, impl_item: &hir::ImplItem) {
-        self.perform_lint(cx, "item", impl_item.id, &impl_item.vis, impl_item.span, false);
+        self.perform_lint(cx, "item", impl_item.hir_id, &impl_item.vis, impl_item.span, false);
     }
 }
 
diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs
index 5fdc5899a72..b4a71b887dc 100644
--- a/src/librustc_metadata/encoder.rs
+++ b/src/librustc_metadata/encoder.rs
@@ -1667,7 +1667,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for EncodeVisitor<'a, 'b, 'tcx> {
         intravisit::walk_variant(self, v, g, id);
 
         if let Some(ref discr) = v.node.disr_expr {
-            let def_id = self.index.tcx.hir().local_def_id(discr.id);
+            let def_id = self.index.tcx.hir().local_def_id_from_hir_id(discr.hir_id);
             self.index.record(def_id, IsolatedEncoder::encode_info_for_anon_const, def_id);
         }
     }
@@ -1719,7 +1719,7 @@ impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> {
     fn encode_info_for_ty(&mut self, ty: &hir::Ty) {
         match ty.node {
             hir::TyKind::Array(_, ref length) => {
-                let def_id = self.tcx.hir().local_def_id(length.id);
+                let def_id = self.tcx.hir().local_def_id_from_hir_id(length.hir_id);
                 self.record(def_id, IsolatedEncoder::encode_info_for_anon_const, def_id);
             }
             _ => {}
diff --git a/src/librustc_mir/borrow_check/borrow_set.rs b/src/librustc_mir/borrow_check/borrow_set.rs
index 2a3a616317c..cbef7a7f6c4 100644
--- a/src/librustc_mir/borrow_check/borrow_set.rs
+++ b/src/librustc_mir/borrow_check/borrow_set.rs
@@ -333,7 +333,7 @@ impl<'a, 'gcx, 'tcx> GatherBorrows<'a, 'gcx, 'tcx> {
         //    TEMP = &foo
         //
         // so extract `temp`.
-        let temp = if let &mir::Place::Local(temp) = assigned_place {
+        let temp = if let &mir::Place::Base(mir::PlaceBase::Local(temp)) = assigned_place {
             temp
         } else {
             span_bug!(
diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs
index 67fbe5762e7..dc1979b6380 100644
--- a/src/librustc_mir/borrow_check/error_reporting.rs
+++ b/src/librustc_mir/borrow_check/error_reporting.rs
@@ -8,7 +8,7 @@ use rustc::middle::region::ScopeTree;
 use rustc::mir::{
     self, AggregateKind, BindingForm, BorrowKind, ClearCrossCrate, Constant,
     ConstraintCategory, Field, Local, LocalDecl, LocalKind, Location, Operand,
-    Place, PlaceProjection, ProjectionElem, Rvalue, Statement, StatementKind,
+    Place, PlaceBase, PlaceProjection, ProjectionElem, Rvalue, Statement, StatementKind,
     TerminatorKind, VarBindingForm,
 };
 use rustc::ty::{self, DefIdTree};
@@ -220,7 +220,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
                         );
                     }
                 }
-                if let Place::Local(local) = place {
+                if let Place::Base(PlaceBase::Local(local)) = place {
                     let decl = &self.mir.local_decls[*local];
                     err.span_label(
                         decl.source_info.span,
@@ -679,7 +679,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
         let borrow_span = borrow_spans.var_or_use();
 
         let proper_span = match *root_place {
-            Place::Local(local) => self.mir.local_decls[local].source_info.span,
+            Place::Base(PlaceBase::Local(local)) => self.mir.local_decls[local].source_info.span,
             _ => drop_span,
         };
 
@@ -1061,7 +1061,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
 
         let (place_desc, note) = if let Some(place_desc) = opt_place_desc {
             let local_kind = match borrow.borrowed_place {
-                Place::Local(local) => {
+                Place::Base(PlaceBase::Local(local)) => {
                     match self.mir.local_kind(local) {
                         LocalKind::ReturnPointer
                         | LocalKind::Temp => bug!("temporary or return pointer with a name"),
@@ -1086,7 +1086,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
             let root_place = self.prefixes(&borrow.borrowed_place, PrefixSet::All)
                 .last()
                 .unwrap();
-            let local = if let Place::Local(local) = *root_place {
+            let local = if let Place::Base(PlaceBase::Local(local)) = *root_place {
                 local
             } else {
                 bug!("report_cannot_return_reference_to_local: not a local")
@@ -1385,7 +1385,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
         assigned_span: Span,
         err_place: &Place<'tcx>,
     ) {
-        let (from_arg, local_decl) = if let Place::Local(local) = *err_place {
+        let (from_arg, local_decl) = if let Place::Base(PlaceBase::Local(local)) = *err_place {
             if let LocalKind::Arg = self.mir.local_kind(local) {
                 (true, Some(&self.mir.local_decls[local]))
             } else {
@@ -1600,13 +1600,13 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
         including_downcast: &IncludingDowncast,
     ) -> Result<(), ()> {
         match *place {
-            Place::Promoted(_) => {
+            Place::Base(PlaceBase::Promoted(_)) => {
                 buf.push_str("promoted");
             }
-            Place::Local(local) => {
+            Place::Base(PlaceBase::Local(local)) => {
                 self.append_local_to_string(local, buf)?;
             }
-            Place::Static(ref static_) => {
+            Place::Base(PlaceBase::Static(ref static_)) => {
                 buf.push_str(&self.infcx.tcx.item_name(static_.def_id).to_string());
             }
             Place::Projection(ref proj) => {
@@ -1630,7 +1630,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
                                     autoderef,
                                     &including_downcast,
                                 )?;
-                            } else if let Place::Local(local) = proj.base {
+                            } else if let Place::Base(PlaceBase::Local(local)) = proj.base {
                                 if let Some(ClearCrossCrate::Set(BindingForm::RefForGuard)) =
                                     self.mir.local_decls[local].is_user_variable
                                 {
@@ -1742,12 +1742,14 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
     /// End-user visible description of the `field`nth field of `base`
     fn describe_field(&self, base: &Place<'_>, field: Field) -> String {
         match *base {
-            Place::Local(local) => {
+            Place::Base(PlaceBase::Local(local)) => {
                 let local = &self.mir.local_decls[local];
                 self.describe_field_from_ty(&local.ty, field)
             }
-            Place::Promoted(ref prom) => self.describe_field_from_ty(&prom.1, field),
-            Place::Static(ref static_) => self.describe_field_from_ty(&static_.ty, field),
+            Place::Base(PlaceBase::Promoted(ref prom)) =>
+                self.describe_field_from_ty(&prom.1, field),
+            Place::Base(PlaceBase::Static(ref static_)) =>
+                self.describe_field_from_ty(&static_.ty, field),
             Place::Projection(ref proj) => match proj.elem {
                 ProjectionElem::Deref => self.describe_field(&proj.base, field),
                 ProjectionElem::Downcast(def, variant_index) =>
@@ -1809,7 +1811,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
 
     /// Checks if a place is a thread-local static.
     pub fn is_place_thread_local(&self, place: &Place<'tcx>) -> bool {
-        if let Place::Static(statik) = place {
+        if let Place::Base(PlaceBase::Static(statik)) = place {
             let attrs = self.infcx.tcx.get_attrs(statik.def_id);
             let is_thread_local = attrs.iter().any(|attr| attr.check_name("thread_local"));
 
@@ -1827,7 +1829,9 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
     fn classify_drop_access_kind(&self, place: &Place<'tcx>) -> StorageDeadOrDrop<'tcx> {
         let tcx = self.infcx.tcx;
         match place {
-            Place::Local(_) | Place::Static(_) | Place::Promoted(_) => {
+            Place::Base(PlaceBase::Local(_)) |
+            Place::Base(PlaceBase::Static(_)) |
+            Place::Base(PlaceBase::Promoted(_)) => {
                 StorageDeadOrDrop::LocalStorageDead
             }
             Place::Projection(box PlaceProjection { base, elem }) => {
@@ -1912,7 +1916,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
             );
             // Check that the initial assignment of the reserve location is into a temporary.
             let mut target = *match reservation {
-                Place::Local(local) if self.mir.local_kind(*local) == LocalKind::Temp => local,
+                Place::Base(PlaceBase::Local(local))
+                    if self.mir.local_kind(*local) == LocalKind::Temp => local,
                 _ => return None,
             };
 
@@ -1924,8 +1929,10 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
                     "annotate_argument_and_return_for_borrow: target={:?} stmt={:?}",
                     target, stmt
                 );
-                if let StatementKind::Assign(Place::Local(assigned_to), box rvalue) = &stmt.kind
-                {
+                if let StatementKind::Assign(
+                    Place::Base(PlaceBase::Local(assigned_to)),
+                    box rvalue
+                ) = &stmt.kind {
                     debug!(
                         "annotate_argument_and_return_for_borrow: assigned_to={:?} \
                          rvalue={:?}",
@@ -2048,7 +2055,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
                 target, terminator
             );
             if let TerminatorKind::Call {
-                destination: Some((Place::Local(assigned_to), _)),
+                destination: Some((Place::Base(PlaceBase::Local(assigned_to)), _)),
                 args,
                 ..
             } = &terminator.kind
@@ -2496,7 +2503,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
             .get(location.statement_index)
         {
             Some(&Statement {
-                kind: StatementKind::Assign(Place::Local(local), _),
+                kind: StatementKind::Assign(Place::Base(PlaceBase::Local(local)), _),
                 ..
             }) => local,
             _ => return OtherUse(use_span),
@@ -2522,7 +2529,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
                     def_id, is_generator, places
                 );
                 if let Some((args_span, var_span)) = self.closure_span(
-                    *def_id, &Place::Local(target), places
+                    *def_id, &Place::Base(PlaceBase::Local(target)), places
                 ) {
                     return ClosureUse {
                         is_generator,
diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs
index 1091646bdd5..715ee856a7a 100644
--- a/src/librustc_mir/borrow_check/mod.rs
+++ b/src/librustc_mir/borrow_check/mod.rs
@@ -8,7 +8,7 @@ use rustc::infer::InferCtxt;
 use rustc::lint::builtin::UNUSED_MUT;
 use rustc::middle::borrowck::SignalledError;
 use rustc::mir::{AggregateKind, BasicBlock, BorrowCheckResult, BorrowKind};
-use rustc::mir::{ClearCrossCrate, Local, Location, Mir, Mutability, Operand, Place};
+use rustc::mir::{ClearCrossCrate, Local, Location, Mir, Mutability, Operand, Place, PlaceBase};
 use rustc::mir::{Field, Projection, ProjectionElem, Rvalue, Statement, StatementKind};
 use rustc::mir::{Terminator, TerminatorKind};
 use rustc::ty::query::Providers;
@@ -588,7 +588,7 @@ impl<'cx, 'gcx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx
             StatementKind::StorageDead(local) => {
                 self.access_place(
                     ContextKind::StorageDead.new(location),
-                    (&Place::Local(local), span),
+                    (&Place::Base(PlaceBase::Local(local)), span),
                     (Shallow(None), Write(WriteKind::StorageDeadOrDrop)),
                     LocalMutationIsAllowed::Yes,
                     flow_state,
@@ -1104,7 +1104,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
         // Special case: you can assign a immutable local variable
         // (e.g., `x = ...`) so long as it has never been initialized
         // before (at this point in the flow).
-        if let &Place::Local(local) = place_span.0 {
+        if let &Place::Base(PlaceBase::Local(local)) = place_span.0 {
             if let Mutability::Not = self.mir.local_decls[local].mutability {
                 // check for reassignments to immutable local variables
                 self.check_if_reassignment_to_immutable_state(
@@ -1231,8 +1231,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
                             // captures of a closure are copied/moved directly
                             // when generating MIR.
                             match operands[field.index()] {
-                                Operand::Move(Place::Local(local))
-                                | Operand::Copy(Place::Local(local)) => {
+                                Operand::Move(Place::Base(PlaceBase::Local(local)))
+                                | Operand::Copy(Place::Base(PlaceBase::Local(local))) => {
                                     self.used_mut.insert(local);
                                 }
                                 Operand::Move(ref place @ Place::Projection(_))
@@ -1242,10 +1242,10 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
                                         self.used_mut_upvars.push(field);
                                     }
                                 }
-                                Operand::Move(Place::Static(..))
-                                | Operand::Copy(Place::Static(..))
-                                | Operand::Move(Place::Promoted(..))
-                                | Operand::Copy(Place::Promoted(..))
+                                Operand::Move(Place::Base(PlaceBase::Static(..)))
+                                | Operand::Copy(Place::Base(PlaceBase::Static(..)))
+                                | Operand::Move(Place::Base(PlaceBase::Promoted(..)))
+                                | Operand::Copy(Place::Base(PlaceBase::Promoted(..)))
                                 | Operand::Constant(..) => {}
                             }
                         }
@@ -1328,14 +1328,14 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
         //
         // FIXME: allow thread-locals to borrow other thread locals?
         let (might_be_alive, will_be_dropped) = match root_place {
-            Place::Promoted(_) => (true, false),
-            Place::Static(_) => {
+            Place::Base(PlaceBase::Promoted(_)) => (true, false),
+            Place::Base(PlaceBase::Static(_)) => {
                 // Thread-locals might be dropped after the function exits, but
                 // "true" statics will never be.
                 let is_thread_local = self.is_place_thread_local(&root_place);
                 (true, is_thread_local)
             }
-            Place::Local(_) => {
+            Place::Base(PlaceBase::Local(_)) => {
                 // Locals are always dropped at function exit, and if they
                 // have a destructor it would've been called already.
                 (false, self.locals_are_invalidated_at_exit)
@@ -1594,10 +1594,10 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
             last_prefix = prefix;
         }
         match *last_prefix {
-            Place::Local(_) => panic!("should have move path for every Local"),
+            Place::Base(PlaceBase::Local(_)) => panic!("should have move path for every Local"),
             Place::Projection(_) => panic!("PrefixSet::All meant don't stop for Projection"),
-            Place::Promoted(_) |
-            Place::Static(_) => Err(NoMovePathFound::ReachedStatic),
+            Place::Base(PlaceBase::Promoted(_)) |
+            Place::Base(PlaceBase::Static(_)) => Err(NoMovePathFound::ReachedStatic),
         }
     }
 
@@ -1623,8 +1623,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
         let mut place = place;
         loop {
             match *place {
-                Place::Promoted(_) |
-                Place::Local(_) | Place::Static(_) => {
+                Place::Base(PlaceBase::Promoted(_)) |
+                Place::Base(PlaceBase::Local(_)) | Place::Base(PlaceBase::Static(_)) => {
                     // assigning to `x` does not require `x` be initialized.
                     break;
                 }
@@ -1947,7 +1947,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
     ) {
         match root_place {
             RootPlace {
-                place: Place::Local(local),
+                place: Place::Base(PlaceBase::Local(local)),
                 is_local_mutation_allowed,
             } => {
                 // If the local may have been initialized, and it is now currently being
@@ -1972,11 +1972,11 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
                 }
             }
             RootPlace {
-                place: Place::Promoted(..),
+                place: Place::Base(PlaceBase::Promoted(..)),
                 is_local_mutation_allowed: _,
             } => {}
             RootPlace {
-                place: Place::Static(..),
+                place: Place::Base(PlaceBase::Static(..)),
                 is_local_mutation_allowed: _,
             } => {}
         }
@@ -1990,7 +1990,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
         is_local_mutation_allowed: LocalMutationIsAllowed,
     ) -> Result<RootPlace<'d, 'tcx>, &'d Place<'tcx>> {
         match *place {
-            Place::Local(local) => {
+            Place::Base(PlaceBase::Local(local)) => {
                 let local = &self.mir.local_decls[local];
                 match local.mutability {
                     Mutability::Not => match is_local_mutation_allowed {
@@ -2012,11 +2012,11 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
             }
             // The rules for promotion are made by `qualify_consts`, there wouldn't even be a
             // `Place::Promoted` if the promotion weren't 100% legal. So we just forward this
-            Place::Promoted(_) => Ok(RootPlace {
+            Place::Base(PlaceBase::Promoted(_)) => Ok(RootPlace {
                 place,
                 is_local_mutation_allowed,
             }),
-            Place::Static(ref static_) => {
+            Place::Base(PlaceBase::Static(ref static_)) => {
                 if self.infcx.tcx.is_static(static_.def_id) != Some(hir::Mutability::MutMutable) {
                     Err(place)
                 } else {
diff --git a/src/librustc_mir/borrow_check/move_errors.rs b/src/librustc_mir/borrow_check/move_errors.rs
index 2a5433d4317..bd4bf67d0b1 100644
--- a/src/librustc_mir/borrow_check/move_errors.rs
+++ b/src/librustc_mir/borrow_check/move_errors.rs
@@ -111,7 +111,7 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
                 // If that ever stops being the case, then the ever initialized
                 // flow could be used.
                 if let Some(StatementKind::Assign(
-                    Place::Local(local),
+                    Place::Base(PlaceBase::Local(local)),
                     box Rvalue::Use(Operand::Move(move_from)),
                 )) = self.mir.basic_blocks()[location.block]
                     .statements
diff --git a/src/librustc_mir/borrow_check/mutability_errors.rs b/src/librustc_mir/borrow_check/mutability_errors.rs
index 008c081aeb6..f68ed4422bc 100644
--- a/src/librustc_mir/borrow_check/mutability_errors.rs
+++ b/src/librustc_mir/borrow_check/mutability_errors.rs
@@ -1,8 +1,8 @@
 use rustc::hir;
 use rustc::hir::Node;
 use rustc::mir::{self, BindingForm, Constant, ClearCrossCrate, Local, Location, Mir};
-use rustc::mir::{Mutability, Operand, Place, Projection, ProjectionElem, Static, Terminator};
-use rustc::mir::TerminatorKind;
+use rustc::mir::{Mutability, Operand, Place, PlaceBase, Projection, ProjectionElem, Static};
+use rustc::mir::{Terminator, TerminatorKind};
 use rustc::ty::{self, Const, DefIdTree, TyS, TyKind, TyCtxt};
 use rustc_data_structures::indexed_vec::Idx;
 use syntax_pos::Span;
@@ -45,9 +45,9 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
         debug!("report_mutability_error: access_place_desc={:?}", access_place_desc);
 
         match the_place_err {
-            Place::Local(local) => {
+            Place::Base(PlaceBase::Local(local)) => {
                 item_msg = format!("`{}`", access_place_desc.unwrap());
-                if let Place::Local(_) = access_place {
+                if let Place::Base(PlaceBase::Local(_)) = access_place {
                     reason = ", as it is not declared as mutable".to_string();
                 } else {
                     let name = self.mir.local_decls[*local]
@@ -78,7 +78,8 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
                 base,
                 elem: ProjectionElem::Deref,
             }) => {
-                if *base == Place::Local(Local::new(1)) && !self.mir.upvar_decls.is_empty() {
+                if *base == Place::Base(PlaceBase::Local(Local::new(1))) &&
+                    !self.mir.upvar_decls.is_empty() {
                     item_msg = format!("`{}`", access_place_desc.unwrap());
                     debug_assert!(self.mir.local_decls[Local::new(1)].ty.is_region_ptr());
                     debug_assert!(is_closure_or_generator(
@@ -92,7 +93,7 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
                         ", as `Fn` closures cannot mutate their captured variables".to_string()
                     }
                 } else if {
-                    if let Place::Local(local) = *base {
+                    if let Place::Base(PlaceBase::Local(local)) = *base {
                         if let Some(ClearCrossCrate::Set(BindingForm::RefForGuard))
                             = self.mir.local_decls[local].is_user_variable {
                                 true
@@ -128,10 +129,10 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
                 }
             }
 
-            Place::Promoted(_) => unreachable!(),
+            Place::Base(PlaceBase::Promoted(_)) => unreachable!(),
 
-            Place::Static(box Static { def_id, ty: _ }) => {
-                if let Place::Static(_) = access_place {
+            Place::Base(PlaceBase::Static(box Static { def_id, ty: _ })) => {
+                if let Place::Base(PlaceBase::Static(_)) = access_place {
                     item_msg = format!("immutable static item `{}`", access_place_desc.unwrap());
                     reason = String::new();
                 } else {
@@ -241,7 +242,7 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
             },
 
             // Suggest removing a `&mut` from the use of a mutable reference.
-            Place::Local(local)
+            Place::Base(PlaceBase::Local(local))
                 if {
                     self.mir.local_decls.get(*local).map(|local_decl| {
                         if let ClearCrossCrate::Set(
@@ -276,7 +277,8 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
 
             // We want to suggest users use `let mut` for local (user
             // variable) mutations...
-            Place::Local(local) if self.mir.local_decls[*local].can_be_made_mutable() => {
+            Place::Base(PlaceBase::Local(local))
+                if self.mir.local_decls[*local].can_be_made_mutable() => {
                 // ... but it doesn't make sense to suggest it on
                 // variables that are `ref x`, `ref mut x`, `&self`,
                 // or `&mut self` (such variables are simply not
@@ -330,7 +332,7 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
             // complete hack to approximate old AST-borrowck
             // diagnostic: if the span starts with a mutable borrow of
             // a local variable, then just suggest the user remove it.
-            Place::Local(_)
+            Place::Base(PlaceBase::Local(_))
                 if {
                     if let Ok(snippet) = self.infcx.tcx.sess.source_map().span_to_snippet(span) {
                         snippet.starts_with("&mut ")
@@ -344,7 +346,7 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
             }
 
             Place::Projection(box Projection {
-                base: Place::Local(local),
+                base: Place::Base(PlaceBase::Local(local)),
                 elem: ProjectionElem::Deref,
             }) if {
                 if let Some(ClearCrossCrate::Set(BindingForm::RefForGuard)) =
@@ -368,7 +370,7 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
             // FIXME: can this case be generalized to work for an
             // arbitrary base for the projection?
             Place::Projection(box Projection {
-                base: Place::Local(local),
+                base: Place::Base(PlaceBase::Local(local)),
                 elem: ProjectionElem::Deref,
             }) if self.mir.local_decls[*local].is_user_variable.is_some() =>
             {
@@ -447,7 +449,8 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
             Place::Projection(box Projection {
                 base,
                 elem: ProjectionElem::Deref,
-            }) if *base == Place::Local(Local::new(1)) && !self.mir.upvar_decls.is_empty() =>
+            }) if *base == Place::Base(PlaceBase::Local(Local::new(1))) &&
+                  !self.mir.upvar_decls.is_empty() =>
             {
                 err.span_label(span, format!("cannot {ACT}", ACT = act));
                 err.span_help(
@@ -457,7 +460,7 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
             }
 
             Place::Projection(box Projection {
-                base: Place::Local(local),
+                base: Place::Base(PlaceBase::Local(local)),
                 elem: ProjectionElem::Deref,
             })  if error_access == AccessKind::MutableBorrow => {
                 err.span_label(span, format!("cannot {ACT}", ACT = act));
diff --git a/src/librustc_mir/borrow_check/nll/constraint_generation.rs b/src/librustc_mir/borrow_check/nll/constraint_generation.rs
index 9eb09b51474..375dd6e97f1 100644
--- a/src/librustc_mir/borrow_check/nll/constraint_generation.rs
+++ b/src/librustc_mir/borrow_check/nll/constraint_generation.rs
@@ -6,7 +6,7 @@ use crate::borrow_check::nll::region_infer::values::LivenessValues;
 use rustc::infer::InferCtxt;
 use rustc::mir::visit::TyContext;
 use rustc::mir::visit::Visitor;
-use rustc::mir::{BasicBlock, BasicBlockData, Location, Mir, Place, Rvalue};
+use rustc::mir::{BasicBlock, BasicBlockData, Location, Mir, Place, PlaceBase, Rvalue};
 use rustc::mir::{SourceInfo, Statement, Terminator};
 use rustc::mir::UserTypeProjection;
 use rustc::ty::fold::TypeFoldable;
@@ -130,7 +130,7 @@ impl<'cg, 'cx, 'gcx, 'tcx> Visitor<'tcx> for ConstraintGeneration<'cg, 'cx, 'gcx
         // When we see `X = ...`, then kill borrows of
         // `(*X).foo` and so forth.
         if let Some(all_facts) = self.all_facts {
-            if let Place::Local(temp) = place {
+            if let Place::Base(PlaceBase::Local(temp)) = place {
                 if let Some(borrow_indices) = self.borrow_set.local_map.get(temp) {
                     all_facts.killed.reserve(borrow_indices.len());
                     for &borrow_index in borrow_indices {
diff --git a/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs b/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs
index 8ea249959dd..17f8c23f4fd 100644
--- a/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs
@@ -6,8 +6,8 @@ use crate::borrow_check::nll::region_infer::{Cause, RegionName};
 use crate::borrow_check::nll::ConstraintDescription;
 use crate::borrow_check::{Context, MirBorrowckCtxt, WriteKind};
 use rustc::mir::{
-    CastKind, ConstraintCategory, FakeReadCause, Local, Location, Mir, Operand, Place, Projection,
-    ProjectionElem, Rvalue, Statement, StatementKind, TerminatorKind,
+    CastKind, ConstraintCategory, FakeReadCause, Local, Location, Mir, Operand, Place, PlaceBase,
+    Projection, ProjectionElem, Rvalue, Statement, StatementKind, TerminatorKind,
 };
 use rustc::ty::{self, TyCtxt};
 use rustc_data_structures::fx::FxHashSet;
@@ -245,7 +245,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
             Some(Cause::LiveVar(local, location)) => {
                 let span = mir.source_info(location).span;
                 let spans = self
-                    .move_spans(&Place::Local(local), location)
+                    .move_spans(&Place::Base(PlaceBase::Local(local)), location)
                     .or_else(|| self.borrow_spans(span, location));
 
                 let borrow_location = context.loc;
@@ -265,7 +265,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
                 let mut should_note_order = false;
                 if mir.local_decls[local].name.is_some() {
                     if let Some((WriteKind::StorageDeadOrDrop, place)) = kind_place {
-                        if let Place::Local(borrowed_local) = place {
+                        if let Place::Base(PlaceBase::Local(borrowed_local)) = place {
                             let dropped_local_scope = mir.local_decls[local].visibility_scope;
                             let borrowed_local_scope =
                                 mir.local_decls[*borrowed_local].visibility_scope;
@@ -481,7 +481,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
                         // Just point to the function, to reduce the chance of overlapping spans.
                         let function_span = match func {
                             Operand::Constant(c) => c.span,
-                            Operand::Copy(Place::Local(l)) | Operand::Move(Place::Local(l)) => {
+                            Operand::Copy(Place::Base(PlaceBase::Local(l))) |
+                            Operand::Move(Place::Base(PlaceBase::Local(l))) => {
                                 let local_decl = &self.mir.local_decls[*l];
                                 if local_decl.name.is_none() {
                                     local_decl.source_info.span
@@ -522,7 +523,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
         // it which simplifies the termination logic.
         let mut queue = vec![location];
         let mut target = if let Some(&Statement {
-            kind: StatementKind::Assign(Place::Local(local), _),
+            kind: StatementKind::Assign(Place::Base(PlaceBase::Local(local)), _),
             ..
         }) = stmt
         {
@@ -547,9 +548,9 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
                 // The only kind of statement that we care about is assignments...
                 if let StatementKind::Assign(place, box rvalue) = &stmt.kind {
                     let into = match place {
-                        Place::Local(into) => into,
+                        Place::Base(PlaceBase::Local(into)) => into,
                         Place::Projection(box Projection {
-                            base: Place::Local(into),
+                            base: Place::Base(PlaceBase::Local(into)),
                             elem: ProjectionElem::Deref,
                         }) => into,
                         _ => {
@@ -563,8 +564,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
                         // If we see a use, we should check whether it is our data, and if so
                         // update the place that we're looking for to that new place.
                         Rvalue::Use(operand) => match operand {
-                            Operand::Copy(Place::Local(from))
-                            | Operand::Move(Place::Local(from))
+                            Operand::Copy(Place::Base(PlaceBase::Local(from)))
+                            | Operand::Move(Place::Base(PlaceBase::Local(from)))
                                 if *from == target =>
                             {
                                 target = *into;
@@ -574,8 +575,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
                         // If we see a unsized cast, then if it is our data we should check
                         // whether it is being cast to a trait object.
                         Rvalue::Cast(CastKind::Unsize, operand, ty) => match operand {
-                            Operand::Copy(Place::Local(from))
-                            | Operand::Move(Place::Local(from))
+                            Operand::Copy(Place::Base(PlaceBase::Local(from)))
+                            | Operand::Move(Place::Base(PlaceBase::Local(from)))
                                 if *from == target =>
                             {
                                 debug!("was_captured_by_trait_object: ty={:?}", ty);
@@ -605,7 +606,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
                 debug!("was_captured_by_trait_object: terminator={:?}", terminator);
 
                 if let TerminatorKind::Call {
-                    destination: Some((Place::Local(dest), block)),
+                    destination: Some((Place::Base(PlaceBase::Local(dest)), block)),
                     args,
                     ..
                 } = &terminator.kind
@@ -616,7 +617,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
                     );
                     // Check if one of the arguments to this function is the target place.
                     let found_target = args.iter().any(|arg| {
-                        if let Operand::Move(Place::Local(potential)) = arg {
+                        if let Operand::Move(Place::Base(PlaceBase::Local(potential))) = arg {
                             *potential == target
                         } else {
                             false
diff --git a/src/librustc_mir/borrow_check/nll/invalidation.rs b/src/librustc_mir/borrow_check/nll/invalidation.rs
index 9c067677621..aafbff35776 100644
--- a/src/librustc_mir/borrow_check/nll/invalidation.rs
+++ b/src/librustc_mir/borrow_check/nll/invalidation.rs
@@ -12,7 +12,7 @@ use crate::borrow_check::path_utils::*;
 use crate::dataflow::move_paths::indexes::BorrowIndex;
 use rustc::ty::TyCtxt;
 use rustc::mir::visit::Visitor;
-use rustc::mir::{BasicBlock, Location, Mir, Place, Rvalue};
+use rustc::mir::{BasicBlock, Location, Mir, Place, PlaceBase, Rvalue};
 use rustc::mir::{Statement, StatementKind};
 use rustc::mir::{Terminator, TerminatorKind};
 use rustc::mir::{Operand, BorrowKind};
@@ -131,7 +131,7 @@ impl<'cx, 'tcx, 'gcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx, 'gcx> {
             StatementKind::StorageDead(local) => {
                 self.access_place(
                     ContextKind::StorageDead.new(location),
-                    &Place::Local(local),
+                    &Place::Base(PlaceBase::Local(local)),
                     (Shallow(None), Write(WriteKind::StorageDeadOrDrop)),
                     LocalMutationIsAllowed::Yes,
                 );
diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs
index df035aab54c..cf054c2d055 100644
--- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs
@@ -451,10 +451,10 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> {
     ) -> PlaceTy<'tcx> {
         debug!("sanitize_place: {:?}", place);
         let place_ty = match *place {
-            Place::Local(index) => PlaceTy::Ty {
+            Place::Base(PlaceBase::Local(index)) => PlaceTy::Ty {
                 ty: self.mir.local_decls[index].ty,
             },
-            Place::Promoted(box (_index, sty)) => {
+            Place::Base(PlaceBase::Promoted(box (_index, sty))) => {
                 let sty = self.sanitize_type(place, sty);
                 // FIXME -- promoted MIR return types reference
                 // various "free regions" (e.g., scopes and things)
@@ -469,7 +469,7 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> {
                 // promoted_mir.return_ty()
                 PlaceTy::Ty { ty: sty }
             }
-            Place::Static(box Static { def_id, ty: sty }) => {
+            Place::Base(PlaceBase::Static(box Static { def_id, ty: sty })) => {
                 let sty = self.sanitize_type(place, sty);
                 let ty = self.tcx().type_of(def_id);
                 let ty = self.cx.normalize(ty, location);
@@ -553,7 +553,7 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> {
                 }
             }
             ProjectionElem::Index(i) => {
-                let index_ty = Place::Local(i).ty(self.mir, tcx).to_ty(tcx);
+                let index_ty = Place::Base(PlaceBase::Local(i)).ty(self.mir, tcx).to_ty(tcx);
                 if index_ty != tcx.types.usize {
                     PlaceTy::Ty {
                         ty: span_mirbug_and_err!(self, i, "index by non-usize {:?}", i),
@@ -1234,7 +1234,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
                 // of lowering. Assignments to other sorts of places *are* interesting
                 // though.
                 let category = match *place {
-                    Place::Local(RETURN_PLACE) => if let Some(BorrowCheckContext {
+                    Place::Base(PlaceBase::Local(RETURN_PLACE)) => if let Some(BorrowCheckContext {
                         universal_regions:
                             UniversalRegions {
                                 defining_ty: DefiningTy::Const(def_id, _),
@@ -1251,7 +1251,8 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
                     } else {
                         ConstraintCategory::Return
                     },
-                    Place::Local(l) if !mir.local_decls[l].is_user_variable.is_some() => {
+                    Place::Base(PlaceBase::Local(l))
+                        if !mir.local_decls[l].is_user_variable.is_some() => {
                         ConstraintCategory::Boring
                     }
                     _ => ConstraintCategory::Assignment,
@@ -1537,7 +1538,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
             Some((ref dest, _target_block)) => {
                 let dest_ty = dest.ty(mir, tcx).to_ty(tcx);
                 let category = match *dest {
-                    Place::Local(RETURN_PLACE) => {
+                    Place::Base(PlaceBase::Local(RETURN_PLACE)) => {
                         if let Some(BorrowCheckContext {
                             universal_regions:
                                 UniversalRegions {
@@ -1556,7 +1557,8 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
                             ConstraintCategory::Return
                         }
                     }
-                    Place::Local(l) if !mir.local_decls[l].is_user_variable.is_some() => {
+                    Place::Base(PlaceBase::Local(l))
+                        if !mir.local_decls[l].is_user_variable.is_some() => {
                         ConstraintCategory::Boring
                     }
                     _ => ConstraintCategory::Assignment,
diff --git a/src/librustc_mir/borrow_check/path_utils.rs b/src/librustc_mir/borrow_check/path_utils.rs
index 9073ae6bed5..9e0bb93c33a 100644
--- a/src/librustc_mir/borrow_check/path_utils.rs
+++ b/src/librustc_mir/borrow_check/path_utils.rs
@@ -3,7 +3,7 @@ use crate::borrow_check::places_conflict;
 use crate::borrow_check::Context;
 use crate::borrow_check::AccessDepth;
 use crate::dataflow::indexes::BorrowIndex;
-use rustc::mir::{BasicBlock, Location, Mir, Place};
+use rustc::mir::{BasicBlock, Location, Mir, Place, PlaceBase};
 use rustc::mir::{ProjectionElem, BorrowKind};
 use rustc::ty::TyCtxt;
 use rustc_data_structures::graph::dominators::Dominators;
@@ -138,9 +138,9 @@ pub(super) fn is_active<'tcx>(
 /// This is called for all Yield statements on movable generators
 pub(super) fn borrow_of_local_data<'tcx>(place: &Place<'tcx>) -> bool {
     match place {
-        Place::Promoted(_) |
-        Place::Static(..) => false,
-        Place::Local(..) => true,
+        Place::Base(PlaceBase::Promoted(_)) |
+        Place::Base(PlaceBase::Static(..)) => false,
+        Place::Base(PlaceBase::Local(..)) => true,
         Place::Projection(box proj) => {
             match proj.elem {
                 // Reborrow of already borrowed data is ignored
diff --git a/src/librustc_mir/borrow_check/place_ext.rs b/src/librustc_mir/borrow_check/place_ext.rs
index d6d2861b557..c05ee3cf65b 100644
--- a/src/librustc_mir/borrow_check/place_ext.rs
+++ b/src/librustc_mir/borrow_check/place_ext.rs
@@ -1,6 +1,6 @@
 use rustc::hir;
 use rustc::mir::ProjectionElem;
-use rustc::mir::{Local, Mir, Place, Mutability};
+use rustc::mir::{Local, Mir, Place, PlaceBase, Mutability};
 use rustc::ty::{self, TyCtxt};
 use crate::borrow_check::borrow_set::LocalsStateAtExit;
 
@@ -30,7 +30,7 @@ impl<'tcx> PlaceExt<'tcx> for Place<'tcx> {
         locals_state_at_exit: &LocalsStateAtExit,
     ) -> bool {
         match self {
-            Place::Promoted(_) => false,
+            Place::Base(PlaceBase::Promoted(_)) => false,
 
             // If a local variable is immutable, then we only need to track borrows to guard
             // against two kinds of errors:
@@ -40,7 +40,7 @@ impl<'tcx> PlaceExt<'tcx> for Place<'tcx> {
             //
             // In particular, the variable cannot be mutated -- the "access checks" will fail --
             // so we don't have to worry about mutation while borrowed.
-            Place::Local(index) => {
+            Place::Base(PlaceBase::Local(index)) => {
                 match locals_state_at_exit {
                     LocalsStateAtExit::AllAreInvalidated => false,
                     LocalsStateAtExit::SomeAreInvalidated { has_storage_dead_or_moved } => {
@@ -51,7 +51,7 @@ impl<'tcx> PlaceExt<'tcx> for Place<'tcx> {
                     }
                 }
             }
-            Place::Static(static_) => {
+            Place::Base(PlaceBase::Static(static_)) => {
                 tcx.is_static(static_.def_id) == Some(hir::Mutability::MutMutable)
             }
             Place::Projection(proj) => match proj.elem {
@@ -88,9 +88,9 @@ impl<'tcx> PlaceExt<'tcx> for Place<'tcx> {
         loop {
             match p {
                 Place::Projection(pi) => p = &pi.base,
-                Place::Promoted(_) |
-                Place::Static(_) => return None,
-                Place::Local(l) => return Some(*l),
+                Place::Base(PlaceBase::Promoted(_)) |
+                Place::Base(PlaceBase::Static(_)) => return None,
+                Place::Base(PlaceBase::Local(l)) => return Some(*l),
             }
         }
     }
diff --git a/src/librustc_mir/borrow_check/places_conflict.rs b/src/librustc_mir/borrow_check/places_conflict.rs
index b5175cf41dd..1d18ada1fb6 100644
--- a/src/librustc_mir/borrow_check/places_conflict.rs
+++ b/src/librustc_mir/borrow_check/places_conflict.rs
@@ -2,8 +2,7 @@ use crate::borrow_check::ArtificialField;
 use crate::borrow_check::Overlap;
 use crate::borrow_check::{Deep, Shallow, AccessDepth};
 use rustc::hir;
-use rustc::mir::{BorrowKind, Mir, Place};
-use rustc::mir::{Projection, ProjectionElem};
+use rustc::mir::{BorrowKind, Mir, Place, PlaceBase, Projection, ProjectionElem};
 use rustc::ty::{self, TyCtxt};
 use std::cmp::max;
 
@@ -60,8 +59,8 @@ pub(super) fn borrow_conflicts_with_place<'gcx, 'tcx>(
 
     // This Local/Local case is handled by the more general code below, but
     // it's so common that it's a speed win to check for it first.
-    if let Place::Local(l1) = borrow_place {
-        if let Place::Local(l2) = access_place {
+    if let Place::Base(PlaceBase::Local(l1)) = borrow_place {
+        if let Place::Base(PlaceBase::Local(l2)) = access_place {
             return l1 == l2;
         }
     }
@@ -339,8 +338,8 @@ fn unroll_place<'tcx, R>(
             op,
         ),
 
-        Place::Promoted(_) |
-        Place::Local(_) | Place::Static(_) => {
+        Place::Base(PlaceBase::Promoted(_)) |
+        Place::Base(PlaceBase::Local(_)) | Place::Base(PlaceBase::Static(_)) => {
             let list = PlaceComponents {
                 component: place,
                 next,
@@ -361,7 +360,7 @@ fn place_element_conflict<'a, 'gcx: 'tcx, 'tcx>(
     bias: PlaceConflictBias,
 ) -> Overlap {
     match (elem1, elem2) {
-        (Place::Local(l1), Place::Local(l2)) => {
+        (Place::Base(PlaceBase::Local(l1)), Place::Base(PlaceBase::Local(l2))) => {
             if l1 == l2 {
                 // the same local - base case, equal
                 debug!("place_element_conflict: DISJOINT-OR-EQ-LOCAL");
@@ -372,7 +371,7 @@ fn place_element_conflict<'a, 'gcx: 'tcx, 'tcx>(
                 Overlap::Disjoint
             }
         }
-        (Place::Static(static1), Place::Static(static2)) => {
+        (Place::Base(PlaceBase::Static(static1)), Place::Base(PlaceBase::Static(static2))) => {
             if static1.def_id != static2.def_id {
                 debug!("place_element_conflict: DISJOINT-STATIC");
                 Overlap::Disjoint
@@ -385,7 +384,7 @@ fn place_element_conflict<'a, 'gcx: 'tcx, 'tcx>(
                 Overlap::EqualOrDisjoint
             }
         }
-        (Place::Promoted(p1), Place::Promoted(p2)) => {
+        (Place::Base(PlaceBase::Promoted(p1)), Place::Base(PlaceBase::Promoted(p2))) => {
             if p1.0 == p2.0 {
                 if let ty::Array(_, size) = p1.1.sty {
                     if size.unwrap_usize(tcx) == 0 {
@@ -403,9 +402,12 @@ fn place_element_conflict<'a, 'gcx: 'tcx, 'tcx>(
                 Overlap::Disjoint
             }
         }
-        (Place::Local(_), Place::Promoted(_)) | (Place::Promoted(_), Place::Local(_)) |
-        (Place::Promoted(_), Place::Static(_)) | (Place::Static(_), Place::Promoted(_)) |
-        (Place::Local(_), Place::Static(_)) | (Place::Static(_), Place::Local(_)) => {
+        (Place::Base(PlaceBase::Local(_)), Place::Base(PlaceBase::Promoted(_))) |
+        (Place::Base(PlaceBase::Promoted(_)), Place::Base(PlaceBase::Local(_))) |
+        (Place::Base(PlaceBase::Promoted(_)), Place::Base(PlaceBase::Static(_))) |
+        (Place::Base(PlaceBase::Static(_)), Place::Base(PlaceBase::Promoted(_))) |
+        (Place::Base(PlaceBase::Local(_)), Place::Base(PlaceBase::Static(_))) |
+        (Place::Base(PlaceBase::Static(_)), Place::Base(PlaceBase::Local(_))) => {
             debug!("place_element_conflict: DISJOINT-STATIC-LOCAL-PROMOTED");
             Overlap::Disjoint
         }
diff --git a/src/librustc_mir/borrow_check/prefixes.rs b/src/librustc_mir/borrow_check/prefixes.rs
index c3a8381cd58..384fd5c9987 100644
--- a/src/librustc_mir/borrow_check/prefixes.rs
+++ b/src/librustc_mir/borrow_check/prefixes.rs
@@ -11,7 +11,7 @@ use super::MirBorrowckCtxt;
 
 use rustc::hir;
 use rustc::ty::{self, TyCtxt};
-use rustc::mir::{Mir, Place, ProjectionElem};
+use rustc::mir::{Mir, Place, PlaceBase, ProjectionElem};
 
 pub trait IsPrefixOf<'tcx> {
     fn is_prefix_of(&self, other: &Place<'tcx>) -> bool;
@@ -26,8 +26,9 @@ impl<'tcx> IsPrefixOf<'tcx> for Place<'tcx> {
             }
 
             match *cursor {
-                Place::Promoted(_) |
-                Place::Local(_) | Place::Static(_) => return false,
+                Place::Base(PlaceBase::Promoted(_)) |
+                Place::Base(PlaceBase::Local(_)) |
+                Place::Base(PlaceBase::Static(_)) => return false,
                 Place::Projection(ref proj) => {
                     cursor = &proj.base;
                 }
@@ -86,9 +87,9 @@ impl<'cx, 'gcx, 'tcx> Iterator for Prefixes<'cx, 'gcx, 'tcx> {
 
         'cursor: loop {
             let proj = match *cursor {
-                Place::Promoted(_) |
-                Place::Local(_) | // search yielded this leaf
-                Place::Static(_) => {
+                Place::Base(PlaceBase::Promoted(_)) |
+                Place::Base(PlaceBase::Local(_)) | // search yielded this leaf
+                Place::Base(PlaceBase::Static(_)) => {
                     self.next = None;
                     return Some(cursor);
                 }
diff --git a/src/librustc_mir/borrow_check/used_muts.rs b/src/librustc_mir/borrow_check/used_muts.rs
index 8c7359bdee7..b102bced0e3 100644
--- a/src/librustc_mir/borrow_check/used_muts.rs
+++ b/src/librustc_mir/borrow_check/used_muts.rs
@@ -1,5 +1,7 @@
 use rustc::mir::visit::{PlaceContext, Visitor};
-use rustc::mir::{BasicBlock, Local, Location, Place, Statement, StatementKind, TerminatorKind};
+use rustc::mir::{
+    BasicBlock, Local, Location, Place, PlaceBase, Statement, StatementKind, TerminatorKind
+};
 
 use rustc_data_structures::fx::FxHashSet;
 
@@ -114,7 +116,7 @@ impl<'visit, 'cx, 'gcx, 'tcx> Visitor<'tcx> for GatherUsedMutsVisitor<'visit, 'c
                     "assignment of {:?} to {:?}, adding {:?} to used mutable set",
                     path.place, local, path.place
                 );
-                if let Place::Local(user_local) = path.place {
+                if let Place::Base(PlaceBase::Local(user_local)) = path.place {
                     self.mbcx.used_mut.insert(user_local);
                 }
             }
diff --git a/src/librustc_mir/build/expr/as_operand.rs b/src/librustc_mir/build/expr/as_operand.rs
index 38fae8539c8..e354a2ee816 100644
--- a/src/librustc_mir/build/expr/as_operand.rs
+++ b/src/librustc_mir/build/expr/as_operand.rs
@@ -74,7 +74,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
             }
             Category::Place | Category::Rvalue(..) => {
                 let operand = unpack!(block = this.as_temp(block, scope, expr, Mutability::Mut));
-                block.and(Operand::Move(Place::Local(operand)))
+                block.and(Operand::Move(Place::Base(PlaceBase::Local(operand))))
             }
         }
     }
diff --git a/src/librustc_mir/build/expr/as_place.rs b/src/librustc_mir/build/expr/as_place.rs
index ed444191226..3bea88024b3 100644
--- a/src/librustc_mir/build/expr/as_place.rs
+++ b/src/librustc_mir/build/expr/as_place.rs
@@ -98,19 +98,19 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                     &lt,
                     Rvalue::BinaryOp(
                         BinOp::Lt,
-                        Operand::Copy(Place::Local(idx)),
+                        Operand::Copy(Place::Base(PlaceBase::Local(idx))),
                         Operand::Copy(len.clone()),
                     ),
                 );
 
                 let msg = BoundsCheck {
                     len: Operand::Move(len),
-                    index: Operand::Copy(Place::Local(idx)),
+                    index: Operand::Copy(Place::Base(PlaceBase::Local(idx))),
                 };
                 let success = this.assert(block, Operand::Move(lt), true, msg, expr_span);
                 success.and(slice.index(idx))
             }
-            ExprKind::SelfRef => block.and(Place::Local(Local::new(1))),
+            ExprKind::SelfRef => block.and(Place::Base(PlaceBase::Local(Local::new(1)))),
             ExprKind::VarRef { id } => {
                 let place = if this.is_bound_var_in_guard(id) && this
                     .hir
@@ -118,17 +118,17 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                     .all_pat_vars_are_implicit_refs_within_guards()
                 {
                     let index = this.var_local_id(id, RefWithinGuard);
-                    Place::Local(index).deref()
+                    Place::Base(PlaceBase::Local(index)).deref()
                 } else {
                     let index = this.var_local_id(id, OutsideGuard);
-                    Place::Local(index)
+                    Place::Base(PlaceBase::Local(index))
                 };
                 block.and(place)
             }
-            ExprKind::StaticRef { id } => block.and(Place::Static(Box::new(Static {
+            ExprKind::StaticRef { id } => block.and(Place::Base(PlaceBase::Static(Box::new(Static {
                 def_id: id,
                 ty: expr.ty,
-            }))),
+            })))),
 
             ExprKind::PlaceTypeAscription { source, user_ty } => {
                 let place = unpack!(block = this.as_place(block, source));
@@ -172,14 +172,14 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                         Statement {
                             source_info,
                             kind: StatementKind::AscribeUserType(
-                                Place::Local(temp.clone()),
+                                Place::Base(PlaceBase::Local(temp.clone())),
                                 Variance::Invariant,
                                 box UserTypeProjection { base: annotation_index, projs: vec![], },
                             ),
                         },
                     );
                 }
-                block.and(Place::Local(temp))
+                block.and(Place::Base(PlaceBase::Local(temp)))
             }
 
             ExprKind::Array { .. }
@@ -219,7 +219,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                 });
                 let temp =
                     unpack!(block = this.as_temp(block, expr.temp_lifetime, expr, mutability));
-                block.and(Place::Local(temp))
+                block.and(Place::Base(PlaceBase::Local(temp)))
             }
         }
     }
diff --git a/src/librustc_mir/build/expr/as_rvalue.rs b/src/librustc_mir/build/expr/as_rvalue.rs
index 88dbd93939e..b00d1c612ed 100644
--- a/src/librustc_mir/build/expr/as_rvalue.rs
+++ b/src/librustc_mir/build/expr/as_rvalue.rs
@@ -127,7 +127,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                     this.schedule_drop_storage_and_value(
                         expr_span,
                         scope,
-                        &Place::Local(result),
+                        &Place::Base(PlaceBase::Local(result)),
                         value.ty,
                     );
                 }
@@ -135,11 +135,16 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                 // malloc some memory of suitable type (thus far, uninitialized):
                 let box_ = Rvalue::NullaryOp(NullOp::Box, value.ty);
                 this.cfg
-                    .push_assign(block, source_info, &Place::Local(result), box_);
+                    .push_assign(block, source_info, &Place::Base(PlaceBase::Local(result)), box_);
 
                 // initialize the box contents:
-                unpack!(block = this.into(&Place::Local(result).deref(), block, value));
-                block.and(Rvalue::Use(Operand::Move(Place::Local(result))))
+                unpack!(
+                    block = this.into(
+                        &Place::Base(PlaceBase::Local(result)).deref(),
+                        block, value
+                    )
+                );
+                block.and(Rvalue::Use(Operand::Move(Place::Base(PlaceBase::Local(result)))))
             }
             ExprKind::Cast { source } => {
                 let source = this.hir.mirror(source);
@@ -522,9 +527,9 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
         let arg_place = unpack!(block = this.as_place(block, arg));
 
         let mutability = match arg_place {
-            Place::Local(local) => this.local_decls[local].mutability,
+            Place::Base(PlaceBase::Local(local)) => this.local_decls[local].mutability,
             Place::Projection(box Projection {
-                base: Place::Local(local),
+                base: Place::Base(PlaceBase::Local(local)),
                 elem: ProjectionElem::Deref,
             }) => {
                 debug_assert!(
@@ -554,11 +559,11 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                 // Not projected from the implicit `self` in a closure.
                 debug_assert!(
                     match *base {
-                        Place::Local(local) => local == Local::new(1),
+                        Place::Base(PlaceBase::Local(local)) => local == Local::new(1),
                         Place::Projection(box Projection {
                             ref base,
                             elem: ProjectionElem::Deref,
-                        }) => *base == Place::Local(Local::new(1)),
+                        }) => *base == Place::Base(PlaceBase::Local(Local::new(1))),
                         _ => false,
                     },
                     "Unexpected capture place"
@@ -583,7 +588,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
         this.cfg.push_assign(
             block,
             source_info,
-            &Place::Local(temp),
+            &Place::Base(PlaceBase::Local(temp)),
             Rvalue::Ref(this.hir.tcx().types.re_erased, borrow_kind, arg_place),
         );
 
@@ -594,12 +599,12 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
             this.schedule_drop_storage_and_value(
                 upvar_span,
                 temp_lifetime,
-                &Place::Local(temp),
+                &Place::Base(PlaceBase::Local(temp)),
                 upvar_ty,
             );
         }
 
-        block.and(Operand::Move(Place::Local(temp)))
+        block.and(Operand::Move(Place::Base(PlaceBase::Local(temp))))
     }
 
     // Helper to get a `-1` value of the appropriate type
diff --git a/src/librustc_mir/build/expr/as_temp.rs b/src/librustc_mir/build/expr/as_temp.rs
index efa1a4895e0..cba771f2706 100644
--- a/src/librustc_mir/build/expr/as_temp.rs
+++ b/src/librustc_mir/build/expr/as_temp.rs
@@ -73,7 +73,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
             );
         }
 
-        unpack!(block = this.into(&Place::Local(temp), block, expr));
+        unpack!(block = this.into(&Place::Base(PlaceBase::Local(temp)), block, expr));
 
         // In constants, temp_lifetime is None for temporaries that live for the
         // 'static lifetime. Thus we do not drop these temporaries and simply leak them.
@@ -88,7 +88,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
             this.schedule_drop_storage_and_value(
                 expr_span,
                 temp_lifetime,
-                &Place::Local(temp),
+                &Place::Base(PlaceBase::Local(temp)),
                 expr_ty,
             );
         }
diff --git a/src/librustc_mir/build/expr/into.rs b/src/librustc_mir/build/expr/into.rs
index 07db67a6ae0..d9839e0c6ec 100644
--- a/src/librustc_mir/build/expr/into.rs
+++ b/src/librustc_mir/build/expr/into.rs
@@ -295,7 +295,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                         is_user_variable: None,
                         is_block_tail: None,
                     });
-                    let ptr_temp = Place::Local(ptr_temp);
+                    let ptr_temp = Place::Base(PlaceBase::Local(ptr_temp));
                     let block = unpack!(this.into(&ptr_temp, block, ptr));
                     this.into(&ptr_temp.deref(), block, val)
                 } else {
diff --git a/src/librustc_mir/build/expr/stmt.rs b/src/librustc_mir/build/expr/stmt.rs
index aadc2368f5a..9527a232795 100644
--- a/src/librustc_mir/build/expr/stmt.rs
+++ b/src/librustc_mir/build/expr/stmt.rs
@@ -139,13 +139,22 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                     Some(value) => {
                         debug!("stmt_expr Return val block_context.push(SubExpr) : {:?}", expr2);
                         this.block_context.push(BlockFrame::SubExpr);
-                        let result = unpack!(this.into(&Place::Local(RETURN_PLACE), block, value));
+                        let result = unpack!(
+                            this.into(
+                                &Place::RETURN_PLACE,
+                                block,
+                                value
+                            )
+                        );
                         this.block_context.pop();
                         result
                     }
                     None => {
-                        this.cfg
-                            .push_assign_unit(block, source_info, &Place::Local(RETURN_PLACE));
+                        this.cfg.push_assign_unit(
+                            block,
+                            source_info,
+                            &Place::RETURN_PLACE,
+                        );
                         block
                     }
                 };
@@ -226,7 +235,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                         }
                     }
                     let temp = this.local_decls.push(local_decl);
-                    let place = Place::Local(temp);
+                    let place = Place::Base(PlaceBase::Local(temp));
                     debug!("created temp {:?} for expr {:?} in block_context: {:?}",
                            temp, expr, this.block_context);
                     place
diff --git a/src/librustc_mir/build/matches/mod.rs b/src/librustc_mir/build/matches/mod.rs
index 2c4eb0bc091..8f1301b743e 100644
--- a/src/librustc_mir/build/matches/mod.rs
+++ b/src/librustc_mir/build/matches/mod.rs
@@ -543,7 +543,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                 kind: StatementKind::StorageLive(local_id),
             },
         );
-        let place = Place::Local(local_id);
+        let place = Place::Base(PlaceBase::Local(local_id));
         let var_ty = self.local_decls[local_id].ty;
         let hir_id = self.hir.tcx().hir().node_to_hir_id(var);
         let region_scope = self.hir.region_scope_tree.var_scope(hir_id.local_id);
@@ -559,7 +559,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
         self.schedule_drop(
             span,
             region_scope,
-            &Place::Local(local_id),
+            &Place::Base(PlaceBase::Local(local_id)),
             var_ty,
             DropKind::Value {
                 cached_block: CachedBlock::default(),
@@ -1452,7 +1452,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                 self.cfg.push_assign(
                     block,
                     scrutinee_source_info,
-                    &Place::Local(temp),
+                    &Place::Base(PlaceBase::Local(temp)),
                     borrow,
                 );
             }
@@ -1478,7 +1478,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                     source_info: guard_end,
                     kind: StatementKind::FakeRead(
                         FakeReadCause::ForMatchGuard,
-                        Place::Local(temp),
+                        Place::Base(PlaceBase::Local(temp)),
                     ),
                 });
             }
@@ -1529,7 +1529,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                 // place they refer to can't be modified by the guard.
                 for binding in by_value_bindings.clone() {
                     let local_id = self.var_local_id(binding.var_id, RefWithinGuard);
-                    let place = Place::Local(local_id);
+                    let place = Place::Base(PlaceBase::Local(local_id));
                     self.cfg.push(
                         block,
                         Statement {
diff --git a/src/librustc_mir/build/misc.rs b/src/librustc_mir/build/misc.rs
index 900f7f1744a..2692c24806f 100644
--- a/src/librustc_mir/build/misc.rs
+++ b/src/librustc_mir/build/misc.rs
@@ -16,7 +16,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
     /// call `schedule_drop` once the temporary is initialized.
     pub fn temp(&mut self, ty: Ty<'tcx>, span: Span) -> Place<'tcx> {
         let temp = self.local_decls.push(LocalDecl::new_temp(ty, span));
-        let place = Place::Local(temp);
+        let place = Place::Base(PlaceBase::Local(temp));
         debug!("temp: created temp {:?} with type {:?}",
                place, self.local_decls[temp].ty);
         place
diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs
index 19507c900da..e4f85887841 100644
--- a/src/librustc_mir/build/mod.rs
+++ b/src/librustc_mir/build/mod.rs
@@ -741,7 +741,7 @@ fn construct_const<'a, 'gcx, 'tcx>(
 
     let mut block = START_BLOCK;
     let expr = builder.hir.mirror(ast_expr);
-    unpack!(block = builder.into_expr(&Place::Local(RETURN_PLACE), block, expr));
+    unpack!(block = builder.into_expr(&Place::RETURN_PLACE, block, expr));
 
     let source_info = builder.source_info(span);
     builder.cfg.terminate(block, source_info, TerminatorKind::Return);
@@ -887,7 +887,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
         for (index, arg_info) in arguments.iter().enumerate() {
             // Function arguments always get the first Local indices after the return place
             let local = Local::new(index + 1);
-            let place = Place::Local(local);
+            let place = Place::Base(PlaceBase::Local(local));
             let &ArgInfo(ty, opt_ty_info, pattern, ref self_binding) = arg_info;
 
             // Make sure we drop (parts of) the argument even when not matched on.
@@ -936,7 +936,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
         }
 
         let body = self.hir.mirror(ast_body);
-        self.into(&Place::Local(RETURN_PLACE), block, body)
+        self.into(&Place::RETURN_PLACE, block, body)
     }
 
     fn get_unit_temp(&mut self) -> Place<'tcx> {
diff --git a/src/librustc_mir/build/scope.rs b/src/librustc_mir/build/scope.rs
index 71acf747d08..4189e3e7ddb 100644
--- a/src/librustc_mir/build/scope.rs
+++ b/src/librustc_mir/build/scope.rs
@@ -662,7 +662,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
             DropKind::Value { .. } => if !needs_drop { return },
             DropKind::Storage => {
                 match *place {
-                    Place::Local(index) => if index.index() <= self.arg_count {
+                    Place::Base(PlaceBase::Local(index)) => if index.index() <= self.arg_count {
                         span_bug!(
                             span, "`schedule_drop` called with index {} and arg_count {}",
                             index.index(),
@@ -936,7 +936,7 @@ fn build_scope_drops<'tcx>(
                 // Drop the storage for both value and storage drops.
                 // Only temps and vars need their storage dead.
                 match drop_data.location {
-                    Place::Local(index) if index.index() > arg_count => {
+                    Place::Base(PlaceBase::Local(index)) if index.index() > arg_count => {
                         cfg.push(block, Statement {
                             source_info,
                             kind: StatementKind::StorageDead(index)
diff --git a/src/librustc_mir/dataflow/drop_flag_effects.rs b/src/librustc_mir/dataflow/drop_flag_effects.rs
index 151a004dce9..f78c82a9302 100644
--- a/src/librustc_mir/dataflow/drop_flag_effects.rs
+++ b/src/librustc_mir/dataflow/drop_flag_effects.rs
@@ -163,7 +163,7 @@ pub(crate) fn drop_flag_effects_for_function_entry<'a, 'gcx, 'tcx, F>(
 {
     let move_data = &ctxt.move_data;
     for arg in mir.args_iter() {
-        let place = mir::Place::Local(arg);
+        let place = mir::Place::Base(mir::PlaceBase::Local(arg));
         let lookup_result = move_data.rev_lookup.find(&place);
         on_lookup_result_bits(tcx, mir, move_data,
                               lookup_result,
diff --git a/src/librustc_mir/dataflow/impls/borrowed_locals.rs b/src/librustc_mir/dataflow/impls/borrowed_locals.rs
index 51d628ce6c5..b9c8879b3c3 100644
--- a/src/librustc_mir/dataflow/impls/borrowed_locals.rs
+++ b/src/librustc_mir/dataflow/impls/borrowed_locals.rs
@@ -92,9 +92,9 @@ struct BorrowedLocalsVisitor<'b, 'c: 'b> {
 
 fn find_local<'tcx>(place: &Place<'tcx>) -> Option<Local> {
     match *place {
-        Place::Local(l) => Some(l),
-        Place::Promoted(_) |
-        Place::Static(..) => None,
+        Place::Base(PlaceBase::Local(l)) => Some(l),
+        Place::Base(PlaceBase::Promoted(_)) |
+        Place::Base(PlaceBase::Static(..)) => None,
         Place::Projection(ref proj) => {
             match proj.elem {
                 ProjectionElem::Deref => None,
diff --git a/src/librustc_mir/dataflow/impls/borrows.rs b/src/librustc_mir/dataflow/impls/borrows.rs
index beb0b318708..b47aff3a4f8 100644
--- a/src/librustc_mir/dataflow/impls/borrows.rs
+++ b/src/librustc_mir/dataflow/impls/borrows.rs
@@ -1,7 +1,7 @@
 use crate::borrow_check::borrow_set::{BorrowSet, BorrowData};
 use crate::borrow_check::place_ext::PlaceExt;
 
-use rustc::mir::{self, Location, Place, Mir};
+use rustc::mir::{self, Location, Place, PlaceBase, Mir};
 use rustc::ty::TyCtxt;
 use rustc::ty::RegionVid;
 
@@ -189,7 +189,7 @@ impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> {
     ) {
         debug!("kill_borrows_on_place: place={:?}", place);
         // Handle the `Place::Local(..)` case first and exit early.
-        if let Place::Local(local) = place {
+        if let Place::Base(PlaceBase::Local(local)) = place {
             if let Some(borrow_indices) = self.borrow_set.local_map.get(&local) {
                 debug!("kill_borrows_on_place: borrow_indices={:?}", borrow_indices);
                 sets.kill_all(borrow_indices);
@@ -285,7 +285,7 @@ impl<'a, 'gcx, 'tcx> BitDenotation<'tcx> for Borrows<'a, 'gcx, 'tcx> {
             mir::StatementKind::StorageDead(local) => {
                 // Make sure there are no remaining borrows for locals that
                 // are gone out of scope.
-                self.kill_borrows_on_place(sets, &Place::Local(local));
+                self.kill_borrows_on_place(sets, &Place::Base(PlaceBase::Local(local)));
             }
 
             mir::StatementKind::InlineAsm { ref outputs, ref asm, .. } => {
diff --git a/src/librustc_mir/dataflow/impls/mod.rs b/src/librustc_mir/dataflow/impls/mod.rs
index cc92ebfab89..4dcfb3f1a7f 100644
--- a/src/librustc_mir/dataflow/impls/mod.rs
+++ b/src/librustc_mir/dataflow/impls/mod.rs
@@ -493,7 +493,8 @@ impl<'a, 'gcx, 'tcx> BitDenotation<'tcx> for EverInitializedPlaces<'a, 'gcx, 'tc
                 // storagedeads after everything ends, so if we don't regard the
                 // storagelive as killing storage, we would have a multiple assignment
                 // to immutable data error.
-                if let LookupResult::Exact(mpi) = rev_lookup.find(&mir::Place::Local(local)) {
+                if let LookupResult::Exact(mpi) =
+                    rev_lookup.find(&mir::Place::Base(mir::PlaceBase::Local(local))) {
                     debug!("stmt {:?} at loc {:?} clears the ever initialized status of {:?}",
                            stmt, location, &init_path_map[mpi]);
                     sets.kill_all(&init_path_map[mpi]);
diff --git a/src/librustc_mir/dataflow/move_paths/builder.rs b/src/librustc_mir/dataflow/move_paths/builder.rs
index 1ae050654b4..7a9140bce62 100644
--- a/src/librustc_mir/dataflow/move_paths/builder.rs
+++ b/src/librustc_mir/dataflow/move_paths/builder.rs
@@ -33,13 +33,13 @@ impl<'a, 'gcx, 'tcx> MoveDataBuilder<'a, 'gcx, 'tcx> {
                 moves: IndexVec::new(),
                 loc_map: LocationMap::new(mir),
                 rev_lookup: MovePathLookup {
-                    locals: mir.local_decls.indices().map(Place::Local).map(|v| {
+                    locals: mir.local_decls.indices().map(PlaceBase::Local).map(|v| {
                         Self::new_move_path(
                             &mut move_paths,
                             &mut path_map,
                             &mut init_path_map,
                             None,
-                            v,
+                            Place::Base(v),
                         )
                     }).collect(),
                     projections: Default::default(),
@@ -96,9 +96,9 @@ impl<'b, 'a, 'gcx, 'tcx> Gatherer<'b, 'a, 'gcx, 'tcx> {
     {
         debug!("lookup({:?})", place);
         match *place {
-            Place::Local(local) => Ok(self.builder.data.rev_lookup.locals[local]),
-            Place::Promoted(..) |
-            Place::Static(..) => {
+            Place::Base(PlaceBase::Local(local)) => Ok(self.builder.data.rev_lookup.locals[local]),
+            Place::Base(PlaceBase::Promoted(..)) |
+            Place::Base(PlaceBase::Static(..)) => {
                 Err(MoveError::cannot_move_out_of(self.loc, Static))
             }
             Place::Projection(ref proj) => {
@@ -285,7 +285,7 @@ impl<'b, 'a, 'gcx, 'tcx> Gatherer<'b, 'a, 'gcx, 'tcx> {
             }
             StatementKind::StorageLive(_) => {}
             StatementKind::StorageDead(local) => {
-                self.gather_move(&Place::Local(local));
+                self.gather_move(&Place::Base(PlaceBase::Local(local)));
             }
             StatementKind::SetDiscriminant{ .. } => {
                 span_bug!(stmt.source_info.span,
@@ -345,7 +345,7 @@ impl<'b, 'a, 'gcx, 'tcx> Gatherer<'b, 'a, 'gcx, 'tcx> {
             TerminatorKind::Unreachable => { }
 
             TerminatorKind::Return => {
-                self.gather_move(&Place::Local(RETURN_PLACE));
+                self.gather_move(&Place::RETURN_PLACE);
             }
 
             TerminatorKind::Assert { ref cond, .. } => {
diff --git a/src/librustc_mir/dataflow/move_paths/mod.rs b/src/librustc_mir/dataflow/move_paths/mod.rs
index efd979a7da4..0c29ea8ab4a 100644
--- a/src/librustc_mir/dataflow/move_paths/mod.rs
+++ b/src/librustc_mir/dataflow/move_paths/mod.rs
@@ -273,9 +273,9 @@ impl<'tcx> MovePathLookup<'tcx> {
     // parent.
     pub fn find(&self, place: &Place<'tcx>) -> LookupResult {
         match *place {
-            Place::Local(local) => LookupResult::Exact(self.locals[local]),
-            Place::Promoted(_) |
-            Place::Static(..) => LookupResult::Parent(None),
+            Place::Base(PlaceBase::Local(local)) => LookupResult::Exact(self.locals[local]),
+            Place::Base(PlaceBase::Promoted(_)) |
+            Place::Base(PlaceBase::Static(..)) => LookupResult::Parent(None),
             Place::Projection(ref proj) => {
                 match self.find(&proj.base) {
                     LookupResult::Exact(base_path) => {
@@ -347,7 +347,7 @@ impl<'a, 'gcx, 'tcx> MoveData<'tcx> {
     pub fn base_local(&self, mut mpi: MovePathIndex) -> Option<Local> {
         loop {
             let path = &self.move_paths[mpi];
-            if let Place::Local(l) = path.place { return Some(l); }
+            if let Place::Base(PlaceBase::Local(l)) = path.place { return Some(l); }
             if let Some(parent) = path.parent { mpi = parent; continue } else { return None }
         }
     }
diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs
index 5548366db66..0751af9b12a 100644
--- a/src/librustc_mir/hair/cx/expr.rs
+++ b/src/librustc_mir/hair/cx/expr.rs
@@ -560,7 +560,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
 
         // Now comes the rote stuff:
         hir::ExprKind::Repeat(ref v, ref count) => {
-            let def_id = cx.tcx.hir().local_def_id(count.id);
+            let def_id = cx.tcx.hir().local_def_id_from_hir_id(count.hir_id);
             let substs = InternalSubsts::identity_for_item(cx.tcx.global_tcx(), def_id);
             let instance = ty::Instance::resolve(
                 cx.tcx.global_tcx(),
diff --git a/src/librustc_mir/hair/pattern/check_match.rs b/src/librustc_mir/hair/pattern/check_match.rs
index 9cecf4af7d4..0f151cd688d 100644
--- a/src/librustc_mir/hair/pattern/check_match.rs
+++ b/src/librustc_mir/hair/pattern/check_match.rs
@@ -346,9 +346,9 @@ fn check_arms<'a, 'tcx>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
                 NotUseful => {
                     match source {
                         hir::MatchSource::IfLetDesugar { .. } => {
-                            cx.tcx.lint_node(
+                            cx.tcx.lint_hir(
                                 lint::builtin::IRREFUTABLE_LET_PATTERNS,
-                                hir_pat.id,
+                                hir_pat.hir_id,
                                 pat.span,
                                 "irrefutable if-let pattern",
                             );
@@ -359,16 +359,16 @@ fn check_arms<'a, 'tcx>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
                             match arm_index {
                                 // The arm with the user-specified pattern.
                                 0 => {
-                                    cx.tcx.lint_node(
+                                    cx.tcx.lint_hir(
                                         lint::builtin::UNREACHABLE_PATTERNS,
-                                        hir_pat.id, pat.span,
+                                        hir_pat.hir_id, pat.span,
                                         "unreachable pattern");
                                 },
                                 // The arm with the wildcard pattern.
                                 1 => {
-                                    cx.tcx.lint_node(
+                                    cx.tcx.lint_hir(
                                         lint::builtin::IRREFUTABLE_LET_PATTERNS,
-                                        hir_pat.id,
+                                        hir_pat.hir_id,
                                         pat.span,
                                         "irrefutable while-let pattern",
                                     );
@@ -379,9 +379,9 @@ fn check_arms<'a, 'tcx>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
 
                         hir::MatchSource::ForLoopDesugar |
                         hir::MatchSource::Normal => {
-                            let mut err = cx.tcx.struct_span_lint_node(
+                            let mut err = cx.tcx.struct_span_lint_hir(
                                 lint::builtin::UNREACHABLE_PATTERNS,
-                                hir_pat.id,
+                                hir_pat.hir_id,
                                 pat.span,
                                 "unreachable pattern",
                             );
diff --git a/src/librustc_mir/hair/pattern/mod.rs b/src/librustc_mir/hair/pattern/mod.rs
index c234c2474ff..d5f2e7a7275 100644
--- a/src/librustc_mir/hair/pattern/mod.rs
+++ b/src/librustc_mir/hair/pattern/mod.rs
@@ -955,8 +955,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
         debug!("const_to_pat: cv.ty={:?} span={:?}", cv.ty, span);
         let kind = match cv.ty.sty {
             ty::Float(_) => {
-                let id = self.tcx.hir().hir_to_node_id(id);
-                self.tcx.lint_node(
+                self.tcx.lint_hir(
                     ::rustc::lint::builtin::ILLEGAL_FLOATING_POINT_LITERAL_PATTERN,
                     id,
                     span,
diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs
index 474df457f61..979595d6c00 100644
--- a/src/librustc_mir/interpret/operand.rs
+++ b/src/librustc_mir/interpret/operand.rs
@@ -515,9 +515,10 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
         layout: Option<TyLayout<'tcx>>,
     ) -> EvalResult<'tcx, OpTy<'tcx, M::PointerTag>> {
         use rustc::mir::Place::*;
+        use rustc::mir::PlaceBase;
         let op = match *mir_place {
-            Local(mir::RETURN_PLACE) => return err!(ReadFromReturnPointer),
-            Local(local) => self.access_local(self.frame(), local, layout)?,
+            Base(PlaceBase::Local(mir::RETURN_PLACE)) => return err!(ReadFromReturnPointer),
+            Base(PlaceBase::Local(local)) => self.access_local(self.frame(), local, layout)?,
 
             Projection(ref proj) => {
                 let op = self.eval_place_to_op(&proj.base, None)?;
diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs
index 7b66d11131c..4df274bc9df 100644
--- a/src/librustc_mir/interpret/place.rs
+++ b/src/librustc_mir/interpret/place.rs
@@ -581,8 +581,9 @@ where
         mir_place: &mir::Place<'tcx>
     ) -> EvalResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> {
         use rustc::mir::Place::*;
+        use rustc::mir::PlaceBase;
         Ok(match *mir_place {
-            Promoted(ref promoted) => {
+            Base(PlaceBase::Promoted(ref promoted)) => {
                 let instance = self.frame().instance;
                 self.const_eval_raw(GlobalId {
                     instance,
@@ -590,7 +591,7 @@ where
                 })?
             }
 
-            Static(ref static_) => {
+            Base(PlaceBase::Static(ref static_)) => {
                 assert!(!static_.ty.needs_subst());
                 let layout = self.layout_of(static_.ty)?;
                 let instance = ty::Instance::mono(*self.tcx, static_.def_id);
@@ -624,8 +625,9 @@ where
         mir_place: &mir::Place<'tcx>
     ) -> EvalResult<'tcx, PlaceTy<'tcx, M::PointerTag>> {
         use rustc::mir::Place::*;
+        use rustc::mir::PlaceBase;
         let place = match *mir_place {
-            Local(mir::RETURN_PLACE) => match self.frame().return_place {
+            Base(PlaceBase::Local(mir::RETURN_PLACE)) => match self.frame().return_place {
                 Some(return_place) =>
                     // We use our layout to verify our assumption; caller will validate
                     // their layout on return.
@@ -635,7 +637,7 @@ where
                     },
                 None => return err!(InvalidNullPointerUsage),
             },
-            Local(local) => PlaceTy {
+            Base(PlaceBase::Local(local)) => PlaceTy {
                 place: Place::Local {
                     frame: self.cur_frame(),
                     local,
diff --git a/src/librustc_mir/interpret/terminator.rs b/src/librustc_mir/interpret/terminator.rs
index c2ee3f5715b..83469d74987 100644
--- a/src/librustc_mir/interpret/terminator.rs
+++ b/src/librustc_mir/interpret/terminator.rs
@@ -352,7 +352,9 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
                     // not advance `caller_iter` for ZSTs.
                     let mut locals_iter = mir.args_iter();
                     while let Some(local) = locals_iter.next() {
-                        let dest = self.eval_place(&mir::Place::Local(local))?;
+                        let dest = self.eval_place(
+                            &mir::Place::Base(mir::PlaceBase::Local(local))
+                        )?;
                         if Some(local) == mir.spread_arg {
                             // Must be a tuple
                             for i in 0..dest.layout.fields.count() {
@@ -371,7 +373,9 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
                     }
                     // Don't forget to check the return type!
                     if let Some(caller_ret) = dest {
-                        let callee_ret = self.eval_place(&mir::Place::Local(mir::RETURN_PLACE))?;
+                        let callee_ret = self.eval_place(
+                            &mir::Place::RETURN_PLACE
+                        )?;
                         if !Self::check_argument_compat(
                             rust_abi,
                             caller_ret.layout,
diff --git a/src/librustc_mir/lints.rs b/src/librustc_mir/lints.rs
index c795b412bfa..bfc977c28cd 100644
--- a/src/librustc_mir/lints.rs
+++ b/src/librustc_mir/lints.rs
@@ -129,12 +129,12 @@ fn check_fn_for_unconditional_recursion(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     // no break */ }`) shouldn't be linted unless it actually
     // recurs.
     if !reached_exit_without_self_call && !self_call_locations.is_empty() {
-        let node_id = tcx.hir().as_local_node_id(def_id).unwrap();
-        let sp = tcx.sess.source_map().def_span(tcx.hir().span(node_id));
-        let mut db = tcx.struct_span_lint_node(UNCONDITIONAL_RECURSION,
-                                                node_id,
-                                                sp,
-                                                "function cannot return without recursing");
+        let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap();
+        let sp = tcx.sess.source_map().def_span(tcx.hir().span_by_hir_id(hir_id));
+        let mut db = tcx.struct_span_lint_hir(UNCONDITIONAL_RECURSION,
+                                              hir_id,
+                                              sp,
+                                              "function cannot return without recursing");
         db.span_label(sp, "cannot return without recursing");
         // offer some help to the programmer.
         for location in &self_call_locations {
diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs
index 4cec306412e..a58c69f636d 100644
--- a/src/librustc_mir/monomorphize/collector.rs
+++ b/src/librustc_mir/monomorphize/collector.rs
@@ -1006,7 +1006,7 @@ impl<'b, 'a, 'v> ItemLikeVisitor<'v> for RootCollector<'b, 'a, 'v> {
     fn visit_impl_item(&mut self, ii: &'v hir::ImplItem) {
         match ii.node {
             hir::ImplItemKind::Method(hir::MethodSig { .. }, _) => {
-                let def_id = self.tcx.hir().local_def_id(ii.id);
+                let def_id = self.tcx.hir().local_def_id_from_hir_id(ii.hir_id);
                 self.push_if_root(def_id);
             }
             _ => { /* Nothing to do here */ }
diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs
index ce7c9af81cb..adc328f1033 100644
--- a/src/librustc_mir/shim.rs
+++ b/src/librustc_mir/shim.rs
@@ -221,7 +221,7 @@ fn build_drop_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
     if let Some(..) = ty {
         // The first argument (index 0), but add 1 for the return value.
-        let dropee_ptr = Place::Local(Local::new(1+0));
+        let dropee_ptr = Place::Base(PlaceBase::Local(Local::new(1+0)));
         if tcx.sess.opts.debugging_opts.mir_emit_retag {
             // Function arguments should be retagged, and we make this one raw.
             mir.basic_blocks_mut()[START_BLOCK].statements.insert(0, Statement {
@@ -317,8 +317,8 @@ fn build_clone_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     let mut builder = CloneShimBuilder::new(tcx, def_id, self_ty);
     let is_copy = self_ty.is_copy_modulo_regions(tcx, tcx.param_env(def_id), builder.span);
 
-    let dest = Place::Local(RETURN_PLACE);
-    let src = Place::Local(Local::new(1+0)).deref();
+    let dest = Place::RETURN_PLACE;
+    let src = Place::Base(PlaceBase::Local(Local::new(1+0))).deref();
 
     match self_ty.sty {
         _ if is_copy => builder.copy_shim(),
@@ -424,10 +424,10 @@ impl<'a, 'tcx> CloneShimBuilder<'a, 'tcx> {
     }
 
     fn copy_shim(&mut self) {
-        let rcvr = Place::Local(Local::new(1+0)).deref();
+        let rcvr = Place::Base(PlaceBase::Local(Local::new(1+0))).deref();
         let ret_statement = self.make_statement(
             StatementKind::Assign(
-                Place::Local(RETURN_PLACE),
+                Place::RETURN_PLACE,
                 box Rvalue::Use(Operand::Copy(rcvr))
             )
         );
@@ -436,9 +436,9 @@ impl<'a, 'tcx> CloneShimBuilder<'a, 'tcx> {
 
     fn make_place(&mut self, mutability: Mutability, ty: Ty<'tcx>) -> Place<'tcx> {
         let span = self.span;
-        Place::Local(
+        Place::Base(PlaceBase::Local(
             self.local_decls.push(temp_decl(mutability, ty, span))
-        )
+        ))
     }
 
     fn make_clone_call(
@@ -546,7 +546,7 @@ impl<'a, 'tcx> CloneShimBuilder<'a, 'tcx> {
         let inits = vec![
             self.make_statement(
                 StatementKind::Assign(
-                    Place::Local(beg),
+                    Place::Base(PlaceBase::Local(beg)),
                     box Rvalue::Use(Operand::Constant(self.make_usize(0)))
                 )
             ),
@@ -564,7 +564,11 @@ impl<'a, 'tcx> CloneShimBuilder<'a, 'tcx> {
         //     BB #3;
         // }
         // BB #4;
-        self.loop_header(Place::Local(beg), end, BasicBlock::new(2), BasicBlock::new(4), false);
+        self.loop_header(Place::Base(PlaceBase::Local(beg)),
+                         end,
+                         BasicBlock::new(2),
+                         BasicBlock::new(4),
+                         false);
 
         // BB #2
         // `dest[i] = Clone::clone(src[beg])`;
@@ -580,10 +584,10 @@ impl<'a, 'tcx> CloneShimBuilder<'a, 'tcx> {
         let statements = vec![
             self.make_statement(
                 StatementKind::Assign(
-                    Place::Local(beg),
+                    Place::Base(PlaceBase::Local(beg)),
                     box Rvalue::BinaryOp(
                         BinOp::Add,
-                        Operand::Copy(Place::Local(beg)),
+                        Operand::Copy(Place::Base(PlaceBase::Local(beg))),
                         Operand::Constant(self.make_usize(1))
                     )
                 )
@@ -603,7 +607,7 @@ impl<'a, 'tcx> CloneShimBuilder<'a, 'tcx> {
         let beg = self.local_decls.push(temp_decl(Mutability::Mut, tcx.types.usize, span));
         let init = self.make_statement(
             StatementKind::Assign(
-                Place::Local(beg),
+                Place::Base(PlaceBase::Local(beg)),
                 box Rvalue::Use(Operand::Constant(self.make_usize(0)))
             )
         );
@@ -614,7 +618,7 @@ impl<'a, 'tcx> CloneShimBuilder<'a, 'tcx> {
         //     BB #8;
         // }
         // BB #9;
-        self.loop_header(Place::Local(beg), Place::Local(end),
+        self.loop_header(Place::Base(PlaceBase::Local(beg)), Place::Base(PlaceBase::Local(end)),
                          BasicBlock::new(7), BasicBlock::new(9), true);
 
         // BB #7 (cleanup)
@@ -630,10 +634,10 @@ impl<'a, 'tcx> CloneShimBuilder<'a, 'tcx> {
         // `goto #6;`
         let statement = self.make_statement(
             StatementKind::Assign(
-                Place::Local(beg),
+                Place::Base(PlaceBase::Local(beg)),
                 box Rvalue::BinaryOp(
                     BinOp::Add,
-                    Operand::Copy(Place::Local(beg)),
+                    Operand::Copy(Place::Base(PlaceBase::Local(beg))),
                     Operand::Constant(self.make_usize(1))
                 )
             )
@@ -718,7 +722,7 @@ fn build_call_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     let source_info = SourceInfo { span, scope: OUTERMOST_SOURCE_SCOPE };
 
     let rcvr_arg = Local::new(1+0);
-    let rcvr_l = Place::Local(rcvr_arg);
+    let rcvr_l = Place::Base(PlaceBase::Local(rcvr_arg));
     let mut statements = vec![];
 
     let rcvr = match rcvr_adjustment {
@@ -748,11 +752,11 @@ fn build_call_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             statements.push(Statement {
                 source_info,
                 kind: StatementKind::Assign(
-                    Place::Local(ref_rcvr),
+                    Place::Base(PlaceBase::Local(ref_rcvr)),
                     box Rvalue::Ref(tcx.types.re_erased, borrow_kind, rcvr_l)
                 )
             });
-            Operand::Move(Place::Local(ref_rcvr))
+            Operand::Move(Place::Base(PlaceBase::Local(ref_rcvr)))
         }
     };
 
@@ -774,12 +778,12 @@ fn build_call_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
     if let Some(untuple_args) = untuple_args {
         args.extend(untuple_args.iter().enumerate().map(|(i, ity)| {
-            let arg_place = Place::Local(Local::new(1+1));
+            let arg_place = Place::Base(PlaceBase::Local(Local::new(1+1)));
             Operand::Move(arg_place.field(Field::new(i), *ity))
         }));
     } else {
         args.extend((1..sig.inputs().len()).map(|i| {
-            Operand::Move(Place::Local(Local::new(1+i)))
+            Operand::Move(Place::Base(PlaceBase::Local(Local::new(1+i))))
         }));
     }
 
@@ -797,7 +801,7 @@ fn build_call_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     block(&mut blocks, statements, TerminatorKind::Call {
         func: callee,
         args,
-        destination: Some((Place::Local(RETURN_PLACE),
+        destination: Some((Place::RETURN_PLACE,
                            BasicBlock::new(1))),
         cleanup: if let Adjustment::RefMut = rcvr_adjustment {
             Some(BasicBlock::new(3))
@@ -810,7 +814,7 @@ fn build_call_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     if let Adjustment::RefMut = rcvr_adjustment {
         // BB #1 - drop for Self
         block(&mut blocks, vec![], TerminatorKind::Drop {
-            location: Place::Local(rcvr_arg),
+            location: Place::Base(PlaceBase::Local(rcvr_arg)),
             target: BasicBlock::new(2),
             unwind: None
         }, false);
@@ -820,7 +824,7 @@ fn build_call_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     if let Adjustment::RefMut = rcvr_adjustment {
         // BB #3 - drop if closure panics
         block(&mut blocks, vec![], TerminatorKind::Drop {
-            location: Place::Local(rcvr_arg),
+            location: Place::Base(PlaceBase::Local(rcvr_arg)),
             target: BasicBlock::new(4),
             unwind: None
         }, true);
@@ -892,11 +896,11 @@ pub fn build_adt_ctor<'a, 'gcx, 'tcx>(infcx: &infer::InferCtxt<'a, 'gcx, 'tcx>,
         statements: vec![Statement {
             source_info,
             kind: StatementKind::Assign(
-                Place::Local(RETURN_PLACE),
+                Place::RETURN_PLACE,
                 box Rvalue::Aggregate(
                     box AggregateKind::Adt(adt_def, variant_no, substs, None, None),
                     (1..sig.inputs().len()+1).map(|i| {
-                        Operand::Move(Place::Local(Local::new(i)))
+                        Operand::Move(Place::Base(PlaceBase::Local(Local::new(i))))
                     }).collect()
                 )
             )
diff --git a/src/librustc_mir/transform/add_moves_for_packed_drops.rs b/src/librustc_mir/transform/add_moves_for_packed_drops.rs
index 4d4c89b8b6a..e8528eee0bc 100644
--- a/src/librustc_mir/transform/add_moves_for_packed_drops.rs
+++ b/src/librustc_mir/transform/add_moves_for_packed_drops.rs
@@ -121,10 +121,10 @@ fn add_move_for_packed_drop<'a, 'tcx>(
 
     patch.add_statement(
         loc, StatementKind::StorageLive(temp));
-    patch.add_assign(loc, Place::Local(temp),
+    patch.add_assign(loc, Place::Base(PlaceBase::Local(temp)),
                      Rvalue::Use(Operand::Move(location.clone())));
     patch.patch_terminator(loc.block, TerminatorKind::Drop {
-        location: Place::Local(temp),
+        location: Place::Base(PlaceBase::Local(temp)),
         target: storage_dead_block,
         unwind
     });
diff --git a/src/librustc_mir/transform/add_retag.rs b/src/librustc_mir/transform/add_retag.rs
index e66c11aa36e..20b75c55867 100644
--- a/src/librustc_mir/transform/add_retag.rs
+++ b/src/librustc_mir/transform/add_retag.rs
@@ -21,9 +21,9 @@ fn is_stable<'tcx>(
 
     match *place {
         // Locals and statics have stable addresses, for sure
-        Local { .. } |
-        Promoted { .. } |
-        Static { .. } =>
+        Base(PlaceBase::Local { .. }) |
+        Base(PlaceBase::Promoted { .. }) |
+        Base(PlaceBase::Static { .. }) =>
             true,
         // Recurse for projections
         Projection(ref proj) => {
@@ -101,7 +101,7 @@ impl MirPass for AddRetag {
             };
             // Gather all arguments, skip return value.
             let places = local_decls.iter_enumerated().skip(1).take(arg_count)
-                    .map(|(local, _)| Place::Local(local))
+                    .map(|(local, _)| Place::Base(PlaceBase::Local(local)))
                     .filter(needs_retag)
                     .collect::<Vec<_>>();
             // Emit their retags.
diff --git a/src/librustc_mir/transform/check_unsafety.rs b/src/librustc_mir/transform/check_unsafety.rs
index 3ed63d749cd..a8816720b28 100644
--- a/src/librustc_mir/transform/check_unsafety.rs
+++ b/src/librustc_mir/transform/check_unsafety.rs
@@ -241,7 +241,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
                     );
                 }
                 let old_source_info = self.source_info;
-                if let &Place::Local(local) = base {
+                if let &Place::Base(PlaceBase::Local(local)) = base {
                     if self.mir.local_decls[local].internal {
                         // Internal locals are used in the `move_val_init` desugaring.
                         // We want to check unsafety against the source info of the
@@ -297,13 +297,13 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
                 }
                 self.source_info = old_source_info;
             }
-            &Place::Local(..) => {
+            &Place::Base(PlaceBase::Local(..)) => {
                 // locals are safe
             }
-            &Place::Promoted(_) => {
+            &Place::Base(PlaceBase::Promoted(_)) => {
                 bug!("unsafety checking should happen before promotion")
             }
-            &Place::Static(box Static { def_id, ty: _ }) => {
+            &Place::Base(PlaceBase::Static(box Static { def_id, ty: _ })) => {
                 if self.tcx.is_static(def_id) == Some(hir::Mutability::MutMutable) {
                     self.require_unsafe("use of mutable static",
                         "mutable statics can be mutated by multiple threads: aliasing violations \
@@ -553,10 +553,8 @@ fn unsafety_check_result<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId)
 }
 
 fn unsafe_derive_on_repr_packed<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) {
-    let lint_node_id = match tcx.hir().as_local_node_id(def_id) {
-        Some(node_id) => node_id,
-        None => bug!("checking unsafety for non-local def id {:?}", def_id)
-    };
+    let lint_hir_id = tcx.hir().as_local_hir_id(def_id).unwrap_or_else(||
+        bug!("checking unsafety for non-local def id {:?}", def_id));
 
     // FIXME: when we make this a hard error, this should have its
     // own error code.
@@ -567,10 +565,10 @@ fn unsafe_derive_on_repr_packed<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: D
         "#[derive] can't be used on a #[repr(packed)] struct that \
          does not derive Copy (error E0133)".to_string()
     };
-    tcx.lint_node(SAFE_PACKED_BORROWS,
-                  lint_node_id,
-                  tcx.def_span(def_id),
-                  &message);
+    tcx.lint_hir(SAFE_PACKED_BORROWS,
+                 lint_hir_id,
+                 tcx.def_span(def_id),
+                 &message);
 }
 
 /// Returns the `HirId` for an enclosing scope that is also `unsafe`.
diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs
index 5ed0055e7c4..9febe6af5b1 100644
--- a/src/librustc_mir/transform/const_prop.rs
+++ b/src/librustc_mir/transform/const_prop.rs
@@ -3,7 +3,7 @@
 
 
 use rustc::hir::def::Def;
-use rustc::mir::{Constant, Location, Place, Mir, Operand, Rvalue, Local};
+use rustc::mir::{Constant, Location, Place, PlaceBase, Mir, Operand, Rvalue, Local};
 use rustc::mir::{NullOp, UnOp, StatementKind, Statement, BasicBlock, LocalKind};
 use rustc::mir::{TerminatorKind, ClearCrossCrate, SourceInfo, BinOp, ProjectionElem};
 use rustc::mir::visit::{Visitor, PlaceContext, MutatingUseContext, NonMutatingUseContext};
@@ -267,7 +267,7 @@ impl<'a, 'mir, 'tcx> ConstPropagator<'a, 'mir, 'tcx> {
 
     fn eval_place(&mut self, place: &Place<'tcx>, source_info: SourceInfo) -> Option<Const<'tcx>> {
         match *place {
-            Place::Local(loc) => self.places[loc].clone(),
+            Place::Base(PlaceBase::Local(loc)) => self.places[loc].clone(),
             Place::Projection(ref proj) => match proj.elem {
                 ProjectionElem::Field(field, _) => {
                     trace!("field proj on {:?}", proj.base);
@@ -282,7 +282,7 @@ impl<'a, 'mir, 'tcx> ConstPropagator<'a, 'mir, 'tcx> {
                 // an `Index` projection would throw us off-track.
                 _ => None,
             },
-            Place::Promoted(ref promoted) => {
+            Place::Base(PlaceBase::Promoted(ref promoted)) => {
                 let generics = self.tcx.generics_of(self.source.def_id());
                 if generics.requires_monomorphization(self.tcx) {
                     // FIXME: can't handle code with generics
@@ -556,7 +556,7 @@ impl<'b, 'a, 'tcx> Visitor<'tcx> for ConstPropagator<'b, 'a, 'tcx> {
                 .to_ty(self.tcx);
             if let Ok(place_layout) = self.tcx.layout_of(self.param_env.and(place_ty)) {
                 if let Some(value) = self.const_prop(rval, place_layout, statement.source_info) {
-                    if let Place::Local(local) = *place {
+                    if let Place::Base(PlaceBase::Local(local)) = *place {
                         trace!("checking whether {:?} can be stored to {:?}", value, local);
                         if self.can_const_prop[local] {
                             trace!("storing {:?} to {:?}", value, local);
@@ -591,7 +591,7 @@ impl<'b, 'a, 'tcx> Visitor<'tcx> for ConstPropagator<'b, 'a, 'tcx> {
                             while let Place::Projection(ref proj) = *place {
                                 place = &proj.base;
                             }
-                            if let Place::Local(local) = *place {
+                            if let Place::Base(PlaceBase::Local(local)) = *place {
                                 self.places[local] = None;
                             }
                         },
@@ -603,10 +603,10 @@ impl<'b, 'a, 'tcx> Visitor<'tcx> for ConstPropagator<'b, 'a, 'tcx> {
                         .unwrap()
                         .source_info
                         .span;
-                    let node_id = self
+                    let hir_id = self
                         .tcx
                         .hir()
-                        .as_local_node_id(self.source.def_id())
+                        .as_local_hir_id(self.source.def_id())
                         .expect("some part of a failing const eval must be local");
                     use rustc::mir::interpret::EvalErrorKind::*;
                     let msg = match msg {
@@ -643,9 +643,9 @@ impl<'b, 'a, 'tcx> Visitor<'tcx> for ConstPropagator<'b, 'a, 'tcx> {
                         // Need proper const propagator for these
                         _ => return,
                     };
-                    self.tcx.lint_node(
+                    self.tcx.lint_hir(
                         ::rustc::lint::builtin::CONST_ERR,
-                        node_id,
+                        hir_id,
                         span,
                         &msg,
                     );
diff --git a/src/librustc_mir/transform/copy_prop.rs b/src/librustc_mir/transform/copy_prop.rs
index 7d907ca3a21..817a2f31c07 100644
--- a/src/librustc_mir/transform/copy_prop.rs
+++ b/src/librustc_mir/transform/copy_prop.rs
@@ -19,7 +19,9 @@
 //! (non-mutating) use of `SRC`. These restrictions are conservative and may be relaxed in the
 //! future.
 
-use rustc::mir::{Constant, Local, LocalKind, Location, Place, Mir, Operand, Rvalue, StatementKind};
+use rustc::mir::{
+    Constant, Local, LocalKind, Location, Place, PlaceBase, Mir, Operand, Rvalue, StatementKind
+};
 use rustc::mir::visit::MutVisitor;
 use rustc::ty::TyCtxt;
 use crate::transform::{MirPass, MirSource};
@@ -94,8 +96,10 @@ impl MirPass for CopyPropagation {
 
                     // That use of the source must be an assignment.
                     match statement.kind {
-                        StatementKind::Assign(Place::Local(local), box Rvalue::Use(ref operand)) if
-                                local == dest_local => {
+                        StatementKind::Assign(
+                            Place::Base(PlaceBase::Local(local)),
+                            box Rvalue::Use(ref operand)
+                        ) if local == dest_local => {
                             let maybe_action = match *operand {
                                 Operand::Copy(ref src_place) |
                                 Operand::Move(ref src_place) => {
@@ -144,12 +148,12 @@ fn eliminate_self_assignments<'tcx>(
             if let Some(stmt) = mir[location.block].statements.get(location.statement_index) {
                 match stmt.kind {
                     StatementKind::Assign(
-                        Place::Local(local),
-                        box Rvalue::Use(Operand::Copy(Place::Local(src_local))),
+                        Place::Base(PlaceBase::Local(local)),
+                        box Rvalue::Use(Operand::Copy(Place::Base(PlaceBase::Local(src_local)))),
                     ) |
                     StatementKind::Assign(
-                        Place::Local(local),
-                        box Rvalue::Use(Operand::Move(Place::Local(src_local))),
+                        Place::Base(PlaceBase::Local(local)),
+                        box Rvalue::Use(Operand::Move(Place::Base(PlaceBase::Local(src_local)))),
                     ) if local == dest_local && dest_local == src_local => {}
                     _ => {
                         continue;
@@ -176,7 +180,7 @@ impl<'tcx> Action<'tcx> {
     fn local_copy(mir: &Mir<'tcx>, def_use_analysis: &DefUseAnalysis<'_>, src_place: &Place<'tcx>)
                   -> Option<Action<'tcx>> {
         // The source must be a local.
-        let src_local = if let Place::Local(local) = *src_place {
+        let src_local = if let Place::Base(PlaceBase::Local(local)) = *src_place {
             local
         } else {
             debug!("  Can't copy-propagate local: source is not a local");
@@ -330,8 +334,8 @@ impl<'tcx> MutVisitor<'tcx> for ConstantPropagationVisitor<'tcx> {
         self.super_operand(operand, location);
 
         match *operand {
-            Operand::Copy(Place::Local(local)) |
-            Operand::Move(Place::Local(local)) if local == self.dest_local => {}
+            Operand::Copy(Place::Base(PlaceBase::Local(local))) |
+            Operand::Move(Place::Base(PlaceBase::Local(local))) if local == self.dest_local => {}
             _ => return,
         }
 
diff --git a/src/librustc_mir/transform/elaborate_drops.rs b/src/librustc_mir/transform/elaborate_drops.rs
index 0f8db5f7334..74175d0149f 100644
--- a/src/librustc_mir/transform/elaborate_drops.rs
+++ b/src/librustc_mir/transform/elaborate_drops.rs
@@ -330,7 +330,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
     }
 
     fn drop_flag(&mut self, index: MovePathIndex) -> Option<Place<'tcx>> {
-        self.drop_flags.get(&index).map(|t| Place::Local(*t))
+        self.drop_flags.get(&index).map(|t| Place::Base(PlaceBase::Local(*t)))
     }
 
     /// create a patch that elaborates all drops in the input
@@ -543,7 +543,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
         if let Some(&flag) = self.drop_flags.get(&path) {
             let span = self.patch.source_info_for_location(self.mir, loc).span;
             let val = self.constant_bool(span, val.value());
-            self.patch.add_assign(loc, Place::Local(flag), val);
+            self.patch.add_assign(loc, Place::Base(PlaceBase::Local(flag)), val);
         }
     }
 
@@ -552,7 +552,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
         let span = self.patch.source_info_for_location(self.mir, loc).span;
         let false_ = self.constant_bool(span, false);
         for flag in self.drop_flags.values() {
-            self.patch.add_assign(loc, Place::Local(*flag), false_.clone());
+            self.patch.add_assign(loc, Place::Base(PlaceBase::Local(*flag)), false_.clone());
         }
     }
 
diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs
index 09142828f18..c455d38cebc 100644
--- a/src/librustc_mir/transform/generator.rs
+++ b/src/librustc_mir/transform/generator.rs
@@ -102,7 +102,7 @@ impl<'tcx> MutVisitor<'tcx> for DerefArgVisitor {
                     place: &mut Place<'tcx>,
                     context: PlaceContext<'tcx>,
                     location: Location) {
-        if *place == Place::Local(self_arg()) {
+        if *place == Place::Base(PlaceBase::Local(self_arg())) {
             *place = Place::Projection(Box::new(Projection {
                 base: place.clone(),
                 elem: ProjectionElem::Deref,
@@ -129,7 +129,7 @@ impl<'tcx> MutVisitor<'tcx> for PinArgVisitor<'tcx> {
                     place: &mut Place<'tcx>,
                     context: PlaceContext<'tcx>,
                     location: Location) {
-        if *place == Place::Local(self_arg()) {
+        if *place == Place::Base(PlaceBase::Local(self_arg())) {
             *place = Place::Projection(Box::new(Projection {
                 base: place.clone(),
                 elem: ProjectionElem::Field(Field::new(0), self.ref_gen_ty),
@@ -183,7 +183,7 @@ impl<'a, 'tcx> TransformVisitor<'a, 'tcx> {
 
     // Create a Place referencing a generator struct field
     fn make_field(&self, idx: usize, ty: Ty<'tcx>) -> Place<'tcx> {
-        let base = Place::Local(self_arg());
+        let base = Place::Base(PlaceBase::Local(self_arg()));
         let field = Projection {
             base: base,
             elem: ProjectionElem::Field(Field::new(idx), ty),
@@ -223,7 +223,7 @@ impl<'a, 'tcx> MutVisitor<'tcx> for TransformVisitor<'a, 'tcx> {
                     place: &mut Place<'tcx>,
                     context: PlaceContext<'tcx>,
                     location: Location) {
-        if let Place::Local(l) = *place {
+        if let Place::Base(PlaceBase::Local(l)) = *place {
             // Replace an Local in the remap with a generator struct access
             if let Some(&(ty, idx)) = self.remap.get(&l) {
                 *place = self.make_field(idx, ty);
@@ -249,7 +249,7 @@ impl<'a, 'tcx> MutVisitor<'tcx> for TransformVisitor<'a, 'tcx> {
         let ret_val = match data.terminator().kind {
             TerminatorKind::Return => Some((VariantIdx::new(1),
                 None,
-                Operand::Move(Place::Local(self.new_ret_local)),
+                Operand::Move(Place::Base(PlaceBase::Local(self.new_ret_local))),
                 None)),
             TerminatorKind::Yield { ref value, resume, drop } => Some((VariantIdx::new(0),
                 Some(resume),
@@ -263,7 +263,7 @@ impl<'a, 'tcx> MutVisitor<'tcx> for TransformVisitor<'a, 'tcx> {
             // We must assign the value first in case it gets declared dead below
             data.statements.push(Statement {
                 source_info,
-                kind: StatementKind::Assign(Place::Local(RETURN_PLACE),
+                kind: StatementKind::Assign(Place::RETURN_PLACE,
                                             box self.make_state(state_idx, v)),
             });
             let state = if let Some(resume) = resume { // Yield
@@ -597,7 +597,7 @@ fn elaborate_generator_drops<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             &Terminator {
                 source_info,
                 kind: TerminatorKind::Drop {
-                    location: Place::Local(local),
+                    location: Place::Base(PlaceBase::Local(local)),
                     target,
                     unwind
                 }
@@ -619,7 +619,7 @@ fn elaborate_generator_drops<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             elaborate_drop(
                 &mut elaborator,
                 source_info,
-                &Place::Local(gen),
+                &Place::Base(PlaceBase::Local(gen)),
                 (),
                 target,
                 unwind,
@@ -693,7 +693,7 @@ fn create_generator_drop_shim<'a, 'tcx>(
         // Alias tracking must know we changed the type
         mir.basic_blocks_mut()[START_BLOCK].statements.insert(0, Statement {
             source_info,
-            kind: StatementKind::Retag(RetagKind::Raw, Place::Local(self_arg())),
+            kind: StatementKind::Retag(RetagKind::Raw, Place::Base(PlaceBase::Local(self_arg()))),
         })
     }
 
@@ -809,7 +809,7 @@ fn insert_clean_drop<'a, 'tcx>(mir: &mut Mir<'tcx>) -> BasicBlock {
     // Create a block to destroy an unresumed generators. This can only destroy upvars.
     let drop_clean = BasicBlock::new(mir.basic_blocks().len());
     let term = TerminatorKind::Drop {
-        location: Place::Local(self_arg()),
+        location: Place::Base(PlaceBase::Local(self_arg())),
         target: return_block,
         unwind: None,
     };
diff --git a/src/librustc_mir/transform/inline.rs b/src/librustc_mir/transform/inline.rs
index 56e4926090e..4cdef015b53 100644
--- a/src/librustc_mir/transform/inline.rs
+++ b/src/librustc_mir/transform/inline.rs
@@ -449,7 +449,7 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> {
                         }
                         // Static variables need a borrow because the callee
                         // might modify the same static.
-                        Place::Static(_) => true,
+                        Place::Base(PlaceBase::Static(_)) => true,
                         _ => false
                     }
                 }
@@ -466,7 +466,7 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> {
                     let temp = LocalDecl::new_temp(ty, callsite.location.span);
 
                     let tmp = caller_mir.local_decls.push(temp);
-                    let tmp = Place::Local(tmp);
+                    let tmp = Place::Base(PlaceBase::Local(tmp));
 
                     let stmt = Statement {
                         source_info: callsite.location,
@@ -560,7 +560,7 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> {
             let tuple = self.create_temp_if_necessary(args.next().unwrap(), callsite, caller_mir);
             assert!(args.next().is_none());
 
-            let tuple = Place::Local(tuple);
+            let tuple = Place::Base(PlaceBase::Local(tuple));
             let tuple_tys = if let ty::Tuple(s) = tuple.ty(caller_mir, tcx).to_ty(tcx).sty {
                 s
             } else {
@@ -599,7 +599,7 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> {
         // FIXME: Analysis of the usage of the arguments to avoid
         // unnecessary temporaries.
 
-        if let Operand::Move(Place::Local(local)) = arg {
+        if let Operand::Move(Place::Base(PlaceBase::Local(local))) = arg {
             if caller_mir.local_kind(local) == LocalKind::Temp {
                 // Reuse the operand if it's a temporary already
                 return local;
@@ -617,7 +617,7 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> {
 
         let stmt = Statement {
             source_info: callsite.location,
-            kind: StatementKind::Assign(Place::Local(arg_tmp), box arg),
+            kind: StatementKind::Assign(Place::Base(PlaceBase::Local(arg_tmp)), box arg),
         };
         caller_mir[callsite.bb].statements.push(stmt);
         arg_tmp
@@ -665,7 +665,7 @@ impl<'a, 'tcx> MutVisitor<'tcx> for Integrator<'a, 'tcx> {
                    _location: Location) {
         if *local == RETURN_PLACE {
             match self.destination {
-                Place::Local(l) => {
+                Place::Base(PlaceBase::Local(l)) => {
                     *local = l;
                     return;
                 },
@@ -686,11 +686,11 @@ impl<'a, 'tcx> MutVisitor<'tcx> for Integrator<'a, 'tcx> {
                     _location: Location) {
 
         match place {
-            Place::Local(RETURN_PLACE) => {
+            Place::Base(PlaceBase::Local(RETURN_PLACE)) => {
                 // Return pointer; update the place itself
                 *place = self.destination.clone();
             },
-            Place::Promoted(ref mut promoted) => {
+            Place::Base(PlaceBase::Promoted(ref mut promoted)) => {
                 if let Some(p) = self.promoted_map.get(promoted.0).cloned() {
                     promoted.0 = p;
                 }
diff --git a/src/librustc_mir/transform/instcombine.rs b/src/librustc_mir/transform/instcombine.rs
index 290915763e2..e0e64fd1f9b 100644
--- a/src/librustc_mir/transform/instcombine.rs
+++ b/src/librustc_mir/transform/instcombine.rs
@@ -1,6 +1,6 @@
 //! Performs various peephole optimizations.
 
-use rustc::mir::{Constant, Location, Place, Mir, Operand, ProjectionElem, Rvalue, Local};
+use rustc::mir::{Constant, Location, Place, PlaceBase, Mir, Operand, ProjectionElem, Rvalue, Local};
 use rustc::mir::visit::{MutVisitor, Visitor};
 use rustc::ty::{TyCtxt, TyKind};
 use rustc::util::nodemap::{FxHashMap, FxHashSet};
@@ -45,7 +45,7 @@ impl<'tcx> MutVisitor<'tcx> for InstCombineVisitor<'tcx> {
             let new_place = match *rvalue {
                 Rvalue::Ref(_, _, Place::Projection(ref mut projection)) => {
                     // Replace with dummy
-                    mem::replace(&mut projection.base, Place::Local(Local::new(0)))
+                    mem::replace(&mut projection.base, Place::Base(PlaceBase::Local(Local::new(0))))
                 }
                 _ => bug!("Detected `&*` but didn't find `&*`!"),
             };
diff --git a/src/librustc_mir/transform/lower_128bit.rs b/src/librustc_mir/transform/lower_128bit.rs
index 3d1f55e530e..ad108587247 100644
--- a/src/librustc_mir/transform/lower_128bit.rs
+++ b/src/librustc_mir/transform/lower_128bit.rs
@@ -86,13 +86,13 @@ impl Lower128Bit {
                     block.statements.push(Statement {
                         source_info: source_info,
                         kind: StatementKind::Assign(
-                            Place::Local(local),
+                            Place::Base(PlaceBase::Local(local)),
                             box Rvalue::Cast(
                                 CastKind::Misc,
                                 rhs,
                                 rhs_override_ty.unwrap())),
                     });
-                    rhs = Operand::Move(Place::Local(local));
+                    rhs = Operand::Move(Place::Base(PlaceBase::Local(local)));
                 }
 
                 let call_did = check_lang_item_type(
diff --git a/src/librustc_mir/transform/promote_consts.rs b/src/librustc_mir/transform/promote_consts.rs
index a6726718e2d..831d8b46a65 100644
--- a/src/librustc_mir/transform/promote_consts.rs
+++ b/src/librustc_mir/transform/promote_consts.rs
@@ -178,7 +178,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
                 span,
                 scope: OUTERMOST_SOURCE_SCOPE
             },
-            kind: StatementKind::Assign(Place::Local(dest), box rvalue)
+            kind: StatementKind::Assign(Place::Base(PlaceBase::Local(dest)), box rvalue)
         });
     }
 
@@ -268,7 +268,9 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
                             func,
                             args,
                             cleanup: None,
-                            destination: Some((Place::Local(new_temp), new_target)),
+                            destination: Some(
+                                (Place::Base(PlaceBase::Local(new_temp)), new_target)
+                            ),
                             from_hir_call,
                         },
                         ..terminator
@@ -292,7 +294,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
                 promoted.span = span;
                 promoted.local_decls[RETURN_PLACE] =
                     LocalDecl::new_return_place(ty, span);
-                Place::Promoted(box (promoted_id, ty))
+                Place::Base(PlaceBase::Promoted(box (promoted_id, ty)))
             };
             let (blocks, local_decls) = self.source.basic_blocks_and_local_decls_mut();
             match candidate {
@@ -373,7 +375,7 @@ pub fn promote_candidates<'a, 'tcx>(mir: &mut Mir<'tcx>,
         match candidate {
             Candidate::Ref(Location { block, statement_index }) => {
                 match mir[block].statements[statement_index].kind {
-                    StatementKind::Assign(Place::Local(local), _) => {
+                    StatementKind::Assign(Place::Base(PlaceBase::Local(local)), _) => {
                         if temps[local] == TempState::PromotedOut {
                             // Already promoted.
                             continue;
@@ -420,7 +422,7 @@ pub fn promote_candidates<'a, 'tcx>(mir: &mut Mir<'tcx>,
     for block in mir.basic_blocks_mut() {
         block.statements.retain(|statement| {
             match statement.kind {
-                StatementKind::Assign(Place::Local(index), _) |
+                StatementKind::Assign(Place::Base(PlaceBase::Local(index)), _) |
                 StatementKind::StorageLive(index) |
                 StatementKind::StorageDead(index) => {
                     !promoted(index)
@@ -430,7 +432,7 @@ pub fn promote_candidates<'a, 'tcx>(mir: &mut Mir<'tcx>,
         });
         let terminator = block.terminator_mut();
         match terminator.kind {
-            TerminatorKind::Drop { location: Place::Local(index), target, .. } => {
+            TerminatorKind::Drop { location: Place::Base(PlaceBase::Local(index)), target, .. } => {
                 if promoted(index) {
                     terminator.kind = TerminatorKind::Goto {
                         target,
diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs
index 285c674643f..d41098e2881 100644
--- a/src/librustc_mir/transform/qualify_consts.rs
+++ b/src/librustc_mir/transform/qualify_consts.rs
@@ -186,9 +186,9 @@ trait Qualif {
 
     fn in_place(cx: &ConstCx<'_, 'tcx>, place: &Place<'tcx>) -> bool {
         match *place {
-            Place::Local(local) => Self::in_local(cx, local),
-            Place::Promoted(_) => bug!("qualifying already promoted MIR"),
-            Place::Static(ref static_) => Self::in_static(cx, static_),
+            Place::Base(PlaceBase::Local(local)) => Self::in_local(cx, local),
+            Place::Base(PlaceBase::Promoted(_)) => bug!("qualifying already promoted MIR"),
+            Place::Base(PlaceBase::Static(ref static_)) => Self::in_static(cx, static_),
             Place::Projection(ref proj) => Self::in_projection(cx, proj),
         }
     }
@@ -730,7 +730,7 @@ impl<'a, 'tcx> Checker<'a, 'tcx> {
                     place = &proj.base;
                 }
                 debug!("qualify_consts: promotion candidate: place={:?}", place);
-                if let Place::Local(local) = *place {
+                if let Place::Base(PlaceBase::Local(local)) = *place {
                     if self.mir.local_kind(local) == LocalKind::Temp {
                         debug!("qualify_consts: promotion candidate: local={:?}", local);
                         // The borrowed place doesn't have `HasMutInterior`
@@ -754,7 +754,7 @@ impl<'a, 'tcx> Checker<'a, 'tcx> {
         let index = loop {
             match dest {
                 // We treat all locals equal in constants
-                Place::Local(index) => break *index,
+                Place::Base(PlaceBase::Local(index)) => break *index,
                 // projections are transparent for assignments
                 // we qualify the entire destination at once, even if just a field would have
                 // stricter qualification
@@ -768,8 +768,9 @@ impl<'a, 'tcx> Checker<'a, 'tcx> {
                     );
                     dest = &proj.base;
                 },
-                Place::Promoted(..) => bug!("promoteds don't exist yet during promotion"),
-                Place::Static(..) => {
+                Place::Base(PlaceBase::Promoted(..)) =>
+                    bug!("promoteds don't exist yet during promotion"),
+                Place::Base(PlaceBase::Static(..)) => {
                     // Catch more errors in the destination. `visit_place` also checks that we
                     // do not try to access statics from constants or try to mutate statics
                     self.visit_place(
@@ -878,7 +879,10 @@ impl<'a, 'tcx> Checker<'a, 'tcx> {
             match *candidate {
                 Candidate::Ref(Location { block: bb, statement_index: stmt_idx }) => {
                     match self.mir[bb].statements[stmt_idx].kind {
-                        StatementKind::Assign(_, box Rvalue::Ref(_, _, Place::Local(index))) => {
+                        StatementKind::Assign(
+                            _,
+                            box Rvalue::Ref(_, _, Place::Base(PlaceBase::Local(index)))
+                        ) => {
                             promoted_temps.insert(index);
                         }
                         _ => {}
@@ -915,9 +919,9 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> {
         debug!("visit_place: place={:?} context={:?} location={:?}", place, context, location);
         self.super_place(place, context, location);
         match *place {
-            Place::Local(_) |
-            Place::Promoted(_) => {}
-            Place::Static(ref global) => {
+            Place::Base(PlaceBase::Local(_)) |
+            Place::Base(PlaceBase::Promoted(_)) => {}
+            Place::Base(PlaceBase::Static(ref global)) => {
                 if self.tcx
                        .get_attrs(global.def_id)
                        .iter()
@@ -1032,7 +1036,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> {
         match *operand {
             Operand::Move(ref place) => {
                 // Mark the consumed locals to indicate later drops are noops.
-                if let Place::Local(local) = *place {
+                if let Place::Base(PlaceBase::Local(local)) = *place {
                     self.cx.per_local[NeedsDrop].remove(local);
                 }
             }
@@ -1335,7 +1339,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> {
                 unleash_miri!(self);
                 // HACK(eddyb): emulate a bit of dataflow analysis,
                 // conservatively, that drop elaboration will do.
-                let needs_drop = if let Place::Local(local) = *place {
+                let needs_drop = if let Place::Base(PlaceBase::Local(local)) = *place {
                     if NeedsDrop::in_local(self, local) {
                         Some(self.mir.local_decls[local].source_info.span)
                     } else {
@@ -1565,7 +1569,11 @@ impl MirPass for QualifyAndPromoteConstants {
                 });
                 let terminator = block.terminator_mut();
                 match terminator.kind {
-                    TerminatorKind::Drop { location: Place::Local(index), target, .. } => {
+                    TerminatorKind::Drop {
+                        location: Place::Base(PlaceBase::Local(index)),
+                        target,
+                        ..
+                    } => {
                         if promoted_temps.contains(index) {
                             terminator.kind = TerminatorKind::Goto {
                                 target,
diff --git a/src/librustc_mir/transform/qualify_min_const_fn.rs b/src/librustc_mir/transform/qualify_min_const_fn.rs
index 34f850fc4aa..6c44fac10f5 100644
--- a/src/librustc_mir/transform/qualify_min_const_fn.rs
+++ b/src/librustc_mir/transform/qualify_min_const_fn.rs
@@ -252,10 +252,11 @@ fn check_place(
     span: Span,
 ) -> McfResult {
     match place {
-        Place::Local(_) => Ok(()),
+        Place::Base(PlaceBase::Local(_)) => Ok(()),
         // promoteds are always fine, they are essentially constants
-        Place::Promoted(_) => Ok(()),
-        Place::Static(_) => Err((span, "cannot access `static` items in const fn".into())),
+        Place::Base(PlaceBase::Promoted(_)) => Ok(()),
+        Place::Base(PlaceBase::Static(_)) =>
+            Err((span, "cannot access `static` items in const fn".into())),
         Place::Projection(proj) => {
             match proj.elem {
                 | ProjectionElem::ConstantIndex { .. } | ProjectionElem::Subslice { .. }
diff --git a/src/librustc_mir/transform/remove_noop_landing_pads.rs b/src/librustc_mir/transform/remove_noop_landing_pads.rs
index 0ad33bff9d6..b7493b25d46 100644
--- a/src/librustc_mir/transform/remove_noop_landing_pads.rs
+++ b/src/librustc_mir/transform/remove_noop_landing_pads.rs
@@ -47,7 +47,7 @@ impl RemoveNoopLandingPads {
                     // These are all nops in a landing pad
                 }
 
-                StatementKind::Assign(Place::Local(_), box Rvalue::Use(_)) => {
+                StatementKind::Assign(Place::Base(PlaceBase::Local(_)), box Rvalue::Use(_)) => {
                     // Writing to a local (e.g., a drop flag) does not
                     // turn a landing pad to a non-nop
                 }
diff --git a/src/librustc_mir/transform/rustc_peek.rs b/src/librustc_mir/transform/rustc_peek.rs
index 40e02e712c1..a44ec526f9d 100644
--- a/src/librustc_mir/transform/rustc_peek.rs
+++ b/src/librustc_mir/transform/rustc_peek.rs
@@ -115,8 +115,8 @@ fn each_block<'a, 'tcx, O>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     };
     assert!(args.len() == 1);
     let peek_arg_place = match args[0] {
-        mir::Operand::Copy(ref place @ mir::Place::Local(_)) |
-        mir::Operand::Move(ref place @ mir::Place::Local(_)) => Some(place),
+        mir::Operand::Copy(ref place @ mir::Place::Base(mir::PlaceBase::Local(_))) |
+        mir::Operand::Move(ref place @ mir::Place::Base(mir::PlaceBase::Local(_))) => Some(place),
         _ => None,
     };
 
diff --git a/src/librustc_mir/transform/uniform_array_move_out.rs b/src/librustc_mir/transform/uniform_array_move_out.rs
index fd8d68a4822..b1d898bb5b0 100644
--- a/src/librustc_mir/transform/uniform_array_move_out.rs
+++ b/src/librustc_mir/transform/uniform_array_move_out.rs
@@ -101,7 +101,7 @@ impl<'a, 'tcx> UniformArrayMoveOutVisitor<'a, 'tcx> {
                     let temp = self.patch.new_temp(item_ty, self.mir.source_info(location).span);
                     self.patch.add_statement(location, StatementKind::StorageLive(temp));
                     self.patch.add_assign(location,
-                                          Place::Local(temp),
+                                          Place::Base(PlaceBase::Local(temp)),
                                           Rvalue::Use(
                                               Operand::Move(
                                                   Place::Projection(box PlaceProjection{
@@ -113,12 +113,16 @@ impl<'a, 'tcx> UniformArrayMoveOutVisitor<'a, 'tcx> {
                                                   }))));
                     temp
                 }).collect();
-                self.patch.add_assign(location,
-                                      dst_place.clone(),
-                                      Rvalue::Aggregate(box AggregateKind::Array(item_ty),
-                                      temps.iter().map(
-                                          |x| Operand::Move(Place::Local(*x))).collect()
-                                      ));
+                self.patch.add_assign(
+                    location,
+                    dst_place.clone(),
+                    Rvalue::Aggregate(
+                        box AggregateKind::Array(item_ty),
+                        temps.iter().map(
+                            |x| Operand::Move(Place::Base(PlaceBase::Local(*x)))
+                        ).collect()
+                    )
+                );
                 for temp in temps {
                     self.patch.add_statement(location, StatementKind::StorageDead(temp));
                 }
@@ -176,7 +180,7 @@ impl MirPass for RestoreSubsliceArrayMoveOut {
                 if let StatementKind::Assign(ref dst_place, ref rval) = statement.kind {
                     if let Rvalue::Aggregate(box AggregateKind::Array(_), ref items) = **rval {
                         let items : Vec<_> = items.iter().map(|item| {
-                            if let Operand::Move(Place::Local(local)) = item {
+                            if let Operand::Move(Place::Base(PlaceBase::Local(local))) = item {
                                 let local_use = &visitor.locals_use[*local];
                                 let opt_index_and_place = Self::try_get_item_source(local_use, mir);
                                 // each local should be used twice:
@@ -257,7 +261,7 @@ impl RestoreSubsliceArrayMoveOut {
             if block.statements.len() > location.statement_index {
                 let statement = &block.statements[location.statement_index];
                 if let StatementKind::Assign(
-                    Place::Local(_),
+                    Place::Base(PlaceBase::Local(_)),
                     box Rvalue::Use(Operand::Move(Place::Projection(box PlaceProjection{
                         ref base, elem: ProjectionElem::ConstantIndex{
                             offset, min_length: _, from_end: false}})))) = statement.kind {
diff --git a/src/librustc_mir/util/elaborate_drops.rs b/src/librustc_mir/util/elaborate_drops.rs
index cf3ba176540..26fa8d6d1f0 100644
--- a/src/librustc_mir/util/elaborate_drops.rs
+++ b/src/librustc_mir/util/elaborate_drops.rs
@@ -486,7 +486,7 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
         // discriminant after it is free-ed, because that
         // way lies only trouble.
         let discr_ty = adt.repr.discr_type().to_ty(self.tcx());
-        let discr = Place::Local(self.new_temp(discr_ty));
+        let discr = Place::Base(PlaceBase::Local(self.new_temp(discr_ty)));
         let discr_rv = Rvalue::Discriminant(self.place.clone());
         let switch_block = BasicBlockData {
             statements: vec![self.assign(&discr, discr_rv)],
@@ -520,11 +520,11 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
             mutbl: hir::Mutability::MutMutable
         });
         let ref_place = self.new_temp(ref_ty);
-        let unit_temp = Place::Local(self.new_temp(tcx.mk_unit()));
+        let unit_temp = Place::Base(PlaceBase::Local(self.new_temp(tcx.mk_unit())));
 
         let result = BasicBlockData {
             statements: vec![self.assign(
-                &Place::Local(ref_place),
+                &Place::Base(PlaceBase::Local(ref_place)),
                 Rvalue::Ref(tcx.types.re_erased,
                             BorrowKind::Mut { allow_two_phase_borrow: false },
                             self.place.clone())
@@ -533,7 +533,7 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
                 kind: TerminatorKind::Call {
                     func: Operand::function_handle(tcx, drop_fn.def_id, substs,
                                                    self.source_info.span),
-                    args: vec![Operand::Move(Place::Local(ref_place))],
+                    args: vec![Operand::Move(Place::Base(PlaceBase::Local(ref_place)))],
                     destination: Some((unit_temp, succ)),
                     cleanup: unwind.into_option(),
                     from_hir_call: true,
@@ -578,8 +578,8 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
             ty: ety,
             mutbl: hir::Mutability::MutMutable
         });
-        let ptr = &Place::Local(self.new_temp(ref_ty));
-        let can_go = &Place::Local(self.new_temp(tcx.types.bool));
+        let ptr = &Place::Base(PlaceBase::Local(self.new_temp(ref_ty)));
+        let can_go = &Place::Base(PlaceBase::Local(self.new_temp(tcx.types.bool)));
 
         let one = self.constant_usize(1);
         let (ptr_next, cur_next) = if ptr_based {
@@ -587,23 +587,23 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
                 tcx.types.re_erased,
                 BorrowKind::Mut { allow_two_phase_borrow: false },
                 Place::Projection(Box::new(Projection {
-                    base: Place::Local(cur),
+                    base: Place::Base(PlaceBase::Local(cur)),
                     elem: ProjectionElem::Deref,
                 }))
              ),
-             Rvalue::BinaryOp(BinOp::Offset, copy(&Place::Local(cur)), one))
+             Rvalue::BinaryOp(BinOp::Offset, copy(&Place::Base(PlaceBase::Local(cur))), one))
         } else {
             (Rvalue::Ref(
                  tcx.types.re_erased,
                  BorrowKind::Mut { allow_two_phase_borrow: false },
                  self.place.clone().index(cur)),
-             Rvalue::BinaryOp(BinOp::Add, copy(&Place::Local(cur)), one))
+             Rvalue::BinaryOp(BinOp::Add, copy(&Place::Base(PlaceBase::Local(cur))), one))
         };
 
         let drop_block = BasicBlockData {
             statements: vec![
                 self.assign(ptr, ptr_next),
-                self.assign(&Place::Local(cur), cur_next)
+                self.assign(&Place::Base(PlaceBase::Local(cur)), cur_next)
             ],
             is_cleanup: unwind.is_cleanup(),
             terminator: Some(Terminator {
@@ -617,7 +617,7 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
         let loop_block = BasicBlockData {
             statements: vec![
                 self.assign(can_go, Rvalue::BinaryOp(BinOp::Eq,
-                                                     copy(&Place::Local(cur)),
+                                                     copy(&Place::Base(PlaceBase::Local(cur))),
                                                      copy(length_or_end)))
             ],
             is_cleanup: unwind.is_cleanup(),
@@ -667,8 +667,8 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
 
         let move_ = |place: &Place<'tcx>| Operand::Move(place.clone());
         let tcx = self.tcx();
-        let size = &Place::Local(self.new_temp(tcx.types.usize));
-        let size_is_zero = &Place::Local(self.new_temp(tcx.types.bool));
+        let size = &Place::Base(PlaceBase::Local(self.new_temp(tcx.types.usize)));
+        let size_is_zero = &Place::Base(PlaceBase::Local(self.new_temp(tcx.types.bool)));
         let base_block = BasicBlockData {
             statements: vec![
                 self.assign(size, Rvalue::NullaryOp(NullOp::SizeOf, ety)),
@@ -703,9 +703,12 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
         };
 
         let cur = self.new_temp(iter_ty);
-        let length = Place::Local(self.new_temp(tcx.types.usize));
+        let length = Place::Base(PlaceBase::Local(self.new_temp(tcx.types.usize)));
         let length_or_end = if ptr_based {
-            Place::Local(self.new_temp(iter_ty))
+            // FIXME check if we want to make it return a `Place` directly
+            // if all use sites want a `Place::Base` anyway.
+            let temp = self.new_temp(iter_ty);
+            Place::Base(PlaceBase::Local(temp))
         } else {
             length.clone()
         };
@@ -728,13 +731,13 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
             unwind,
             ptr_based);
 
-        let cur = Place::Local(cur);
+        let cur = Place::Base(PlaceBase::Local(cur));
         let zero = self.constant_usize(0);
         let mut drop_block_stmts = vec![];
         drop_block_stmts.push(self.assign(&length, Rvalue::Len(self.place.clone())));
         if ptr_based {
             let tmp_ty = tcx.mk_mut_ptr(self.place_ty(self.place));
-            let tmp = Place::Local(self.new_temp(tmp_ty));
+            let tmp = Place::Base(PlaceBase::Local(self.new_temp(tmp_ty)));
             // tmp = &mut P;
             // cur = tmp as *mut T;
             // end = Offset(cur, len);
@@ -883,7 +886,7 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
         unwind: Unwind
     ) -> BasicBlock {
         let tcx = self.tcx();
-        let unit_temp = Place::Local(self.new_temp(tcx.mk_unit()));
+        let unit_temp = Place::Base(PlaceBase::Local(self.new_temp(tcx.mk_unit())));
         let free_func = tcx.require_lang_item(lang_items::BoxFreeFnLangItem);
         let args = adt.variants[VariantIdx::new(0)].fields.iter().enumerate().map(|(i, f)| {
             let field = Field::new(i);
diff --git a/src/librustc_mir/util/graphviz.rs b/src/librustc_mir/util/graphviz.rs
index e93b96c1216..5d495fc0458 100644
--- a/src/librustc_mir/util/graphviz.rs
+++ b/src/librustc_mir/util/graphviz.rs
@@ -134,7 +134,11 @@ fn write_graph_label<'a, 'gcx, 'tcx, W: Write>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
         if i > 0 {
             write!(w, ", ")?;
         }
-        write!(w, "{:?}: {}", Place::Local(arg), escape(&mir.local_decls[arg].ty))?;
+        write!(w,
+               "{:?}: {}",
+               Place::Base(PlaceBase::Local(arg)),
+               escape(&mir.local_decls[arg].ty)
+        )?;
     }
 
     write!(w, ") -&gt; {}", escape(mir.return_ty()))?;
@@ -150,10 +154,10 @@ fn write_graph_label<'a, 'gcx, 'tcx, W: Write>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
 
         if let Some(name) = decl.name {
             write!(w, r#"{:?}: {}; // {}<br align="left"/>"#,
-                   Place::Local(local), escape(&decl.ty), name)?;
+                   Place::Base(PlaceBase::Local(local)), escape(&decl.ty), name)?;
         } else {
             write!(w, r#"let mut {:?}: {};<br align="left"/>"#,
-                   Place::Local(local), escape(&decl.ty))?;
+                   Place::Base(PlaceBase::Local(local)), escape(&decl.ty))?;
         }
     }
 
diff --git a/src/librustc_mir/util/pretty.rs b/src/librustc_mir/util/pretty.rs
index 8177de50776..c3fbee3a2a6 100644
--- a/src/librustc_mir/util/pretty.rs
+++ b/src/librustc_mir/util/pretty.rs
@@ -625,7 +625,7 @@ fn write_mir_sig(
             if i != 0 {
                 write!(w, ", ")?;
             }
-            write!(w, "{:?}: {}", Place::Local(arg), mir.local_decls[arg].ty)?;
+            write!(w, "{:?}: {}", Place::Base(PlaceBase::Local(arg)), mir.local_decls[arg].ty)?;
         }
 
         write!(w, ") -> {}", mir.return_ty())?;
diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs
index 27103ab9965..4a73f86ef6f 100644
--- a/src/librustc_privacy/lib.rs
+++ b/src/librustc_privacy/lib.rs
@@ -290,10 +290,10 @@ fn def_id_visibility<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId)
 // Set the correct `TypeckTables` for the given `item_id` (or an empty table if
 // there is no `TypeckTables` for the item).
 fn item_tables<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                         node_id: ast::NodeId,
+                         hir_id: hir::HirId,
                          empty_tables: &'a ty::TypeckTables<'tcx>)
                          -> &'a ty::TypeckTables<'tcx> {
-    let def_id = tcx.hir().local_def_id(node_id);
+    let def_id = tcx.hir().local_def_id_from_hir_id(hir_id);
     if tcx.has_typeck_tables(def_id) { tcx.typeck_tables_of(def_id) } else { empty_tables }
 }
 
@@ -841,7 +841,7 @@ impl<'a, 'tcx> Visitor<'tcx> for NamePrivacyVisitor<'a, 'tcx> {
     fn visit_item(&mut self, item: &'tcx hir::Item) {
         let orig_current_item = mem::replace(&mut self.current_item, item.id);
         let orig_tables =
-            mem::replace(&mut self.tables, item_tables(self.tcx, item.id, self.empty_tables));
+            mem::replace(&mut self.tables, item_tables(self.tcx, item.hir_id, self.empty_tables));
         intravisit::walk_item(self, item);
         self.current_item = orig_current_item;
         self.tables = orig_tables;
@@ -849,14 +849,14 @@ impl<'a, 'tcx> Visitor<'tcx> for NamePrivacyVisitor<'a, 'tcx> {
 
     fn visit_trait_item(&mut self, ti: &'tcx hir::TraitItem) {
         let orig_tables =
-            mem::replace(&mut self.tables, item_tables(self.tcx, ti.id, self.empty_tables));
+            mem::replace(&mut self.tables, item_tables(self.tcx, ti.hir_id, self.empty_tables));
         intravisit::walk_trait_item(self, ti);
         self.tables = orig_tables;
     }
 
     fn visit_impl_item(&mut self, ii: &'tcx hir::ImplItem) {
         let orig_tables =
-            mem::replace(&mut self.tables, item_tables(self.tcx, ii.id, self.empty_tables));
+            mem::replace(&mut self.tables, item_tables(self.tcx, ii.hir_id, self.empty_tables));
         intravisit::walk_impl_item(self, ii);
         self.tables = orig_tables;
     }
@@ -1114,7 +1114,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> {
             mem::replace(&mut self.current_item, self.tcx.hir().local_def_id(item.id));
         let orig_in_body = mem::replace(&mut self.in_body, false);
         let orig_tables =
-            mem::replace(&mut self.tables, item_tables(self.tcx, item.id, self.empty_tables));
+            mem::replace(&mut self.tables, item_tables(self.tcx, item.hir_id, self.empty_tables));
         intravisit::walk_item(self, item);
         self.tables = orig_tables;
         self.in_body = orig_in_body;
@@ -1123,14 +1123,14 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> {
 
     fn visit_trait_item(&mut self, ti: &'tcx hir::TraitItem) {
         let orig_tables =
-            mem::replace(&mut self.tables, item_tables(self.tcx, ti.id, self.empty_tables));
+            mem::replace(&mut self.tables, item_tables(self.tcx, ti.hir_id, self.empty_tables));
         intravisit::walk_trait_item(self, ti);
         self.tables = orig_tables;
     }
 
     fn visit_impl_item(&mut self, ii: &'tcx hir::ImplItem) {
         let orig_tables =
-            mem::replace(&mut self.tables, item_tables(self.tcx, ii.id, self.empty_tables));
+            mem::replace(&mut self.tables, item_tables(self.tcx, ii.hir_id, self.empty_tables));
         intravisit::walk_impl_item(self, ii);
         self.tables = orig_tables;
     }
@@ -1318,7 +1318,9 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> {
                                      match impl_item.node {
                                          hir::ImplItemKind::Const(..) |
                                          hir::ImplItemKind::Method(..) => {
-                                             self.access_levels.is_reachable(impl_item.id)
+                                             let node_id = self.tcx.hir().hir_to_node_id(
+                                                impl_item.hir_id);
+                                             self.access_levels.is_reachable(node_id)
                                          }
                                          hir::ImplItemKind::Existential(..) |
                                          hir::ImplItemKind::Type(_) => false,
@@ -1340,10 +1342,11 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> {
                                 // don't erroneously report errors for private
                                 // types in private items.
                                 let impl_item = self.tcx.hir().impl_item(impl_item_ref.id);
+                                let node_id = self.tcx.hir().hir_to_node_id(impl_item.hir_id);
                                 match impl_item.node {
                                     hir::ImplItemKind::Const(..) |
                                     hir::ImplItemKind::Method(..)
-                                        if self.item_is_public(&impl_item.id, &impl_item.vis) =>
+                                        if self.item_is_public(&node_id, &impl_item.vis) =>
                                     {
                                         intravisit::walk_impl_item(self, impl_item)
                                     }
@@ -1495,7 +1498,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> {
 
 struct SearchInterfaceForPrivateItemsVisitor<'a, 'tcx: 'a> {
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
-    item_id: ast::NodeId,
+    item_id: hir::HirId,
     item_def_id: DefId,
     span: Span,
     /// The visitor checks that each component type is at least this visible.
@@ -1539,17 +1542,17 @@ impl<'a, 'tcx: 'a> SearchInterfaceForPrivateItemsVisitor<'a, 'tcx> {
 
     fn check_def_id(&mut self, def_id: DefId, kind: &str, descr: &dyn fmt::Display) -> bool {
         if self.leaks_private_dep(def_id) {
-            self.tcx.lint_node(lint::builtin::EXPORTED_PRIVATE_DEPENDENCIES,
-                               self.item_id,
-                               self.span,
-                               &format!("{} `{}` from private dependency '{}' in public \
-                                         interface", kind, descr,
-                                         self.tcx.crate_name(def_id.krate)));
+            self.tcx.lint_hir(lint::builtin::EXPORTED_PRIVATE_DEPENDENCIES,
+                              self.item_id,
+                              self.span,
+                              &format!("{} `{}` from private dependency '{}' in public \
+                                        interface", kind, descr,
+                                        self.tcx.crate_name(def_id.krate)));
 
         }
 
-        let node_id = match self.tcx.hir().as_local_node_id(def_id) {
-            Some(node_id) => node_id,
+        let hir_id = match self.tcx.hir().as_local_hir_id(def_id) {
+            Some(hir_id) => hir_id,
             None => return false,
         };
 
@@ -1567,8 +1570,8 @@ impl<'a, 'tcx: 'a> SearchInterfaceForPrivateItemsVisitor<'a, 'tcx> {
                 err.emit();
             } else {
                 let err_code = if kind == "trait" { "E0445" } else { "E0446" };
-                self.tcx.lint_node(lint::builtin::PRIVATE_IN_PUBLIC, node_id, self.span,
-                                   &format!("{} (error {})", msg, err_code));
+                self.tcx.lint_hir(lint::builtin::PRIVATE_IN_PUBLIC, hir_id, self.span,
+                                  &format!("{} (error {})", msg, err_code));
             }
 
         }
@@ -1604,20 +1607,20 @@ struct PrivateItemsInPublicInterfacesVisitor<'a, 'tcx: 'a> {
 }
 
 impl<'a, 'tcx> PrivateItemsInPublicInterfacesVisitor<'a, 'tcx> {
-    fn check(&self, item_id: ast::NodeId, required_visibility: ty::Visibility)
+    fn check(&self, item_id: hir::HirId, required_visibility: ty::Visibility)
              -> SearchInterfaceForPrivateItemsVisitor<'a, 'tcx> {
         let mut has_old_errors = false;
 
         // Slow path taken only if there any errors in the crate.
         for &id in self.old_error_set {
             // Walk up the nodes until we find `item_id` (or we hit a root).
-            let mut id = self.tcx.hir().hir_to_node_id(id);
+            let mut id = id;
             loop {
                 if id == item_id {
                     has_old_errors = true;
                     break;
                 }
-                let parent = self.tcx.hir().get_parent_node(id);
+                let parent = self.tcx.hir().get_parent_node_by_hir_id(id);
                 if parent == id {
                     break;
                 }
@@ -1632,8 +1635,8 @@ impl<'a, 'tcx> PrivateItemsInPublicInterfacesVisitor<'a, 'tcx> {
         SearchInterfaceForPrivateItemsVisitor {
             tcx: self.tcx,
             item_id,
-            item_def_id: self.tcx.hir().local_def_id(item_id),
-            span: self.tcx.hir().span(item_id),
+            item_def_id: self.tcx.hir().local_def_id_from_hir_id(item_id),
+            span: self.tcx.hir().span_by_hir_id(item_id),
             required_visibility,
             has_pub_restricted: self.has_pub_restricted,
             has_old_errors,
@@ -1642,9 +1645,9 @@ impl<'a, 'tcx> PrivateItemsInPublicInterfacesVisitor<'a, 'tcx> {
         }
     }
 
-    fn check_trait_or_impl_item(&self, node_id: ast::NodeId, assoc_item_kind: AssociatedItemKind,
+    fn check_trait_or_impl_item(&self, hir_id: hir::HirId, assoc_item_kind: AssociatedItemKind,
                                 defaultness: hir::Defaultness, vis: ty::Visibility) {
-        let mut check = self.check(node_id, vis);
+        let mut check = self.check(hir_id, vis);
 
         let (check_ty, is_assoc_ty) = match assoc_item_kind {
             AssociatedItemKind::Const | AssociatedItemKind::Method { .. } => (true, false),
@@ -1682,30 +1685,31 @@ impl<'a, 'tcx> Visitor<'tcx> for PrivateItemsInPublicInterfacesVisitor<'a, 'tcx>
             // Subitems of these items have inherited publicity.
             hir::ItemKind::Const(..) | hir::ItemKind::Static(..) |
             hir::ItemKind::Fn(..) | hir::ItemKind::Ty(..) => {
-                self.check(item.id, item_visibility).generics().predicates().ty();
+                self.check(item.hir_id, item_visibility).generics().predicates().ty();
             }
             hir::ItemKind::Existential(..) => {
                 // `ty()` for existential types is the underlying type,
                 // it's not a part of interface, so we skip it.
-                self.check(item.id, item_visibility).generics().predicates();
+                self.check(item.hir_id, item_visibility).generics().predicates();
             }
             hir::ItemKind::Trait(.., ref trait_item_refs) => {
-                self.check(item.id, item_visibility).generics().predicates();
+                self.check(item.hir_id, item_visibility).generics().predicates();
 
                 for trait_item_ref in trait_item_refs {
-                    self.check_trait_or_impl_item(trait_item_ref.id.node_id, trait_item_ref.kind,
+                    let hir_id = tcx.hir().node_to_hir_id(trait_item_ref.id.node_id);
+                    self.check_trait_or_impl_item(hir_id, trait_item_ref.kind,
                                                   trait_item_ref.defaultness, item_visibility);
                 }
             }
             hir::ItemKind::TraitAlias(..) => {
-                self.check(item.id, item_visibility).generics().predicates();
+                self.check(item.hir_id, item_visibility).generics().predicates();
             }
             hir::ItemKind::Enum(ref def, _) => {
-                self.check(item.id, item_visibility).generics().predicates();
+                self.check(item.hir_id, item_visibility).generics().predicates();
 
                 for variant in &def.variants {
                     for field in variant.node.data.fields() {
-                        self.check(field.id, item_visibility).ty();
+                        self.check(field.hir_id, item_visibility).ty();
                     }
                 }
             }
@@ -1713,17 +1717,17 @@ impl<'a, 'tcx> Visitor<'tcx> for PrivateItemsInPublicInterfacesVisitor<'a, 'tcx>
             hir::ItemKind::ForeignMod(ref foreign_mod) => {
                 for foreign_item in &foreign_mod.items {
                     let vis = ty::Visibility::from_hir(&foreign_item.vis, item.id, tcx);
-                    self.check(foreign_item.id, vis).generics().predicates().ty();
+                    self.check(foreign_item.hir_id, vis).generics().predicates().ty();
                 }
             }
             // Subitems of structs and unions have their own publicity.
             hir::ItemKind::Struct(ref struct_def, _) |
             hir::ItemKind::Union(ref struct_def, _) => {
-                self.check(item.id, item_visibility).generics().predicates();
+                self.check(item.hir_id, item_visibility).generics().predicates();
 
                 for field in struct_def.fields() {
                     let field_visibility = ty::Visibility::from_hir(&field.vis, item.id, tcx);
-                    self.check(field.id, min(item_visibility, field_visibility, tcx)).ty();
+                    self.check(field.hir_id, min(item_visibility, field_visibility, tcx)).ty();
                 }
             }
             // An inherent impl is public when its type is public
@@ -1732,7 +1736,7 @@ impl<'a, 'tcx> Visitor<'tcx> for PrivateItemsInPublicInterfacesVisitor<'a, 'tcx>
             // Subitems of trait impls have inherited publicity.
             hir::ItemKind::Impl(.., ref trait_ref, _, ref impl_item_refs) => {
                 let impl_vis = ty::Visibility::of_impl(item.id, tcx, &Default::default());
-                self.check(item.id, impl_vis).generics().predicates();
+                self.check(item.hir_id, impl_vis).generics().predicates();
                 for impl_item_ref in impl_item_refs {
                     let impl_item = tcx.hir().impl_item(impl_item_ref.id);
                     let impl_item_vis = if trait_ref.is_none() {
@@ -1740,7 +1744,8 @@ impl<'a, 'tcx> Visitor<'tcx> for PrivateItemsInPublicInterfacesVisitor<'a, 'tcx>
                     } else {
                         impl_vis
                     };
-                    self.check_trait_or_impl_item(impl_item_ref.id.node_id, impl_item_ref.kind,
+                    let hir_id = tcx.hir().node_to_hir_id(impl_item_ref.id.node_id);
+                    self.check_trait_or_impl_item(hir_id, impl_item_ref.kind,
                                                   impl_item_ref.defaultness, impl_item_vis);
                 }
             }
diff --git a/src/librustc_traits/lowering/mod.rs b/src/librustc_traits/lowering/mod.rs
index d261b2382e7..44883d438a1 100644
--- a/src/librustc_traits/lowering/mod.rs
+++ b/src/librustc_traits/lowering/mod.rs
@@ -612,8 +612,8 @@ struct ClauseDumper<'a, 'tcx: 'a> {
 }
 
 impl<'a, 'tcx> ClauseDumper<'a, 'tcx> {
-    fn process_attrs(&mut self, node_id: ast::NodeId, attrs: &[ast::Attribute]) {
-        let def_id = self.tcx.hir().local_def_id(node_id);
+    fn process_attrs(&mut self, hir_id: hir::HirId, attrs: &[ast::Attribute]) {
+        let def_id = self.tcx.hir().local_def_id_from_hir_id(hir_id);
         for attr in attrs {
             let mut clauses = None;
 
@@ -655,22 +655,22 @@ impl<'a, 'tcx> Visitor<'tcx> for ClauseDumper<'a, 'tcx> {
     }
 
     fn visit_item(&mut self, item: &'tcx hir::Item) {
-        self.process_attrs(item.id, &item.attrs);
+        self.process_attrs(item.hir_id, &item.attrs);
         intravisit::walk_item(self, item);
     }
 
     fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem) {
-        self.process_attrs(trait_item.id, &trait_item.attrs);
+        self.process_attrs(trait_item.hir_id, &trait_item.attrs);
         intravisit::walk_trait_item(self, trait_item);
     }
 
     fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem) {
-        self.process_attrs(impl_item.id, &impl_item.attrs);
+        self.process_attrs(impl_item.hir_id, &impl_item.attrs);
         intravisit::walk_impl_item(self, impl_item);
     }
 
     fn visit_struct_field(&mut self, s: &'tcx hir::StructField) {
-        self.process_attrs(s.id, &s.attrs);
+        self.process_attrs(s.hir_id, &s.attrs);
         intravisit::walk_struct_field(self, s);
     }
 }
diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs
index 4a88922b50e..5dbcf908020 100644
--- a/src/librustc_typeck/astconv.rs
+++ b/src/librustc_typeck/astconv.rs
@@ -718,7 +718,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o {
             // specify type to assert that error was already reported in Err case:
             let predicate: Result<_, ErrorReported> =
                 self.ast_type_binding_to_poly_projection_predicate(
-                    trait_ref.ref_id, poly_trait_ref, binding, speculative, &mut dup_bindings);
+                    trait_ref.hir_ref_id, poly_trait_ref, binding, speculative, &mut dup_bindings);
             // okay to ignore Err because of ErrorReported (see above)
             Some((predicate.ok()?, binding.span))
         }));
@@ -802,7 +802,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o {
 
     fn ast_type_binding_to_poly_projection_predicate(
         &self,
-        ref_id: ast::NodeId,
+        hir_ref_id: hir::HirId,
         trait_ref: ty::PolyTraitRef<'tcx>,
         binding: &ConvertedBinding<'tcx>,
         speculative: bool,
@@ -874,7 +874,6 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o {
                                           binding.item_name, binding.span)
         }?;
 
-        let hir_ref_id = self.tcx().hir().node_to_hir_id(ref_id);
         let (assoc_ident, def_scope) =
             tcx.adjust_ident(binding.item_name, candidate.def_id(), hir_ref_id);
         let assoc_ty = tcx.associated_items(candidate.def_id()).find(|i| {
@@ -1798,7 +1797,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o {
                 self.associated_path_to_ty(ast_ty.hir_id, ast_ty.span, ty, def, segment, false).0
             }
             hir::TyKind::Array(ref ty, ref length) => {
-                let length_def_id = tcx.hir().local_def_id(length.id);
+                let length_def_id = tcx.hir().local_def_id_from_hir_id(length.hir_id);
                 let substs = InternalSubsts::identity_for_item(tcx, length_def_id);
                 let length = ty::LazyConst::Unevaluated(length_def_id, substs);
                 let length = tcx.mk_lazy_const(length);
diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs
index 100e55fc367..e27672842db 100644
--- a/src/librustc_typeck/check/_match.rs
+++ b/src/librustc_typeck/check/_match.rs
@@ -227,7 +227,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                 self.demand_eqtype_pat(pat.span, expected, rhs_ty, match_discrim_span);
                 common_type
             }
-            PatKind::Binding(ba, var_id, _, _, ref sub) => {
+            PatKind::Binding(ba, _, var_id, _, ref sub) => {
                 let bm = if ba == hir::BindingAnnotation::Unannotated {
                     def_bm
                 } else {
@@ -239,7 +239,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                     .pat_binding_modes_mut()
                     .insert(pat.hir_id, bm);
                 debug!("check_pat_walk: pat.hir_id={:?} bm={:?}", pat.hir_id, bm);
-                let local_ty = self.local_ty(pat.span, pat.id).decl_ty;
+                let local_ty = self.local_ty(pat.span, pat.hir_id).decl_ty;
                 match bm {
                     ty::BindByReference(mutbl) => {
                         // if the binding is like
@@ -265,7 +265,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
 
                 // if there are multiple arms, make sure they all agree on
                 // what the type of the binding `x` ought to be
-                if var_id != pat.id {
+                if var_id != pat.hir_id {
                     let vt = self.local_ty(pat.span, var_id).decl_ty;
                     self.demand_eqtype_pat(pat.span, vt, local_ty, match_discrim_span);
                 }
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index 5769ab25312..80ffe441561 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -137,7 +137,7 @@ use crate::TypeAndSubsts;
 use crate::lint;
 use crate::util::captures::Captures;
 use crate::util::common::{ErrorReported, indenter};
-use crate::util::nodemap::{DefIdMap, DefIdSet, FxHashMap, FxHashSet, HirIdMap, NodeMap};
+use crate::util::nodemap::{DefIdMap, DefIdSet, FxHashMap, FxHashSet, HirIdMap};
 
 pub use self::Expectation::*;
 use self::autoderef::Autoderef;
@@ -194,7 +194,7 @@ pub struct Inherited<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
 
     tables: MaybeInProgressTables<'a, 'tcx>,
 
-    locals: RefCell<NodeMap<LocalTy<'tcx>>>,
+    locals: RefCell<HirIdMap<LocalTy<'tcx>>>,
 
     fulfillment_cx: RefCell<Box<dyn TraitEngine<'tcx>>>,
 
@@ -943,7 +943,7 @@ struct GatherLocalsVisitor<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
 }
 
 impl<'a, 'gcx, 'tcx> GatherLocalsVisitor<'a, 'gcx, 'tcx> {
-    fn assign(&mut self, span: Span, nid: ast::NodeId, ty_opt: Option<LocalTy<'tcx>>) -> Ty<'tcx> {
+    fn assign(&mut self, span: Span, nid: hir::HirId, ty_opt: Option<LocalTy<'tcx>>) -> Ty<'tcx> {
         match ty_opt {
             None => {
                 // infer the variable's type
@@ -994,19 +994,19 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for GatherLocalsVisitor<'a, 'gcx, 'tcx> {
             },
             None => None,
         };
-        self.assign(local.span, local.id, local_ty);
+        self.assign(local.span, local.hir_id, local_ty);
 
         debug!("Local variable {:?} is assigned type {}",
                local.pat,
                self.fcx.ty_to_string(
-                   self.fcx.locals.borrow().get(&local.id).unwrap().clone().decl_ty));
+                   self.fcx.locals.borrow().get(&local.hir_id).unwrap().clone().decl_ty));
         intravisit::walk_local(self, local);
     }
 
     // Add pattern bindings.
     fn visit_pat(&mut self, p: &'gcx hir::Pat) {
         if let PatKind::Binding(_, _, _, ident, _) = p.node {
-            let var_ty = self.assign(p.span, p.id, None);
+            let var_ty = self.assign(p.span, p.hir_id, None);
 
             if !self.fcx.tcx.features().unsized_locals {
                 self.fcx.require_type_is_sized(var_ty, p.span,
@@ -1016,7 +1016,7 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for GatherLocalsVisitor<'a, 'gcx, 'tcx> {
             debug!("Pattern binding {} is assigned to {} with type {:?}",
                    ident,
                    self.fcx.ty_to_string(
-                       self.fcx.locals.borrow().get(&p.id).unwrap().clone().decl_ty),
+                       self.fcx.locals.borrow().get(&p.hir_id).unwrap().clone().decl_ty),
                    var_ty);
         }
         intravisit::walk_pat(self, p);
@@ -1554,7 +1554,8 @@ fn check_impl_items_against_trait<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     // Check existing impl methods to see if they are both present in trait
     // and compatible with trait signature
     for impl_item in impl_items() {
-        let ty_impl_item = tcx.associated_item(tcx.hir().local_def_id(impl_item.id));
+        let ty_impl_item = tcx.associated_item(
+            tcx.hir().local_def_id_from_hir_id(impl_item.hir_id));
         let ty_trait_item = tcx.associated_items(impl_trait_ref.def_id)
             .find(|ac| Namespace::from(&impl_item.node) == Namespace::from(ac.kind) &&
                        tcx.hygienic_eq(ty_impl_item.ident, ac.ident, impl_trait_ref.def_id))
@@ -1870,7 +1871,7 @@ pub fn check_enum<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
     for v in vs {
         if let Some(ref e) = v.node.disr_expr {
-            tcx.typeck_tables_of(tcx.hir().local_def_id(e.id));
+            tcx.typeck_tables_of(tcx.hir().local_def_id_from_hir_id(e.hir_id));
         }
     }
 
@@ -2124,10 +2125,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         format!("{:?}", self_ptr)
     }
 
-    pub fn local_ty(&self, span: Span, nid: ast::NodeId) -> LocalTy<'tcx> {
+    pub fn local_ty(&self, span: Span, nid: hir::HirId) -> LocalTy<'tcx> {
         self.locals.borrow().get(&nid).cloned().unwrap_or_else(||
             span_bug!(span, "no type for local variable {}",
-                      self.tcx.hir().node_to_string(nid))
+                      self.tcx.hir().hir_to_string(nid))
         )
     }
 
@@ -4552,7 +4553,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                 tcx.mk_array(element_ty, args.len() as u64)
             }
             ExprKind::Repeat(ref element, ref count) => {
-                let count_def_id = tcx.hir().local_def_id(count.id);
+                let count_def_id = tcx.hir().local_def_id_from_hir_id(count.hir_id);
                 let param_env = ty::ParamEnv::empty();
                 let substs = InternalSubsts::identity_for_item(tcx.global_tcx(), count_def_id);
                 let instance = ty::Instance::resolve(
@@ -4805,7 +4806,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         // See #44848.
         let ref_bindings = local.pat.contains_explicit_ref_binding();
 
-        let local_ty = self.local_ty(init.span, local.id).revealed_ty;
+        let local_ty = self.local_ty(init.span, local.hir_id).revealed_ty;
         if let Some(m) = ref_bindings {
             // Somewhat subtle: if we have a `ref` binding in the pattern,
             // we want to avoid introducing coercions for the RHS. This is
@@ -4824,7 +4825,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
     }
 
     pub fn check_decl_local(&self, local: &'gcx hir::Local) {
-        let t = self.local_ty(local.span, local.id).decl_ty;
+        let t = self.local_ty(local.span, local.hir_id).decl_ty;
         self.write_ty(local.hir_id, t);
 
         if let Some(ref init) = local.init {
@@ -5378,7 +5379,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
 
         match def {
             Def::Local(nid) | Def::Upvar(nid, ..) => {
-                let ty = self.local_ty(span, nid).decl_ty;
+                let hid = self.tcx.hir().node_to_hir_id(nid);
+                let ty = self.local_ty(span, hid).decl_ty;
                 let ty = self.normalize_associated_types_in(span, &ty);
                 self.write_ty(hir_id, ty);
                 return (ty, def);
diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs
index 69f2a17fdf1..b7c862a89a1 100644
--- a/src/librustc_typeck/check/wfcheck.rs
+++ b/src/librustc_typeck/check/wfcheck.rs
@@ -108,14 +108,14 @@ pub fn check_item_well_formed<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: Def
             check_item_fn(tcx, item);
         }
         hir::ItemKind::Static(ref ty, ..) => {
-            check_item_type(tcx, item.id, ty.span, false);
+            check_item_type(tcx, item.hir_id, ty.span, false);
         }
         hir::ItemKind::Const(ref ty, ..) => {
-            check_item_type(tcx, item.id, ty.span, false);
+            check_item_type(tcx, item.hir_id, ty.span, false);
         }
         hir::ItemKind::ForeignMod(ref module) => for it in module.items.iter() {
             if let hir::ForeignItemKind::Static(ref ty, ..) = it.node {
-                check_item_type(tcx, it.id, ty.span, true);
+                check_item_type(tcx, it.hir_id, ty.span, true);
             }
         },
         hir::ItemKind::Struct(ref struct_def, ref ast_generics) => {
@@ -157,7 +157,7 @@ pub fn check_trait_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) {
         hir::TraitItemKind::Method(ref sig, _) => Some(sig),
         _ => None
     };
-    check_associated_item(tcx, trait_item.id, trait_item.span, method_sig);
+    check_associated_item(tcx, trait_item.hir_id, trait_item.span, method_sig);
 }
 
 pub fn check_impl_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) {
@@ -168,18 +168,18 @@ pub fn check_impl_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) {
         hir::ImplItemKind::Method(ref sig, _) => Some(sig),
         _ => None
     };
-    check_associated_item(tcx, impl_item.id, impl_item.span, method_sig);
+    check_associated_item(tcx, impl_item.hir_id, impl_item.span, method_sig);
 }
 
 fn check_associated_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                                   item_id: ast::NodeId,
+                                   item_id: hir::HirId,
                                    span: Span,
                                    sig_if_method: Option<&hir::MethodSig>) {
     debug!("check_associated_item: {:?}", item_id);
 
     let code = ObligationCauseCode::MiscObligation;
     for_id(tcx, item_id, span).with_fcx(|fcx, tcx| {
-        let item = fcx.tcx.associated_item(fcx.tcx.hir().local_def_id(item_id));
+        let item = fcx.tcx.associated_item(fcx.tcx.hir().local_def_id_from_hir_id(item_id));
 
         let (mut implied_bounds, self_ty) = match item.container {
             ty::TraitContainer(_) => (vec![], fcx.tcx.mk_self_type()),
@@ -220,16 +220,15 @@ fn check_associated_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
 fn for_item<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'gcx>, item: &hir::Item)
                             -> CheckWfFcxBuilder<'a, 'gcx, 'tcx> {
-    for_id(tcx, item.id, item.span)
+    for_id(tcx, item.hir_id, item.span)
 }
 
-fn for_id<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'gcx>, id: ast::NodeId, span: Span)
+fn for_id<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'gcx>, id: hir::HirId, span: Span)
                           -> CheckWfFcxBuilder<'a, 'gcx, 'tcx> {
-    let def_id = tcx.hir().local_def_id(id);
-    let hir_id = tcx.hir().node_to_hir_id(id);
+    let def_id = tcx.hir().local_def_id_from_hir_id(id);
     CheckWfFcxBuilder {
         inherited: Inherited::build(tcx, def_id),
-        id: hir_id,
+        id,
         span,
         param_env: tcx.param_env(def_id),
     }
@@ -339,14 +338,14 @@ fn check_item_fn<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item: &hir::Item) {
 
 fn check_item_type<'a, 'tcx>(
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
-    item_id: ast::NodeId,
+    item_id: hir::HirId,
     ty_span: Span,
     allow_foreign_ty: bool,
 ) {
     debug!("check_item_type: {:?}", item_id);
 
     for_id(tcx, item_id, ty_span).with_fcx(|fcx, gcx| {
-        let ty = gcx.type_of(gcx.hir().local_def_id(item_id));
+        let ty = gcx.type_of(gcx.hir().local_def_id_from_hir_id(item_id));
         let item_ty = fcx.normalize_associated_types_in(ty_span, &ty);
 
         let mut forbid_unsized = true;
@@ -1025,13 +1024,13 @@ impl<'a, 'tcx> ItemLikeVisitor<'tcx> for CheckTypeWellFormedVisitor<'a, 'tcx> {
 
     fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem) {
         debug!("visit_trait_item: {:?}", trait_item);
-        let def_id = self.tcx.hir().local_def_id(trait_item.id);
+        let def_id = self.tcx.hir().local_def_id_from_hir_id(trait_item.hir_id);
         self.tcx.ensure().check_trait_item_well_formed(def_id);
     }
 
     fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem) {
         debug!("visit_impl_item: {:?}", impl_item);
-        let def_id = self.tcx.hir().local_def_id(impl_item.id);
+        let def_id = self.tcx.hir().local_def_id_from_hir_id(impl_item.hir_id);
         self.tcx.ensure().check_impl_item_well_formed(def_id);
     }
 }
diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs
index 7c1283a6d21..5981d9bb66b 100644
--- a/src/librustc_typeck/check/writeback.rs
+++ b/src/librustc_typeck/check/writeback.rs
@@ -287,7 +287,7 @@ impl<'cx, 'gcx, 'tcx> Visitor<'gcx> for WritebackCx<'cx, 'gcx, 'tcx> {
 
     fn visit_local(&mut self, l: &'gcx hir::Local) {
         intravisit::walk_local(self, l);
-        let var_ty = self.fcx.local_ty(l.span, l.id).decl_ty;
+        let var_ty = self.fcx.local_ty(l.span, l.hir_id).decl_ty;
         let var_ty = self.resolve(&var_ty, &l.span);
         self.write_ty_to_tables(l.hir_id, var_ty);
     }
diff --git a/src/librustc_typeck/check_unused.rs b/src/librustc_typeck/check_unused.rs
index 70f7c30f7ec..4c6d7710009 100644
--- a/src/librustc_typeck/check_unused.rs
+++ b/src/librustc_typeck/check_unused.rs
@@ -34,7 +34,7 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for CheckVisitor<'a, 'tcx> {
             return;
         }
         if let hir::ItemKind::Use(ref path, _) = item.node {
-            self.check_import(item.id, path.span);
+            self.check_import(item.hir_id, path.span);
         }
     }
 
@@ -51,14 +51,13 @@ struct CheckVisitor<'a, 'tcx: 'a> {
 }
 
 impl<'a, 'tcx> CheckVisitor<'a, 'tcx> {
-    fn check_import(&self, id: ast::NodeId, span: Span) {
-        let def_id = self.tcx.hir().local_def_id(id);
+    fn check_import(&self, id: hir::HirId, span: Span) {
+        let def_id = self.tcx.hir().local_def_id_from_hir_id(id);
         if !self.tcx.maybe_unused_trait_import(def_id) {
             return;
         }
 
-        let import_def_id = self.tcx.hir().local_def_id(id);
-        if self.used_trait_imports.contains(&import_def_id) {
+        if self.used_trait_imports.contains(&def_id) {
             return;
         }
 
@@ -67,7 +66,7 @@ impl<'a, 'tcx> CheckVisitor<'a, 'tcx> {
         } else {
             "unused import".to_owned()
         };
-        self.tcx.lint_node(lint::builtin::UNUSED_IMPORTS, id, span, &msg);
+        self.tcx.lint_hir(lint::builtin::UNUSED_IMPORTS, id, span, &msg);
     }
 }
 
@@ -121,8 +120,8 @@ fn unused_crates_lint<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>) {
     });
 
     for extern_crate in &crates_to_lint {
-        let id = tcx.hir().as_local_node_id(extern_crate.def_id).unwrap();
-        let item = tcx.hir().expect_item(id);
+        let id = tcx.hir().as_local_hir_id(extern_crate.def_id).unwrap();
+        let item = tcx.hir().expect_item_by_hir_id(id);
 
         // If the crate is fully unused, we suggest removing it altogether.
         // We do this in any edition.
@@ -135,7 +134,7 @@ fn unused_crates_lint<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>) {
                     .map(|attr| attr.span)
                     .fold(span, |acc, attr_span| acc.to(attr_span));
 
-                tcx.struct_span_lint_node(lint, id, span, msg)
+                tcx.struct_span_lint_hir(lint, id, span, msg)
                     .span_suggestion_short(
                         span_with_attrs,
                         "remove it",
@@ -177,7 +176,7 @@ fn unused_crates_lint<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>) {
             None => format!("use {};", item.ident.name),
         };
         let replacement = visibility_qualified(&item.vis, base_replacement);
-        tcx.struct_span_lint_node(lint, id, extern_crate.span, msg)
+        tcx.struct_span_lint_hir(lint, id, extern_crate.span, msg)
             .span_suggestion_short(
                 extern_crate.span,
                 &help,
diff --git a/src/librustc_typeck/coherence/inherent_impls_overlap.rs b/src/librustc_typeck/coherence/inherent_impls_overlap.rs
index 282f1bad172..a51f45a6ff8 100644
--- a/src/librustc_typeck/coherence/inherent_impls_overlap.rs
+++ b/src/librustc_typeck/coherence/inherent_impls_overlap.rs
@@ -36,11 +36,11 @@ impl<'a, 'tcx> InherentOverlapChecker<'a, 'tcx> {
 
             for &item2 in &impl_items2[..] {
                 if (name, namespace) == name_and_namespace(item2) {
-                    let node_id = self.tcx.hir().as_local_node_id(impl1);
-                    let mut err = if used_to_be_allowed && node_id.is_some() {
-                        self.tcx.struct_span_lint_node(
+                    let hir_id = self.tcx.hir().as_local_hir_id(impl1);
+                    let mut err = if used_to_be_allowed && hir_id.is_some() {
+                        self.tcx.struct_span_lint_hir(
                             lint::builtin::INCOHERENT_FUNDAMENTAL_IMPLS,
-                            node_id.unwrap(),
+                            hir_id.unwrap(),
                             self.tcx.span_of_impl(item1).unwrap(),
                             &format!("duplicate definitions with name `{}` (E0592)", name)
                         )
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index 167fb109567..16102ad4cde 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -152,12 +152,12 @@ impl<'a, 'tcx> Visitor<'tcx> for CollectItemTypesVisitor<'a, 'tcx> {
     }
 
     fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem) {
-        convert_trait_item(self.tcx, trait_item.id);
+        convert_trait_item(self.tcx, trait_item.hir_id);
         intravisit::walk_trait_item(self, trait_item);
     }
 
     fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem) {
-        convert_impl_item(self.tcx, impl_item.id);
+        convert_impl_item(self.tcx, impl_item.hir_id);
         intravisit::walk_impl_item(self, impl_item);
     }
 }
@@ -479,9 +479,9 @@ fn convert_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item_id: ast::NodeId) {
     }
 }
 
-fn convert_trait_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, trait_item_id: ast::NodeId) {
-    let trait_item = tcx.hir().expect_trait_item(trait_item_id);
-    let def_id = tcx.hir().local_def_id(trait_item.id);
+fn convert_trait_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, trait_item_id: hir::HirId) {
+    let trait_item = tcx.hir().expect_trait_item_by_hir_id(trait_item_id);
+    let def_id = tcx.hir().local_def_id_from_hir_id(trait_item.hir_id);
     tcx.generics_of(def_id);
 
     match trait_item.node {
@@ -500,12 +500,12 @@ fn convert_trait_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, trait_item_id: ast:
     tcx.predicates_of(def_id);
 }
 
-fn convert_impl_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, impl_item_id: ast::NodeId) {
-    let def_id = tcx.hir().local_def_id(impl_item_id);
+fn convert_impl_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, impl_item_id: hir::HirId) {
+    let def_id = tcx.hir().local_def_id_from_hir_id(impl_item_id);
     tcx.generics_of(def_id);
     tcx.type_of(def_id);
     tcx.predicates_of(def_id);
-    if let hir::ImplItemKind::Method(..) = tcx.hir().expect_impl_item(impl_item_id).node {
+    if let hir::ImplItemKind::Method(..) = tcx.hir().expect_impl_item_by_hir_id(impl_item_id).node {
         tcx.fn_sig(def_id);
     }
 }
@@ -532,7 +532,7 @@ fn convert_enum_variant_types<'a, 'tcx>(
         let wrapped_discr = prev_discr.map_or(initial, |d| d.wrap_incr(tcx));
         prev_discr = Some(
             if let Some(ref e) = variant.node.disr_expr {
-                let expr_did = tcx.hir().local_def_id(e.id);
+                let expr_did = tcx.hir().local_def_id_from_hir_id(e.hir_id);
                 def.eval_explicit_discr(tcx, expr_did)
             } else if let Some(discr) = repr_type.disr_incr(tcx, prev_discr) {
                 Some(discr)
@@ -637,7 +637,7 @@ fn adt_def<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx ty::Ad
                         let did = tcx.hir().local_def_id(v.node.data.id());
                         let discr = if let Some(ref e) = v.node.disr_expr {
                             distance_from_explicit = 0;
-                            ty::VariantDiscr::Explicit(tcx.hir().local_def_id(e.id))
+                            ty::VariantDiscr::Explicit(tcx.hir().local_def_id_from_hir_id(e.hir_id))
                         } else {
                             ty::VariantDiscr::Relative(distance_from_explicit)
                         };
@@ -1142,11 +1142,11 @@ fn report_assoc_ty_on_inherent_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, span:
 fn type_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Ty<'tcx> {
     use rustc::hir::*;
 
-    let node_id = tcx.hir().as_local_node_id(def_id).unwrap();
+    let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap();
 
     let icx = ItemCtxt::new(tcx, def_id);
 
-    match tcx.hir().get(node_id) {
+    match tcx.hir().get_by_hir_id(hir_id) {
         Node::TraitItem(item) => match item.node {
             TraitItemKind::Method(..) => {
                 let substs = InternalSubsts::identity_for_item(tcx, def_id);
@@ -1166,7 +1166,7 @@ fn type_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Ty<'tcx> {
             ImplItemKind::Const(ref ty, _) => icx.to_ty(ty),
             ImplItemKind::Existential(_) => {
                 if tcx
-                    .impl_trait_ref(tcx.hir().get_parent_did(node_id))
+                    .impl_trait_ref(tcx.hir().get_parent_did_by_hir_id(hir_id))
                     .is_none()
                 {
                     report_assoc_ty_on_inherent_impl(tcx, item.span);
@@ -1176,7 +1176,7 @@ fn type_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Ty<'tcx> {
             }
             ImplItemKind::Type(ref ty) => {
                 if tcx
-                    .impl_trait_ref(tcx.hir().get_parent_did(node_id))
+                    .impl_trait_ref(tcx.hir().get_parent_did_by_hir_id(hir_id))
                     .is_none()
                 {
                     report_assoc_ty_on_inherent_impl(tcx, item.span);
@@ -1259,7 +1259,7 @@ fn type_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Ty<'tcx> {
             ..
         }) => match *def {
             VariantData::Unit(..) | VariantData::Struct(..) => {
-                tcx.type_of(tcx.hir().get_parent_did(node_id))
+                tcx.type_of(tcx.hir().get_parent_did_by_hir_id(hir_id))
             }
             VariantData::Tuple(..) => {
                 let substs = InternalSubsts::identity_for_item(tcx, def_id);
@@ -1274,7 +1274,6 @@ fn type_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Ty<'tcx> {
             ..
         }) => {
             if gen.is_some() {
-                let hir_id = tcx.hir().node_to_hir_id(node_id);
                 return tcx.typeck_tables_of(def_id).node_type(hir_id);
             }
 
@@ -1285,7 +1284,9 @@ fn type_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Ty<'tcx> {
             tcx.mk_closure(def_id, substs)
         }
 
-        Node::AnonConst(_) => match tcx.hir().get(tcx.hir().get_parent_node(node_id)) {
+        Node::AnonConst(_) => match tcx.hir().get_by_hir_id(
+            tcx.hir().get_parent_node_by_hir_id(hir_id))
+        {
             Node::Ty(&hir::Ty {
                 node: hir::TyKind::Array(_, ref constant),
                 ..
@@ -1297,7 +1298,7 @@ fn type_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Ty<'tcx> {
             | Node::Expr(&hir::Expr {
                 node: ExprKind::Repeat(_, ref constant),
                 ..
-            }) if constant.id == node_id =>
+            }) if constant.hir_id == hir_id =>
             {
                 tcx.types.usize
             }
@@ -1309,9 +1310,9 @@ fn type_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Ty<'tcx> {
                         ..
                     },
                 ..
-            }) if e.id == node_id =>
+            }) if e.hir_id == hir_id =>
             {
-                tcx.adt_def(tcx.hir().get_parent_did(node_id))
+                tcx.adt_def(tcx.hir().get_parent_did_by_hir_id(hir_id))
                     .repr
                     .discr_type()
                     .to_ty(tcx)
@@ -1484,7 +1485,7 @@ fn find_existential_constraints<'a, 'tcx>(
             }
         }
         fn visit_impl_item(&mut self, it: &'tcx ImplItem) {
-            let def_id = self.tcx.hir().local_def_id(it.id);
+            let def_id = self.tcx.hir().local_def_id_from_hir_id(it.hir_id);
             // the existential type itself or its children are not within its reveal scope
             if def_id != self.def_id {
                 self.check(def_id);
@@ -1492,7 +1493,7 @@ fn find_existential_constraints<'a, 'tcx>(
             }
         }
         fn visit_trait_item(&mut self, it: &'tcx TraitItem) {
-            let def_id = self.tcx.hir().local_def_id(it.id);
+            let def_id = self.tcx.hir().local_def_id_from_hir_id(it.hir_id);
             self.check(def_id);
             intravisit::walk_trait_item(self, it);
         }
@@ -2062,7 +2063,8 @@ fn explicit_predicates_of<'a, 'tcx>(
             };
 
             let assoc_ty =
-                tcx.mk_projection(tcx.hir().local_def_id(trait_item.id), self_trait_ref.substs);
+                tcx.mk_projection(tcx.hir().local_def_id_from_hir_id(trait_item.hir_id),
+                    self_trait_ref.substs);
 
             let bounds = compute_bounds(
                 &ItemCtxt::new(tcx, def_id),
diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs
index 00c2ab79286..a918113b1fc 100644
--- a/src/librustc_typeck/lib.rs
+++ b/src/librustc_typeck/lib.rs
@@ -386,8 +386,8 @@ pub fn hir_trait_to_predicates<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, hir_trait:
     // In case there are any projections etc, find the "environment"
     // def-id that will be used to determine the traits/predicates in
     // scope.  This is derived from the enclosing item-like thing.
-    let env_node_id = tcx.hir().get_parent(hir_trait.ref_id);
-    let env_def_id = tcx.hir().local_def_id(env_node_id);
+    let env_hir_id = tcx.hir().get_parent_item(hir_trait.hir_ref_id);
+    let env_def_id = tcx.hir().local_def_id_from_hir_id(env_hir_id);
     let item_cx = self::collect::ItemCtxt::new(tcx, env_def_id);
     let mut projections = Vec::new();
     let (principal, _) = astconv::AstConv::instantiate_poly_trait_ref_inner(
diff --git a/src/librustc_typeck/variance/constraints.rs b/src/librustc_typeck/variance/constraints.rs
index 7b94b047c92..d8d93b462a9 100644
--- a/src/librustc_typeck/variance/constraints.rs
+++ b/src/librustc_typeck/variance/constraints.rs
@@ -6,7 +6,6 @@
 use hir::def_id::DefId;
 use rustc::ty::subst::{UnpackedKind, SubstsRef};
 use rustc::ty::{self, Ty, TyCtxt};
-use syntax::ast;
 use rustc::hir;
 use rustc::hir::itemlikevisit::ItemLikeVisitor;
 
@@ -72,31 +71,31 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for ConstraintContext<'a, 'tcx> {
         match item.node {
             hir::ItemKind::Struct(ref struct_def, _) |
             hir::ItemKind::Union(ref struct_def, _) => {
-                self.visit_node_helper(item.id);
+                self.visit_node_helper(item.hir_id);
 
                 if let hir::VariantData::Tuple(..) = *struct_def {
-                    self.visit_node_helper(struct_def.id());
+                    self.visit_node_helper(struct_def.hir_id());
                 }
             }
 
             hir::ItemKind::Enum(ref enum_def, _) => {
-                self.visit_node_helper(item.id);
+                self.visit_node_helper(item.hir_id);
 
                 for variant in &enum_def.variants {
                     if let hir::VariantData::Tuple(..) = variant.node.data {
-                        self.visit_node_helper(variant.node.data.id());
+                        self.visit_node_helper(variant.node.data.hir_id());
                     }
                 }
             }
 
             hir::ItemKind::Fn(..) => {
-                self.visit_node_helper(item.id);
+                self.visit_node_helper(item.hir_id);
             }
 
             hir::ItemKind::ForeignMod(ref foreign_mod) => {
                 for foreign_item in &foreign_mod.items {
                     if let hir::ForeignItemKind::Fn(..) = foreign_item.node {
-                        self.visit_node_helper(foreign_item.id);
+                        self.visit_node_helper(foreign_item.hir_id);
                     }
                 }
             }
@@ -107,21 +106,21 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for ConstraintContext<'a, 'tcx> {
 
     fn visit_trait_item(&mut self, trait_item: &hir::TraitItem) {
         if let hir::TraitItemKind::Method(..) = trait_item.node {
-            self.visit_node_helper(trait_item.id);
+            self.visit_node_helper(trait_item.hir_id);
         }
     }
 
     fn visit_impl_item(&mut self, impl_item: &hir::ImplItem) {
         if let hir::ImplItemKind::Method(..) = impl_item.node {
-            self.visit_node_helper(impl_item.id);
+            self.visit_node_helper(impl_item.hir_id);
         }
     }
 }
 
 impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
-    fn visit_node_helper(&mut self, id: ast::NodeId) {
+    fn visit_node_helper(&mut self, id: hir::HirId) {
         let tcx = self.terms_cx.tcx;
-        let def_id = tcx.hir().local_def_id(id);
+        let def_id = tcx.hir().local_def_id_from_hir_id(id);
         self.build_constraints_for_item(def_id);
     }
 
@@ -138,7 +137,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
             return;
         }
 
-        let id = tcx.hir().as_local_node_id(def_id).unwrap();
+        let id = tcx.hir().as_local_hir_id(def_id).unwrap();
         let inferred_start = self.terms_cx.inferred_starts[&id];
         let current_item = &CurrentItem { inferred_start };
         match tcx.type_of(def_id).sty {
@@ -356,7 +355,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
             return;
         }
 
-        let (local, remote) = if let Some(id) = self.tcx().hir().as_local_node_id(def_id) {
+        let (local, remote) = if let Some(id) = self.tcx().hir().as_local_hir_id(def_id) {
             (Some(self.terms_cx.inferred_starts[&id]), None)
         } else {
             (None, Some(self.tcx().variances_of(def_id)))
diff --git a/src/librustc_typeck/variance/solve.rs b/src/librustc_typeck/variance/solve.rs
index f962c1313a9..cec33ba87de 100644
--- a/src/librustc_typeck/variance/solve.rs
+++ b/src/librustc_typeck/variance/solve.rs
@@ -83,7 +83,7 @@ impl<'a, 'tcx> SolveContext<'a, 'tcx> {
 
         let solutions = &self.solutions;
         self.terms_cx.inferred_starts.iter().map(|(&id, &InferredIndex(start))| {
-            let def_id = tcx.hir().local_def_id(id);
+            let def_id = tcx.hir().local_def_id_from_hir_id(id);
             let generics = tcx.generics_of(def_id);
 
             let mut variances = solutions[start..start+generics.count()].to_vec();
diff --git a/src/librustc_typeck/variance/terms.rs b/src/librustc_typeck/variance/terms.rs
index 4e562992e8c..e564a8658fc 100644
--- a/src/librustc_typeck/variance/terms.rs
+++ b/src/librustc_typeck/variance/terms.rs
@@ -12,10 +12,9 @@
 use arena::TypedArena;
 use rustc::ty::{self, TyCtxt};
 use std::fmt;
-use syntax::ast;
 use rustc::hir;
 use rustc::hir::itemlikevisit::ItemLikeVisitor;
-use crate::util::nodemap::NodeMap;
+use crate::util::nodemap::HirIdMap;
 
 use self::VarianceTerm::*;
 
@@ -55,11 +54,11 @@ pub struct TermsContext<'a, 'tcx: 'a> {
     // For marker types, UnsafeCell, and other lang items where
     // variance is hardcoded, records the item-id and the hardcoded
     // variance.
-    pub lang_items: Vec<(ast::NodeId, Vec<ty::Variance>)>,
+    pub lang_items: Vec<(hir::HirId, Vec<ty::Variance>)>,
 
     // Maps from the node id of an item to the first inferred index
     // used for its type & region parameters.
-    pub inferred_starts: NodeMap<InferredIndex>,
+    pub inferred_starts: HirIdMap<InferredIndex>,
 
     // Maps from an InferredIndex to the term for that variable.
     pub inferred_terms: Vec<VarianceTermPtr<'a>>,
@@ -86,7 +85,7 @@ pub fn determine_parameters_to_be_inferred<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>
     terms_cx
 }
 
-fn lang_items(tcx: TyCtxt<'_, '_, '_>) -> Vec<(ast::NodeId, Vec<ty::Variance>)> {
+fn lang_items(tcx: TyCtxt<'_, '_, '_>) -> Vec<(hir::HirId, Vec<ty::Variance>)> {
     let lang_items = tcx.lang_items();
     let all = vec![
         (lang_items.phantom_data(), vec![ty::Covariant]),
@@ -96,14 +95,14 @@ fn lang_items(tcx: TyCtxt<'_, '_, '_>) -> Vec<(ast::NodeId, Vec<ty::Variance>)>
     all.into_iter() // iterating over (Option<DefId>, Variance)
        .filter(|&(ref d,_)| d.is_some())
        .map(|(d, v)| (d.unwrap(), v)) // (DefId, Variance)
-       .filter_map(|(d, v)| tcx.hir().as_local_node_id(d).map(|n| (n, v))) // (NodeId, Variance)
+       .filter_map(|(d, v)| tcx.hir().as_local_hir_id(d).map(|n| (n, v))) // (HirId, Variance)
        .collect()
 }
 
 impl<'a, 'tcx> TermsContext<'a, 'tcx> {
-    fn add_inferreds_for_item(&mut self, id: ast::NodeId) {
+    fn add_inferreds_for_item(&mut self, id: hir::HirId) {
         let tcx = self.tcx;
-        let def_id = tcx.hir().local_def_id(id);
+        let def_id = tcx.hir().local_def_id_from_hir_id(id);
         let count = tcx.generics_of(def_id).count();
 
         if count == 0 {
@@ -134,31 +133,31 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for TermsContext<'a, 'tcx> {
         match item.node {
             hir::ItemKind::Struct(ref struct_def, _) |
             hir::ItemKind::Union(ref struct_def, _) => {
-                self.add_inferreds_for_item(item.id);
+                self.add_inferreds_for_item(item.hir_id);
 
                 if let hir::VariantData::Tuple(..) = *struct_def {
-                    self.add_inferreds_for_item(struct_def.id());
+                    self.add_inferreds_for_item(struct_def.hir_id());
                 }
             }
 
             hir::ItemKind::Enum(ref enum_def, _) => {
-                self.add_inferreds_for_item(item.id);
+                self.add_inferreds_for_item(item.hir_id);
 
                 for variant in &enum_def.variants {
                     if let hir::VariantData::Tuple(..) = variant.node.data {
-                        self.add_inferreds_for_item(variant.node.data.id());
+                        self.add_inferreds_for_item(variant.node.data.hir_id());
                     }
                 }
             }
 
             hir::ItemKind::Fn(..) => {
-                self.add_inferreds_for_item(item.id);
+                self.add_inferreds_for_item(item.hir_id);
             }
 
             hir::ItemKind::ForeignMod(ref foreign_mod) => {
                 for foreign_item in &foreign_mod.items {
                     if let hir::ForeignItemKind::Fn(..) = foreign_item.node {
-                        self.add_inferreds_for_item(foreign_item.id);
+                        self.add_inferreds_for_item(foreign_item.hir_id);
                     }
                 }
             }
@@ -169,13 +168,13 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for TermsContext<'a, 'tcx> {
 
     fn visit_trait_item(&mut self, trait_item: &hir::TraitItem) {
         if let hir::TraitItemKind::Method(..) = trait_item.node {
-            self.add_inferreds_for_item(trait_item.id);
+            self.add_inferreds_for_item(trait_item.hir_id);
         }
     }
 
     fn visit_impl_item(&mut self, impl_item: &hir::ImplItem) {
         if let hir::ImplItemKind::Method(..) = impl_item.node {
-            self.add_inferreds_for_item(impl_item.id);
+            self.add_inferreds_for_item(impl_item.hir_id);
         }
     }
 }
diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs
index 952541bb85f..d07a4579ad5 100644
--- a/src/librustdoc/clean/auto_trait.rs
+++ b/src/librustdoc/clean/auto_trait.rs
@@ -115,7 +115,6 @@ impl<'a, 'tcx, 'rcx> AutoTraitFinder<'a, 'tcx, 'rcx> {
         if result.is_auto() {
             let trait_ = hir::TraitRef {
                 path: get_path_for_type(self.cx.tcx, trait_def_id, hir::def::Def::Trait),
-                ref_id: ast::DUMMY_NODE_ID,
                 hir_ref_id: hir::DUMMY_HIR_ID,
             };
 
diff --git a/src/librustdoc/clean/blanket_impl.rs b/src/librustdoc/clean/blanket_impl.rs
index 55abcb4a93b..5a13490eecc 100644
--- a/src/librustdoc/clean/blanket_impl.rs
+++ b/src/librustdoc/clean/blanket_impl.rs
@@ -123,7 +123,6 @@ impl<'a, 'tcx, 'rcx> BlanketImplFinder <'a, 'tcx, 'rcx> {
                             path: get_path_for_type(infcx.tcx,
                                                     trait_def_id,
                                                     hir::def::Def::Trait),
-                            ref_id: ast::DUMMY_NODE_ID,
                             hir_ref_id: hir::DUMMY_HIR_ID,
                         };
                         let provided_trait_methods =
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 53dcc258c69..d88d0dab4f0 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -2022,14 +2022,15 @@ impl Clean<Item> for hir::TraitItem {
                 AssociatedTypeItem(bounds.clean(cx), default.clean(cx))
             }
         };
+        let local_did = cx.tcx.hir().local_def_id_from_hir_id(self.hir_id);
         Item {
             name: Some(self.ident.name.clean(cx)),
             attrs: self.attrs.clean(cx),
             source: self.span.clean(cx),
-            def_id: cx.tcx.hir().local_def_id(self.id),
+            def_id: local_did,
             visibility: None,
-            stability: get_stability(cx, cx.tcx.hir().local_def_id(self.id)),
-            deprecation: get_deprecation(cx, cx.tcx.hir().local_def_id(self.id)),
+            stability: get_stability(cx, local_did),
+            deprecation: get_deprecation(cx, local_did),
             inner,
         }
     }
@@ -2054,14 +2055,15 @@ impl Clean<Item> for hir::ImplItem {
                 generics: Generics::default(),
             }, true),
         };
+        let local_did = cx.tcx.hir().local_def_id_from_hir_id(self.hir_id);
         Item {
             name: Some(self.ident.name.clean(cx)),
             source: self.span.clean(cx),
             attrs: self.attrs.clean(cx),
-            def_id: cx.tcx.hir().local_def_id(self.id),
+            def_id: local_did,
             visibility: self.vis.clean(cx),
-            stability: get_stability(cx, cx.tcx.hir().local_def_id(self.id)),
-            deprecation: get_deprecation(cx, cx.tcx.hir().local_def_id(self.id)),
+            stability: get_stability(cx, local_did),
+            deprecation: get_deprecation(cx, local_did),
             inner,
         }
     }
@@ -2531,7 +2533,7 @@ impl Clean<Type> for hir::Ty {
             }
             TyKind::Slice(ref ty) => Slice(box ty.clean(cx)),
             TyKind::Array(ref ty, ref length) => {
-                let def_id = cx.tcx.hir().local_def_id(length.id);
+                let def_id = cx.tcx.hir().local_def_id_from_hir_id(length.hir_id);
                 let param_env = cx.tcx.param_env(def_id);
                 let substs = InternalSubsts::identity_for_item(cx.tcx, def_id);
                 let cid = GlobalId {
diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs
index 67f291285c4..25c86b24c18 100644
--- a/src/librustdoc/passes/collect_intra_doc_links.rs
+++ b/src/librustdoc/passes/collect_intra_doc_links.rs
@@ -473,9 +473,9 @@ fn resolution_failure(
 ) {
     let sp = span_of_attrs(attrs);
 
-    let mut diag = cx.tcx.struct_span_lint_node(
+    let mut diag = cx.tcx.struct_span_lint_hir(
         lint::builtin::INTRA_DOC_LINK_RESOLUTION_FAILURE,
-        NodeId::from_u32(0),
+        hir::CRATE_HIR_ID,
         sp,
         &format!("`[{}]` cannot be resolved, ignoring it...", path_str),
     );
diff --git a/src/librustdoc/passes/mod.rs b/src/librustdoc/passes/mod.rs
index 3a9d8ef20ce..d6f3585a04f 100644
--- a/src/librustdoc/passes/mod.rs
+++ b/src/librustdoc/passes/mod.rs
@@ -1,12 +1,12 @@
 //! Contains information about "passes", used to modify crate information during the documentation
 //! process.
 
+use rustc::hir;
 use rustc::hir::def_id::DefId;
 use rustc::lint as lint;
 use rustc::middle::privacy::AccessLevels;
 use rustc::util::nodemap::DefIdSet;
 use std::mem;
-use syntax::ast::NodeId;
 use syntax_pos::{DUMMY_SP, Span};
 use std::ops::Range;
 
@@ -312,18 +312,18 @@ pub fn look_for_tests<'a, 'tcx: 'a, 'rcx: 'a>(
 
     if find_testable_code(&dox, &mut tests, ErrorCodes::No).is_ok() {
         if check_missing_code == true && tests.found_tests == 0 {
-            let mut diag = cx.tcx.struct_span_lint_node(
+            let mut diag = cx.tcx.struct_span_lint_hir(
                 lint::builtin::MISSING_DOC_CODE_EXAMPLES,
-                NodeId::from_u32(0),
+                hir::CRATE_HIR_ID,
                 span_of_attrs(&item.attrs),
                 "Missing code example in this documentation");
             diag.emit();
         } else if check_missing_code == false &&
                   tests.found_tests > 0 &&
                   !cx.renderinfo.borrow().access_levels.is_doc_reachable(item.def_id) {
-            let mut diag = cx.tcx.struct_span_lint_node(
+            let mut diag = cx.tcx.struct_span_lint_hir(
                 lint::builtin::PRIVATE_DOC_TESTS,
-                NodeId::from_u32(0),
+                hir::CRATE_HIR_ID,
                 span_of_attrs(&item.attrs),
                 "Documentation test in private item");
             diag.emit();
diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs
index 5c7fb1b8044..ea821a1d939 100644
--- a/src/libtest/lib.rs
+++ b/src/libtest/lib.rs
@@ -366,6 +366,7 @@ pub struct TestOpts {
     pub list: bool,
     pub filter: Option<String>,
     pub filter_exact: bool,
+    pub exclude_should_panic: bool,
     pub run_ignored: RunIgnored,
     pub run_tests: bool,
     pub bench_benchmarks: bool,
@@ -385,6 +386,7 @@ impl TestOpts {
             list: false,
             filter: None,
             filter_exact: false,
+            exclude_should_panic: false,
             run_ignored: RunIgnored::No,
             run_tests: false,
             bench_benchmarks: false,
@@ -406,6 +408,7 @@ fn optgroups() -> getopts::Options {
     let mut opts = getopts::Options::new();
     opts.optflag("", "include-ignored", "Run ignored and not ignored tests")
         .optflag("", "ignored", "Run only ignored tests")
+        .optflag("", "exclude-should-panic", "Excludes tests marked as should_panic")
         .optflag("", "test", "Run tests and not benchmarks")
         .optflag("", "bench", "Run benchmarks instead of tests")
         .optflag("", "list", "List all tests and benchmarks")
@@ -558,6 +561,13 @@ pub fn parse_opts(args: &[String]) -> Option<OptRes> {
         None
     };
 
+    let exclude_should_panic = matches.opt_present("exclude-should-panic");
+    if !allow_unstable && exclude_should_panic {
+        return Some(Err(
+            "The \"exclude-should-panic\" flag is only accepted on the nightly compiler".into(),
+        ));
+    }
+
     let include_ignored = matches.opt_present("include-ignored");
     if !allow_unstable && include_ignored {
         return Some(Err(
@@ -648,6 +658,7 @@ pub fn parse_opts(args: &[String]) -> Option<OptRes> {
         list,
         filter,
         filter_exact: exact,
+        exclude_should_panic,
         run_ignored,
         run_tests,
         bench_benchmarks,
@@ -1365,6 +1376,11 @@ pub fn filter_tests(opts: &TestOpts, tests: Vec<TestDescAndFn>) -> Vec<TestDescA
     // Skip tests that match any of the skip filters
     filtered.retain(|test| !opts.skip.iter().any(|sf| matches_filter(test, sf)));
 
+    // Excludes #[should_panic] tests
+    if opts.exclude_should_panic {
+        filtered.retain(|test| test.desc.should_panic == ShouldPanic::No);
+    }
+
     // maybe unignore tests
     match opts.run_ignored {
         RunIgnored::Yes => {
@@ -1984,6 +2000,29 @@ mod tests {
     }
 
     #[test]
+    pub fn exclude_should_panic_option() {
+        let mut opts = TestOpts::new();
+        opts.run_tests = true;
+        opts.exclude_should_panic = true;
+
+        let mut tests = one_ignored_one_unignored_test();
+        tests.push(TestDescAndFn {
+            desc: TestDesc {
+                name: StaticTestName("3"),
+                ignore: false,
+                should_panic: ShouldPanic::Yes,
+                allow_fail: false,
+            },
+            testfn: DynTestFn(Box::new(move || {})),
+        });
+
+        let filtered = filter_tests(&opts, tests);
+
+        assert_eq!(filtered.len(), 2);
+        assert!(filtered.iter().all(|test| test.desc.should_panic == ShouldPanic::No));
+    }
+
+    #[test]
     pub fn exact_filter_match() {
         fn tests() -> Vec<TestDescAndFn> {
             vec!["base", "base::test", "base::test1", "base::test2"]
diff --git a/src/test/ui-fulldeps/auxiliary/lint_tool_test.rs b/src/test/ui-fulldeps/auxiliary/lint_tool_test.rs
index 1a9bd9e66db..d25a5ea3746 100644
--- a/src/test/ui-fulldeps/auxiliary/lint_tool_test.rs
+++ b/src/test/ui-fulldeps/auxiliary/lint_tool_test.rs
@@ -13,7 +13,11 @@ use rustc::lint::{EarlyContext, LintContext, LintPass, EarlyLintPass,
 use rustc_plugin::Registry;
 use syntax::ast;
 declare_tool_lint!(pub clippy::TEST_LINT, Warn, "Warn about stuff");
-declare_tool_lint!(pub clippy::TEST_GROUP, Warn, "Warn about other stuff");
+declare_tool_lint!(
+    /// Some docs
+    pub clippy::TEST_GROUP,
+    Warn, "Warn about other stuff"
+);
 
 struct Pass;
 
diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs
index 94dd5478e52..0169725fa29 100644
--- a/src/tools/tidy/src/deps.rs
+++ b/src/tools/tidy/src/deps.rs
@@ -49,13 +49,13 @@ const EXCEPTIONS: &[&str] = &[
 ];
 
 /// Which crates to check against the whitelist?
-const WHITELIST_CRATES: &[CrateVersion] = &[
+const WHITELIST_CRATES: &[CrateVersion<'_>] = &[
     CrateVersion("rustc", "0.0.0"),
     CrateVersion("rustc_codegen_llvm", "0.0.0"),
 ];
 
 /// Whitelist of crates rustc is allowed to depend on. Avoid adding to the list if possible.
-const WHITELIST: &[Crate] = &[
+const WHITELIST: &[Crate<'_>] = &[
     Crate("adler32"),
     Crate("aho-corasick"),
     Crate("arrayvec"),
@@ -183,7 +183,7 @@ struct Crate<'a>(&'a str); // (name)
 #[derive(Copy, Clone, PartialOrd, Ord, PartialEq, Eq, Debug, Hash)]
 struct CrateVersion<'a>(&'a str, &'a str); // (name, version)
 
-impl<'a> Crate<'a> {
+impl Crate<'_> {
     pub fn id_str(&self) -> String {
         format!("{} ", self.0)
     }
@@ -330,10 +330,10 @@ fn get_deps(path: &Path, cargo: &Path) -> Resolve {
 
 /// Checks the dependencies of the given crate from the given cargo metadata to see if they are on
 /// the whitelist. Returns a list of illegal dependencies.
-fn check_crate_whitelist<'a, 'b>(
-    whitelist: &'a HashSet<Crate>,
+fn check_crate_whitelist<'a>(
+    whitelist: &'a HashSet<Crate<'_>>,
     resolve: &'a Resolve,
-    visited: &'b mut BTreeSet<CrateVersion<'a>>,
+    visited: &mut BTreeSet<CrateVersion<'a>>,
     krate: CrateVersion<'a>,
     must_be_on_whitelist: bool,
 ) -> BTreeSet<Crate<'a>> {
diff --git a/src/tools/tidy/src/features.rs b/src/tools/tidy/src/features.rs
index 7126c0c2f6e..1eab217027c 100644
--- a/src/tools/tidy/src/features.rs
+++ b/src/tools/tidy/src/features.rs
@@ -22,7 +22,7 @@ pub enum Status {
 }
 
 impl fmt::Display for Status {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         let as_str = match *self {
             Status::Stable => "stable",
             Status::Unstable => "unstable",
diff --git a/src/tools/tidy/src/lib.rs b/src/tools/tidy/src/lib.rs
index 022c53f909c..c4a1246ffdf 100644
--- a/src/tools/tidy/src/lib.rs
+++ b/src/tools/tidy/src/lib.rs
@@ -3,7 +3,8 @@
 //! This library contains the tidy lints and exposes it
 //! to be used by tools.
 
-extern crate serde;
+#![deny(rust_2018_idioms)]
+
 extern crate serde_json;
 #[macro_use]
 extern crate serde_derive;