diff --git a/.mailmap b/.mailmap
index 63a49cd413287..2d5759b539e5d 100644
--- a/.mailmap
+++ b/.mailmap
@@ -6,7 +6,7 @@
 #
 
 Aaron Todd <github@opprobrio.us>
-Aaron Power <theaaronepower@gmail.com>
+Aaron Power <theaaronepower@gmail.com> Erin Power <xampprocky@gmail.com>
 Abhishek Chanda <abhishek.becs@gmail.com> Abhishek Chanda <abhishek@cloudscaling.com>
 Adolfo Ochagavía <aochagavia92@gmail.com>
 Adrien Tétar <adri-from-59@hotmail.fr>
diff --git a/Cargo.lock b/Cargo.lock
index 392f3e8e4bdce..bb2b69be9490f 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -253,7 +253,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "cargo"
-version = "0.37.0"
+version = "0.38.0"
 dependencies = [
  "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
  "bufstream 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -261,7 +261,7 @@ dependencies = [
  "bytesize 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "core-foundation 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "crates-io 0.25.0",
+ "crates-io 0.26.0",
  "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "crypto-hash 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "curl 0.4.21 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -278,7 +278,7 @@ dependencies = [
  "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "home 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "ignore 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)",
- "im-rc 12.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "im-rc 13.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "jobserver 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -300,6 +300,7 @@ dependencies = [
  "serde_ignored 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)",
  "shell-escape 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "strip-ansi-escapes 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "tar 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)",
  "tempfile 3.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -537,7 +538,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "crates-io"
-version = "0.25.0"
+version = "0.26.0"
 dependencies = [
  "curl 0.4.21 (registry+https://github.com/rust-lang/crates.io-index)",
  "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1163,10 +1164,11 @@ dependencies = [
 
 [[package]]
 name = "im-rc"
-version = "12.3.0"
+version = "13.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "sized-chunks 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -2239,7 +2241,7 @@ dependencies = [
 name = "rls"
 version = "1.36.0"
 dependencies = [
- "cargo 0.37.0",
+ "cargo 0.38.0",
  "cargo_metadata 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "clippy_lints 0.0.212",
  "crossbeam-channel 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2996,6 +2998,7 @@ dependencies = [
  "rustc_cratesio_shim 0.0.0",
  "rustc_data_structures 0.0.0",
  "serialize 0.0.0",
+ "syntax_pos 0.0.0",
 ]
 
 [[package]]
@@ -3263,6 +3266,14 @@ name = "siphasher"
 version = "0.2.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
+[[package]]
+name = "sized-chunks"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "slab"
 version = "0.4.2"
@@ -3348,6 +3359,14 @@ name = "string_cache_shared"
 version = "0.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
+[[package]]
+name = "strip-ansi-escapes"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "vte 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "strsim"
 version = "0.7.0"
@@ -3924,6 +3943,11 @@ name = "utf8-ranges"
 version = "1.0.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
+[[package]]
+name = "utf8parse"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
 [[package]]
 name = "vcpkg"
 version = "0.2.6"
@@ -3954,6 +3978,14 @@ name = "void"
 version = "1.0.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
+[[package]]
+name = "vte"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "utf8parse 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "wait-timeout"
 version = "0.1.5"
@@ -4158,7 +4190,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e"
 "checksum if_chain 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4bac95d9aa0624e7b78187d6fb8ab012b41d9f6f54b1bcb61e61c4845f8357ec"
 "checksum ignore 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "8dc57fa12805f367736a38541ac1a9fc6a52812a0ca959b1d4d4b640a89eb002"
-"checksum im-rc 12.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9460397452f537fd51808056ff209f4c4c4c9d20d42ae952f517708726284972"
+"checksum im-rc 13.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0a0197597d095c0d11107975d3175173f810ee572c2501ff4de64f4f3f119806"
 "checksum iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dbe6e417e7d0975db6512b90796e8ce223145ac4e33c377e4a42882a0e88bb08"
 "checksum is-match 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7e5b386aef33a1c677be65237cb9d32c3f3ef56bd035949710c4bb13083eb053"
 "checksum itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)" = "f58856976b776fedd95533137617a02fb25719f40e7d9b01c7043cd65474f450"
@@ -4309,6 +4341,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum shlex 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7fdf1b9db47230893d76faad238fd6097fd6d6a9245cd7a4d90dbd639536bbd2"
 "checksum signal-hook 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "1f272d1b7586bec132ed427f532dd418d8beca1ca7f2caf7df35569b1415a4b4"
 "checksum siphasher 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0df90a788073e8d0235a67e50441d47db7c8ad9debd91cbf43736a2a92d36537"
+"checksum sized-chunks 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a2a2eb3fe454976eefb479f78f9b394d34d661b647c6326a3a6e66f68bb12c26"
 "checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8"
 "checksum smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)" = "b73ea3738b47563803ef814925e69be00799a8c07420be8b996f8e98fb2336db"
 "checksum socket2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "c4d11a52082057d87cb5caa31ad812f4504b97ab44732cd8359df2e9ff9f48e7"
@@ -4316,6 +4349,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum string_cache 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "25d70109977172b127fe834e5449e5ab1740b9ba49fa18a2020f509174f25423"
 "checksum string_cache_codegen 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1eea1eee654ef80933142157fdad9dd8bc43cf7c74e999e369263496f04ff4da"
 "checksum string_cache_shared 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b1884d1bc09741d466d9b14e6d37ac89d6909cbcac41dd9ae982d4d063bbedfc"
+"checksum strip-ansi-escapes 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9d63676e2abafa709460982ddc02a3bb586b6d15a49b75c212e06edd3933acee"
 "checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550"
 "checksum strum 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f6c3a2071519ab6a48f465808c4c1ffdd00dfc8e93111d02b4fc5abab177676e"
 "checksum strum_macros 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8baacebd7b7c9b864d83a6ba7a246232983e277b86fa5cdec77f565715a4b136"
@@ -4368,11 +4402,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum url_serde 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "74e7d099f1ee52f823d4bdd60c93c3602043c728f5db3b97bdb548467f7bddea"
 "checksum utf-8 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f1262dfab4c30d5cb7c07026be00ee343a6cf5027fdc0104a9160f354e5db75c"
 "checksum utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "796f7e48bef87609f7ade7e06495a87d5cd06c7866e6a5cbfceffc558a243737"
+"checksum utf8parse 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8772a4ccbb4e89959023bc5b7cb8623a795caa7092d99f3aa9501b9484d4557d"
 "checksum vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "def296d3eb3b12371b2c7d0e83bfe1403e4db2d7a0bba324a12b21c4ee13143d"
 "checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a"
 "checksum vergen 3.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "6aba5e34f93dc7051dfad05b98a18e9156f27e7b431fe1d2398cb6061c0a1dba"
 "checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd"
 "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
+"checksum vte 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4f42f536e22f7fcbb407639765c8fd78707a33109301f834a594758bedd6e8cf"
 "checksum wait-timeout 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "b9f3bf741a801531993db6478b95682117471f76916f5e690dd8d45395b09349"
 "checksum walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "9d9d7ed3431229a144296213105a390676cc49c9b6a72bd19f3176c98e129fa1"
 "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
diff --git a/README.md b/README.md
index 75d7823490a20..b522b161ecf93 100644
--- a/README.md
+++ b/README.md
@@ -134,9 +134,8 @@ MSVC builds of Rust additionally require an installation of Visual Studio 2017
 
 [Visual Studio Build Tools]: https://visualstudio.microsoft.com/downloads/#build-tools-for-visual-studio-2019
 
-At last check (cmake 3.14.3 and msvc 16.0.3) using the 2019 tools fails to
-build the in-tree LLVM build with a CMake error, so use 2017 instead by
-including the “MSVC v141 – VS 2017 C++ x64/x86 build tools (v14.16)” component.
+(If you're installing cmake yourself, be careful that “C++ CMake tools for
+Windows” doesn't get included under “Individual components”.)
 
 With these dependencies installed, you can build the compiler in a `cmd.exe`
 shell with:
@@ -151,7 +150,7 @@ then you may need to force rustbuild to use an older version. This can be done
 by manually calling the appropriate vcvars file before running the bootstrap.
 
 ```batch
-> CALL "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\amd64\vcvars64.bat"
+> CALL "C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Auxiliary\Build\vcvars64.bat"
 > python x.py build
 ```
 
diff --git a/appveyor.yml b/appveyor.yml
index c35da8927ce93..6dc33f30c7e2b 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -104,7 +104,7 @@ environment:
     DEPLOY: 1
   - CI_JOB_NAME: dist-i686-mingw
     MSYS_BITS: 32
-    RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu --enable-full-tools
+    RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu --enable-full-tools --enable-profiler
     SCRIPT: python x.py dist
     MINGW_URL: https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror
     MINGW_ARCHIVE: i686-6.3.0-release-posix-dwarf-rt_v5-rev2.7z
@@ -114,7 +114,7 @@ environment:
   - CI_JOB_NAME: dist-x86_64-mingw
     MSYS_BITS: 64
     SCRIPT: python x.py dist
-    RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu --enable-full-tools
+    RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu --enable-full-tools --enable-profiler
     MINGW_URL: https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror
     MINGW_ARCHIVE: x86_64-6.3.0-release-posix-seh-rt_v5-rev2.7z
     MINGW_DIR: mingw64
diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs
index da2e03a1a0848..b89cd4981a721 100644
--- a/src/bootstrap/native.rs
+++ b/src/bootstrap/native.rs
@@ -204,7 +204,7 @@ impl Step for Llvm {
         }
 
         if want_lldb {
-            cfg.define("LLVM_ENABLE_PROJECTS", "clang;lldb");
+            cfg.define("LLVM_ENABLE_PROJECTS", "clang;lldb;compiler-rt");
             // For the time being, disable code signing.
             cfg.define("LLDB_CODESIGN_IDENTITY", "");
             cfg.define("LLDB_NO_DEBUGSERVER", "ON");
diff --git a/src/ci/docker/x86_64-gnu-tools/checktools.sh b/src/ci/docker/x86_64-gnu-tools/checktools.sh
index a0fe307cffcdb..af0198705a2fe 100755
--- a/src/ci/docker/x86_64-gnu-tools/checktools.sh
+++ b/src/ci/docker/x86_64-gnu-tools/checktools.sh
@@ -74,9 +74,7 @@ status_check() {
     check_dispatch $1 beta nomicon src/doc/nomicon
     check_dispatch $1 beta reference src/doc/reference
     check_dispatch $1 beta rust-by-example src/doc/rust-by-example
-    # Temporarily disabled until
-    # https://github.com/rust-lang/rust/issues/60459 is fixed.
-    # check_dispatch $1 beta edition-guide src/doc/edition-guide
+    check_dispatch $1 beta edition-guide src/doc/edition-guide
     check_dispatch $1 beta rls src/tools/rls
     check_dispatch $1 beta rustfmt src/tools/rustfmt
     check_dispatch $1 beta clippy-driver src/tools/clippy
diff --git a/src/doc/rustc/src/lints/listing/warn-by-default.md b/src/doc/rustc/src/lints/listing/warn-by-default.md
index ba927b1ef3b57..f090f142c0816 100644
--- a/src/doc/rustc/src/lints/listing/warn-by-default.md
+++ b/src/doc/rustc/src/lints/listing/warn-by-default.md
@@ -529,18 +529,21 @@ This lint detects bounds in type aliases. These are not currently enforced.
 Some example code that triggers this lint:
 
 ```rust
+#[allow(dead_code)]
 type SendVec<T: Send> = Vec<T>;
 ```
 
 This will produce:
 
 ```text
-warning: type alias is never used: `SendVec`
- --> src/main.rs:1:1
+warning: bounds on generic parameters are not enforced in type aliases
+ --> src/lib.rs:2:17
   |
-1 | type SendVec<T: Send> = Vec<T>;
-  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+2 | type SendVec<T: Send> = Vec<T>;
+  |                 ^^^^
   |
+  = note: #[warn(type_alias_bounds)] on by default
+  = help: the bound will not be checked when the type alias is used, and should be removed
 ```
 
 ## tyvar-behind-raw-pointer
diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs
index 97c2d8e7a8e79..bf8f5b8b91a1e 100644
--- a/src/liballoc/boxed.rs
+++ b/src/liballoc/boxed.rs
@@ -759,13 +759,14 @@ impl<A, F: Fn<A> + ?Sized> Fn<A> for Box<F> {
     }
 }
 
+/// `FnBox` is deprecated and will be removed.
+/// `Box<dyn FnOnce()>` can be called directly, since Rust 1.35.0.
+///
 /// `FnBox` is a version of the `FnOnce` intended for use with boxed
-/// closure objects. The idea is that where one would normally store a
-/// `Box<dyn FnOnce()>` in a data structure, you should use
+/// closure objects. The idea was that where one would normally store a
+/// `Box<dyn FnOnce()>` in a data structure, you whould use
 /// `Box<dyn FnBox()>`. The two traits behave essentially the same, except
-/// that a `FnBox` closure can only be called if it is boxed. (Note
-/// that `FnBox` may be deprecated in the future if `Box<dyn FnOnce()>`
-/// closures become directly usable.)
+/// that a `FnBox` closure can only be called if it is boxed.
 ///
 /// # Examples
 ///
@@ -777,6 +778,7 @@ impl<A, F: Fn<A> + ?Sized> Fn<A> for Box<F> {
 ///
 /// ```
 /// #![feature(fnbox)]
+/// #![allow(deprecated)]
 ///
 /// use std::boxed::FnBox;
 /// use std::collections::HashMap;
@@ -796,16 +798,38 @@ impl<A, F: Fn<A> + ?Sized> Fn<A> for Box<F> {
 ///     }
 /// }
 /// ```
+///
+/// In Rust 1.35.0 or later, use `FnOnce`, `FnMut`, or `Fn` instead:
+///
+/// ```
+/// use std::collections::HashMap;
+///
+/// fn make_map() -> HashMap<i32, Box<dyn FnOnce() -> i32>> {
+///     let mut map: HashMap<i32, Box<dyn FnOnce() -> i32>> = HashMap::new();
+///     map.insert(1, Box::new(|| 22));
+///     map.insert(2, Box::new(|| 44));
+///     map
+/// }
+///
+/// fn main() {
+///     let mut map = make_map();
+///     for i in &[1, 2] {
+///         let f = map.remove(&i).unwrap();
+///         assert_eq!(f(), i * 22);
+///     }
+/// }
+/// ```
 #[rustc_paren_sugar]
-#[unstable(feature = "fnbox",
-           reason = "will be deprecated if and when `Box<FnOnce>` becomes usable", issue = "28796")]
+#[unstable(feature = "fnbox", issue = "28796")]
+#[rustc_deprecated(reason = "use `FnOnce`, `FnMut`, or `Fn` instead", since = "1.37.0")]
 pub trait FnBox<A>: FnOnce<A> {
     /// Performs the call operation.
     fn call_box(self: Box<Self>, args: A) -> Self::Output;
 }
 
-#[unstable(feature = "fnbox",
-           reason = "will be deprecated if and when `Box<FnOnce>` becomes usable", issue = "28796")]
+#[unstable(feature = "fnbox", issue = "28796")]
+#[rustc_deprecated(reason = "use `FnOnce`, `FnMut`, or `Fn` instead", since = "1.37.0")]
+#[allow(deprecated, deprecated_in_future)]
 impl<A, F> FnBox<A> for F
     where F: FnOnce<A>
 {
diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs
index 9672cf4ffed36..8034140903768 100644
--- a/src/libcore/cell.rs
+++ b/src/libcore/cell.rs
@@ -11,7 +11,7 @@
 //! mutate it.
 //!
 //! Shareable mutable containers exist to permit mutability in a controlled manner, even in the
-//! presence of aliasing. Both `Cell<T>` and `RefCell<T>` allows to do this in a single threaded
+//! presence of aliasing. Both `Cell<T>` and `RefCell<T>` allow doing this in a single-threaded
 //! way. However, neither `Cell<T>` nor `RefCell<T>` are thread safe (they do not implement
 //! `Sync`). If you need to do aliasing and mutation between multiple threads it is possible to
 //! use [`Mutex`](../../std/sync/struct.Mutex.html),
diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs
index 932c0eaa4c7b1..7ec75ed011488 100644
--- a/src/libcore/num/mod.rs
+++ b/src/libcore/num/mod.rs
@@ -473,6 +473,7 @@ assert_eq!(m, ", $reversed, ");
             #[unstable(feature = "reverse_bits", issue = "48763")]
             #[rustc_const_unstable(feature = "const_int_conversion")]
             #[inline]
+            #[must_use]
             pub const fn reverse_bits(self) -> Self {
                 (self as $UnsignedT).reverse_bits() as Self
             }
@@ -2522,6 +2523,7 @@ assert_eq!(m, ", $reversed, ");
 ```"),
             #[unstable(feature = "reverse_bits", issue = "48763")]
             #[inline]
+            #[must_use]
             pub const fn reverse_bits(self) -> Self {
                 intrinsics::bitreverse(self as $ActualT) as Self
             }
diff --git a/src/libcore/num/wrapping.rs b/src/libcore/num/wrapping.rs
index a3491bc3dc664..5eb5ec558f8c1 100644
--- a/src/libcore/num/wrapping.rs
+++ b/src/libcore/num/wrapping.rs
@@ -524,6 +524,7 @@ assert_eq!(n.trailing_zeros(), 3);
             /// ```
             #[unstable(feature = "reverse_bits", issue = "48763")]
             #[inline]
+            #[must_use]
             pub const fn reverse_bits(self) -> Self {
                 Wrapping(self.0.reverse_bits())
             }
diff --git a/src/libprofiler_builtins/build.rs b/src/libprofiler_builtins/build.rs
index 491986480deba..0b2bda577d75f 100644
--- a/src/libprofiler_builtins/build.rs
+++ b/src/libprofiler_builtins/build.rs
@@ -41,7 +41,11 @@ fn main() {
         cfg.flag("-fomit-frame-pointer");
         cfg.flag("-ffreestanding");
         cfg.define("VISIBILITY_HIDDEN", None);
-        cfg.define("COMPILER_RT_HAS_UNAME", Some("1"));
+        if !target.contains("windows") {
+            cfg.define("COMPILER_RT_HAS_UNAME", Some("1"));
+        } else {
+            profile_sources.push("WindowsMMap.c");
+        }
     }
 
     // Assume that the Unixes we are building this for have fnctl() available
diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs
index 3d83918bd0a66..1d51e7cd74222 100644
--- a/src/librustc/hir/lowering.rs
+++ b/src/librustc/hir/lowering.rs
@@ -1145,9 +1145,7 @@ impl<'a> LoweringContext<'a> {
         let unstable_span = self.sess.source_map().mark_span_with_reason(
             CompilerDesugaringKind::Async,
             span,
-            Some(vec![
-                Symbol::intern("gen_future"),
-            ].into()),
+            Some(vec![sym::gen_future].into()),
         );
         let gen_future = self.expr_std_path(
             unstable_span, &[sym::future, sym::from_generator], None, ThinVec::new());
@@ -2958,7 +2956,7 @@ impl<'a> LoweringContext<'a> {
             ident: match f.ident {
                 Some(ident) => ident,
                 // FIXME(jseyfried): positional field hygiene
-                None => Ident::new(Symbol::intern(&index.to_string()), f.span),
+                None => Ident::new(sym::integer(index), f.span),
             },
             vis: self.lower_visibility(&f.vis, None),
             ty: self.lower_ty(&f.ty, ImplTraitContext::disallowed()),
@@ -4177,9 +4175,7 @@ impl<'a> LoweringContext<'a> {
                     let unstable_span = this.sess.source_map().mark_span_with_reason(
                         CompilerDesugaringKind::TryBlock,
                         body.span,
-                        Some(vec![
-                            Symbol::intern("try_trait"),
-                        ].into()),
+                        Some(vec![sym::try_trait].into()),
                     );
                     let mut block = this.lower_block(body, true).into_inner();
                     let tail = block.expr.take().map_or_else(
diff --git a/src/librustc/hir/map/def_collector.rs b/src/librustc/hir/map/def_collector.rs
index bb9e76f026246..bde27c71f9a6d 100644
--- a/src/librustc/hir/map/def_collector.rs
+++ b/src/librustc/hir/map/def_collector.rs
@@ -5,8 +5,7 @@ use crate::session::CrateDisambiguator;
 use syntax::ast::*;
 use syntax::ext::hygiene::Mark;
 use syntax::visit;
-use syntax::symbol::kw;
-use syntax::symbol::Symbol;
+use syntax::symbol::{kw, sym};
 use syntax::parse::token::{self, Token};
 use syntax_pos::Span;
 
@@ -221,7 +220,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
                           _: &'a Generics, _: NodeId, _: Span) {
         for (index, field) in data.fields().iter().enumerate() {
             let name = field.ident.map(|ident| ident.name)
-                .unwrap_or_else(|| Symbol::intern(&index.to_string()));
+                .unwrap_or_else(|| sym::integer(index));
             let def = self.create_def(field.id,
                                       DefPathData::ValueNs(name.as_interned_str()),
                                       field.span);
diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs
index 103580a598fcd..034ef32aafe01 100644
--- a/src/librustc/middle/lang_items.rs
+++ b/src/librustc/middle/lang_items.rs
@@ -210,8 +210,8 @@ impl<'a, 'tcx> LanguageItemCollector<'a, 'tcx> {
 pub fn extract(attrs: &[ast::Attribute]) -> Option<(Symbol, Span)> {
     attrs.iter().find_map(|attr| Some(match attr {
         _ if attr.check_name(sym::lang) => (attr.value_str()?, attr.span),
-        _ if attr.check_name(sym::panic_handler) => (Symbol::intern("panic_impl"), attr.span),
-        _ if attr.check_name(sym::alloc_error_handler) => (Symbol::intern("oom"), attr.span),
+        _ if attr.check_name(sym::panic_handler) => (sym::panic_impl, attr.span),
+        _ if attr.check_name(sym::alloc_error_handler) => (sym::oom, attr.span),
         _ => return None,
     }))
 }
diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs
index c7f8cf684e6b1..6af43b04a7d60 100644
--- a/src/librustc/middle/mem_categorization.rs
+++ b/src/librustc/middle/mem_categorization.rs
@@ -1316,7 +1316,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
 
                 for (i, subpat) in subpats.iter().enumerate_and_adjust(expected_len, ddpos) {
                     let subpat_ty = self.pat_ty_adjusted(&subpat)?; // see (*2)
-                    let interior = InteriorField(FieldIndex(i, Name::intern(&i.to_string())));
+                    let interior = InteriorField(FieldIndex(i, sym::integer(i)));
                     let subcmt = Rc::new(
                         self.cat_imm_interior(pat, cmt.clone(), subpat_ty, interior));
                     self.cat_pattern_(subcmt, &subpat, op)?;
@@ -1363,7 +1363,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
                 };
                 for (i, subpat) in subpats.iter().enumerate_and_adjust(expected_len, ddpos) {
                     let subpat_ty = self.pat_ty_adjusted(&subpat)?; // see (*2)
-                    let interior = InteriorField(FieldIndex(i, Name::intern(&i.to_string())));
+                    let interior = InteriorField(FieldIndex(i, sym::integer(i)));
                     let subcmt = Rc::new(
                         self.cat_imm_interior(pat, cmt.clone(), subpat_ty, interior));
                     self.cat_pattern_(subcmt, &subpat, op)?;
diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs
index fa4e8e3d4769d..3d78b9b6382b7 100644
--- a/src/librustc/middle/region.rs
+++ b/src/librustc/middle/region.rs
@@ -658,12 +658,15 @@ impl<'tcx> ScopeTree {
             // The lifetime was defined on node that doesn't own a body,
             // which in practice can only mean a trait or an impl, that
             // is the parent of a method, and that is enforced below.
-            assert_eq!(Some(param_owner_id), self.root_parent,
-                       "free_scope: {:?} not recognized by the \
-                        region scope tree for {:?} / {:?}",
-                       param_owner,
-                       self.root_parent.map(|id| tcx.hir().local_def_id_from_hir_id(id)),
-                       self.root_body.map(|hir_id| DefId::local(hir_id.owner)));
+            if Some(param_owner_id) != self.root_parent {
+                tcx.sess.delay_span_bug(
+                    DUMMY_SP,
+                    &format!("free_scope: {:?} not recognized by the \
+                              region scope tree for {:?} / {:?}",
+                             param_owner,
+                             self.root_parent.map(|id| tcx.hir().local_def_id_from_hir_id(id)),
+                             self.root_body.map(|hir_id| DefId::local(hir_id.owner))));
+            }
 
             // The trait/impl lifetime is in scope for the method's body.
             self.root_body.unwrap().local_id
diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs
index ac0e99137cbc3..66fa9a5c6f106 100644
--- a/src/librustc/middle/stability.rs
+++ b/src/librustc/middle/stability.rs
@@ -437,7 +437,7 @@ impl<'a, 'tcx> Index<'tcx> {
                         reason: Some(Symbol::intern(reason)),
                         issue: 27812,
                     },
-                    feature: Symbol::intern("rustc_private"),
+                    feature: sym::rustc_private,
                     rustc_depr: None,
                     const_stability: None,
                     promotable: false,
@@ -880,7 +880,7 @@ pub fn check_unused_or_stable_features<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
     // FIXME: only remove `libc` when `stdbuild` is active.
     // FIXME: remove special casing for `test`.
     remaining_lib_features.remove(&Symbol::intern("libc"));
-    remaining_lib_features.remove(&Symbol::intern("test"));
+    remaining_lib_features.remove(&sym::test);
 
     let check_features =
         |remaining_lib_features: &mut FxHashMap<_, _>, defined_features: &[_]| {
diff --git a/src/librustc/mir/cache.rs b/src/librustc/mir/cache.rs
index 1cc927b1f720f..007013f8f8287 100644
--- a/src/librustc/mir/cache.rs
+++ b/src/librustc/mir/cache.rs
@@ -3,7 +3,7 @@ use rustc_data_structures::sync::{RwLock, MappedReadGuard, ReadGuard};
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher,
                                            StableHasherResult};
 use crate::ich::StableHashingContext;
-use crate::mir::{Mir, BasicBlock};
+use crate::mir::{Body, BasicBlock};
 
 use crate::rustc_serialize as serialize;
 
@@ -47,7 +47,7 @@ impl Cache {
 
     pub fn predecessors(
         &self,
-        mir: &Mir<'_>
+        mir: &Body<'_>
     ) -> MappedReadGuard<'_, IndexVec<BasicBlock, Vec<BasicBlock>>> {
         if self.predecessors.borrow().is_none() {
             *self.predecessors.borrow_mut() = Some(calculate_predecessors(mir));
@@ -57,7 +57,7 @@ impl Cache {
     }
 }
 
-fn calculate_predecessors(mir: &Mir<'_>) -> IndexVec<BasicBlock, Vec<BasicBlock>> {
+fn calculate_predecessors(mir: &Body<'_>) -> IndexVec<BasicBlock, Vec<BasicBlock>> {
     let mut result = IndexVec::from_elem(vec![], mir.basic_blocks());
     for (bb, data) in mir.basic_blocks().iter_enumerated() {
         if let Some(ref term) = data.terminator {
diff --git a/src/librustc/mir/interpret/pointer.rs b/src/librustc/mir/interpret/pointer.rs
index 59b7891b90fde..356c4cc16c23c 100644
--- a/src/librustc/mir/interpret/pointer.rs
+++ b/src/librustc/mir/interpret/pointer.rs
@@ -1,3 +1,5 @@
+use std::fmt;
+
 use crate::mir;
 use crate::ty::layout::{self, HasDataLayout, Size};
 use rustc_macros::HashStable;
@@ -70,7 +72,7 @@ impl<T: layout::HasDataLayout> PointerArithmetic for T {}
 ///
 /// Pointer is also generic over the `Tag` associated with each pointer,
 /// which is used to do provenance tracking during execution.
-#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd,
+#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd,
          RustcEncodable, RustcDecodable, Hash, HashStable)]
 pub struct Pointer<Tag=(),Id=AllocId> {
     pub alloc_id: Id,
@@ -80,6 +82,18 @@ pub struct Pointer<Tag=(),Id=AllocId> {
 
 static_assert_size!(Pointer, 16);
 
+impl<Tag: fmt::Debug, Id: fmt::Debug> fmt::Debug for Pointer<Tag, Id> {
+    default fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "{:?}.{:#x}[{:?}]", self.alloc_id, self.offset.bytes(), self.tag)
+    }
+}
+// Specialization for no tag
+impl<Id: fmt::Debug> fmt::Debug for Pointer<(), Id> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "{:?}.{:#x}", self.alloc_id, self.offset.bytes())
+    }
+}
+
 /// Produces a `Pointer` which points to the beginning of the Allocation
 impl From<AllocId> for Pointer {
     #[inline(always)]
diff --git a/src/librustc/mir/interpret/value.rs b/src/librustc/mir/interpret/value.rs
index 551b86390db4c..6b6f7f7a30740 100644
--- a/src/librustc/mir/interpret/value.rs
+++ b/src/librustc/mir/interpret/value.rs
@@ -93,7 +93,7 @@ impl<'tcx> ConstValue<'tcx> {
 /// `memory::Allocation`. It is in many ways like a small chunk of a `Allocation`, up to 8 bytes in
 /// size. Like a range of bytes in an `Allocation`, a `Scalar` can either represent the raw bytes
 /// of a simple value or a pointer into another `Allocation`
-#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd,
+#[derive(Clone, Copy, Eq, PartialEq, Ord, PartialOrd,
          RustcEncodable, RustcDecodable, Hash, HashStable)]
 pub enum Scalar<Tag=(), Id=AllocId> {
     /// The raw bytes of a simple value.
@@ -113,6 +113,27 @@ pub enum Scalar<Tag=(), Id=AllocId> {
 #[cfg(target_arch = "x86_64")]
 static_assert_size!(Scalar, 24);
 
+impl<Tag: fmt::Debug, Id: fmt::Debug> fmt::Debug for Scalar<Tag, Id> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        match self {
+            Scalar::Ptr(ptr) =>
+                write!(f, "{:?}", ptr),
+            &Scalar::Bits { bits, size } => {
+                if size == 0 {
+                    assert_eq!(bits, 0, "ZST value must be 0");
+                    write!(f, "<ZST>")
+                } else {
+                    assert_eq!(truncate(bits, Size::from_bytes(size as u64)), bits,
+                            "Scalar value {:#x} exceeds size of {} bytes", bits, size);
+                    // Format as hex number wide enough to fit any value of the given `size`.
+                    // So bits=20, size=1 will be "0x14", but with size=4 it'll be "0x00000014".
+                    write!(f, "0x{:>0width$x}", bits, width=(size*2) as usize)
+                }
+            }
+        }
+    }
+}
+
 impl<Tag> fmt::Display for Scalar<Tag> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         match self {
@@ -412,7 +433,7 @@ impl<Tag> From<Pointer<Tag>> for Scalar<Tag> {
     }
 }
 
-#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, RustcEncodable, RustcDecodable, Hash)]
+#[derive(Clone, Copy, Eq, PartialEq, Ord, PartialOrd, RustcEncodable, RustcDecodable, Hash)]
 pub enum ScalarMaybeUndef<Tag=(), Id=AllocId> {
     Scalar(Scalar<Tag, Id>),
     Undef,
@@ -425,6 +446,15 @@ impl<Tag> From<Scalar<Tag>> for ScalarMaybeUndef<Tag> {
     }
 }
 
+impl<Tag: fmt::Debug, Id: fmt::Debug> fmt::Debug for ScalarMaybeUndef<Tag, Id> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        match self {
+            ScalarMaybeUndef::Undef => write!(f, "Undef"),
+            ScalarMaybeUndef::Scalar(s) => write!(f, "{:?}", s),
+        }
+    }
+}
+
 impl<Tag> fmt::Display for ScalarMaybeUndef<Tag> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         match self {
diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs
index aab9d5e3a02be..c0d607a55ee86 100644
--- a/src/librustc/mir/mod.rs
+++ b/src/librustc/mir/mod.rs
@@ -62,7 +62,7 @@ impl<'tcx> HasLocalDecls<'tcx> for LocalDecls<'tcx> {
     }
 }
 
-impl<'tcx> HasLocalDecls<'tcx> for Mir<'tcx> {
+impl<'tcx> HasLocalDecls<'tcx> for Body<'tcx> {
     fn local_decls(&self) -> &LocalDecls<'tcx> {
         &self.local_decls
     }
@@ -88,7 +88,7 @@ impl MirPhase {
 
 /// Lowered representation of a single function.
 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
-pub struct Mir<'tcx> {
+pub struct Body<'tcx> {
     /// List of basic blocks. References to basic block use a newtyped index type `BasicBlock`
     /// that indexes into this vector.
     basic_blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>,
@@ -109,15 +109,15 @@ pub struct Mir<'tcx> {
     pub source_scope_local_data: ClearCrossCrate<IndexVec<SourceScope, SourceScopeLocalData>>,
 
     /// Rvalues promoted from this function, such as borrows of constants.
-    /// Each of them is the Mir of a constant with the fn's type parameters
+    /// Each of them is the Body of a constant with the fn's type parameters
     /// in scope, but a separate set of locals.
-    pub promoted: IndexVec<Promoted, Mir<'tcx>>,
+    pub promoted: IndexVec<Promoted, Body<'tcx>>,
 
     /// Yields type of the function, if it is a generator.
     pub yield_ty: Option<Ty<'tcx>>,
 
     /// Generator drop glue
-    pub generator_drop: Option<Box<Mir<'tcx>>>,
+    pub generator_drop: Option<Box<Body<'tcx>>>,
 
     /// The layout of a generator. Produced by the state transformation.
     pub generator_layout: Option<GeneratorLayout<'tcx>>,
@@ -169,12 +169,12 @@ pub struct Mir<'tcx> {
     cache: cache::Cache,
 }
 
-impl<'tcx> Mir<'tcx> {
+impl<'tcx> Body<'tcx> {
     pub fn new(
         basic_blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>,
         source_scopes: IndexVec<SourceScope, SourceScopeData>,
         source_scope_local_data: ClearCrossCrate<IndexVec<SourceScope, SourceScopeLocalData>>,
-        promoted: IndexVec<Promoted, Mir<'tcx>>,
+        promoted: IndexVec<Promoted, Body<'tcx>>,
         yield_ty: Option<Ty<'tcx>>,
         local_decls: LocalDecls<'tcx>,
         user_type_annotations: CanonicalUserTypeAnnotations<'tcx>,
@@ -191,7 +191,7 @@ impl<'tcx> Mir<'tcx> {
             local_decls.len()
         );
 
-        Mir {
+        Body {
             phase: MirPhase::Build,
             basic_blocks,
             source_scopes,
@@ -425,7 +425,7 @@ pub enum Safety {
     ExplicitUnsafe(hir::HirId),
 }
 
-impl_stable_hash_for!(struct Mir<'tcx> {
+impl_stable_hash_for!(struct Body<'tcx> {
     phase,
     basic_blocks,
     source_scopes,
@@ -444,7 +444,7 @@ impl_stable_hash_for!(struct Mir<'tcx> {
     cache
 });
 
-impl<'tcx> Index<BasicBlock> for Mir<'tcx> {
+impl<'tcx> Index<BasicBlock> for Body<'tcx> {
     type Output = BasicBlockData<'tcx>;
 
     #[inline]
@@ -453,7 +453,7 @@ impl<'tcx> Index<BasicBlock> for Mir<'tcx> {
     }
 }
 
-impl<'tcx> IndexMut<BasicBlock> for Mir<'tcx> {
+impl<'tcx> IndexMut<BasicBlock> for Body<'tcx> {
     #[inline]
     fn index_mut(&mut self, index: BasicBlock) -> &mut BasicBlockData<'tcx> {
         &mut self.basic_blocks_mut()[index]
@@ -601,7 +601,7 @@ newtype_index! {
     }
 }
 
-/// Classifies locals into categories. See `Mir::local_kind`.
+/// Classifies locals into categories. See `Body::local_kind`.
 #[derive(PartialEq, Eq, Debug, HashStable)]
 pub enum LocalKind {
     /// User-declared variable binding
@@ -2897,23 +2897,23 @@ fn def_path_str(def_id: DefId) -> String {
     ty::tls::with(|tcx| tcx.def_path_str(def_id))
 }
 
-impl<'tcx> graph::DirectedGraph for Mir<'tcx> {
+impl<'tcx> graph::DirectedGraph for Body<'tcx> {
     type Node = BasicBlock;
 }
 
-impl<'tcx> graph::WithNumNodes for Mir<'tcx> {
+impl<'tcx> graph::WithNumNodes for Body<'tcx> {
     fn num_nodes(&self) -> usize {
         self.basic_blocks.len()
     }
 }
 
-impl<'tcx> graph::WithStartNode for Mir<'tcx> {
+impl<'tcx> graph::WithStartNode for Body<'tcx> {
     fn start_node(&self) -> Self::Node {
         START_BLOCK
     }
 }
 
-impl<'tcx> graph::WithPredecessors for Mir<'tcx> {
+impl<'tcx> graph::WithPredecessors for Body<'tcx> {
     fn predecessors<'graph>(
         &'graph self,
         node: Self::Node,
@@ -2922,7 +2922,7 @@ impl<'tcx> graph::WithPredecessors for Mir<'tcx> {
     }
 }
 
-impl<'tcx> graph::WithSuccessors for Mir<'tcx> {
+impl<'tcx> graph::WithSuccessors for Body<'tcx> {
     fn successors<'graph>(
         &'graph self,
         node: Self::Node,
@@ -2931,12 +2931,12 @@ impl<'tcx> graph::WithSuccessors for Mir<'tcx> {
     }
 }
 
-impl<'a, 'b> graph::GraphPredecessors<'b> for Mir<'a> {
+impl<'a, 'b> graph::GraphPredecessors<'b> for Body<'a> {
     type Item = BasicBlock;
     type Iter = IntoIter<BasicBlock>;
 }
 
-impl<'a, 'b> graph::GraphSuccessors<'b> for Mir<'a> {
+impl<'a, 'b> graph::GraphSuccessors<'b> for Body<'a> {
     type Item = BasicBlock;
     type Iter = iter::Cloned<Successors<'b>>;
 }
@@ -2975,7 +2975,7 @@ impl Location {
     }
 
     /// Returns `true` if `other` is earlier in the control flow graph than `self`.
-    pub fn is_predecessor_of<'tcx>(&self, other: Location, mir: &Mir<'tcx>) -> bool {
+    pub fn is_predecessor_of<'tcx>(&self, other: Location, mir: &Body<'tcx>) -> bool {
         // If we are in the same block as the other location and are an earlier statement
         // then we are a predecessor of `other`.
         if self.block == other.block && self.statement_index < other.statement_index {
@@ -3228,7 +3228,7 @@ CloneTypeFoldableAndLiftImpls! {
 }
 
 BraceStructTypeFoldableImpl! {
-    impl<'tcx> TypeFoldable<'tcx> for Mir<'tcx> {
+    impl<'tcx> TypeFoldable<'tcx> for Body<'tcx> {
         phase,
         basic_blocks,
         source_scopes,
diff --git a/src/librustc/mir/traversal.rs b/src/librustc/mir/traversal.rs
index f8398c27cc2da..75d995d801d78 100644
--- a/src/librustc/mir/traversal.rs
+++ b/src/librustc/mir/traversal.rs
@@ -21,14 +21,14 @@ use super::*;
 /// A preorder traversal of this graph is either `A B D C` or `A C D B`
 #[derive(Clone)]
 pub struct Preorder<'a, 'tcx: 'a> {
-    mir: &'a Mir<'tcx>,
+    mir: &'a Body<'tcx>,
     visited: BitSet<BasicBlock>,
     worklist: Vec<BasicBlock>,
     root_is_start_block: bool,
 }
 
 impl<'a, 'tcx> Preorder<'a, 'tcx> {
-    pub fn new(mir: &'a Mir<'tcx>, root: BasicBlock) -> Preorder<'a, 'tcx> {
+    pub fn new(mir: &'a Body<'tcx>, root: BasicBlock) -> Preorder<'a, 'tcx> {
         let worklist = vec![root];
 
         Preorder {
@@ -40,7 +40,7 @@ impl<'a, 'tcx> Preorder<'a, 'tcx> {
     }
 }
 
-pub fn preorder<'a, 'tcx>(mir: &'a Mir<'tcx>) -> Preorder<'a, 'tcx> {
+pub fn preorder<'a, 'tcx>(mir: &'a Body<'tcx>) -> Preorder<'a, 'tcx> {
     Preorder::new(mir, START_BLOCK)
 }
 
@@ -99,14 +99,14 @@ impl<'a, 'tcx> Iterator for Preorder<'a, 'tcx> {
 ///
 /// A Postorder traversal of this graph is `D B C A` or `D C B A`
 pub struct Postorder<'a, 'tcx: 'a> {
-    mir: &'a Mir<'tcx>,
+    mir: &'a Body<'tcx>,
     visited: BitSet<BasicBlock>,
     visit_stack: Vec<(BasicBlock, Successors<'a>)>,
     root_is_start_block: bool,
 }
 
 impl<'a, 'tcx> Postorder<'a, 'tcx> {
-    pub fn new(mir: &'a Mir<'tcx>, root: BasicBlock) -> Postorder<'a, 'tcx> {
+    pub fn new(mir: &'a Body<'tcx>, root: BasicBlock) -> Postorder<'a, 'tcx> {
         let mut po = Postorder {
             mir,
             visited: BitSet::new_empty(mir.basic_blocks().len()),
@@ -194,7 +194,7 @@ impl<'a, 'tcx> Postorder<'a, 'tcx> {
     }
 }
 
-pub fn postorder<'a, 'tcx>(mir: &'a Mir<'tcx>) -> Postorder<'a, 'tcx> {
+pub fn postorder<'a, 'tcx>(mir: &'a Body<'tcx>) -> Postorder<'a, 'tcx> {
     Postorder::new(mir, START_BLOCK)
 }
 
@@ -252,13 +252,13 @@ impl<'a, 'tcx> Iterator for Postorder<'a, 'tcx> {
 /// to re-use the traversal
 #[derive(Clone)]
 pub struct ReversePostorder<'a, 'tcx: 'a> {
-    mir: &'a Mir<'tcx>,
+    mir: &'a Body<'tcx>,
     blocks: Vec<BasicBlock>,
     idx: usize
 }
 
 impl<'a, 'tcx> ReversePostorder<'a, 'tcx> {
-    pub fn new(mir: &'a Mir<'tcx>, root: BasicBlock) -> ReversePostorder<'a, 'tcx> {
+    pub fn new(mir: &'a Body<'tcx>, root: BasicBlock) -> ReversePostorder<'a, 'tcx> {
         let blocks : Vec<_> = Postorder::new(mir, root).map(|(bb, _)| bb).collect();
 
         let len = blocks.len();
@@ -276,7 +276,7 @@ impl<'a, 'tcx> ReversePostorder<'a, 'tcx> {
 }
 
 
-pub fn reverse_postorder<'a, 'tcx>(mir: &'a Mir<'tcx>) -> ReversePostorder<'a, 'tcx> {
+pub fn reverse_postorder<'a, 'tcx>(mir: &'a Body<'tcx>) -> ReversePostorder<'a, 'tcx> {
     ReversePostorder::new(mir, START_BLOCK)
 }
 
diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs
index f71a0d102e625..232b216737266 100644
--- a/src/librustc/mir/visit.rs
+++ b/src/librustc/mir/visit.rs
@@ -71,8 +71,8 @@ macro_rules! make_mir_visitor {
             // Override these, and call `self.super_xxx` to revert back to the
             // default behavior.
 
-            fn visit_mir(&mut self, mir: & $($mutability)? Mir<'tcx>) {
-                self.super_mir(mir);
+            fn visit_body(&mut self, mir: & $($mutability)? Body<'tcx>) {
+                self.super_body(mir);
             }
 
             fn visit_basic_block_data(&mut self,
@@ -251,8 +251,8 @@ macro_rules! make_mir_visitor {
             // The `super_xxx` methods comprise the default behavior and are
             // not meant to be overridden.
 
-            fn super_mir(&mut self,
-                         mir: & $($mutability)? Mir<'tcx>) {
+            fn super_body(&mut self,
+                         mir: & $($mutability)? Body<'tcx>) {
                 if let Some(yield_ty) = &$($mutability)? mir.yield_ty {
                     self.visit_ty(yield_ty, TyContext::YieldTy(SourceInfo {
                         span: mir.span,
@@ -825,7 +825,7 @@ macro_rules! make_mir_visitor {
 
             // Convenience methods
 
-            fn visit_location(&mut self, mir: & $($mutability)? Mir<'tcx>, location: Location) {
+            fn visit_location(&mut self, mir: & $($mutability)? Body<'tcx>, location: Location) {
                 let basic_block = & $($mutability)? mir[location.block];
                 if basic_block.statements.len() == location.statement_index {
                     if let Some(ref $($mutability)? terminator) = basic_block.terminator {
diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs
index c03cd7e268ef5..42bf8eefe048f 100644
--- a/src/librustc/query/mod.rs
+++ b/src/librustc/query/mod.rs
@@ -97,26 +97,26 @@ rustc_queries! {
 
         /// Fetch the MIR for a given `DefId` right after it's built - this includes
         /// unreachable code.
-        query mir_built(_: DefId) -> &'tcx Steal<mir::Mir<'tcx>> {}
+        query mir_built(_: DefId) -> &'tcx Steal<mir::Body<'tcx>> {}
 
         /// Fetch the MIR for a given `DefId` up till the point where it is
         /// ready for const evaluation.
         ///
         /// See the README for the `mir` module for details.
-        query mir_const(_: DefId) -> &'tcx Steal<mir::Mir<'tcx>> {
+        query mir_const(_: DefId) -> &'tcx Steal<mir::Body<'tcx>> {
             no_hash
         }
 
-        query mir_validated(_: DefId) -> &'tcx Steal<mir::Mir<'tcx>> {
+        query mir_validated(_: DefId) -> &'tcx Steal<mir::Body<'tcx>> {
             no_hash
         }
 
         /// MIR after our optimization passes have run. This is MIR that is ready
         /// for codegen. This is also the only query that can fetch non-local MIR, at present.
-        query optimized_mir(key: DefId) -> &'tcx mir::Mir<'tcx> {
+        query optimized_mir(key: DefId) -> &'tcx mir::Body<'tcx> {
             cache { key.is_local() }
             load_cached(tcx, id) {
-                let mir: Option<crate::mir::Mir<'tcx>> = tcx.queries.on_disk_cache
+                let mir: Option<crate::mir::Body<'tcx>> = tcx.queries.on_disk_cache
                                                             .try_load_query_result(tcx, id);
                 mir.map(|x| tcx.alloc_mir(x))
             }
@@ -456,7 +456,7 @@ rustc_queries! {
         /// in the case of closures, this will be redirected to the enclosing function.
         query region_scope_tree(_: DefId) -> &'tcx region::ScopeTree {}
 
-        query mir_shims(key: ty::InstanceDef<'tcx>) -> &'tcx mir::Mir<'tcx> {
+        query mir_shims(key: ty::InstanceDef<'tcx>) -> &'tcx mir::Body<'tcx> {
             no_force
             desc { |tcx| "generating MIR shim for `{}`", tcx.def_path_str(key.def_id()) }
         }
diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs
index f16137bd2c27a..44b6e03655773 100644
--- a/src/librustc/session/config.rs
+++ b/src/librustc/session/config.rs
@@ -19,7 +19,7 @@ use syntax::source_map::{FileName, FilePathMapping};
 use syntax::edition::{Edition, EDITION_NAME_LIST, DEFAULT_EDITION};
 use syntax::parse::token;
 use syntax::parse;
-use syntax::symbol::Symbol;
+use syntax::symbol::{sym, Symbol};
 use syntax::feature_gate::UnstableFeatures;
 use errors::emitter::HumanReadableErrorType;
 
@@ -1381,7 +1381,7 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
                      "insert profiling code"),
     pgo_gen: PgoGenerate = (PgoGenerate::Disabled, parse_pgo_generate, [TRACKED],
         "Generate PGO profile data, to a given file, or to the default location if it's empty."),
-    pgo_use: String = (String::new(), parse_string, [TRACKED],
+    pgo_use: Option<PathBuf> = (None, parse_opt_pathbuf, [TRACKED],
         "Use PGO profile data from the given profile file."),
     disable_instrumentation_preinliner: bool = (false, parse_bool, [TRACKED],
         "Disable the instrumentation pre-inliner, useful for profiling / PGO."),
@@ -1503,31 +1503,31 @@ pub fn default_configuration(sess: &Session) -> ast::CrateConfig {
         Some(Symbol::intern(vendor)),
     ));
     if sess.target.target.options.has_elf_tls {
-        ret.insert((Symbol::intern("target_thread_local"), None));
+        ret.insert((sym::target_thread_local, None));
     }
     for &i in &[8, 16, 32, 64, 128] {
         if i >= min_atomic_width && i <= max_atomic_width {
             let s = i.to_string();
             ret.insert((
-                Symbol::intern("target_has_atomic"),
+                sym::target_has_atomic,
                 Some(Symbol::intern(&s)),
             ));
             if &s == wordsz {
                 ret.insert((
-                    Symbol::intern("target_has_atomic"),
+                    sym::target_has_atomic,
                     Some(Symbol::intern("ptr")),
                 ));
             }
         }
     }
     if atomic_cas {
-        ret.insert((Symbol::intern("target_has_atomic"), Some(Symbol::intern("cas"))));
+        ret.insert((sym::target_has_atomic, Some(Symbol::intern("cas"))));
     }
     if sess.opts.debug_assertions {
         ret.insert((Symbol::intern("debug_assertions"), None));
     }
     if sess.opts.crate_types.contains(&CrateType::ProcMacro) {
-        ret.insert((Symbol::intern("proc_macro"), None));
+        ret.insert((sym::proc_macro, None));
     }
     ret
 }
@@ -1547,7 +1547,7 @@ pub fn build_configuration(sess: &Session, mut user_cfg: ast::CrateConfig) -> as
     let default_cfg = default_configuration(sess);
     // If the user wants a test runner, then add the test cfg
     if sess.opts.test {
-        user_cfg.insert((Symbol::intern("test"), None));
+        user_cfg.insert((sym::test, None));
     }
     user_cfg.extend(default_cfg.iter().cloned());
     user_cfg
@@ -2021,7 +2021,7 @@ pub fn build_session_options_and_crate_config(
         }
     }
 
-    if debugging_opts.pgo_gen.enabled() && !debugging_opts.pgo_use.is_empty() {
+    if debugging_opts.pgo_gen.enabled() && debugging_opts.pgo_use.is_some() {
         early_error(
             error_format,
             "options `-Z pgo-gen` and `-Z pgo-use` are exclusive",
@@ -2702,7 +2702,7 @@ mod tests {
     use std::path::PathBuf;
     use super::{Externs, OutputType, OutputTypes};
     use rustc_target::spec::{MergeFunctions, PanicStrategy, RelroLevel};
-    use syntax::symbol::Symbol;
+    use syntax::symbol::sym;
     use syntax::edition::{Edition, DEFAULT_EDITION};
     use syntax;
     use super::Options;
@@ -2744,7 +2744,7 @@ mod tests {
             let (sessopts, cfg) = build_session_options_and_crate_config(matches);
             let sess = build_session(sessopts, None, registry);
             let cfg = build_configuration(&sess, to_crate_config(cfg));
-            assert!(cfg.contains(&(Symbol::intern("test"), None)));
+            assert!(cfg.contains(&(sym::test, None)));
         });
     }
 
@@ -2752,7 +2752,6 @@ mod tests {
     // another --cfg test
     #[test]
     fn test_switch_implies_cfg_test_unless_cfg_test() {
-        use syntax::symbol::sym;
         syntax::with_default_globals(|| {
             let matches = &match optgroups().parse(&["--test".to_string(),
                                                      "--cfg=test".to_string()]) {
@@ -3212,7 +3211,7 @@ mod tests {
         assert_ne!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
 
         opts = reference.clone();
-        opts.debugging_opts.pgo_use = String::from("abc");
+        opts.debugging_opts.pgo_use = Some(PathBuf::from("abc"));
         assert_ne!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
 
         opts = reference.clone();
diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs
index 4d47491661e86..3d8092f6e0070 100644
--- a/src/librustc/session/mod.rs
+++ b/src/librustc/session/mod.rs
@@ -1272,6 +1272,15 @@ fn validate_commandline_args_with_session_available(sess: &Session) {
         sess.err("Linker plugin based LTO is not supported together with \
                   `-C prefer-dynamic` when targeting MSVC");
     }
+
+    // Make sure that any given profiling data actually exists so LLVM can't
+    // decide to silently skip PGO.
+    if let Some(ref path) = sess.opts.debugging_opts.pgo_use {
+        if !path.exists() {
+            sess.err(&format!("File `{}` passed to `-Zpgo-use` does not exist.",
+                              path.display()));
+        }
+    }
 }
 
 /// Hash value constructed out of all the `-C metadata` arguments passed to the
diff --git a/src/librustc/traits/on_unimplemented.rs b/src/librustc/traits/on_unimplemented.rs
index f9ceeb5bfc01b..1c17ace90c2fb 100644
--- a/src/librustc/traits/on_unimplemented.rs
+++ b/src/librustc/traits/on_unimplemented.rs
@@ -226,12 +226,12 @@ impl<'a, 'gcx, 'tcx> OnUnimplementedFormatString {
         Ok(result)
     }
 
-    fn verify(&self,
-              tcx: TyCtxt<'a, 'gcx, 'tcx>,
-              trait_def_id: DefId,
-              span: Span)
-              -> Result<(), ErrorReported>
-    {
+    fn verify(
+        &self,
+        tcx: TyCtxt<'a, 'gcx, 'tcx>,
+        trait_def_id: DefId,
+        span: Span,
+    ) -> Result<(), ErrorReported> {
         let name = tcx.item_name(trait_def_id);
         let generics = tcx.generics_of(trait_def_id);
         let parser = Parser::new(&self.0, None, vec![], false);
@@ -272,12 +272,12 @@ impl<'a, 'gcx, 'tcx> OnUnimplementedFormatString {
         result
     }
 
-    pub fn format(&self,
-                  tcx: TyCtxt<'a, 'gcx, 'tcx>,
-                  trait_ref: ty::TraitRef<'tcx>,
-                  options: &FxHashMap<String, String>)
-                  -> String
-    {
+    pub fn format(
+        &self,
+        tcx: TyCtxt<'a, 'gcx, 'tcx>,
+        trait_ref: ty::TraitRef<'tcx>,
+        options: &FxHashMap<String, String>,
+    ) -> String {
         let name = tcx.item_name(trait_ref.def_id);
         let trait_str = tcx.def_path_str(trait_ref.def_id);
         let generics = tcx.generics_of(trait_ref.def_id);
diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs
index d83b2ce842a88..0ad2888b6c469 100644
--- a/src/librustc/ty/context.rs
+++ b/src/librustc/ty/context.rs
@@ -23,7 +23,7 @@ use crate::middle::cstore::EncodedMetadata;
 use crate::middle::lang_items;
 use crate::middle::resolve_lifetime::{self, ObjectLifetimeDefault};
 use crate::middle::stability;
-use crate::mir::{self, Mir, interpret, ProjectionKind};
+use crate::mir::{self, Body, interpret, ProjectionKind};
 use crate::mir::interpret::{ConstValue, Allocation};
 use crate::ty::subst::{Kind, InternalSubsts, SubstsRef, Subst};
 use crate::ty::ReprOptions;
@@ -103,8 +103,8 @@ pub struct GlobalArenas<'tcx> {
     generics: TypedArena<ty::Generics>,
     trait_def: TypedArena<ty::TraitDef>,
     adt_def: TypedArena<ty::AdtDef>,
-    steal_mir: TypedArena<Steal<Mir<'tcx>>>,
-    mir: TypedArena<Mir<'tcx>>,
+    steal_mir: TypedArena<Steal<Body<'tcx>>>,
+    mir: TypedArena<Body<'tcx>>,
     tables: TypedArena<ty::TypeckTables<'tcx>>,
     /// miri allocations
     const_allocs: TypedArena<interpret::Allocation>,
@@ -1151,11 +1151,11 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
         self.global_arenas.generics.alloc(generics)
     }
 
-    pub fn alloc_steal_mir(self, mir: Mir<'gcx>) -> &'gcx Steal<Mir<'gcx>> {
+    pub fn alloc_steal_mir(self, mir: Body<'gcx>) -> &'gcx Steal<Body<'gcx>> {
         self.global_arenas.steal_mir.alloc(Steal::new(mir))
     }
 
-    pub fn alloc_mir(self, mir: Mir<'gcx>) -> &'gcx Mir<'gcx> {
+    pub fn alloc_mir(self, mir: Body<'gcx>) -> &'gcx Body<'gcx> {
         self.global_arenas.mir.alloc(mir)
     }
 
diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs
index 99c3293168754..01ea88ae9dcae 100644
--- a/src/librustc/ty/mod.rs
+++ b/src/librustc/ty/mod.rs
@@ -19,7 +19,7 @@ use crate::ich::StableHashingContext;
 use crate::infer::canonical::Canonical;
 use crate::middle::lang_items::{FnTraitLangItem, FnMutTraitLangItem, FnOnceTraitLangItem};
 use crate::middle::resolve_lifetime::ObjectLifetimeDefault;
-use crate::mir::Mir;
+use crate::mir::Body;
 use crate::mir::interpret::{GlobalId, ErrorHandled};
 use crate::mir::GeneratorLayout;
 use crate::session::CrateDisambiguator;
@@ -3002,7 +3002,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
 
     /// Returns the possibly-auto-generated MIR of a `(DefId, Subst)` pair.
     pub fn instance_mir(self, instance: ty::InstanceDef<'gcx>)
-                        -> &'gcx Mir<'gcx>
+                        -> &'gcx Body<'gcx>
     {
         match instance {
             ty::InstanceDef::Item(did) => {
diff --git a/src/librustc/ty/steal.rs b/src/librustc/ty/steal.rs
index a8f9301ba51c9..a5a0b198734c1 100644
--- a/src/librustc/ty/steal.rs
+++ b/src/librustc/ty/steal.rs
@@ -9,7 +9,7 @@ use rustc_data_structures::sync::{RwLock, ReadGuard, MappedReadGuard};
 /// queries are these pure functions that produce an immutable value
 /// (since if you did the query twice, you could observe the
 /// mutations). So instead we have the query produce a `&'tcx
-/// Steal<Mir<'tcx>>` (to be very specific). Now we can read from this
+/// Steal<Body<'tcx>>` (to be very specific). Now we can read from this
 /// as much as we want (using `borrow()`), but you can also
 /// `steal()`. Once you steal, any further attempt to read will panic.
 /// Therefore, we know that -- assuming no ICE -- nobody is observing
diff --git a/src/librustc/ty/subst.rs b/src/librustc/ty/subst.rs
index 72dfe581ba735..75ba1dd46ca2a 100644
--- a/src/librustc/ty/subst.rs
+++ b/src/librustc/ty/subst.rs
@@ -479,21 +479,22 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for SubstFolder<'a, 'gcx, 'tcx> {
         // the specialized routine `ty::replace_late_regions()`.
         match *r {
             ty::ReEarlyBound(data) => {
-                let r = self.substs.get(data.index as usize).map(|k| k.unpack());
-                match r {
+                let rk = self.substs.get(data.index as usize).map(|k| k.unpack());
+                match rk {
                     Some(UnpackedKind::Lifetime(lt)) => {
                         self.shift_region_through_binders(lt)
                     }
                     _ => {
                         let span = self.span.unwrap_or(DUMMY_SP);
-                        span_bug!(
-                            span,
+                        let msg = format!(
                             "Region parameter out of range \
                              when substituting in region {} (root type={:?}) \
                              (index={})",
                             data.name,
                             self.root_ty,
                             data.index);
+                        self.tcx.sess.delay_span_bug(span, &msg);
+                        r
                     }
                 }
             }
diff --git a/src/librustc_allocator/expand.rs b/src/librustc_allocator/expand.rs
index b9cd30694f6e8..3ec06b17aff22 100644
--- a/src/librustc_allocator/expand.rs
+++ b/src/librustc_allocator/expand.rs
@@ -91,9 +91,7 @@ impl MutVisitor for ExpandAllocatorDirectives<'_> {
             call_site: item.span, // use the call site of the static
             def_site: None,
             format: MacroAttribute(Symbol::intern(name)),
-            allow_internal_unstable: Some(vec![
-                Symbol::intern("rustc_attrs"),
-            ].into()),
+            allow_internal_unstable: Some(vec![sym::rustc_attrs].into()),
             allow_internal_unsafe: false,
             local_inner_macros: false,
             edition: self.sess.edition,
@@ -223,7 +221,7 @@ impl AllocFnFactory<'_> {
     }
 
     fn attrs(&self) -> Vec<Attribute> {
-        let special = Symbol::intern("rustc_std_internal_symbol");
+        let special = sym::rustc_std_internal_symbol;
         let special = self.cx.meta_word(self.span, special);
         vec![self.cx.attribute(self.span, special)]
     }
diff --git a/src/librustc_codegen_llvm/back/write.rs b/src/librustc_codegen_llvm/back/write.rs
index 66ba95810a625..1eee9ab8c0b67 100644
--- a/src/librustc_codegen_llvm/back/write.rs
+++ b/src/librustc_codegen_llvm/back/write.rs
@@ -721,11 +721,9 @@ pub unsafe fn with_llvm_pmb(llmod: &llvm::Module,
         }
     };
 
-    let pgo_use_path = if config.pgo_use.is_empty() {
-        None
-    } else {
-        Some(CString::new(config.pgo_use.as_bytes()).unwrap())
-    };
+    let pgo_use_path = config.pgo_use.as_ref().map(|path_buf| {
+        CString::new(path_buf.to_string_lossy().as_bytes()).unwrap()
+    });
 
     llvm::LLVMRustConfigurePassManagerBuilder(
         builder,
diff --git a/src/librustc_codegen_llvm/debuginfo/create_scope_map.rs b/src/librustc_codegen_llvm/debuginfo/create_scope_map.rs
index c8ddf733ecf1f..8b3ed5b0c623a 100644
--- a/src/librustc_codegen_llvm/debuginfo/create_scope_map.rs
+++ b/src/librustc_codegen_llvm/debuginfo/create_scope_map.rs
@@ -5,7 +5,7 @@ use super::utils::{DIB, span_start};
 use crate::llvm;
 use crate::llvm::debuginfo::{DIScope, DISubprogram};
 use crate::common::CodegenCx;
-use rustc::mir::{Mir, SourceScope};
+use rustc::mir::{Body, SourceScope};
 
 use libc::c_uint;
 
@@ -20,7 +20,7 @@ use syntax_pos::BytePos;
 /// If debuginfo is disabled, the returned vector is empty.
 pub fn create_mir_scopes(
     cx: &CodegenCx<'ll, '_>,
-    mir: &Mir<'_>,
+    mir: &Body<'_>,
     debug_context: &FunctionDebugContext<&'ll DISubprogram>,
 ) -> IndexVec<SourceScope, MirDebugScope<&'ll DIScope>> {
     let null_scope = MirDebugScope {
@@ -55,7 +55,7 @@ pub fn create_mir_scopes(
 }
 
 fn make_mir_scope(cx: &CodegenCx<'ll, '_>,
-                  mir: &Mir<'_>,
+                  mir: &Body<'_>,
                   has_variables: &BitSet<SourceScope>,
                   debug_context: &FunctionDebugContextData<&'ll DISubprogram>,
                   scope: SourceScope,
diff --git a/src/librustc_codegen_llvm/debuginfo/mod.rs b/src/librustc_codegen_llvm/debuginfo/mod.rs
index 527290392fff4..6fa594d445300 100644
--- a/src/librustc_codegen_llvm/debuginfo/mod.rs
+++ b/src/librustc_codegen_llvm/debuginfo/mod.rs
@@ -239,7 +239,7 @@ impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> {
         instance: Instance<'tcx>,
         sig: ty::FnSig<'tcx>,
         llfn: &'ll Value,
-        mir: &mir::Mir<'_>,
+        mir: &mir::Body<'_>,
     ) -> FunctionDebugContext<&'ll DISubprogram> {
         if self.sess().opts.debuginfo == DebugInfo::None {
             return FunctionDebugContext::DebugInfoDisabled;
@@ -523,7 +523,7 @@ impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> {
 
     fn create_mir_scopes(
         &self,
-        mir: &mir::Mir<'_>,
+        mir: &mir::Body<'_>,
         debug_context: &mut FunctionDebugContext<&'ll DISubprogram>,
     ) -> IndexVec<mir::SourceScope, MirDebugScope<&'ll DIScope>> {
         create_scope_map::create_mir_scopes(self, mir, debug_context)
diff --git a/src/librustc_codegen_ssa/back/write.rs b/src/librustc_codegen_ssa/back/write.rs
index 1c793996c83db..74c41969268e9 100644
--- a/src/librustc_codegen_ssa/back/write.rs
+++ b/src/librustc_codegen_ssa/back/write.rs
@@ -57,7 +57,7 @@ pub struct ModuleConfig {
     pub opt_size: Option<config::OptLevel>,
 
     pub pgo_gen: PgoGenerate,
-    pub pgo_use: String,
+    pub pgo_use: Option<PathBuf>,
 
     // Flags indicating which outputs to produce.
     pub emit_pre_lto_bc: bool,
@@ -95,7 +95,7 @@ impl ModuleConfig {
             opt_size: None,
 
             pgo_gen: PgoGenerate::Disabled,
-            pgo_use: String::new(),
+            pgo_use: None,
 
             emit_no_opt_bc: false,
             emit_pre_lto_bc: false,
diff --git a/src/librustc_codegen_ssa/mir/analyze.rs b/src/librustc_codegen_ssa/mir/analyze.rs
index 06d7b6c78f14b..bb6a13ed15a52 100644
--- a/src/librustc_codegen_ssa/mir/analyze.rs
+++ b/src/librustc_codegen_ssa/mir/analyze.rs
@@ -18,7 +18,7 @@ pub fn non_ssa_locals<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(
     let mir = fx.mir;
     let mut analyzer = LocalAnalyzer::new(fx);
 
-    analyzer.visit_mir(mir);
+    analyzer.visit_body(mir);
 
     for (index, ty) in mir.local_decls.iter().map(|l| l.ty).enumerate() {
         let ty = fx.monomorphize(&ty);
@@ -272,9 +272,9 @@ impl CleanupKind {
     }
 }
 
-pub fn cleanup_kinds<'a, 'tcx>(mir: &mir::Mir<'tcx>) -> IndexVec<mir::BasicBlock, CleanupKind> {
+pub fn cleanup_kinds<'a, 'tcx>(mir: &mir::Body<'tcx>) -> IndexVec<mir::BasicBlock, CleanupKind> {
     fn discover_masters<'tcx>(result: &mut IndexVec<mir::BasicBlock, CleanupKind>,
-                              mir: &mir::Mir<'tcx>) {
+                              mir: &mir::Body<'tcx>) {
         for (bb, data) in mir.basic_blocks().iter_enumerated() {
             match data.terminator().kind {
                 TerminatorKind::Goto { .. } |
@@ -304,7 +304,7 @@ pub fn cleanup_kinds<'a, 'tcx>(mir: &mir::Mir<'tcx>) -> IndexVec<mir::BasicBlock
     }
 
     fn propagate<'tcx>(result: &mut IndexVec<mir::BasicBlock, CleanupKind>,
-                       mir: &mir::Mir<'tcx>) {
+                       mir: &mir::Body<'tcx>) {
         let mut funclet_succs = IndexVec::from_elem(None, mir.basic_blocks());
 
         let mut set_successor = |funclet: mir::BasicBlock, succ| {
diff --git a/src/librustc_codegen_ssa/mir/mod.rs b/src/librustc_codegen_ssa/mir/mod.rs
index fed12c9a29fd2..4a43201dedf37 100644
--- a/src/librustc_codegen_ssa/mir/mod.rs
+++ b/src/librustc_codegen_ssa/mir/mod.rs
@@ -1,6 +1,6 @@
 use rustc::ty::{self, Ty, TypeFoldable, UpvarSubsts};
 use rustc::ty::layout::{TyLayout, HasTyCtxt, FnTypeExt};
-use rustc::mir::{self, Mir};
+use rustc::mir::{self, Body};
 use rustc::session::config::DebugInfo;
 use rustc_mir::monomorphize::Instance;
 use rustc_target::abi::call::{FnType, PassMode, IgnoreMode};
@@ -27,7 +27,7 @@ use self::operand::{OperandRef, OperandValue};
 pub struct FunctionCx<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> {
     instance: Instance<'tcx>,
 
-    mir: &'a mir::Mir<'tcx>,
+    mir: &'a mir::Body<'tcx>,
 
     debug_context: FunctionDebugContext<Bx::DIScope>,
 
@@ -196,7 +196,7 @@ impl<'a, 'tcx: 'a, V: CodegenObject> LocalRef<'tcx, V> {
 pub fn codegen_mir<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(
     cx: &'a Bx::CodegenCx,
     llfn: Bx::Value,
-    mir: &'a Mir<'tcx>,
+    mir: &'a Body<'tcx>,
     instance: Instance<'tcx>,
     sig: ty::FnSig<'tcx>,
 ) {
@@ -360,7 +360,7 @@ pub fn codegen_mir<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(
 }
 
 fn create_funclets<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(
-    mir: &'a Mir<'tcx>,
+    mir: &'a Body<'tcx>,
     bx: &mut Bx,
     cleanup_kinds: &IndexVec<mir::BasicBlock, CleanupKind>,
     block_bxs: &IndexVec<mir::BasicBlock, Bx::BasicBlock>)
diff --git a/src/librustc_codegen_ssa/traits/debuginfo.rs b/src/librustc_codegen_ssa/traits/debuginfo.rs
index aadffc5932ba8..37b7a15e2ba5e 100644
--- a/src/librustc_codegen_ssa/traits/debuginfo.rs
+++ b/src/librustc_codegen_ssa/traits/debuginfo.rs
@@ -22,12 +22,12 @@ pub trait DebugInfoMethods<'tcx>: BackendTypes {
         instance: Instance<'tcx>,
         sig: ty::FnSig<'tcx>,
         llfn: Self::Value,
-        mir: &mir::Mir<'_>,
+        mir: &mir::Body<'_>,
     ) -> FunctionDebugContext<Self::DIScope>;
 
     fn create_mir_scopes(
         &self,
-        mir: &mir::Mir<'_>,
+        mir: &mir::Body<'_>,
         debug_context: &mut FunctionDebugContext<Self::DIScope>,
     ) -> IndexVec<mir::SourceScope, MirDebugScope<Self::DIScope>>;
     fn extend_scope_to_file(
diff --git a/src/librustc_interface/util.rs b/src/librustc_interface/util.rs
index 09bb547191f49..4ff996d1f5707 100644
--- a/src/librustc_interface/util.rs
+++ b/src/librustc_interface/util.rs
@@ -68,7 +68,7 @@ pub fn add_configuration(
     sess: &Session,
     codegen_backend: &dyn CodegenBackend,
 ) {
-    let tf = Symbol::intern("target_feature");
+    let tf = sym::target_feature;
 
     cfg.extend(
         codegen_backend
diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs
index d52e497cf63d9..d184c671bbaf8 100644
--- a/src/librustc_lint/builtin.rs
+++ b/src/librustc_lint/builtin.rs
@@ -1439,8 +1439,8 @@ impl KeywordIdents {
     {
         let next_edition = match cx.sess.edition() {
             Edition::Edition2015 => {
-                match &ident.as_str()[..] {
-                    "async" | "await" | "try" => Edition::Edition2018,
+                match ident.name {
+                    kw::Async | kw::Await | kw::Try => Edition::Edition2018,
 
                     // rust-lang/rust#56327: Conservatively do not
                     // attempt to report occurrences of `dyn` within
@@ -1454,7 +1454,7 @@ impl KeywordIdents {
                     // its precise role in the parsed AST and thus are
                     // assured this is truly an attempt to use it as
                     // an identifier.
-                    "dyn" if !under_macro => Edition::Edition2018,
+                    kw::Dyn if !under_macro => Edition::Edition2018,
 
                     _ => return,
                 }
diff --git a/src/librustc_macros/src/symbols.rs b/src/librustc_macros/src/symbols.rs
index 3883682fa9df5..1f6e54807d8cb 100644
--- a/src/librustc_macros/src/symbols.rs
+++ b/src/librustc_macros/src/symbols.rs
@@ -96,6 +96,7 @@ pub fn symbols(input: TokenStream) -> TokenStream {
 
     let mut keyword_stream = quote! {};
     let mut symbols_stream = quote! {};
+    let mut digits_stream = quote! {};
     let mut prefill_stream = quote! {};
     let mut counter = 0u32;
     let mut keys = HashSet::<String>::new();
@@ -106,6 +107,7 @@ pub fn symbols(input: TokenStream) -> TokenStream {
         }
     };
 
+    // Generate the listed keywords.
     for keyword in &input.keywords.0 {
         let name = &keyword.name;
         let value = &keyword.value;
@@ -119,6 +121,7 @@ pub fn symbols(input: TokenStream) -> TokenStream {
         counter += 1;
     }
 
+    // Generate the listed symbols.
     for symbol in &input.symbols.0 {
         let name = &symbol.name;
         let value = match &symbol.value {
@@ -135,6 +138,19 @@ pub fn symbols(input: TokenStream) -> TokenStream {
         counter += 1;
     }
 
+    // Generate symbols for the strings "0", "1", ..., "9".
+    for n in 0..10 {
+        let n = n.to_string();
+        check_dup(&n);
+        prefill_stream.extend(quote! {
+            #n,
+        });
+        digits_stream.extend(quote! {
+            Symbol::new(#counter),
+        });
+        counter += 1;
+    }
+
     let tt = TokenStream::from(quote! {
         macro_rules! keywords {
             () => {
@@ -145,6 +161,10 @@ pub fn symbols(input: TokenStream) -> TokenStream {
         macro_rules! symbols {
             () => {
                 #symbols_stream
+
+                pub const digits_array: &[Symbol; 10] = &[
+                    #digits_stream
+                ];
             }
         }
 
diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs
index fae4c244d6e14..c2c40ea79e8f5 100644
--- a/src/librustc_metadata/cstore_impl.rs
+++ b/src/librustc_metadata/cstore_impl.rs
@@ -431,9 +431,7 @@ impl cstore::CStore {
             let client = proc_macro::bridge::client::Client::expand1(proc_macro::quote);
             let ext = SyntaxExtension::ProcMacro {
                 expander: Box::new(BangProcMacro { client }),
-                allow_internal_unstable: Some(vec![
-                    Symbol::intern("proc_macro_def_site"),
-                ].into()),
+                allow_internal_unstable: Some(vec![sym::proc_macro_def_site].into()),
                 edition: data.root.edition,
             };
             return LoadedMacro::ProcMacro(Lrc::new(ext));
diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs
index 958c81989ffd6..217fb8d891c92 100644
--- a/src/librustc_metadata/decoder.rs
+++ b/src/librustc_metadata/decoder.rs
@@ -18,7 +18,7 @@ use rustc::mir::interpret::AllocDecodingSession;
 use rustc::session::Session;
 use rustc::ty::{self, Ty, TyCtxt};
 use rustc::ty::codec::TyDecoder;
-use rustc::mir::Mir;
+use rustc::mir::Body;
 use rustc::util::captures::Captures;
 
 use std::io;
@@ -887,7 +887,7 @@ impl<'a, 'tcx> CrateMetadata {
     pub fn maybe_get_optimized_mir(&self,
                                    tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                    id: DefIndex)
-                                   -> Option<Mir<'tcx>> {
+                                   -> Option<Body<'tcx>> {
         match self.is_proc_macro(id) {
             true => None,
             false => self.entry(id).mir.map(|mir| mir.decode((self, tcx))),
diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs
index 1a9d996131dc0..38baeb4d08ac5 100644
--- a/src/librustc_metadata/encoder.rs
+++ b/src/librustc_metadata/encoder.rs
@@ -1026,7 +1026,7 @@ impl EncodeContext<'_, 'tcx> {
         self.lazy_seq(param_names.iter().map(|ident| ident.name))
     }
 
-    fn encode_optimized_mir(&mut self, def_id: DefId) -> Option<Lazy<mir::Mir<'tcx>>> {
+    fn encode_optimized_mir(&mut self, def_id: DefId) -> Option<Lazy<mir::Body<'tcx>>> {
         debug!("EntryBuilder::encode_mir({:?})", def_id);
         if self.tcx.mir_keys(LOCAL_CRATE).contains(&def_id) {
             let mir = self.tcx.optimized_mir(def_id);
diff --git a/src/librustc_metadata/schema.rs b/src/librustc_metadata/schema.rs
index 0ad3251540716..06c0e1714f97b 100644
--- a/src/librustc_metadata/schema.rs
+++ b/src/librustc_metadata/schema.rs
@@ -222,7 +222,7 @@ pub struct Entry<'tcx> {
     pub predicates: Option<Lazy<ty::GenericPredicates<'tcx>>>,
     pub predicates_defined_on: Option<Lazy<ty::GenericPredicates<'tcx>>>,
 
-    pub mir: Option<Lazy<mir::Mir<'tcx>>>,
+    pub mir: Option<Lazy<mir::Body<'tcx>>>,
 }
 
 #[derive(Copy, Clone, RustcEncodable, RustcDecodable)]
diff --git a/src/librustc_mir/borrow_check/borrow_set.rs b/src/librustc_mir/borrow_check/borrow_set.rs
index 5ced497baa1fd..d9d6fe0affb32 100644
--- a/src/librustc_mir/borrow_check/borrow_set.rs
+++ b/src/librustc_mir/borrow_check/borrow_set.rs
@@ -5,7 +5,7 @@ use crate::dataflow::indexes::BorrowIndex;
 use crate::dataflow::move_paths::MoveData;
 use rustc::mir::traversal;
 use rustc::mir::visit::{PlaceContext, Visitor, NonUseContext, MutatingUseContext};
-use rustc::mir::{self, Location, Mir, Local};
+use rustc::mir::{self, Location, Body, Local};
 use rustc::ty::{RegionVid, TyCtxt};
 use rustc::util::nodemap::{FxHashMap, FxHashSet};
 use rustc_data_structures::indexed_vec::IndexVec;
@@ -90,7 +90,7 @@ crate enum LocalsStateAtExit {
 impl LocalsStateAtExit {
     fn build(
         locals_are_invalidated_at_exit: bool,
-        mir: &Mir<'tcx>,
+        mir: &Body<'tcx>,
         move_data: &MoveData<'tcx>
     ) -> Self {
         struct HasStorageDead(BitSet<Local>);
@@ -107,7 +107,7 @@ impl LocalsStateAtExit {
             LocalsStateAtExit::AllAreInvalidated
         } else {
             let mut has_storage_dead = HasStorageDead(BitSet::new_empty(mir.local_decls.len()));
-            has_storage_dead.visit_mir(mir);
+            has_storage_dead.visit_body(mir);
             let mut has_storage_dead_or_moved = has_storage_dead.0;
             for move_out in &move_data.moves {
                 if let Some(index) = move_data.base_local(move_out.path) {
@@ -123,7 +123,7 @@ impl LocalsStateAtExit {
 impl<'tcx> BorrowSet<'tcx> {
     pub fn build(
         tcx: TyCtxt<'_, '_, 'tcx>,
-        mir: &Mir<'tcx>,
+        mir: &Body<'tcx>,
         locals_are_invalidated_at_exit: bool,
         move_data: &MoveData<'tcx>
     ) -> Self {
@@ -163,7 +163,7 @@ impl<'tcx> BorrowSet<'tcx> {
 
 struct GatherBorrows<'a, 'gcx: 'tcx, 'tcx: 'a> {
     tcx: TyCtxt<'a, 'gcx, 'tcx>,
-    mir: &'a Mir<'tcx>,
+    mir: &'a Body<'tcx>,
     idx_vec: IndexVec<BorrowIndex, BorrowData<'tcx>>,
     location_map: FxHashMap<Location, BorrowIndex>,
     activation_map: FxHashMap<Location, Vec<BorrowIndex>>,
diff --git a/src/librustc_mir/borrow_check/location.rs b/src/librustc_mir/borrow_check/location.rs
index 20a477576c95c..feade0d2a4aee 100644
--- a/src/librustc_mir/borrow_check/location.rs
+++ b/src/librustc_mir/borrow_check/location.rs
@@ -1,4 +1,4 @@
-use rustc::mir::{BasicBlock, Location, Mir};
+use rustc::mir::{BasicBlock, Location, Body};
 use rustc_data_structures::indexed_vec::{Idx, IndexVec};
 
 /// Maps between a MIR Location, which identifies a particular
@@ -30,7 +30,7 @@ crate enum RichLocation {
 }
 
 impl LocationTable {
-    crate fn new(mir: &Mir<'_>) -> Self {
+    crate fn new(mir: &Body<'_>) -> Self {
         let mut num_points = 0;
         let statements_before_block = mir.basic_blocks()
             .iter()
diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs
index 437f95e332a3d..82be2405701d5 100644
--- a/src/librustc_mir/borrow_check/mod.rs
+++ b/src/librustc_mir/borrow_check/mod.rs
@@ -10,7 +10,9 @@ use rustc::lint::builtin::{MUTABLE_BORROW_RESERVATION_CONFLICT};
 use rustc::middle::borrowck::SignalledError;
 use rustc::mir::{AggregateKind, BasicBlock, BorrowCheckResult, BorrowKind};
 use rustc::mir::{
-    ClearCrossCrate, Local, Location, Mir, Mutability, Operand, Place, PlaceBase, Static, StaticKind
+    ClearCrossCrate, Local, Location, Body, Mutability, Operand, Place, PlaceBase, Static,
+
+    StaticKind
 };
 use rustc::mir::{Field, Projection, ProjectionElem, Rvalue, Statement, StatementKind};
 use rustc::mir::{Terminator, TerminatorKind};
@@ -118,7 +120,7 @@ fn mir_borrowck<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> BorrowC
     }
 
     let opt_closure_req = tcx.infer_ctxt().enter(|infcx| {
-        let input_mir: &Mir<'_> = &input_mir.borrow();
+        let input_mir: &Body<'_> = &input_mir.borrow();
         do_mir_borrowck(&infcx, input_mir, def_id)
     });
     debug!("mir_borrowck done");
@@ -128,7 +130,7 @@ fn mir_borrowck<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> BorrowC
 
 fn do_mir_borrowck<'a, 'gcx, 'tcx>(
     infcx: &InferCtxt<'a, 'gcx, 'tcx>,
-    input_mir: &Mir<'gcx>,
+    input_mir: &Body<'gcx>,
     def_id: DefId,
 ) -> BorrowCheckResult<'gcx> {
     debug!("do_mir_borrowck(def_id = {:?})", def_id);
@@ -175,7 +177,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
     // requires first making our own copy of the MIR. This copy will
     // be modified (in place) to contain non-lexical lifetimes. It
     // will have a lifetime tied to the inference context.
-    let mut mir: Mir<'tcx> = input_mir.clone();
+    let mut mir: Body<'tcx> = input_mir.clone();
     let free_regions = nll::replace_regions_in_mir(infcx, def_id, param_env, &mut mir);
     let mir = &mir; // no further changes
     let location_table = &LocationTable::new(mir);
@@ -451,7 +453,7 @@ fn downgrade_if_error(diag: &mut Diagnostic) {
 
 pub struct MirBorrowckCtxt<'cx, 'gcx: 'tcx, 'tcx: 'cx> {
     infcx: &'cx InferCtxt<'cx, 'gcx, 'tcx>,
-    mir: &'cx Mir<'tcx>,
+    mir: &'cx Body<'tcx>,
     mir_def_id: DefId,
     move_data: &'cx MoveData<'tcx>,
 
@@ -537,7 +539,7 @@ pub struct MirBorrowckCtxt<'cx, 'gcx: 'tcx, 'tcx: 'cx> {
 impl<'cx, 'gcx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
     type FlowState = Flows<'cx, 'gcx, 'tcx>;
 
-    fn mir(&self) -> &'cx Mir<'tcx> {
+    fn mir(&self) -> &'cx Body<'tcx> {
         self.mir
     }
 
diff --git a/src/librustc_mir/borrow_check/mutability_errors.rs b/src/librustc_mir/borrow_check/mutability_errors.rs
index 16fbc8d6bb299..a292115707d8e 100644
--- a/src/librustc_mir/borrow_check/mutability_errors.rs
+++ b/src/librustc_mir/borrow_check/mutability_errors.rs
@@ -1,6 +1,6 @@
 use rustc::hir;
 use rustc::hir::Node;
-use rustc::mir::{self, BindingForm, Constant, ClearCrossCrate, Local, Location, Mir};
+use rustc::mir::{self, BindingForm, Constant, ClearCrossCrate, Local, Location, Body};
 use rustc::mir::{
     Mutability, Operand, Place, PlaceBase, Projection, ProjectionElem, Static, StaticKind,
 };
@@ -562,7 +562,7 @@ fn suggest_ampmut_self<'cx, 'gcx, 'tcx>(
 // by trying (3.), then (2.) and finally falling back on (1.).
 fn suggest_ampmut<'cx, 'gcx, 'tcx>(
     tcx: TyCtxt<'cx, 'gcx, 'tcx>,
-    mir: &Mir<'tcx>,
+    mir: &Body<'tcx>,
     local: Local,
     local_decl: &mir::LocalDecl<'tcx>,
     opt_ty_info: Option<Span>,
diff --git a/src/librustc_mir/borrow_check/nll/constraint_generation.rs b/src/librustc_mir/borrow_check/nll/constraint_generation.rs
index b0e395cbbdfb5..b485f37b78c2d 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, PlaceBase, Rvalue};
+use rustc::mir::{BasicBlock, BasicBlockData, Location, Body, Place, PlaceBase, Rvalue};
 use rustc::mir::{SourceInfo, Statement, Terminator};
 use rustc::mir::UserTypeProjection;
 use rustc::ty::fold::TypeFoldable;
@@ -18,7 +18,7 @@ pub(super) fn generate_constraints<'cx, 'gcx, 'tcx>(
     liveness_constraints: &mut LivenessValues<RegionVid>,
     all_facts: &mut Option<AllFacts>,
     location_table: &LocationTable,
-    mir: &Mir<'tcx>,
+    mir: &Body<'tcx>,
     borrow_set: &BorrowSet<'tcx>,
 ) {
     let mut cg = ConstraintGeneration {
diff --git a/src/librustc_mir/borrow_check/nll/explain_borrow/find_use.rs b/src/librustc_mir/borrow_check/nll/explain_borrow/find_use.rs
index 9a2090d05084d..3921246b06d38 100644
--- a/src/librustc_mir/borrow_check/nll/explain_borrow/find_use.rs
+++ b/src/librustc_mir/borrow_check/nll/explain_borrow/find_use.rs
@@ -5,12 +5,12 @@ use crate::borrow_check::nll::region_infer::{Cause, RegionInferenceContext};
 use crate::borrow_check::nll::ToRegionVid;
 use crate::util::liveness::{self, DefUse};
 use rustc::mir::visit::{MirVisitable, PlaceContext, Visitor};
-use rustc::mir::{Local, Location, Mir};
+use rustc::mir::{Local, Location, Body};
 use rustc::ty::{RegionVid, TyCtxt};
 use rustc_data_structures::fx::FxHashSet;
 
 crate fn find<'tcx>(
-    mir: &Mir<'tcx>,
+    mir: &Body<'tcx>,
     regioncx: &Rc<RegionInferenceContext<'tcx>>,
     tcx: TyCtxt<'_, '_, 'tcx>,
     region_vid: RegionVid,
@@ -28,7 +28,7 @@ crate fn find<'tcx>(
 }
 
 struct UseFinder<'cx, 'gcx: 'tcx, 'tcx: 'cx> {
-    mir: &'cx Mir<'tcx>,
+    mir: &'cx Body<'tcx>,
     regioncx: &'cx Rc<RegionInferenceContext<'tcx>>,
     tcx: TyCtxt<'cx, 'gcx, 'tcx>,
     region_vid: RegionVid,
@@ -100,7 +100,7 @@ impl<'cx, 'gcx, 'tcx> UseFinder<'cx, 'gcx, 'tcx> {
 }
 
 struct DefUseVisitor<'cx, 'gcx: 'tcx, 'tcx: 'cx> {
-    mir: &'cx Mir<'tcx>,
+    mir: &'cx Body<'tcx>,
     tcx: TyCtxt<'cx, 'gcx, 'tcx>,
     region_vid: RegionVid,
     def_use_result: Option<DefUseResult>,
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 6bca470bf3e5f..60c46b36f5f06 100644
--- a/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs
@@ -6,7 +6,7 @@ use crate::borrow_check::nll::region_infer::{Cause, RegionName};
 use crate::borrow_check::nll::ConstraintDescription;
 use crate::borrow_check::{MirBorrowckCtxt, WriteKind};
 use rustc::mir::{
-    CastKind, ConstraintCategory, FakeReadCause, Local, Location, Mir, Operand, Place, PlaceBase,
+    CastKind, ConstraintCategory, FakeReadCause, Local, Location, Body, Operand, Place, PlaceBase,
     Projection, ProjectionElem, Rvalue, Statement, StatementKind, TerminatorKind,
 };
 use rustc::ty::{self, TyCtxt};
@@ -54,7 +54,7 @@ impl BorrowExplanation {
     pub(in crate::borrow_check) fn add_explanation_to_diagnostic<'cx, 'gcx, 'tcx>(
         &self,
         tcx: TyCtxt<'cx, 'gcx, 'tcx>,
-        mir: &Mir<'tcx>,
+        mir: &Body<'tcx>,
         err: &mut DiagnosticBuilder<'_>,
         borrow_desc: &str,
         borrow_span: Option<Span>,
diff --git a/src/librustc_mir/borrow_check/nll/invalidation.rs b/src/librustc_mir/borrow_check/nll/invalidation.rs
index e3ab48ccff15b..017f4d48c1200 100644
--- a/src/librustc_mir/borrow_check/nll/invalidation.rs
+++ b/src/librustc_mir/borrow_check/nll/invalidation.rs
@@ -11,7 +11,7 @@ use crate::borrow_check::path_utils::*;
 use crate::dataflow::indexes::BorrowIndex;
 use rustc::ty::TyCtxt;
 use rustc::mir::visit::Visitor;
-use rustc::mir::{BasicBlock, Location, Mir, Place, PlaceBase, Rvalue};
+use rustc::mir::{BasicBlock, Location, Body, Place, PlaceBase, Rvalue};
 use rustc::mir::{Statement, StatementKind};
 use rustc::mir::TerminatorKind;
 use rustc::mir::{Operand, BorrowKind};
@@ -21,7 +21,7 @@ pub(super) fn generate_invalidates<'cx, 'gcx, 'tcx>(
     tcx: TyCtxt<'cx, 'gcx, 'tcx>,
     all_facts: &mut Option<AllFacts>,
     location_table: &LocationTable,
-    mir: &Mir<'tcx>,
+    mir: &Body<'tcx>,
     borrow_set: &BorrowSet<'tcx>,
 ) {
     if all_facts.is_none() {
@@ -39,7 +39,7 @@ pub(super) fn generate_invalidates<'cx, 'gcx, 'tcx>(
             mir,
             dominators,
         };
-        ig.visit_mir(mir);
+        ig.visit_body(mir);
     }
 }
 
@@ -47,7 +47,7 @@ struct InvalidationGenerator<'cx, 'tcx: 'cx, 'gcx: 'tcx> {
     tcx: TyCtxt<'cx, 'gcx, 'tcx>,
     all_facts: &'cx mut AllFacts,
     location_table: &'cx LocationTable,
-    mir: &'cx Mir<'tcx>,
+    mir: &'cx Body<'tcx>,
     dominators: Dominators<BasicBlock>,
     borrow_set: &'cx BorrowSet<'tcx>,
 }
diff --git a/src/librustc_mir/borrow_check/nll/mod.rs b/src/librustc_mir/borrow_check/nll/mod.rs
index fa490c108c896..0fb1705c8c294 100644
--- a/src/librustc_mir/borrow_check/nll/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/mod.rs
@@ -11,7 +11,7 @@ use crate::transform::MirSource;
 use crate::borrow_check::Upvar;
 use rustc::hir::def_id::DefId;
 use rustc::infer::InferCtxt;
-use rustc::mir::{ClosureOutlivesSubject, ClosureRegionRequirements, Mir};
+use rustc::mir::{ClosureOutlivesSubject, ClosureRegionRequirements, Body};
 use rustc::ty::{self, RegionKind, RegionVid};
 use rustc_errors::Diagnostic;
 use std::fmt::Debug;
@@ -50,7 +50,7 @@ pub(in crate::borrow_check) fn replace_regions_in_mir<'cx, 'gcx, 'tcx>(
     infcx: &InferCtxt<'cx, 'gcx, 'tcx>,
     def_id: DefId,
     param_env: ty::ParamEnv<'tcx>,
-    mir: &mut Mir<'tcx>,
+    mir: &mut Body<'tcx>,
 ) -> UniversalRegions<'tcx> {
     debug!("replace_regions_in_mir(def_id={:?})", def_id);
 
@@ -73,7 +73,7 @@ pub(in crate::borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>(
     infcx: &InferCtxt<'cx, 'gcx, 'tcx>,
     def_id: DefId,
     universal_regions: UniversalRegions<'tcx>,
-    mir: &Mir<'tcx>,
+    mir: &Body<'tcx>,
     upvars: &[Upvar],
     location_table: &LocationTable,
     param_env: ty::ParamEnv<'gcx>,
@@ -213,7 +213,7 @@ pub(in crate::borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>(
 fn dump_mir_results<'a, 'gcx, 'tcx>(
     infcx: &InferCtxt<'a, 'gcx, 'tcx>,
     source: MirSource<'tcx>,
-    mir: &Mir<'tcx>,
+    mir: &Body<'tcx>,
     regioncx: &RegionInferenceContext<'_>,
     closure_region_requirements: &Option<ClosureRegionRequirements<'_>>,
 ) {
@@ -273,7 +273,7 @@ fn dump_mir_results<'a, 'gcx, 'tcx>(
 
 fn dump_annotation<'a, 'gcx, 'tcx>(
     infcx: &InferCtxt<'a, 'gcx, 'tcx>,
-    mir: &Mir<'tcx>,
+    mir: &Body<'tcx>,
     mir_def_id: DefId,
     regioncx: &RegionInferenceContext<'tcx>,
     closure_region_requirements: &Option<ClosureRegionRequirements<'_>>,
diff --git a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs
index 18ca105070e8f..db43ea0558cc7 100644
--- a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs
@@ -9,7 +9,7 @@ use rustc::hir::def_id::DefId;
 use rustc::infer::error_reporting::nice_region_error::NiceRegionError;
 use rustc::infer::InferCtxt;
 use rustc::infer::NLLRegionVariableOrigin;
-use rustc::mir::{ConstraintCategory, Location, Mir};
+use rustc::mir::{ConstraintCategory, Location, Body};
 use rustc::ty::{self, RegionVid};
 use rustc_data_structures::indexed_vec::IndexVec;
 use rustc_errors::{Diagnostic, DiagnosticBuilder};
@@ -62,7 +62,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     /// path to blame.
     fn best_blame_constraint(
         &self,
-        mir: &Mir<'tcx>,
+        mir: &Body<'tcx>,
         from_region: RegionVid,
         target_test: impl Fn(RegionVid) -> bool,
     ) -> (ConstraintCategory, bool, Span) {
@@ -237,7 +237,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     /// Here we would be invoked with `fr = 'a` and `outlived_fr = `'b`.
     pub(super) fn report_error(
         &self,
-        mir: &Mir<'tcx>,
+        mir: &Body<'tcx>,
         upvars: &[Upvar],
         infcx: &InferCtxt<'_, '_, 'tcx>,
         mir_def_id: DefId,
@@ -357,7 +357,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     /// ```
     fn report_fnmut_error(
         &self,
-        mir: &Mir<'tcx>,
+        mir: &Body<'tcx>,
         upvars: &[Upvar],
         infcx: &InferCtxt<'_, '_, 'tcx>,
         mir_def_id: DefId,
@@ -422,7 +422,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     /// ```
     fn report_escaping_data_error(
         &self,
-        mir: &Mir<'tcx>,
+        mir: &Body<'tcx>,
         upvars: &[Upvar],
         infcx: &InferCtxt<'_, '_, 'tcx>,
         mir_def_id: DefId,
@@ -514,7 +514,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     /// ```
     fn report_general_error(
         &self,
-        mir: &Mir<'tcx>,
+        mir: &Body<'tcx>,
         upvars: &[Upvar],
         infcx: &InferCtxt<'_, '_, 'tcx>,
         mir_def_id: DefId,
@@ -667,7 +667,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
 
     crate fn free_region_constraint_info(
         &self,
-        mir: &Mir<'tcx>,
+        mir: &Body<'tcx>,
         upvars: &[Upvar],
         mir_def_id: DefId,
         infcx: &InferCtxt<'_, '_, 'tcx>,
@@ -724,7 +724,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     // Finds a good span to blame for the fact that `fr1` outlives `fr2`.
     crate fn find_outlives_blame_span(
         &self,
-        mir: &Mir<'tcx>,
+        mir: &Body<'tcx>,
         fr1: RegionVid,
         fr2: RegionVid,
     ) -> (ConstraintCategory, Span) {
@@ -735,7 +735,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
 
     fn retrieve_closure_constraint_info(
         &self,
-        mir: &Mir<'tcx>,
+        mir: &Body<'tcx>,
         constraint: &OutlivesConstraint,
     ) -> (ConstraintCategory, bool, Span) {
         let loc = match constraint.locations {
diff --git a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs
index f3cfc1a59a981..25415039fc80a 100644
--- a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs
+++ b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs
@@ -7,7 +7,7 @@ use rustc::hir;
 use rustc::hir::def::{Res, DefKind};
 use rustc::hir::def_id::DefId;
 use rustc::infer::InferCtxt;
-use rustc::mir::Mir;
+use rustc::mir::Body;
 use rustc::ty::subst::{SubstsRef, UnpackedKind};
 use rustc::ty::{self, RegionKind, RegionVid, Ty, TyCtxt};
 use rustc::ty::print::RegionHighlightMode;
@@ -152,7 +152,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     crate fn give_region_a_name(
         &self,
         infcx: &InferCtxt<'_, '_, 'tcx>,
-        mir: &Mir<'tcx>,
+        mir: &Body<'tcx>,
         upvars: &[Upvar],
         mir_def_id: DefId,
         fr: RegionVid,
@@ -332,7 +332,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     fn give_name_if_anonymous_region_appears_in_arguments(
         &self,
         infcx: &InferCtxt<'_, '_, 'tcx>,
-        mir: &Mir<'tcx>,
+        mir: &Body<'tcx>,
         mir_def_id: DefId,
         fr: RegionVid,
         counter: &mut usize,
@@ -360,7 +360,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     fn give_name_if_we_can_match_hir_ty_from_argument(
         &self,
         infcx: &InferCtxt<'_, '_, 'tcx>,
-        mir: &Mir<'tcx>,
+        mir: &Body<'tcx>,
         mir_def_id: DefId,
         needle_fr: RegionVid,
         argument_ty: Ty<'tcx>,
@@ -406,7 +406,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     fn give_name_if_we_cannot_match_hir_ty(
         &self,
         infcx: &InferCtxt<'_, '_, 'tcx>,
-        mir: &Mir<'tcx>,
+        mir: &Body<'tcx>,
         needle_fr: RegionVid,
         argument_ty: Ty<'tcx>,
         counter: &mut usize,
@@ -676,7 +676,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     fn give_name_if_anonymous_region_appears_in_output(
         &self,
         infcx: &InferCtxt<'_, '_, 'tcx>,
-        mir: &Mir<'tcx>,
+        mir: &Body<'tcx>,
         mir_def_id: DefId,
         fr: RegionVid,
         counter: &mut usize,
@@ -736,7 +736,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     fn give_name_if_anonymous_region_appears_in_yield_ty(
         &self,
         infcx: &InferCtxt<'_, '_, 'tcx>,
-        mir: &Mir<'tcx>,
+        mir: &Body<'tcx>,
         mir_def_id: DefId,
         fr: RegionVid,
         counter: &mut usize,
diff --git a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/var_name.rs b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/var_name.rs
index d8f34233839b9..c02a492c34100 100644
--- a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/var_name.rs
+++ b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/var_name.rs
@@ -1,7 +1,7 @@
 use crate::borrow_check::nll::region_infer::RegionInferenceContext;
 use crate::borrow_check::nll::ToRegionVid;
 use crate::borrow_check::Upvar;
-use rustc::mir::{Local, Mir};
+use rustc::mir::{Local, Body};
 use rustc::ty::{RegionVid, TyCtxt};
 use rustc_data_structures::indexed_vec::Idx;
 use syntax::source_map::Span;
@@ -11,7 +11,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     crate fn get_var_name_and_span_for_region(
         &self,
         tcx: TyCtxt<'_, '_, 'tcx>,
-        mir: &Mir<'tcx>,
+        mir: &Body<'tcx>,
         upvars: &[Upvar],
         fr: RegionVid,
     ) -> Option<(Option<Symbol>, Span)> {
@@ -120,7 +120,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     /// declared.
     crate fn get_argument_name_and_span_for_region(
         &self,
-        mir: &Mir<'tcx>,
+        mir: &Body<'tcx>,
         argument_index: usize,
     ) -> (Option<Symbol>, Span) {
         let implicit_inputs = self.universal_regions.defining_ty.implicit_inputs();
diff --git a/src/librustc_mir/borrow_check/nll/region_infer/mod.rs b/src/librustc_mir/borrow_check/nll/region_infer/mod.rs
index 9dd18ab76a5f2..4a00571feb110 100644
--- a/src/librustc_mir/borrow_check/nll/region_infer/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/region_infer/mod.rs
@@ -13,7 +13,7 @@ use rustc::infer::region_constraints::{GenericKind, VarInfos, VerifyBound};
 use rustc::infer::{InferCtxt, NLLRegionVariableOrigin, RegionVariableOrigin};
 use rustc::mir::{
     ClosureOutlivesRequirement, ClosureOutlivesSubject, ClosureRegionRequirements,
-    ConstraintCategory, Local, Location, Mir,
+    ConstraintCategory, Local, Location, Body,
 };
 use rustc::ty::{self, subst::SubstsRef, RegionVid, Ty, TyCtxt, TypeFoldable};
 use rustc::util::common::{self, ErrorReported};
@@ -185,7 +185,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         universal_regions: Rc<UniversalRegions<'tcx>>,
         placeholder_indices: Rc<PlaceholderIndices>,
         universal_region_relations: Rc<UniversalRegionRelations<'tcx>>,
-        _mir: &Mir<'tcx>,
+        _mir: &Body<'tcx>,
         outlives_constraints: ConstraintSet,
         closure_bounds_mapping: FxHashMap<
             Location,
@@ -400,7 +400,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     pub(super) fn solve<'gcx>(
         &mut self,
         infcx: &InferCtxt<'_, 'gcx, 'tcx>,
-        mir: &Mir<'tcx>,
+        mir: &Body<'tcx>,
         upvars: &[Upvar],
         mir_def_id: DefId,
         errors_buffer: &mut Vec<Diagnostic>,
@@ -416,7 +416,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     fn solve_inner<'gcx>(
         &mut self,
         infcx: &InferCtxt<'_, 'gcx, 'tcx>,
-        mir: &Mir<'tcx>,
+        mir: &Body<'tcx>,
         upvars: &[Upvar],
         mir_def_id: DefId,
         errors_buffer: &mut Vec<Diagnostic>,
@@ -468,7 +468,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     /// for each region variable until all the constraints are
     /// satisfied. Note that some values may grow **too** large to be
     /// feasible, but we check this later.
-    fn propagate_constraints(&mut self, _mir: &Mir<'tcx>) {
+    fn propagate_constraints(&mut self, _mir: &Body<'tcx>) {
         debug!("propagate_constraints()");
 
         debug!("propagate_constraints: constraints={:#?}", {
@@ -581,7 +581,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     fn check_type_tests<'gcx>(
         &self,
         infcx: &InferCtxt<'_, 'gcx, 'tcx>,
-        mir: &Mir<'tcx>,
+        mir: &Body<'tcx>,
         mir_def_id: DefId,
         mut propagated_outlives_requirements: Option<&mut Vec<ClosureOutlivesRequirement<'gcx>>>,
         errors_buffer: &mut Vec<Diagnostic>,
@@ -725,7 +725,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     fn try_promote_type_test<'gcx>(
         &self,
         infcx: &InferCtxt<'_, 'gcx, 'tcx>,
-        mir: &Mir<'tcx>,
+        mir: &Body<'tcx>,
         type_test: &TypeTest<'tcx>,
         propagated_outlives_requirements: &mut Vec<ClosureOutlivesRequirement<'gcx>>,
     ) -> bool {
@@ -944,7 +944,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     fn eval_verify_bound(
         &self,
         tcx: TyCtxt<'_, '_, 'tcx>,
-        mir: &Mir<'tcx>,
+        mir: &Body<'tcx>,
         generic_ty: Ty<'tcx>,
         lower_bound: RegionVid,
         verify_bound: &VerifyBound<'tcx>,
@@ -977,7 +977,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     fn eval_if_eq(
         &self,
         tcx: TyCtxt<'_, '_, 'tcx>,
-        mir: &Mir<'tcx>,
+        mir: &Body<'tcx>,
         generic_ty: Ty<'tcx>,
         lower_bound: RegionVid,
         test_ty: Ty<'tcx>,
@@ -1037,7 +1037,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     // Evaluate whether `sup_region: sub_region @ point`.
     fn eval_outlives(
         &self,
-        _mir: &Mir<'tcx>,
+        _mir: &Body<'tcx>,
         sup_region: RegionVid,
         sub_region: RegionVid,
     ) -> bool {
@@ -1105,7 +1105,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     fn check_universal_regions<'gcx>(
         &self,
         infcx: &InferCtxt<'_, 'gcx, 'tcx>,
-        mir: &Mir<'tcx>,
+        mir: &Body<'tcx>,
         upvars: &[Upvar],
         mir_def_id: DefId,
         mut propagated_outlives_requirements: Option<&mut Vec<ClosureOutlivesRequirement<'gcx>>>,
@@ -1150,7 +1150,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     fn check_universal_region<'gcx>(
         &self,
         infcx: &InferCtxt<'_, 'gcx, 'tcx>,
-        mir: &Mir<'tcx>,
+        mir: &Body<'tcx>,
         upvars: &[Upvar],
         mir_def_id: DefId,
         longer_fr: RegionVid,
@@ -1216,7 +1216,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         longer_fr: RegionVid,
         shorter_fr: RegionVid,
         infcx: &InferCtxt<'_, 'gcx, 'tcx>,
-        mir: &Mir<'tcx>,
+        mir: &Body<'tcx>,
         upvars: &[Upvar],
         mir_def_id: DefId,
         propagated_outlives_requirements: &mut Option<&mut Vec<ClosureOutlivesRequirement<'gcx>>>,
@@ -1282,7 +1282,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     fn check_bound_universal_region<'gcx>(
         &self,
         infcx: &InferCtxt<'_, 'gcx, 'tcx>,
-        mir: &Mir<'tcx>,
+        mir: &Body<'tcx>,
         _mir_def_id: DefId,
         longer_fr: RegionVid,
         placeholder: ty::PlaceholderRegion,
diff --git a/src/librustc_mir/borrow_check/nll/region_infer/values.rs b/src/librustc_mir/borrow_check/nll/region_infer/values.rs
index 2101447965a15..8822d7bb37393 100644
--- a/src/librustc_mir/borrow_check/nll/region_infer/values.rs
+++ b/src/librustc_mir/borrow_check/nll/region_infer/values.rs
@@ -1,4 +1,4 @@
-use rustc::mir::{BasicBlock, Location, Mir};
+use rustc::mir::{BasicBlock, Location, Body};
 use rustc::ty::{self, RegionVid};
 use rustc_data_structures::bit_set::{HybridBitSet, SparseBitMatrix};
 use rustc_data_structures::fx::FxHashMap;
@@ -20,7 +20,7 @@ crate struct RegionValueElements {
 }
 
 impl RegionValueElements {
-    crate fn new(mir: &Mir<'_>) -> Self {
+    crate fn new(mir: &Body<'_>) -> Self {
         let mut num_points = 0;
         let statements_before_block: IndexVec<BasicBlock, usize> = mir.basic_blocks()
             .iter()
@@ -92,7 +92,7 @@ impl RegionValueElements {
     /// Pushes all predecessors of `index` onto `stack`.
     crate fn push_predecessors(
         &self,
-        mir: &Mir<'_>,
+        mir: &Body<'_>,
         index: PointIndex,
         stack: &mut Vec<PointIndex>,
     ) {
diff --git a/src/librustc_mir/borrow_check/nll/renumber.rs b/src/librustc_mir/borrow_check/nll/renumber.rs
index 58e567c39a9bb..a3b142c2ffcc3 100644
--- a/src/librustc_mir/borrow_check/nll/renumber.rs
+++ b/src/librustc_mir/borrow_check/nll/renumber.rs
@@ -1,17 +1,17 @@
 use rustc::ty::subst::SubstsRef;
 use rustc::ty::{self, ClosureSubsts, GeneratorSubsts, Ty, TypeFoldable};
-use rustc::mir::{Location, Mir};
+use rustc::mir::{Location, Body};
 use rustc::mir::visit::{MutVisitor, TyContext};
 use rustc::infer::{InferCtxt, NLLRegionVariableOrigin};
 
 /// Replaces all free regions appearing in the MIR with fresh
 /// inference variables, returning the number of variables created.
-pub fn renumber_mir<'tcx>(infcx: &InferCtxt<'_, '_, 'tcx>, mir: &mut Mir<'tcx>) {
+pub fn renumber_mir<'tcx>(infcx: &InferCtxt<'_, '_, 'tcx>, mir: &mut Body<'tcx>) {
     debug!("renumber_mir()");
     debug!("renumber_mir: mir.arg_count={:?}", mir.arg_count);
 
     let mut visitor = NLLVisitor { infcx };
-    visitor.visit_mir(mir);
+    visitor.visit_body(mir);
 }
 
 /// Replaces all regions appearing in `value` with fresh inference
@@ -47,12 +47,12 @@ impl<'a, 'gcx, 'tcx> NLLVisitor<'a, 'gcx, 'tcx> {
 }
 
 impl<'a, 'gcx, 'tcx> MutVisitor<'tcx> for NLLVisitor<'a, 'gcx, 'tcx> {
-    fn visit_mir(&mut self, mir: &mut Mir<'tcx>) {
+    fn visit_body(&mut self, mir: &mut Body<'tcx>) {
         for promoted in mir.promoted.iter_mut() {
-            self.visit_mir(promoted);
+            self.visit_body(promoted);
         }
 
-        self.super_mir(mir);
+        self.super_body(mir);
     }
 
     fn visit_ty(&mut self, ty: &mut Ty<'tcx>, ty_context: TyContext) {
diff --git a/src/librustc_mir/borrow_check/nll/type_check/input_output.rs b/src/librustc_mir/borrow_check/nll/type_check/input_output.rs
index 50828c294fa1b..120088e1784d4 100644
--- a/src/librustc_mir/borrow_check/nll/type_check/input_output.rs
+++ b/src/librustc_mir/borrow_check/nll/type_check/input_output.rs
@@ -20,7 +20,7 @@ use super::{Locations, TypeChecker};
 impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
     pub(super) fn equate_inputs_and_outputs(
         &mut self,
-        mir: &Mir<'tcx>,
+        mir: &Body<'tcx>,
         universal_regions: &UniversalRegions<'tcx>,
         normalized_inputs_and_output: &[Ty<'tcx>],
     ) {
diff --git a/src/librustc_mir/borrow_check/nll/type_check/liveness/local_use_map.rs b/src/librustc_mir/borrow_check/nll/type_check/liveness/local_use_map.rs
index 6ba41806a313f..e1a7b9babd48a 100644
--- a/src/librustc_mir/borrow_check/nll/type_check/liveness/local_use_map.rs
+++ b/src/librustc_mir/borrow_check/nll/type_check/liveness/local_use_map.rs
@@ -1,7 +1,7 @@
 use crate::borrow_check::nll::region_infer::values::{PointIndex, RegionValueElements};
 use crate::util::liveness::{categorize, DefUse};
 use rustc::mir::visit::{PlaceContext, Visitor};
-use rustc::mir::{Local, Location, Mir};
+use rustc::mir::{Local, Location, Body};
 use rustc_data_structures::indexed_vec::{Idx, IndexVec};
 use rustc_data_structures::vec_linked_list as vll;
 
@@ -60,7 +60,7 @@ impl LocalUseMap {
     crate fn build(
         live_locals: &Vec<Local>,
         elements: &RegionValueElements,
-        mir: &Mir<'_>,
+        mir: &Body<'_>,
     ) -> Self {
         let nones = IndexVec::from_elem_n(None, mir.local_decls.len());
         let mut local_use_map = LocalUseMap {
@@ -81,7 +81,7 @@ impl LocalUseMap {
             elements,
             locals_with_use_data,
         }
-        .visit_mir(mir);
+        .visit_body(mir);
 
         local_use_map
     }
diff --git a/src/librustc_mir/borrow_check/nll/type_check/liveness/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/liveness/mod.rs
index 58a164b38f911..3cefab36e2351 100644
--- a/src/librustc_mir/borrow_check/nll/type_check/liveness/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/type_check/liveness/mod.rs
@@ -7,7 +7,7 @@ use crate::borrow_check::nll::ToRegionVid;
 use crate::dataflow::move_paths::MoveData;
 use crate::dataflow::FlowAtLocation;
 use crate::dataflow::MaybeInitializedPlaces;
-use rustc::mir::{Local, Mir};
+use rustc::mir::{Local, Body};
 use rustc::ty::{RegionVid, TyCtxt};
 use rustc_data_structures::fx::FxHashSet;
 use std::rc::Rc;
@@ -27,7 +27,7 @@ mod trace;
 /// performed before
 pub(super) fn generate<'gcx, 'tcx>(
     typeck: &mut TypeChecker<'_, 'gcx, 'tcx>,
-    mir: &Mir<'tcx>,
+    mir: &Body<'tcx>,
     elements: &Rc<RegionValueElements>,
     flow_inits: &mut FlowAtLocation<'tcx, MaybeInitializedPlaces<'_, 'gcx, 'tcx>>,
     move_data: &MoveData<'tcx>,
@@ -77,7 +77,7 @@ pub(super) fn generate<'gcx, 'tcx>(
 fn compute_live_locals(
     tcx: TyCtxt<'_, '_, 'tcx>,
     free_regions: &FxHashSet<RegionVid>,
-    mir: &Mir<'tcx>,
+    mir: &Body<'tcx>,
 ) -> Vec<Local> {
     let live_locals: Vec<Local> = mir
         .local_decls
diff --git a/src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs b/src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs
index 87e9a704fac1e..345780c4760eb 100644
--- a/src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs
+++ b/src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs
@@ -7,7 +7,7 @@ use crate::dataflow::indexes::MovePathIndex;
 use crate::dataflow::move_paths::MoveData;
 use crate::dataflow::{FlowAtLocation, FlowsAtLocation, MaybeInitializedPlaces};
 use rustc::infer::canonical::QueryRegionConstraint;
-use rustc::mir::{BasicBlock, ConstraintCategory, Local, Location, Mir};
+use rustc::mir::{BasicBlock, ConstraintCategory, Local, Location, Body};
 use rustc::traits::query::dropck_outlives::DropckOutlivesResult;
 use rustc::traits::query::type_op::outlives::DropckOutlives;
 use rustc::traits::query::type_op::TypeOp;
@@ -32,7 +32,7 @@ use std::rc::Rc;
 /// this respects `#[may_dangle]` annotations).
 pub(super) fn trace(
     typeck: &mut TypeChecker<'_, 'gcx, 'tcx>,
-    mir: &Mir<'tcx>,
+    mir: &Body<'tcx>,
     elements: &Rc<RegionValueElements>,
     flow_inits: &mut FlowAtLocation<'tcx, MaybeInitializedPlaces<'_, 'gcx, 'tcx>>,
     move_data: &MoveData<'tcx>,
@@ -72,7 +72,7 @@ where
     elements: &'me RegionValueElements,
 
     /// MIR we are analyzing.
-    mir: &'me Mir<'tcx>,
+    mir: &'me Body<'tcx>,
 
     /// Mapping to/from the various indices used for initialization tracking.
     move_data: &'me MoveData<'tcx>,
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 4589e4ef036a4..52d91b4ac40d5 100644
--- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs
@@ -29,7 +29,7 @@ use rustc::infer::{InferCtxt, InferOk, LateBoundRegionConversionTime, NLLRegionV
 use rustc::infer::type_variable::TypeVariableOrigin;
 use rustc::mir::interpret::{InterpError::BoundsCheck, ConstValue};
 use rustc::mir::tcx::PlaceTy;
-use rustc::mir::visit::{PlaceContext, Visitor, MutatingUseContext, NonMutatingUseContext};
+use rustc::mir::visit::{PlaceContext, Visitor, NonMutatingUseContext};
 use rustc::mir::*;
 use rustc::traits::query::type_op;
 use rustc::traits::query::type_op::custom::CustomTypeOp;
@@ -112,7 +112,7 @@ mod relate_tys;
 pub(crate) fn type_check<'gcx, 'tcx>(
     infcx: &InferCtxt<'_, 'gcx, 'tcx>,
     param_env: ty::ParamEnv<'gcx>,
-    mir: &Mir<'tcx>,
+    mir: &Body<'tcx>,
     mir_def_id: DefId,
     universal_regions: &Rc<UniversalRegions<'tcx>>,
     location_table: &LocationTable,
@@ -179,7 +179,7 @@ fn type_check_internal<'a, 'gcx, 'tcx, R>(
     infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
     mir_def_id: DefId,
     param_env: ty::ParamEnv<'gcx>,
-    mir: &'a Mir<'tcx>,
+    mir: &'a Body<'tcx>,
     region_bound_pairs: &'a RegionBoundPairs<'tcx>,
     implicit_region_bound: ty::Region<'tcx>,
     borrowck_context: &'a mut BorrowCheckContext<'a, 'tcx>,
@@ -198,7 +198,7 @@ fn type_check_internal<'a, 'gcx, 'tcx, R>(
     );
     let errors_reported = {
         let mut verifier = TypeVerifier::new(&mut checker, mir);
-        verifier.visit_mir(mir);
+        verifier.visit_body(mir);
         verifier.errors_reported
     };
 
@@ -253,7 +253,7 @@ enum FieldAccessError {
 /// is a problem.
 struct TypeVerifier<'a, 'b: 'a, 'gcx: 'tcx, 'tcx: 'b> {
     cx: &'a mut TypeChecker<'b, 'gcx, 'tcx>,
-    mir: &'b Mir<'tcx>,
+    mir: &'b Body<'tcx>,
     last_span: Span,
     mir_def_id: DefId,
     errors_reported: bool,
@@ -368,7 +368,7 @@ impl<'a, 'b, 'gcx, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'gcx, 'tcx> {
         }
     }
 
-    fn visit_mir(&mut self, mir: &Mir<'tcx>) {
+    fn visit_body(&mut self, mir: &Body<'tcx>) {
         self.sanitize_type(&"return type", mir.return_ty());
         for local_decl in &mir.local_decls {
             self.sanitize_type(local_decl, local_decl.ty);
@@ -376,12 +376,12 @@ impl<'a, 'b, 'gcx, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'gcx, 'tcx> {
         if self.errors_reported {
             return;
         }
-        self.super_mir(mir);
+        self.super_body(mir);
     }
 }
 
 impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> {
-    fn new(cx: &'a mut TypeChecker<'b, 'gcx, 'tcx>, mir: &'b Mir<'tcx>) -> Self {
+    fn new(cx: &'a mut TypeChecker<'b, 'gcx, 'tcx>, mir: &'b Body<'tcx>) -> Self {
         TypeVerifier {
             mir,
             mir_def_id: cx.mir_def_id,
@@ -447,95 +447,98 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> {
         context: PlaceContext,
     ) -> PlaceTy<'tcx> {
         debug!("sanitize_place: {:?}", place);
-        let place_ty = match place {
-            Place::Base(PlaceBase::Local(index)) =>
-                PlaceTy::from_ty(self.mir.local_decls[*index].ty),
-            Place::Base(PlaceBase::Static(box Static { kind, ty: sty })) => {
-                let sty = self.sanitize_type(place, sty);
-                let check_err =
-                    |verifier: &mut TypeVerifier<'a, 'b, 'gcx, 'tcx>,
-                     place: &Place<'tcx>,
-                     ty,
-                     sty| {
-                        if let Err(terr) = verifier.cx.eq_types(
-                            sty,
-                            ty,
-                            location.to_locations(),
-                            ConstraintCategory::Boring,
-                        ) {
-                            span_mirbug!(
-                            verifier,
-                            place,
-                            "bad promoted type ({:?}: {:?}): {:?}",
-                            ty,
-                            sty,
-                            terr
-                        );
+
+        place.iterate(|place_base, place_projection| {
+            let mut place_ty = match place_base {
+                PlaceBase::Local(index) =>
+                    PlaceTy::from_ty(self.mir.local_decls[*index].ty),
+                PlaceBase::Static(box Static { kind, ty: sty }) => {
+                    let sty = self.sanitize_type(place, sty);
+                    let check_err =
+                        |verifier: &mut TypeVerifier<'a, 'b, 'gcx, 'tcx>,
+                         place: &Place<'tcx>,
+                         ty,
+                         sty| {
+                            if let Err(terr) = verifier.cx.eq_types(
+                                sty,
+                                ty,
+                                location.to_locations(),
+                                ConstraintCategory::Boring,
+                            ) {
+                                span_mirbug!(
+                                verifier,
+                                place,
+                                "bad promoted type ({:?}: {:?}): {:?}",
+                                ty,
+                                sty,
+                                terr
+                            );
+                            };
                         };
-                    };
-                match kind {
-                    StaticKind::Promoted(promoted) => {
-                        if !self.errors_reported {
-                            let promoted_mir = &self.mir.promoted[*promoted];
-                            self.sanitize_promoted(promoted_mir, location);
-
-                            let promoted_ty = promoted_mir.return_ty();
-                            check_err(self, place, promoted_ty, sty);
+                    match kind {
+                        StaticKind::Promoted(promoted) => {
+                            if !self.errors_reported {
+                                let promoted_mir = &self.mir.promoted[*promoted];
+                                self.sanitize_promoted(promoted_mir, location);
+
+                                let promoted_ty = promoted_mir.return_ty();
+                                check_err(self, place, promoted_ty, sty);
+                            }
                         }
-                    }
-                    StaticKind::Static(def_id) => {
-                        let ty = self.tcx().type_of(*def_id);
-                        let ty = self.cx.normalize(ty, location);
+                        StaticKind::Static(def_id) => {
+                            let ty = self.tcx().type_of(*def_id);
+                            let ty = self.cx.normalize(ty, location);
 
-                        check_err(self, place, ty, sty);
+                            check_err(self, place, ty, sty);
+                        }
                     }
+                    PlaceTy::from_ty(sty)
+                }
+            };
+
+            // FIXME use place_projection.is_empty() when is available
+            if let Place::Base(_) = place {
+                if let PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy) = context {
+                    let tcx = self.tcx();
+                    let trait_ref = ty::TraitRef {
+                        def_id: tcx.lang_items().copy_trait().unwrap(),
+                        substs: tcx.mk_substs_trait(place_ty.ty, &[]),
+                    };
+
+                    // In order to have a Copy operand, the type T of the
+                    // value must be Copy. Note that we prove that T: Copy,
+                    // rather than using the `is_copy_modulo_regions`
+                    // test. This is important because
+                    // `is_copy_modulo_regions` ignores the resulting region
+                    // obligations and assumes they pass. This can result in
+                    // bounds from Copy impls being unsoundly ignored (e.g.,
+                    // #29149). Note that we decide to use Copy before knowing
+                    // whether the bounds fully apply: in effect, the rule is
+                    // that if a value of some type could implement Copy, then
+                    // it must.
+                    self.cx.prove_trait_ref(
+                        trait_ref,
+                        location.to_locations(),
+                        ConstraintCategory::CopyBound,
+                    );
                 }
-                PlaceTy::from_ty(sty)
             }
-            Place::Projection(ref proj) => {
-                let base_context = if context.is_mutating_use() {
-                    PlaceContext::MutatingUse(MutatingUseContext::Projection)
-                } else {
-                    PlaceContext::NonMutatingUse(NonMutatingUseContext::Projection)
-                };
-                let base_ty = self.sanitize_place(&proj.base, location, base_context);
-                if base_ty.variant_index.is_none() {
-                    if base_ty.ty.references_error() {
+
+            for proj in place_projection {
+                if place_ty.variant_index.is_none() {
+                    if place_ty.ty.references_error() {
                         assert!(self.errors_reported);
                         return PlaceTy::from_ty(self.tcx().types.err);
                     }
                 }
-                self.sanitize_projection(base_ty, &proj.elem, place, location)
+                place_ty = self.sanitize_projection(place_ty, &proj.elem, place, location)
             }
-        };
-        if let PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy) = context {
-            let tcx = self.tcx();
-            let trait_ref = ty::TraitRef {
-                def_id: tcx.lang_items().copy_trait().unwrap(),
-                substs: tcx.mk_substs_trait(place_ty.ty, &[]),
-            };
 
-            // In order to have a Copy operand, the type T of the
-            // value must be Copy. Note that we prove that T: Copy,
-            // rather than using the `is_copy_modulo_regions`
-            // test. This is important because
-            // `is_copy_modulo_regions` ignores the resulting region
-            // obligations and assumes they pass. This can result in
-            // bounds from Copy impls being unsoundly ignored (e.g.,
-            // #29149). Note that we decide to use Copy before knowing
-            // whether the bounds fully apply: in effect, the rule is
-            // that if a value of some type could implement Copy, then
-            // it must.
-            self.cx.prove_trait_ref(
-                trait_ref,
-                location.to_locations(),
-                ConstraintCategory::CopyBound,
-            );
-        }
-        place_ty
+            place_ty
+        })
     }
 
-    fn sanitize_promoted(&mut self, promoted_mir: &'b Mir<'tcx>, location: Location) {
+    fn sanitize_promoted(&mut self, promoted_mir: &'b Body<'tcx>, location: Location) {
         // Determine the constraints from the promoted MIR by running the type
         // checker on the promoted MIR, then transfer the constraints back to
         // the main MIR, changing the locations to the provided location.
@@ -559,7 +562,7 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> {
             &mut closure_bounds
         );
 
-        self.visit_mir(promoted_mir);
+        self.visit_body(promoted_mir);
 
         if !self.errors_reported {
             // if verifier failed, don't do further checks to avoid ICEs
@@ -966,7 +969,7 @@ impl Locations {
     }
 
     /// Gets a span representing the location.
-    pub fn span(&self, mir: &Mir<'_>) -> Span {
+    pub fn span(&self, mir: &Body<'_>) -> Span {
         match self {
             Locations::All(span) => *span,
             Locations::Single(l) => mir.source_info(*l).span,
@@ -977,7 +980,7 @@ impl Locations {
 impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
     fn new(
         infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
-        mir: &'a Mir<'tcx>,
+        mir: &'a Body<'tcx>,
         mir_def_id: DefId,
         param_env: ty::ParamEnv<'gcx>,
         region_bound_pairs: &'a RegionBoundPairs<'tcx>,
@@ -1314,7 +1317,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
         self.infcx.tcx
     }
 
-    fn check_stmt(&mut self, mir: &Mir<'tcx>, stmt: &Statement<'tcx>, location: Location) {
+    fn check_stmt(&mut self, mir: &Body<'tcx>, stmt: &Statement<'tcx>, location: Location) {
         debug!("check_stmt: {:?}", stmt);
         let tcx = self.tcx();
         match stmt.kind {
@@ -1453,7 +1456,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
 
     fn check_terminator(
         &mut self,
-        mir: &Mir<'tcx>,
+        mir: &Body<'tcx>,
         term: &Terminator<'tcx>,
         term_location: Location,
     ) {
@@ -1615,7 +1618,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
 
     fn check_call_dest(
         &mut self,
-        mir: &Mir<'tcx>,
+        mir: &Body<'tcx>,
         term: &Terminator<'tcx>,
         sig: &ty::FnSig<'tcx>,
         destination: &Option<(Place<'tcx>, BasicBlock)>,
@@ -1684,7 +1687,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
 
     fn check_call_inputs(
         &mut self,
-        mir: &Mir<'tcx>,
+        mir: &Body<'tcx>,
         term: &Terminator<'tcx>,
         sig: &ty::FnSig<'tcx>,
         args: &[Operand<'tcx>],
@@ -1725,7 +1728,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
         }
     }
 
-    fn check_iscleanup(&mut self, mir: &Mir<'tcx>, block_data: &BasicBlockData<'tcx>) {
+    fn check_iscleanup(&mut self, mir: &Body<'tcx>, block_data: &BasicBlockData<'tcx>) {
         let is_cleanup = block_data.is_cleanup;
         self.last_span = block_data.terminator().source_info.span;
         match block_data.terminator().kind {
@@ -1817,7 +1820,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
 
     fn assert_iscleanup(
         &mut self,
-        mir: &Mir<'tcx>,
+        mir: &Body<'tcx>,
         ctxt: &dyn fmt::Debug,
         bb: BasicBlock,
         iscleanuppad: bool,
@@ -1833,7 +1836,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
         }
     }
 
-    fn check_local(&mut self, mir: &Mir<'tcx>, local: Local, local_decl: &LocalDecl<'tcx>) {
+    fn check_local(&mut self, mir: &Body<'tcx>, local: Local, local_decl: &LocalDecl<'tcx>) {
         match mir.local_kind(local) {
             LocalKind::ReturnPointer | LocalKind::Arg => {
                 // return values of normal functions are required to be
@@ -1935,7 +1938,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
         }
     }
 
-    fn check_rvalue(&mut self, mir: &Mir<'tcx>, rvalue: &Rvalue<'tcx>, location: Location) {
+    fn check_rvalue(&mut self, mir: &Body<'tcx>, rvalue: &Rvalue<'tcx>, location: Location) {
         let tcx = self.tcx();
 
         match rvalue {
@@ -2271,7 +2274,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
 
     fn check_aggregate_rvalue(
         &mut self,
-        mir: &Mir<'tcx>,
+        mir: &Body<'tcx>,
         rvalue: &Rvalue<'tcx>,
         aggregate_kind: &AggregateKind<'tcx>,
         operands: &[Operand<'tcx>],
@@ -2329,7 +2332,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
     /// - `borrowed_place`: the place `P` being borrowed
     fn add_reborrow_constraint(
         &mut self,
-        mir: &Mir<'tcx>,
+        mir: &Body<'tcx>,
         location: Location,
         borrow_region: ty::Region<'tcx>,
         borrowed_place: &Place<'tcx>,
@@ -2618,7 +2621,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
         })
     }
 
-    fn typeck_mir(&mut self, mir: &Mir<'tcx>) {
+    fn typeck_mir(&mut self, mir: &Body<'tcx>) {
         self.last_span = mir.span;
         debug!("run_on_mir: {:?}", mir.span);
 
diff --git a/src/librustc_mir/borrow_check/path_utils.rs b/src/librustc_mir/borrow_check/path_utils.rs
index 0c2a4ef45f104..557d235c23f05 100644
--- a/src/librustc_mir/borrow_check/path_utils.rs
+++ b/src/librustc_mir/borrow_check/path_utils.rs
@@ -2,7 +2,7 @@ use crate::borrow_check::borrow_set::{BorrowSet, BorrowData, TwoPhaseActivation}
 use crate::borrow_check::places_conflict;
 use crate::borrow_check::AccessDepth;
 use crate::dataflow::indexes::BorrowIndex;
-use rustc::mir::{BasicBlock, Location, Mir, Place, PlaceBase};
+use rustc::mir::{BasicBlock, Location, Body, Place, PlaceBase};
 use rustc::mir::{ProjectionElem, BorrowKind};
 use rustc::ty::TyCtxt;
 use rustc_data_structures::graph::dominators::Dominators;
@@ -25,7 +25,7 @@ pub(super) enum Control {
 pub(super) fn each_borrow_involving_path<'a, 'tcx, 'gcx: 'tcx, F, I, S> (
     s: &mut S,
     tcx: TyCtxt<'a, 'gcx, 'tcx>,
-    mir: &Mir<'tcx>,
+    mir: &Body<'tcx>,
     _location: Location,
     access_place: (AccessDepth, &Place<'tcx>),
     borrow_set: &BorrowSet<'tcx>,
@@ -131,22 +131,20 @@ pub(super) fn is_active<'tcx>(
 /// Determines if a given borrow is borrowing local data
 /// 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::Base(PlaceBase::Static(..)) => false,
-        Place::Base(PlaceBase::Local(..)) => true,
-        Place::Projection(box proj) => {
-            match proj.elem {
-                // Reborrow of already borrowed data is ignored
-                // Any errors will be caught on the initial borrow
-                ProjectionElem::Deref => false,
+    place.iterate(|place_base, place_projection| {
+        match place_base {
+            PlaceBase::Static(..) => return false,
+            PlaceBase::Local(..) => {},
+        }
 
-                // For interior references and downcasts, find out if the base is local
-                ProjectionElem::Field(..)
-                    | ProjectionElem::Index(..)
-                    | ProjectionElem::ConstantIndex { .. }
-                | ProjectionElem::Subslice { .. }
-                | ProjectionElem::Downcast(..) => borrow_of_local_data(&proj.base),
+        for proj in place_projection {
+            // Reborrow of already borrowed data is ignored
+            // Any errors will be caught on the initial borrow
+            if proj.elem == ProjectionElem::Deref {
+                return false;
             }
         }
-    }
+
+        true
+    })
 }
diff --git a/src/librustc_mir/borrow_check/place_ext.rs b/src/librustc_mir/borrow_check/place_ext.rs
index cf9a6165d71a2..9306e88e9ae9c 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::{Mir, Place, PlaceBase, Mutability, Static, StaticKind};
+use rustc::mir::{Body, Place, PlaceBase, Mutability, Static, StaticKind};
 use rustc::ty::{self, TyCtxt};
 use crate::borrow_check::borrow_set::LocalsStateAtExit;
 
@@ -13,7 +13,7 @@ crate trait PlaceExt<'tcx> {
     fn ignore_borrow(
         &self,
         tcx: TyCtxt<'_, '_, 'tcx>,
-        mir: &Mir<'tcx>,
+        mir: &Body<'tcx>,
         locals_state_at_exit: &LocalsStateAtExit,
         ) -> bool;
 }
@@ -22,43 +22,39 @@ impl<'tcx> PlaceExt<'tcx> for Place<'tcx> {
     fn ignore_borrow(
         &self,
         tcx: TyCtxt<'_, '_, 'tcx>,
-        mir: &Mir<'tcx>,
+        mir: &Body<'tcx>,
         locals_state_at_exit: &LocalsStateAtExit,
     ) -> bool {
-        match self {
-            // If a local variable is immutable, then we only need to track borrows to guard
-            // against two kinds of errors:
-            // * The variable being dropped while still borrowed (e.g., because the fn returns
-            //   a reference to a local variable)
-            // * The variable being moved while still borrowed
-            //
-            // In particular, the variable cannot be mutated -- the "access checks" will fail --
-            // so we don't have to worry about mutation while borrowed.
-            Place::Base(PlaceBase::Local(index)) => {
-                match locals_state_at_exit {
-                    LocalsStateAtExit::AllAreInvalidated => false,
-                    LocalsStateAtExit::SomeAreInvalidated { has_storage_dead_or_moved } => {
-                        let ignore = !has_storage_dead_or_moved.contains(*index) &&
-                            mir.local_decls[*index].mutability == Mutability::Not;
-                        debug!("ignore_borrow: local {:?} => {:?}", index, ignore);
-                        ignore
+        self.iterate(|place_base, place_projection| {
+            let ignore = match place_base {
+                // If a local variable is immutable, then we only need to track borrows to guard
+                // against two kinds of errors:
+                // * The variable being dropped while still borrowed (e.g., because the fn returns
+                //   a reference to a local variable)
+                // * The variable being moved while still borrowed
+                //
+                // In particular, the variable cannot be mutated -- the "access checks" will fail --
+                // so we don't have to worry about mutation while borrowed.
+                PlaceBase::Local(index) => {
+                    match locals_state_at_exit {
+                        LocalsStateAtExit::AllAreInvalidated => false,
+                        LocalsStateAtExit::SomeAreInvalidated { has_storage_dead_or_moved } => {
+                            let ignore = !has_storage_dead_or_moved.contains(*index) &&
+                                mir.local_decls[*index].mutability == Mutability::Not;
+                            debug!("ignore_borrow: local {:?} => {:?}", index, ignore);
+                            ignore
+                        }
                     }
                 }
-            }
-            Place::Base(PlaceBase::Static(box Static{ kind: StaticKind::Promoted(_), .. })) =>
-                false,
-            Place::Base(PlaceBase::Static(box Static{ kind: StaticKind::Static(def_id), .. })) => {
-                tcx.is_mutable_static(*def_id)
-            }
-            Place::Projection(proj) => match proj.elem {
-                ProjectionElem::Field(..)
-                | ProjectionElem::Downcast(..)
-                | ProjectionElem::Subslice { .. }
-                | ProjectionElem::ConstantIndex { .. }
-                | ProjectionElem::Index(_) => proj.base.ignore_borrow(
-                    tcx, mir, locals_state_at_exit),
+                PlaceBase::Static(box Static{ kind: StaticKind::Promoted(_), .. }) =>
+                    false,
+                PlaceBase::Static(box Static{ kind: StaticKind::Static(def_id), .. }) => {
+                    tcx.is_mutable_static(*def_id)
+                }
+            };
 
-                ProjectionElem::Deref => {
+            for proj in place_projection {
+                if proj.elem == ProjectionElem::Deref {
                     let ty = proj.base.ty(mir, tcx).ty;
                     match ty.sty {
                         // For both derefs of raw pointers and `&T`
@@ -71,11 +67,13 @@ impl<'tcx> PlaceExt<'tcx> for Place<'tcx> {
                         // original path into a new variable and
                         // borrowed *that* one, leaving the original
                         // path unborrowed.
-                        ty::RawPtr(..) | ty::Ref(_, _, hir::MutImmutable) => true,
-                        _ => proj.base.ignore_borrow(tcx, mir, locals_state_at_exit),
+                        ty::RawPtr(..) | ty::Ref(_, _, hir::MutImmutable) => return true,
+                        _ => {}
                     }
                 }
-            },
-        }
+            }
+
+            ignore
+        })
     }
 }
diff --git a/src/librustc_mir/borrow_check/places_conflict.rs b/src/librustc_mir/borrow_check/places_conflict.rs
index 1bf606109dc76..0393a20bb80e6 100644
--- a/src/librustc_mir/borrow_check/places_conflict.rs
+++ b/src/librustc_mir/borrow_check/places_conflict.rs
@@ -3,7 +3,7 @@ use crate::borrow_check::Overlap;
 use crate::borrow_check::{Deep, Shallow, AccessDepth};
 use rustc::hir;
 use rustc::mir::{
-    BorrowKind, Mir, Place, PlaceBase, PlaceProjection, ProjectionElem, PlaceProjectionsIter,
+    BorrowKind, Body, Place, PlaceBase, PlaceProjection, ProjectionElem, PlaceProjectionsIter,
     StaticKind
 };
 use rustc::ty::{self, TyCtxt};
@@ -26,7 +26,7 @@ crate enum PlaceConflictBias {
 /// dataflow).
 crate fn places_conflict<'gcx, 'tcx>(
     tcx: TyCtxt<'_, 'gcx, 'tcx>,
-    mir: &Mir<'tcx>,
+    mir: &Body<'tcx>,
     borrow_place: &Place<'tcx>,
     access_place: &Place<'tcx>,
     bias: PlaceConflictBias,
@@ -48,7 +48,7 @@ crate fn places_conflict<'gcx, 'tcx>(
 /// order to make the conservative choice and preserve soundness.
 pub(super) fn borrow_conflicts_with_place<'gcx, 'tcx>(
     tcx: TyCtxt<'_, 'gcx, 'tcx>,
-    mir: &Mir<'tcx>,
+    mir: &Body<'tcx>,
     borrow_place: &Place<'tcx>,
     borrow_kind: BorrowKind,
     access_place: &Place<'tcx>,
@@ -85,7 +85,7 @@ pub(super) fn borrow_conflicts_with_place<'gcx, 'tcx>(
 
 fn place_components_conflict<'gcx, 'tcx>(
     tcx: TyCtxt<'_, 'gcx, 'tcx>,
-    mir: &Mir<'tcx>,
+    mir: &Body<'tcx>,
     borrow_projections: (&PlaceBase<'tcx>, PlaceProjectionsIter<'_, 'tcx>),
     borrow_kind: BorrowKind,
     access_projections: (&PlaceBase<'tcx>, PlaceProjectionsIter<'_, 'tcx>),
@@ -367,7 +367,7 @@ fn place_base_conflict<'a, 'gcx: 'tcx, 'tcx>(
 // between `elem1` and `elem2`.
 fn place_projection_conflict<'a, 'gcx: 'tcx, 'tcx>(
     tcx: TyCtxt<'a, 'gcx, 'tcx>,
-    mir: &Mir<'tcx>,
+    mir: &Body<'tcx>,
     pi1: &PlaceProjection<'tcx>,
     pi2: &PlaceProjection<'tcx>,
     bias: PlaceConflictBias,
diff --git a/src/librustc_mir/borrow_check/prefixes.rs b/src/librustc_mir/borrow_check/prefixes.rs
index 866f1cf994e69..0e1abeba70dff 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, PlaceBase, ProjectionElem};
+use rustc::mir::{Body, Place, PlaceBase, ProjectionElem};
 
 pub trait IsPrefixOf<'tcx> {
     fn is_prefix_of(&self, other: &Place<'tcx>) -> bool;
@@ -38,7 +38,7 @@ impl<'tcx> IsPrefixOf<'tcx> for Place<'tcx> {
 
 
 pub(super) struct Prefixes<'cx, 'gcx: 'tcx, 'tcx: 'cx> {
-    mir: &'cx Mir<'tcx>,
+    mir: &'cx Body<'tcx>,
     tcx: TyCtxt<'cx, 'gcx, 'tcx>,
     kind: PrefixSet,
     next: Option<&'cx Place<'tcx>>,
diff --git a/src/librustc_mir/borrow_check/used_muts.rs b/src/librustc_mir/borrow_check/used_muts.rs
index f4866fad9a5fd..abfc2f9466c8e 100644
--- a/src/librustc_mir/borrow_check/used_muts.rs
+++ b/src/librustc_mir/borrow_check/used_muts.rs
@@ -34,7 +34,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
                 never_initialized_mut_locals: &mut never_initialized_mut_locals,
                 mbcx: self,
             };
-            visitor.visit_mir(visitor.mbcx.mir);
+            visitor.visit_body(visitor.mbcx.mir);
         }
 
         // Take the union of the existed `used_mut` set with those variables we've found were
diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs
index 55b5d5d1471ac..5d79ef6a4bbc9 100644
--- a/src/librustc_mir/build/mod.rs
+++ b/src/librustc_mir/build/mod.rs
@@ -26,7 +26,7 @@ use syntax_pos::Span;
 use super::lints;
 
 /// Construct the MIR for a given `DefId`.
-pub fn mir_build<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Mir<'tcx> {
+pub fn mir_build<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Body<'tcx> {
     let id = tcx.hir().as_local_hir_id(def_id).unwrap();
 
     // Figure out what primary body this item has.
@@ -169,9 +169,9 @@ pub fn mir_build<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Mir<'t
             tcx,
             span: mir.span
         };
-        globalizer.visit_mir(&mut mir);
+        globalizer.visit_body(&mut mir);
         let mir = unsafe {
-            mem::transmute::<Mir<'_>, Mir<'tcx>>(mir)
+            mem::transmute::<Body<'_>, Body<'tcx>>(mir)
         };
 
         mir_util::dump_mir(tcx, None, "mir_map", &0,
@@ -236,7 +236,7 @@ impl<'a, 'gcx: 'tcx, 'tcx> MutVisitor<'tcx> for GlobalizeMir<'a, 'gcx> {
 fn create_constructor_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                      ctor_id: hir::HirId,
                                      v: &'tcx hir::VariantData)
-                                     -> Mir<'tcx>
+                                     -> Body<'tcx>
 {
     let span = tcx.hir().span_by_hir_id(ctor_id);
     if let hir::VariantData::Tuple(ref fields, ctor_id) = *v {
@@ -249,9 +249,9 @@ fn create_constructor_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                 tcx,
                 span: mir.span
             };
-            globalizer.visit_mir(&mut mir);
+            globalizer.visit_body(&mut mir);
             let mir = unsafe {
-                mem::transmute::<Mir<'_>, Mir<'tcx>>(mir)
+                mem::transmute::<Body<'_>, Body<'tcx>>(mir)
             };
 
             mir_util::dump_mir(tcx, None, "mir_map", &0,
@@ -628,7 +628,7 @@ fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>,
                                    yield_ty: Option<Ty<'gcx>>,
                                    return_ty_span: Span,
                                    body: &'gcx hir::Body)
-                                   -> Mir<'tcx>
+                                   -> Body<'tcx>
     where A: Iterator<Item=ArgInfo<'gcx>>
 {
     let arguments: Vec<_> = arguments.collect();
@@ -748,7 +748,7 @@ fn construct_const<'a, 'gcx, 'tcx>(
     body_id: hir::BodyId,
     const_ty: Ty<'tcx>,
     const_ty_span: Span,
-) -> Mir<'tcx> {
+) -> Body<'tcx> {
     let tcx = hir.tcx();
     let owner_id = tcx.hir().body_owner(body_id);
     let span = tcx.hir().span(owner_id);
@@ -787,7 +787,7 @@ fn construct_const<'a, 'gcx, 'tcx>(
 
 fn construct_error<'a, 'gcx, 'tcx>(hir: Cx<'a, 'gcx, 'tcx>,
                                    body_id: hir::BodyId)
-                                   -> Mir<'tcx> {
+                                   -> Body<'tcx> {
     let owner_id = hir.tcx().hir().body_owner(body_id);
     let span = hir.tcx().hir().span(owner_id);
     let ty = hir.tcx().types.err;
@@ -849,14 +849,14 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
 
     fn finish(self,
               yield_ty: Option<Ty<'tcx>>)
-              -> Mir<'tcx> {
+              -> Body<'tcx> {
         for (index, block) in self.cfg.basic_blocks.iter().enumerate() {
             if block.terminator.is_none() {
                 span_bug!(self.fn_span, "no terminator on block {:?}", index);
             }
         }
 
-        Mir::new(
+        Body::new(
             self.cfg.basic_blocks,
             self.source_scopes,
             ClearCrossCrate::Set(self.source_scope_local_data),
diff --git a/src/librustc_mir/const_eval.rs b/src/librustc_mir/const_eval.rs
index 866b6492d10bc..95f380e3b7f61 100644
--- a/src/librustc_mir/const_eval.rs
+++ b/src/librustc_mir/const_eval.rs
@@ -54,7 +54,7 @@ pub(crate) fn mk_eval_cx<'a, 'mir, 'tcx>(
 pub(crate) fn eval_promoted<'a, 'mir, 'tcx>(
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     cid: GlobalId<'tcx>,
-    mir: &'mir mir::Mir<'tcx>,
+    mir: &'mir mir::Body<'tcx>,
     param_env: ty::ParamEnv<'tcx>,
 ) -> EvalResult<'tcx, MPlaceTy<'tcx>> {
     let span = tcx.def_span(cid.instance.def_id());
@@ -111,7 +111,7 @@ fn op_to_const<'tcx>(
 fn eval_body_using_ecx<'mir, 'tcx>(
     ecx: &mut CompileTimeEvalContext<'_, 'mir, 'tcx>,
     cid: GlobalId<'tcx>,
-    mir: &'mir mir::Mir<'tcx>,
+    mir: &'mir mir::Body<'tcx>,
     param_env: ty::ParamEnv<'tcx>,
 ) -> EvalResult<'tcx, MPlaceTy<'tcx>> {
     debug!("eval_body_using_ecx: {:?}, {:?}", cid, param_env);
@@ -305,7 +305,7 @@ impl<'a, 'mir, 'tcx> interpret::Machine<'a, 'mir, 'tcx>
         args: &[OpTy<'tcx>],
         dest: Option<PlaceTy<'tcx>>,
         ret: Option<mir::BasicBlock>,
-    ) -> EvalResult<'tcx, Option<&'mir mir::Mir<'tcx>>> {
+    ) -> EvalResult<'tcx, Option<&'mir mir::Body<'tcx>>> {
         debug!("eval_fn_call: {:?}", instance);
         // Only check non-glue functions
         if let ty::InstanceDef::Item(def_id) = instance.def {
diff --git a/src/librustc_mir/dataflow/drop_flag_effects.rs b/src/librustc_mir/dataflow/drop_flag_effects.rs
index aae4590a387a7..90ab3e9e5d93a 100644
--- a/src/librustc_mir/dataflow/drop_flag_effects.rs
+++ b/src/librustc_mir/dataflow/drop_flag_effects.rs
@@ -1,4 +1,4 @@
-use rustc::mir::{self, Mir, Location};
+use rustc::mir::{self, Body, Location};
 use rustc::ty::{self, TyCtxt};
 use crate::util::elaborate_drops::DropFlagState;
 
@@ -47,7 +47,7 @@ pub fn move_path_children_matching<'tcx, F>(move_data: &MoveData<'tcx>,
 //
 // FIXME: we have to do something for moving slice patterns.
 fn place_contents_drop_state_cannot_differ<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
-                                                            mir: &Mir<'tcx>,
+                                                            mir: &Body<'tcx>,
                                                             place: &mir::Place<'tcx>) -> bool {
     let ty = place.ty(mir, tcx).ty;
     match ty.sty {
@@ -74,7 +74,7 @@ fn place_contents_drop_state_cannot_differ<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx,
 
 pub(crate) fn on_lookup_result_bits<'a, 'gcx, 'tcx, F>(
     tcx: TyCtxt<'a, 'gcx, 'tcx>,
-    mir: &Mir<'tcx>,
+    mir: &Body<'tcx>,
     move_data: &MoveData<'tcx>,
     lookup_result: LookupResult,
     each_child: F)
@@ -92,7 +92,7 @@ pub(crate) fn on_lookup_result_bits<'a, 'gcx, 'tcx, F>(
 
 pub(crate) fn on_all_children_bits<'a, 'gcx, 'tcx, F>(
     tcx: TyCtxt<'a, 'gcx, 'tcx>,
-    mir: &Mir<'tcx>,
+    mir: &Body<'tcx>,
     move_data: &MoveData<'tcx>,
     move_path_index: MovePathIndex,
     mut each_child: F)
@@ -100,7 +100,7 @@ pub(crate) fn on_all_children_bits<'a, 'gcx, 'tcx, F>(
 {
     fn is_terminal_path<'a, 'gcx, 'tcx>(
         tcx: TyCtxt<'a, 'gcx, 'tcx>,
-        mir: &Mir<'tcx>,
+        mir: &Body<'tcx>,
         move_data: &MoveData<'tcx>,
         path: MovePathIndex) -> bool
     {
@@ -110,7 +110,7 @@ pub(crate) fn on_all_children_bits<'a, 'gcx, 'tcx, F>(
 
     fn on_all_children_bits<'a, 'gcx, 'tcx, F>(
         tcx: TyCtxt<'a, 'gcx, 'tcx>,
-        mir: &Mir<'tcx>,
+        mir: &Body<'tcx>,
         move_data: &MoveData<'tcx>,
         move_path_index: MovePathIndex,
         each_child: &mut F)
@@ -133,7 +133,7 @@ pub(crate) fn on_all_children_bits<'a, 'gcx, 'tcx, F>(
 
 pub(crate) fn on_all_drop_children_bits<'a, 'gcx, 'tcx, F>(
     tcx: TyCtxt<'a, 'gcx, 'tcx>,
-    mir: &Mir<'tcx>,
+    mir: &Body<'tcx>,
     ctxt: &MoveDataParamEnv<'gcx, 'tcx>,
     path: MovePathIndex,
     mut each_child: F)
@@ -156,7 +156,7 @@ pub(crate) fn on_all_drop_children_bits<'a, 'gcx, 'tcx, F>(
 
 pub(crate) fn drop_flag_effects_for_function_entry<'a, 'gcx, 'tcx, F>(
     tcx: TyCtxt<'a, 'gcx, 'tcx>,
-    mir: &Mir<'tcx>,
+    mir: &Body<'tcx>,
     ctxt: &MoveDataParamEnv<'gcx, 'tcx>,
     mut callback: F)
     where F: FnMut(MovePathIndex, DropFlagState)
@@ -173,7 +173,7 @@ pub(crate) fn drop_flag_effects_for_function_entry<'a, 'gcx, 'tcx, F>(
 
 pub(crate) fn drop_flag_effects_for_location<'a, 'gcx, 'tcx, F>(
     tcx: TyCtxt<'a, 'gcx, 'tcx>,
-    mir: &Mir<'tcx>,
+    mir: &Body<'tcx>,
     ctxt: &MoveDataParamEnv<'gcx, 'tcx>,
     loc: Location,
     mut callback: F)
@@ -205,7 +205,7 @@ pub(crate) fn drop_flag_effects_for_location<'a, 'gcx, 'tcx, F>(
 
 pub(crate) fn for_location_inits<'a, 'gcx, 'tcx, F>(
     tcx: TyCtxt<'a, 'gcx, 'tcx>,
-    mir: &Mir<'tcx>,
+    mir: &Body<'tcx>,
     move_data: &MoveData<'tcx>,
     loc: Location,
     mut callback: F)
diff --git a/src/librustc_mir/dataflow/graphviz.rs b/src/librustc_mir/dataflow/graphviz.rs
index d68377681f1ca..4965f1a585d48 100644
--- a/src/librustc_mir/dataflow/graphviz.rs
+++ b/src/librustc_mir/dataflow/graphviz.rs
@@ -1,7 +1,7 @@
 //! Hook into libgraphviz for rendering dataflow graphs for MIR.
 
 use rustc::hir::def_id::DefId;
-use rustc::mir::{BasicBlock, Mir};
+use rustc::mir::{BasicBlock, Body};
 
 use std::fs;
 use std::io;
@@ -17,7 +17,7 @@ use super::DebugFormatted;
 pub trait MirWithFlowState<'tcx> {
     type BD: BitDenotation<'tcx>;
     fn def_id(&self) -> DefId;
-    fn mir(&self) -> &Mir<'tcx>;
+    fn mir(&self) -> &Body<'tcx>;
     fn flow_state(&self) -> &DataflowState<'tcx, Self::BD>;
 }
 
@@ -26,7 +26,7 @@ impl<'a, 'tcx, BD> MirWithFlowState<'tcx> for DataflowBuilder<'a, 'tcx, BD>
 {
     type BD = BD;
     fn def_id(&self) -> DefId { self.def_id }
-    fn mir(&self) -> &Mir<'tcx> { self.flow_state.mir() }
+    fn mir(&self) -> &Body<'tcx> { self.flow_state.mir() }
     fn flow_state(&self) -> &DataflowState<'tcx, Self::BD> { &self.flow_state.flow_state }
 }
 
@@ -59,7 +59,7 @@ pub type Node = BasicBlock;
 #[derive(Copy, Clone, PartialEq, Eq, Debug)]
 pub struct Edge { source: BasicBlock, index: usize }
 
-fn outgoing(mir: &Mir<'_>, bb: BasicBlock) -> Vec<Edge> {
+fn outgoing(mir: &Body<'_>, bb: BasicBlock) -> Vec<Edge> {
     (0..mir[bb].terminator().successors().count())
         .map(|index| Edge { source: bb, index: index}).collect()
 }
@@ -124,7 +124,7 @@ where MWF: MirWithFlowState<'tcx>,
                                          n: &Node,
                                          w: &mut W,
                                          block: BasicBlock,
-                                         mir: &Mir<'_>) -> io::Result<()> {
+                                         mir: &Body<'_>) -> io::Result<()> {
         // Header rows
         const HDRS: [&str; 4] = ["ENTRY", "MIR", "BLOCK GENS", "BLOCK KILLS"];
         const HDR_FMT: &str = "bgcolor=\"grey\"";
@@ -149,7 +149,7 @@ where MWF: MirWithFlowState<'tcx>,
                                             n: &Node,
                                             w: &mut W,
                                             block: BasicBlock,
-                                            mir: &Mir<'_>)
+                                            mir: &Body<'_>)
                                             -> io::Result<()> {
         let i = n.index();
 
@@ -199,7 +199,7 @@ where MWF: MirWithFlowState<'tcx>,
                                           n: &Node,
                                           w: &mut W,
                                           block: BasicBlock,
-                                          mir: &Mir<'_>)
+                                          mir: &Body<'_>)
                                           -> io::Result<()> {
         let i = n.index();
 
diff --git a/src/librustc_mir/dataflow/impls/borrowed_locals.rs b/src/librustc_mir/dataflow/impls/borrowed_locals.rs
index 42c2387b7052d..47af10a1c5023 100644
--- a/src/librustc_mir/dataflow/impls/borrowed_locals.rs
+++ b/src/librustc_mir/dataflow/impls/borrowed_locals.rs
@@ -12,16 +12,16 @@ use crate::dataflow::BitDenotation;
 /// immovable generators.
 #[derive(Copy, Clone)]
 pub struct HaveBeenBorrowedLocals<'a, 'tcx: 'a> {
-    mir: &'a Mir<'tcx>,
+    mir: &'a Body<'tcx>,
 }
 
 impl<'a, 'tcx: 'a> HaveBeenBorrowedLocals<'a, 'tcx> {
-    pub fn new(mir: &'a Mir<'tcx>)
+    pub fn new(mir: &'a Body<'tcx>)
                -> Self {
         HaveBeenBorrowedLocals { mir }
     }
 
-    pub fn mir(&self) -> &Mir<'tcx> {
+    pub fn mir(&self) -> &Body<'tcx> {
         self.mir
     }
 }
@@ -91,16 +91,19 @@ struct BorrowedLocalsVisitor<'b, 'c: 'b> {
 }
 
 fn find_local<'tcx>(place: &Place<'tcx>) -> Option<Local> {
-    match *place {
-        Place::Base(PlaceBase::Local(l)) => Some(l),
-        Place::Base(PlaceBase::Static(..)) => None,
-        Place::Projection(ref proj) => {
-            match proj.elem {
-                ProjectionElem::Deref => None,
-                _ => find_local(&proj.base)
+    place.iterate(|place_base, place_projection| {
+        for proj in place_projection {
+            if proj.elem == ProjectionElem::Deref {
+                return None;
             }
         }
-    }
+
+        if let PlaceBase::Local(local) = place_base {
+            Some(*local)
+        } else {
+            None
+        }
+    })
 }
 
 impl<'tcx, 'b, 'c> Visitor<'tcx> for BorrowedLocalsVisitor<'b, 'c> {
diff --git a/src/librustc_mir/dataflow/impls/borrows.rs b/src/librustc_mir/dataflow/impls/borrows.rs
index 43cb0ed4565fe..99051fb37f148 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, PlaceBase, Mir};
+use rustc::mir::{self, Location, Place, PlaceBase, Body};
 use rustc::ty::TyCtxt;
 use rustc::ty::RegionVid;
 
@@ -31,7 +31,7 @@ newtype_index! {
 /// borrows in compact bitvectors.
 pub struct Borrows<'a, 'gcx: 'tcx, 'tcx: 'a> {
     tcx: TyCtxt<'a, 'gcx, 'tcx>,
-    mir: &'a Mir<'tcx>,
+    mir: &'a Body<'tcx>,
 
     borrow_set: Rc<BorrowSet<'tcx>>,
     borrows_out_of_scope_at_location: FxHashMap<Location, Vec<BorrowIndex>>,
@@ -48,7 +48,7 @@ struct StackEntry {
 }
 
 fn precompute_borrows_out_of_scope<'tcx>(
-    mir: &Mir<'tcx>,
+    mir: &Body<'tcx>,
     regioncx: &Rc<RegionInferenceContext<'tcx>>,
     borrows_out_of_scope_at_location: &mut FxHashMap<Location, Vec<BorrowIndex>>,
     borrow_index: BorrowIndex,
@@ -136,7 +136,7 @@ fn precompute_borrows_out_of_scope<'tcx>(
 impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> {
     crate fn new(
         tcx: TyCtxt<'a, 'gcx, 'tcx>,
-        mir: &'a Mir<'tcx>,
+        mir: &'a Body<'tcx>,
         nonlexical_regioncx: Rc<RegionInferenceContext<'tcx>>,
         borrow_set: &Rc<BorrowSet<'tcx>>,
     ) -> Self {
diff --git a/src/librustc_mir/dataflow/impls/mod.rs b/src/librustc_mir/dataflow/impls/mod.rs
index 03d55b84f32e2..4f3b180edd111 100644
--- a/src/librustc_mir/dataflow/impls/mod.rs
+++ b/src/librustc_mir/dataflow/impls/mod.rs
@@ -3,7 +3,7 @@
 //! zero-sized structure.
 
 use rustc::ty::TyCtxt;
-use rustc::mir::{self, Mir, Location};
+use rustc::mir::{self, Body, Location};
 use rustc_data_structures::bit_set::{BitSet, BitSetOperator};
 use rustc_data_structures::indexed_vec::Idx;
 
@@ -65,13 +65,13 @@ pub(super) mod borrows;
 /// places that would require a dynamic drop-flag at that statement.
 pub struct MaybeInitializedPlaces<'a, 'gcx: 'tcx, 'tcx: 'a> {
     tcx: TyCtxt<'a, 'gcx, 'tcx>,
-    mir: &'a Mir<'tcx>,
+    mir: &'a Body<'tcx>,
     mdpe: &'a MoveDataParamEnv<'gcx, 'tcx>,
 }
 
 impl<'a, 'gcx: 'tcx, 'tcx> MaybeInitializedPlaces<'a, 'gcx, 'tcx> {
     pub fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>,
-               mir: &'a Mir<'tcx>,
+               mir: &'a Body<'tcx>,
                mdpe: &'a MoveDataParamEnv<'gcx, 'tcx>)
                -> Self
     {
@@ -120,13 +120,13 @@ impl<'a, 'gcx, 'tcx> HasMoveData<'tcx> for MaybeInitializedPlaces<'a, 'gcx, 'tcx
 /// places that would require a dynamic drop-flag at that statement.
 pub struct MaybeUninitializedPlaces<'a, 'gcx: 'tcx, 'tcx: 'a> {
     tcx: TyCtxt<'a, 'gcx, 'tcx>,
-    mir: &'a Mir<'tcx>,
+    mir: &'a Body<'tcx>,
     mdpe: &'a MoveDataParamEnv<'gcx, 'tcx>,
 }
 
 impl<'a, 'gcx, 'tcx> MaybeUninitializedPlaces<'a, 'gcx, 'tcx> {
     pub fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>,
-               mir: &'a Mir<'tcx>,
+               mir: &'a Body<'tcx>,
                mdpe: &'a MoveDataParamEnv<'gcx, 'tcx>)
                -> Self
     {
@@ -174,13 +174,13 @@ impl<'a, 'gcx, 'tcx> HasMoveData<'tcx> for MaybeUninitializedPlaces<'a, 'gcx, 't
 /// that would require a dynamic drop-flag at that statement.
 pub struct DefinitelyInitializedPlaces<'a, 'gcx: 'tcx, 'tcx: 'a> {
     tcx: TyCtxt<'a, 'gcx, 'tcx>,
-    mir: &'a Mir<'tcx>,
+    mir: &'a Body<'tcx>,
     mdpe: &'a MoveDataParamEnv<'gcx, 'tcx>,
 }
 
 impl<'a, 'gcx, 'tcx: 'a> DefinitelyInitializedPlaces<'a, 'gcx, 'tcx> {
     pub fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>,
-               mir: &'a Mir<'tcx>,
+               mir: &'a Body<'tcx>,
                mdpe: &'a MoveDataParamEnv<'gcx, 'tcx>)
                -> Self
     {
@@ -223,13 +223,13 @@ impl<'a, 'gcx, 'tcx: 'a> HasMoveData<'tcx> for DefinitelyInitializedPlaces<'a, '
 /// ```
 pub struct EverInitializedPlaces<'a, 'gcx: 'tcx, 'tcx: 'a> {
     tcx: TyCtxt<'a, 'gcx, 'tcx>,
-    mir: &'a Mir<'tcx>,
+    mir: &'a Body<'tcx>,
     mdpe: &'a MoveDataParamEnv<'gcx, 'tcx>,
 }
 
 impl<'a, 'gcx: 'tcx, 'tcx: 'a> EverInitializedPlaces<'a, 'gcx, 'tcx> {
     pub fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>,
-               mir: &'a Mir<'tcx>,
+               mir: &'a Body<'tcx>,
                mdpe: &'a MoveDataParamEnv<'gcx, 'tcx>)
                -> Self
     {
diff --git a/src/librustc_mir/dataflow/impls/storage_liveness.rs b/src/librustc_mir/dataflow/impls/storage_liveness.rs
index 3bf11c57379c2..ab79d6cc947e8 100644
--- a/src/librustc_mir/dataflow/impls/storage_liveness.rs
+++ b/src/librustc_mir/dataflow/impls/storage_liveness.rs
@@ -5,16 +5,16 @@ use crate::dataflow::BitDenotation;
 
 #[derive(Copy, Clone)]
 pub struct MaybeStorageLive<'a, 'tcx: 'a> {
-    mir: &'a Mir<'tcx>,
+    mir: &'a Body<'tcx>,
 }
 
 impl<'a, 'tcx: 'a> MaybeStorageLive<'a, 'tcx> {
-    pub fn new(mir: &'a Mir<'tcx>)
+    pub fn new(mir: &'a Body<'tcx>)
                -> Self {
         MaybeStorageLive { mir }
     }
 
-    pub fn mir(&self) -> &Mir<'tcx> {
+    pub fn mir(&self) -> &Body<'tcx> {
         self.mir
     }
 }
diff --git a/src/librustc_mir/dataflow/mod.rs b/src/librustc_mir/dataflow/mod.rs
index a9d23a0afeabc..26bad0cb04d70 100644
--- a/src/librustc_mir/dataflow/mod.rs
+++ b/src/librustc_mir/dataflow/mod.rs
@@ -7,7 +7,7 @@ use rustc_data_structures::work_queue::WorkQueue;
 
 use rustc::hir::def_id::DefId;
 use rustc::ty::{self, TyCtxt};
-use rustc::mir::{self, Mir, BasicBlock, BasicBlockData, Location, Statement, Terminator};
+use rustc::mir::{self, Body, BasicBlock, BasicBlockData, Location, Statement, Terminator};
 use rustc::mir::traversal;
 use rustc::session::Session;
 
@@ -122,7 +122,7 @@ pub struct MoveDataParamEnv<'gcx, 'tcx> {
 }
 
 pub(crate) fn do_dataflow<'a, 'gcx, 'tcx, BD, P>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
-                                                 mir: &'a Mir<'tcx>,
+                                                 mir: &'a Body<'tcx>,
                                                  def_id: DefId,
                                                  attributes: &[ast::Attribute],
                                                  dead_unwinds: &BitSet<BasicBlock>,
@@ -343,13 +343,13 @@ pub(crate) trait DataflowResultsConsumer<'a, 'tcx: 'a> {
 
     // Delegated Hooks: Provide access to the MIR and process the flow state.
 
-    fn mir(&self) -> &'a Mir<'tcx>;
+    fn mir(&self) -> &'a Body<'tcx>;
 }
 
 pub fn state_for_location<'tcx, T: BitDenotation<'tcx>>(loc: Location,
                                                         analysis: &T,
                                                         result: &DataflowResults<'tcx, T>,
-                                                        mir: &Mir<'tcx>)
+                                                        mir: &Body<'tcx>)
     -> BitSet<T::Idx> {
     let mut on_entry = result.sets().on_entry_set_for(loc.block.index()).to_owned();
     let mut kill_set = on_entry.to_hybrid();
@@ -384,7 +384,7 @@ pub struct DataflowAnalysis<'a, 'tcx: 'a, O> where O: BitDenotation<'tcx>
 {
     flow_state: DataflowState<'tcx, O>,
     dead_unwinds: &'a BitSet<mir::BasicBlock>,
-    mir: &'a Mir<'tcx>,
+    mir: &'a Body<'tcx>,
 }
 
 impl<'a, 'tcx: 'a, O> DataflowAnalysis<'a, 'tcx, O> where O: BitDenotation<'tcx>
@@ -393,7 +393,7 @@ impl<'a, 'tcx: 'a, O> DataflowAnalysis<'a, 'tcx, O> where O: BitDenotation<'tcx>
         DataflowResults(self.flow_state)
     }
 
-    pub fn mir(&self) -> &'a Mir<'tcx> { self.mir }
+    pub fn mir(&self) -> &'a Body<'tcx> { self.mir }
 }
 
 pub struct DataflowResults<'tcx, O>(pub(crate) DataflowState<'tcx, O>) where O: BitDenotation<'tcx>;
@@ -697,7 +697,7 @@ pub trait BitDenotation<'tcx>: BitSetOperator {
 
 impl<'a, 'tcx, D> DataflowAnalysis<'a, 'tcx, D> where D: BitDenotation<'tcx>
 {
-    pub fn new(mir: &'a Mir<'tcx>,
+    pub fn new(mir: &'a Body<'tcx>,
                dead_unwinds: &'a BitSet<mir::BasicBlock>,
                denotation: D) -> Self where D: InitialFlow {
         let bits_per_block = denotation.bits_per_block();
diff --git a/src/librustc_mir/dataflow/move_paths/builder.rs b/src/librustc_mir/dataflow/move_paths/builder.rs
index 2471c01e3f3d0..6930be972eee4 100644
--- a/src/librustc_mir/dataflow/move_paths/builder.rs
+++ b/src/librustc_mir/dataflow/move_paths/builder.rs
@@ -13,14 +13,14 @@ use super::{MoveError, InitIndex, Init, InitLocation, LookupResult, InitKind};
 use super::IllegalMoveOriginKind::*;
 
 struct MoveDataBuilder<'a, 'gcx: 'tcx, 'tcx: 'a> {
-    mir: &'a Mir<'tcx>,
+    mir: &'a Body<'tcx>,
     tcx: TyCtxt<'a, 'gcx, 'tcx>,
     data: MoveData<'tcx>,
     errors: Vec<(Place<'tcx>, MoveError<'tcx>)>,
 }
 
 impl<'a, 'gcx, 'tcx> MoveDataBuilder<'a, 'gcx, 'tcx> {
-    fn new(mir: &'a Mir<'tcx>, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Self {
+    fn new(mir: &'a Body<'tcx>, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Self {
         let mut move_paths = IndexVec::new();
         let mut path_map = IndexVec::new();
         let mut init_path_map = IndexVec::new();
@@ -198,7 +198,7 @@ impl<'a, 'gcx, 'tcx> MoveDataBuilder<'a, 'gcx, 'tcx> {
 }
 
 pub(super) fn gather_moves<'a, 'gcx, 'tcx>(
-    mir: &Mir<'tcx>,
+    mir: &Body<'tcx>,
     tcx: TyCtxt<'a, 'gcx, 'tcx>
 ) -> Result<MoveData<'tcx>, (MoveData<'tcx>, Vec<(Place<'tcx>, MoveError<'tcx>)>)> {
     let mut builder = MoveDataBuilder::new(mir, tcx);
diff --git a/src/librustc_mir/dataflow/move_paths/mod.rs b/src/librustc_mir/dataflow/move_paths/mod.rs
index 6d619793160fb..0d20040d0d2d7 100644
--- a/src/librustc_mir/dataflow/move_paths/mod.rs
+++ b/src/librustc_mir/dataflow/move_paths/mod.rs
@@ -138,7 +138,7 @@ impl<T> IndexMut<Location> for LocationMap<T> {
 }
 
 impl<T> LocationMap<T> where T: Default + Clone {
-    fn new(mir: &Mir<'_>) -> Self {
+    fn new(mir: &Body<'_>) -> Self {
         LocationMap {
             map: mir.basic_blocks().iter().map(|block| {
                 vec![T::default(); block.statements.len()+1]
@@ -205,7 +205,7 @@ impl fmt::Debug for Init {
 }
 
 impl Init {
-    crate fn span<'gcx>(&self, mir: &Mir<'gcx>) -> Span {
+    crate fn span<'gcx>(&self, mir: &Body<'gcx>) -> Span {
         match self.location {
             InitLocation::Argument(local) => mir.local_decls[local].source_info.span,
             InitLocation::Statement(location) => mir.source_info(location).span,
@@ -241,21 +241,22 @@ impl MovePathLookup {
     // unknown place, but will rather return the nearest available
     // parent.
     pub fn find(&self, place: &Place<'tcx>) -> LookupResult {
-        match *place {
-            Place::Base(PlaceBase::Local(local)) => LookupResult::Exact(self.locals[local]),
-            Place::Base(PlaceBase::Static(..)) => LookupResult::Parent(None),
-            Place::Projection(ref proj) => {
-                match self.find(&proj.base) {
-                    LookupResult::Exact(base_path) => {
-                        match self.projections.get(&(base_path, proj.elem.lift())) {
-                            Some(&subpath) => LookupResult::Exact(subpath),
-                            None => LookupResult::Parent(Some(base_path))
-                        }
-                    }
-                    inexact => inexact
+        place.iterate(|place_base, place_projection| {
+            let mut result = match place_base {
+                PlaceBase::Local(local) => self.locals[*local],
+                PlaceBase::Static(..) => return LookupResult::Parent(None),
+            };
+
+            for proj in place_projection {
+                if let Some(&subpath) = self.projections.get(&(result, proj.elem.lift())) {
+                    result = subpath;
+                } else {
+                    return LookupResult::Parent(Some(result));
                 }
             }
-        }
+
+            LookupResult::Exact(result)
+        })
     }
 
     pub fn find_local(&self, local: Local) -> MovePathIndex {
@@ -305,7 +306,7 @@ impl<'tcx> MoveError<'tcx> {
 }
 
 impl<'a, 'gcx, 'tcx> MoveData<'tcx> {
-    pub fn gather_moves(mir: &Mir<'tcx>, tcx: TyCtxt<'a, 'gcx, 'tcx>)
+    pub fn gather_moves(mir: &Body<'tcx>, tcx: TyCtxt<'a, 'gcx, 'tcx>)
                         -> Result<Self, (Self, Vec<(Place<'tcx>, MoveError<'tcx>)>)> {
         builder::gather_moves(mir, tcx)
     }
diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs
index d4c1e5416d565..e11fe516a8bbb 100644
--- a/src/librustc_mir/interpret/eval_context.rs
+++ b/src/librustc_mir/interpret/eval_context.rs
@@ -53,7 +53,7 @@ pub struct Frame<'mir, 'tcx: 'mir, Tag=(), Extra=()> {
     // Function and callsite information
     ////////////////////////////////////////////////////////////////////////////////
     /// The MIR for the function called on this frame.
-    pub mir: &'mir mir::Mir<'tcx>,
+    pub mir: &'mir mir::Body<'tcx>,
 
     /// The def_id and substs of the current function.
     pub instance: ty::Instance<'tcx>,
@@ -244,7 +244,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tc
     }
 
     #[inline(always)]
-    pub(super) fn mir(&self) -> &'mir mir::Mir<'tcx> {
+    pub(super) fn mir(&self) -> &'mir mir::Body<'tcx> {
         self.frame().mir
     }
 
@@ -294,7 +294,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tc
     pub fn load_mir(
         &self,
         instance: ty::InstanceDef<'tcx>,
-    ) -> EvalResult<'tcx, &'tcx mir::Mir<'tcx>> {
+    ) -> EvalResult<'tcx, &'tcx mir::Body<'tcx>> {
         // do not continue if typeck errors occurred (can only occur in local crate)
         let did = instance.def_id();
         if did.is_local()
@@ -472,7 +472,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tc
         &mut self,
         instance: ty::Instance<'tcx>,
         span: source_map::Span,
-        mir: &'mir mir::Mir<'tcx>,
+        mir: &'mir mir::Body<'tcx>,
         return_place: Option<PlaceTy<'tcx, M::PointerTag>>,
         return_to_block: StackPopCleanup,
     ) -> EvalResult<'tcx> {
diff --git a/src/librustc_mir/interpret/machine.rs b/src/librustc_mir/interpret/machine.rs
index 288ffbf3cd616..873c2d2ec6088 100644
--- a/src/librustc_mir/interpret/machine.rs
+++ b/src/librustc_mir/interpret/machine.rs
@@ -117,7 +117,7 @@ pub trait Machine<'a, 'mir, 'tcx>: Sized {
         args: &[OpTy<'tcx, Self::PointerTag>],
         dest: Option<PlaceTy<'tcx, Self::PointerTag>>,
         ret: Option<mir::BasicBlock>,
-    ) -> EvalResult<'tcx, Option<&'mir mir::Mir<'tcx>>>;
+    ) -> EvalResult<'tcx, Option<&'mir mir::Body<'tcx>>>;
 
     /// Directly process an intrinsic without pushing a stack frame.
     /// If this returns successfully, the engine will take care of jumping to the next block.
diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs
index 9c2b491925f47..a674389a93695 100644
--- a/src/librustc_mir/interpret/operand.rs
+++ b/src/librustc_mir/interpret/operand.rs
@@ -467,22 +467,34 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M>
         mir_place: &mir::Place<'tcx>,
         layout: Option<TyLayout<'tcx>>,
     ) -> EvalResult<'tcx, OpTy<'tcx, M::PointerTag>> {
-        use rustc::mir::Place::*;
+        use rustc::mir::Place;
         use rustc::mir::PlaceBase;
-        let op = match *mir_place {
-            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)?;
-                self.operand_projection(op, &proj.elem)?
-            }
+        mir_place.iterate(|place_base, place_projection| {
+            let mut op = match place_base {
+                PlaceBase::Local(mir::RETURN_PLACE) => return err!(ReadFromReturnPointer),
+                PlaceBase::Local(local) => {
+                    // FIXME use place_projection.is_empty() when is available
+                    let layout = if let Place::Base(_) = mir_place {
+                        layout
+                    } else {
+                        None
+                    };
+
+                    self.access_local(self.frame(), *local, layout)?
+                }
+                PlaceBase::Static(place_static) => {
+                    self.eval_static_to_mplace(place_static)?.into()
+                }
+            };
 
-            _ => self.eval_place_to_mplace(mir_place)?.into(),
-        };
+            for proj in place_projection {
+                op = self.operand_projection(op, &proj.elem)?
+            }
 
-        trace!("eval_place_to_op: got {:?}", *op);
-        Ok(op)
+            trace!("eval_place_to_op: got {:?}", *op);
+            Ok(op)
+        })
     }
 
     /// Evaluate the operand, returning a place where you can then find the data.
diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs
index 0cc480028161f..65e5e23e38424 100644
--- a/src/librustc_mir/interpret/place.rs
+++ b/src/librustc_mir/interpret/place.rs
@@ -562,15 +562,14 @@ where
 
     /// Evaluate statics and promoteds to an `MPlace`. Used to share some code between
     /// `eval_place` and `eval_place_to_op`.
-    pub(super) fn eval_place_to_mplace(
+    pub(super) fn eval_static_to_mplace(
         &self,
-        mir_place: &mir::Place<'tcx>
+        place_static: &mir::Static<'tcx>
     ) -> EvalResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> {
-        use rustc::mir::Place::*;
-        use rustc::mir::PlaceBase;
-        use rustc::mir::{Static, StaticKind};
-        Ok(match *mir_place {
-            Base(PlaceBase::Static(box Static { kind: StaticKind::Promoted(promoted), .. })) => {
+        use rustc::mir::StaticKind;
+
+        Ok(match place_static.kind {
+            StaticKind::Promoted(promoted) => {
                 let instance = self.frame().instance;
                 self.const_eval_raw(GlobalId {
                     instance,
@@ -578,7 +577,8 @@ where
                 })?
             }
 
-            Base(PlaceBase::Static(box Static { kind: StaticKind::Static(def_id), ty })) => {
+            StaticKind::Static(def_id) => {
+                let ty = place_static.ty;
                 assert!(!ty.needs_subst());
                 let layout = self.layout_of(ty)?;
                 let instance = ty::Instance::mono(*self.tcx, def_id);
@@ -600,8 +600,6 @@ where
                 let alloc = self.tcx.alloc_map.lock().intern_static(cid.instance.def_id());
                 MPlaceTy::from_aligned_ptr(Pointer::from(alloc).with_default_tag(), layout)
             }
-
-            _ => bug!("eval_place_to_mplace called on {:?}", mir_place),
         })
     }
 
@@ -613,7 +611,7 @@ where
     ) -> EvalResult<'tcx, PlaceTy<'tcx, M::PointerTag>> {
         use rustc::mir::Place::*;
         use rustc::mir::PlaceBase;
-        let place = match *mir_place {
+        let place = match mir_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
@@ -628,17 +626,19 @@ where
                 // This works even for dead/uninitialized locals; we check further when writing
                 place: Place::Local {
                     frame: self.cur_frame(),
-                    local,
+                    local: *local,
                 },
-                layout: self.layout_of_local(self.frame(), local, None)?,
+                layout: self.layout_of_local(self.frame(), *local, None)?,
             },
 
-            Projection(ref proj) => {
+            Projection(proj) => {
                 let place = self.eval_place(&proj.base)?;
                 self.place_projection(place, &proj.elem)?
             }
 
-            _ => self.eval_place_to_mplace(mir_place)?.into(),
+            Base(PlaceBase::Static(place_static)) => {
+                self.eval_static_to_mplace(place_static)?.into()
+            }
         };
 
         self.dump_place(place.place);
diff --git a/src/librustc_mir/interpret/validity.rs b/src/librustc_mir/interpret/validity.rs
index 0d3ee830574ba..ccc38191a93b8 100644
--- a/src/librustc_mir/interpret/validity.rs
+++ b/src/librustc_mir/interpret/validity.rs
@@ -2,7 +2,7 @@ use std::fmt::Write;
 use std::hash::Hash;
 use std::ops::RangeInclusive;
 
-use syntax_pos::symbol::Symbol;
+use syntax_pos::symbol::{sym, Symbol};
 use rustc::hir;
 use rustc::ty::layout::{self, Size, Align, TyLayout, LayoutOf, VariantIdx};
 use rustc::ty;
@@ -188,7 +188,7 @@ impl<'rt, 'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> ValidityVisitor<'rt, 'a, '
 
                 PathElem::ClosureVar(name.unwrap_or_else(|| {
                     // Fall back to showing the field index.
-                    Symbol::intern(&field.to_string())
+                    sym::integer(field)
                 }))
             }
 
diff --git a/src/librustc_mir/lints.rs b/src/librustc_mir/lints.rs
index 572f7133cad84..5c0074ac9b77b 100644
--- a/src/librustc_mir/lints.rs
+++ b/src/librustc_mir/lints.rs
@@ -3,12 +3,12 @@ use rustc::hir::def_id::DefId;
 use rustc::hir::intravisit::FnKind;
 use rustc::hir::map::blocks::FnLikeNode;
 use rustc::lint::builtin::UNCONDITIONAL_RECURSION;
-use rustc::mir::{self, Mir, TerminatorKind};
+use rustc::mir::{self, Body, TerminatorKind};
 use rustc::ty::{self, AssociatedItem, AssociatedItemContainer, Instance, TyCtxt};
 use rustc::ty::subst::InternalSubsts;
 
 pub fn check(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-             mir: &Mir<'tcx>,
+             mir: &Body<'tcx>,
              def_id: DefId) {
     let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap();
 
@@ -19,7 +19,7 @@ pub fn check(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
 fn check_fn_for_unconditional_recursion(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                         fn_kind: FnKind<'_>,
-                                        mir: &Mir<'tcx>,
+                                        mir: &Body<'tcx>,
                                         def_id: DefId) {
     if let FnKind::Closure(_) = fn_kind {
         // closures can't recur, so they don't matter.
diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs
index 91cf0fbb9b44f..4aa316d8da4e0 100644
--- a/src/librustc_mir/monomorphize/collector.rs
+++ b/src/librustc_mir/monomorphize/collector.rs
@@ -517,7 +517,7 @@ fn check_type_length_limit<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
 struct MirNeighborCollector<'a, 'tcx: 'a> {
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
-    mir: &'a mir::Mir<'tcx>,
+    mir: &'a mir::Body<'tcx>,
     output: &'a mut Vec<MonoItem<'tcx>>,
     param_substs: SubstsRef<'tcx>,
 }
@@ -1218,7 +1218,7 @@ fn collect_neighbours<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         mir: &mir,
         output,
         param_substs: instance.substs,
-    }.visit_mir(&mir);
+    }.visit_body(&mir);
     let param_env = ty::ParamEnv::reveal_all();
     for i in 0..mir.promoted.len() {
         use rustc_data_structures::indexed_vec::Idx;
diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs
index b9224d973fe7b..cd641d06aee7a 100644
--- a/src/librustc_mir/shim.rs
+++ b/src/librustc_mir/shim.rs
@@ -28,7 +28,7 @@ pub fn provide(providers: &mut Providers<'_>) {
 
 fn make_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                        instance: ty::InstanceDef<'tcx>)
-                       -> &'tcx Mir<'tcx>
+                       -> &'tcx Body<'tcx>
 {
     debug!("make_shim({:?})", instance);
 
@@ -169,7 +169,7 @@ fn local_decls_for_sig<'tcx>(sig: &ty::FnSig<'tcx>, span: Span)
 fn build_drop_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                              def_id: DefId,
                              ty: Option<Ty<'tcx>>)
-                             -> Mir<'tcx>
+                             -> Body<'tcx>
 {
     debug!("build_drop_shim(def_id={:?}, ty={:?})", def_id, ty);
 
@@ -202,7 +202,7 @@ fn build_drop_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     block(&mut blocks, TerminatorKind::Goto { target: return_block });
     block(&mut blocks, TerminatorKind::Return);
 
-    let mut mir = Mir::new(
+    let mut mir = Body::new(
         blocks,
         IndexVec::from_elem_n(
             SourceScopeData { span: span, parent_scope: None }, 1
@@ -256,7 +256,7 @@ fn build_drop_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 }
 
 pub struct DropShimElaborator<'a, 'tcx: 'a> {
-    pub mir: &'a Mir<'tcx>,
+    pub mir: &'a Body<'tcx>,
     pub patch: MirPatch<'tcx>,
     pub tcx: TyCtxt<'a, 'tcx, 'tcx>,
     pub param_env: ty::ParamEnv<'tcx>,
@@ -272,7 +272,7 @@ impl<'a, 'tcx> DropElaborator<'a, 'tcx> for DropShimElaborator<'a, 'tcx> {
     type Path = ();
 
     fn patch(&mut self) -> &mut MirPatch<'tcx> { &mut self.patch }
-    fn mir(&self) -> &'a Mir<'tcx> { self.mir }
+    fn mir(&self) -> &'a Body<'tcx> { self.mir }
     fn tcx(&self) -> TyCtxt<'a, 'tcx, 'tcx> { self.tcx }
     fn param_env(&self) -> ty::ParamEnv<'tcx> { self.param_env }
 
@@ -309,7 +309,7 @@ impl<'a, 'tcx> DropElaborator<'a, 'tcx> for DropShimElaborator<'a, 'tcx> {
 fn build_clone_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                               def_id: DefId,
                               self_ty: Ty<'tcx>)
-                              -> Mir<'tcx>
+                              -> Body<'tcx>
 {
     debug!("build_clone_shim(def_id={:?})", def_id);
 
@@ -371,8 +371,8 @@ impl<'a, 'tcx> CloneShimBuilder<'a, 'tcx> {
         }
     }
 
-    fn into_mir(self) -> Mir<'tcx> {
-        Mir::new(
+    fn into_mir(self) -> Body<'tcx> {
+        Body::new(
             self.blocks,
             IndexVec::from_elem_n(
                 SourceScopeData { span: self.span, parent_scope: None }, 1
@@ -700,7 +700,7 @@ fn build_call_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                              rcvr_adjustment: Adjustment,
                              call_kind: CallKind,
                              untuple_args: Option<&[Ty<'tcx>]>)
-                             -> Mir<'tcx>
+                             -> Body<'tcx>
 {
     debug!("build_call_shim(def_id={:?}, rcvr_adjustment={:?}, \
             call_kind={:?}, untuple_args={:?})",
@@ -827,7 +827,7 @@ fn build_call_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         block(&mut blocks, vec![], TerminatorKind::Resume, true);
     }
 
-    let mut mir = Mir::new(
+    let mut mir = Body::new(
         blocks,
         IndexVec::from_elem_n(
             SourceScopeData { span: span, parent_scope: None }, 1
@@ -852,7 +852,7 @@ pub fn build_adt_ctor<'a, 'gcx, 'tcx>(infcx: &infer::InferCtxt<'a, 'gcx, 'tcx>,
                                       ctor_id: hir::HirId,
                                       fields: &[hir::StructField],
                                       span: Span)
-                                      -> Mir<'tcx>
+                                      -> Body<'tcx>
 {
     let tcx = infcx.tcx;
     let gcx = tcx.global_tcx();
@@ -906,7 +906,7 @@ pub fn build_adt_ctor<'a, 'gcx, 'tcx>(infcx: &infer::InferCtxt<'a, 'gcx, 'tcx>,
         is_cleanup: false
     };
 
-    Mir::new(
+    Body::new(
         IndexVec::from_elem_n(start_block, 1),
         IndexVec::from_elem_n(
             SourceScopeData { span: span, parent_scope: None }, 1
diff --git a/src/librustc_mir/transform/add_call_guards.rs b/src/librustc_mir/transform/add_call_guards.rs
index 88042d64e96b7..712e9b1fe2505 100644
--- a/src/librustc_mir/transform/add_call_guards.rs
+++ b/src/librustc_mir/transform/add_call_guards.rs
@@ -34,13 +34,13 @@ impl MirPass for AddCallGuards {
     fn run_pass<'a, 'tcx>(&self,
                           _tcx: TyCtxt<'a, 'tcx, 'tcx>,
                           _src: MirSource<'tcx>,
-                          mir: &mut Mir<'tcx>) {
+                          mir: &mut Body<'tcx>) {
         self.add_call_guards(mir);
     }
 }
 
 impl AddCallGuards {
-    pub fn add_call_guards(&self, mir: &mut Mir<'_>) {
+    pub fn add_call_guards(&self, mir: &mut Body<'_>) {
         let pred_count: IndexVec<_, _> =
             mir.predecessors().iter().map(|ps| ps.len()).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 b6436ec70eef2..f7a4bf759545c 100644
--- a/src/librustc_mir/transform/add_moves_for_packed_drops.rs
+++ b/src/librustc_mir/transform/add_moves_for_packed_drops.rs
@@ -43,7 +43,7 @@ impl MirPass for AddMovesForPackedDrops {
     fn run_pass<'a, 'tcx>(&self,
                           tcx: TyCtxt<'a, 'tcx, 'tcx>,
                           src: MirSource<'tcx>,
-                          mir: &mut Mir<'tcx>)
+                          mir: &mut Body<'tcx>)
     {
         debug!("add_moves_for_packed_drops({:?} @ {:?})", src, mir.span);
         add_moves_for_packed_drops(tcx, mir, src.def_id());
@@ -52,7 +52,7 @@ impl MirPass for AddMovesForPackedDrops {
 
 pub fn add_moves_for_packed_drops<'a, 'tcx>(
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
-    mir: &mut Mir<'tcx>,
+    mir: &mut Body<'tcx>,
     def_id: DefId)
 {
     let patch = add_moves_for_packed_drops_patch(tcx, mir, def_id);
@@ -61,7 +61,7 @@ pub fn add_moves_for_packed_drops<'a, 'tcx>(
 
 fn add_moves_for_packed_drops_patch<'a, 'tcx>(
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
-    mir: &Mir<'tcx>,
+    mir: &Body<'tcx>,
     def_id: DefId)
     -> MirPatch<'tcx>
 {
@@ -92,7 +92,7 @@ fn add_moves_for_packed_drops_patch<'a, 'tcx>(
 
 fn add_move_for_packed_drop<'a, 'tcx>(
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
-    mir: &Mir<'tcx>,
+    mir: &Body<'tcx>,
     patch: &mut MirPatch<'tcx>,
     terminator: &Terminator<'tcx>,
     loc: Location,
diff --git a/src/librustc_mir/transform/add_retag.rs b/src/librustc_mir/transform/add_retag.rs
index 32c9953ee9e08..23319f7055183 100644
--- a/src/librustc_mir/transform/add_retag.rs
+++ b/src/librustc_mir/transform/add_retag.rs
@@ -77,7 +77,7 @@ impl MirPass for AddRetag {
     fn run_pass<'a, 'tcx>(&self,
                           tcx: TyCtxt<'a, 'tcx, 'tcx>,
                           _src: MirSource<'tcx>,
-                          mir: &mut Mir<'tcx>)
+                          mir: &mut Body<'tcx>)
     {
         if !tcx.sess.opts.debugging_opts.mir_emit_retag {
             return;
diff --git a/src/librustc_mir/transform/check_unsafety.rs b/src/librustc_mir/transform/check_unsafety.rs
index 394d1f06029cb..8ec8a8fa12eec 100644
--- a/src/librustc_mir/transform/check_unsafety.rs
+++ b/src/librustc_mir/transform/check_unsafety.rs
@@ -19,7 +19,7 @@ use std::ops::Bound;
 use crate::util;
 
 pub struct UnsafetyChecker<'a, 'tcx: 'a> {
-    mir: &'a Mir<'tcx>,
+    mir: &'a Body<'tcx>,
     const_context: bool,
     min_const_fn: bool,
     source_scope_local_data: &'a IndexVec<SourceScope, SourceScopeLocalData>,
@@ -36,7 +36,7 @@ impl<'a, 'gcx, 'tcx> UnsafetyChecker<'a, 'tcx> {
     fn new(
         const_context: bool,
         min_const_fn: bool,
-        mir: &'a Mir<'tcx>,
+        mir: &'a Body<'tcx>,
         source_scope_local_data: &'a IndexVec<SourceScope, SourceScopeLocalData>,
         tcx: TyCtxt<'a, 'tcx, 'tcx>,
         param_env: ty::ParamEnv<'tcx>,
@@ -538,7 +538,7 @@ fn unsafety_check_result<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId)
     let mut checker = UnsafetyChecker::new(
         const_context, min_const_fn,
         mir, source_scope_local_data, tcx, param_env);
-    checker.visit_mir(mir);
+    checker.visit_body(mir);
 
     check_unused_unsafe(tcx, def_id, &checker.used_unsafe, &mut checker.inherited_blocks);
     UnsafetyCheckResult {
diff --git a/src/librustc_mir/transform/cleanup_post_borrowck.rs b/src/librustc_mir/transform/cleanup_post_borrowck.rs
index 64fd0b1365690..63a1b059d9017 100644
--- a/src/librustc_mir/transform/cleanup_post_borrowck.rs
+++ b/src/librustc_mir/transform/cleanup_post_borrowck.rs
@@ -16,7 +16,7 @@
 //! [`FakeRead`]: rustc::mir::StatementKind::FakeRead
 //! [`Nop`]: rustc::mir::StatementKind::Nop
 
-use rustc::mir::{BorrowKind, Rvalue, Location, Mir};
+use rustc::mir::{BorrowKind, Rvalue, Location, Body};
 use rustc::mir::{Statement, StatementKind};
 use rustc::mir::visit::MutVisitor;
 use rustc::ty::TyCtxt;
@@ -30,9 +30,9 @@ impl MirPass for CleanupNonCodegenStatements {
     fn run_pass<'a, 'tcx>(&self,
                           _tcx: TyCtxt<'a, 'tcx, 'tcx>,
                           _source: MirSource<'tcx>,
-                          mir: &mut Mir<'tcx>) {
+                          mir: &mut Body<'tcx>) {
         let mut delete = DeleteNonCodegenStatements;
-        delete.visit_mir(mir);
+        delete.visit_body(mir);
     }
 }
 
diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs
index 8f3dd72c4f245..de5f845e06eaa 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::DefKind;
 use rustc::mir::{
-    AggregateKind, Constant, Location, Place, PlaceBase, Mir, Operand, Rvalue, Local,
+    AggregateKind, Constant, Location, Place, PlaceBase, Body, Operand, Rvalue, Local,
     NullOp, UnOp, StatementKind, Statement, LocalKind, Static, StaticKind,
     TerminatorKind, Terminator,  ClearCrossCrate, SourceInfo, BinOp, ProjectionElem,
     SourceScope, SourceScopeLocalData, LocalDecl, Promoted,
@@ -33,7 +33,7 @@ impl MirPass for ConstProp {
     fn run_pass<'a, 'tcx>(&self,
                           tcx: TyCtxt<'a, 'tcx, 'tcx>,
                           source: MirSource<'tcx>,
-                          mir: &mut Mir<'tcx>) {
+                          mir: &mut Body<'tcx>) {
         // will be evaluated by miri and produce its errors there
         if source.promoted.is_some() {
             return;
@@ -63,7 +63,7 @@ impl MirPass for ConstProp {
         // That would require an uniform one-def no-mutation analysis
         // and RPO (or recursing when needing the value of a local).
         let mut optimization_finder = ConstPropagator::new(mir, tcx, source);
-        optimization_finder.visit_mir(mir);
+        optimization_finder.visit_body(mir);
 
         // put back the data we stole from `mir`
         std::mem::replace(
@@ -91,7 +91,7 @@ struct ConstPropagator<'a, 'mir, 'tcx:'a+'mir> {
     param_env: ParamEnv<'tcx>,
     source_scope_local_data: ClearCrossCrate<IndexVec<SourceScope, SourceScopeLocalData>>,
     local_decls: IndexVec<Local, LocalDecl<'tcx>>,
-    promoted: IndexVec<Promoted, Mir<'tcx>>,
+    promoted: IndexVec<Promoted, Body<'tcx>>,
 }
 
 impl<'a, 'b, 'tcx> LayoutOf for ConstPropagator<'a, 'b, 'tcx> {
@@ -119,7 +119,7 @@ impl<'a, 'b, 'tcx> HasTyCtxt<'tcx> for ConstPropagator<'a, 'b, 'tcx> {
 
 impl<'a, 'mir, 'tcx> ConstPropagator<'a, 'mir, 'tcx> {
     fn new(
-        mir: &mut Mir<'tcx>,
+        mir: &mut Body<'tcx>,
         tcx: TyCtxt<'a, 'tcx, 'tcx>,
         source: MirSource<'tcx>,
     ) -> ConstPropagator<'a, 'mir, 'tcx> {
@@ -143,7 +143,7 @@ impl<'a, 'mir, 'tcx> ConstPropagator<'a, 'mir, 'tcx> {
             can_const_prop,
             places: IndexVec::from_elem(None, &mir.local_decls),
             source_scope_local_data,
-            //FIXME(wesleywiser) we can't steal this because `Visitor::super_visit_mir()` needs it
+            //FIXME(wesleywiser) we can't steal this because `Visitor::super_visit_body()` needs it
             local_decls: mir.local_decls.clone(),
             promoted,
         }
@@ -566,7 +566,7 @@ struct CanConstProp {
 
 impl CanConstProp {
     /// returns true if `local` can be propagated
-    fn check(mir: &Mir<'_>) -> IndexVec<Local, bool> {
+    fn check(mir: &Body<'_>) -> IndexVec<Local, bool> {
         let mut cpv = CanConstProp {
             can_const_prop: IndexVec::from_elem(true, &mir.local_decls),
             found_assignment: IndexVec::from_elem(false, &mir.local_decls),
@@ -579,7 +579,7 @@ impl CanConstProp {
             // FIXME(oli-obk): lint if return value is constant
             *val = mir.local_kind(local) == LocalKind::Temp;
         }
-        cpv.visit_mir(mir);
+        cpv.visit_body(mir);
         cpv.can_const_prop
     }
 }
diff --git a/src/librustc_mir/transform/copy_prop.rs b/src/librustc_mir/transform/copy_prop.rs
index dfe2e991ba97b..c48d2d295711a 100644
--- a/src/librustc_mir/transform/copy_prop.rs
+++ b/src/librustc_mir/transform/copy_prop.rs
@@ -20,7 +20,7 @@
 //! future.
 
 use rustc::mir::{
-    Constant, Local, LocalKind, Location, Place, PlaceBase, Mir, Operand, Rvalue, StatementKind
+    Constant, Local, LocalKind, Location, Place, PlaceBase, Body, Operand, Rvalue, StatementKind
 };
 use rustc::mir::visit::MutVisitor;
 use rustc::ty::TyCtxt;
@@ -33,7 +33,7 @@ impl MirPass for CopyPropagation {
     fn run_pass<'a, 'tcx>(&self,
                           tcx: TyCtxt<'a, 'tcx, 'tcx>,
                           _source: MirSource<'tcx>,
-                          mir: &mut Mir<'tcx>) {
+                          mir: &mut Body<'tcx>) {
         // We only run when the MIR optimization level is > 1.
         // This avoids a slow pass, and messing up debug info.
         if tcx.sess.opts.debugging_opts.mir_opt_level <= 1 {
@@ -135,7 +135,7 @@ impl MirPass for CopyPropagation {
 }
 
 fn eliminate_self_assignments(
-    mir: &mut Mir<'_>,
+    mir: &mut Body<'_>,
     def_use_analysis: &DefUseAnalysis,
 ) -> bool {
     let mut changed = false;
@@ -177,7 +177,7 @@ enum Action<'tcx> {
 }
 
 impl<'tcx> Action<'tcx> {
-    fn local_copy(mir: &Mir<'tcx>, def_use_analysis: &DefUseAnalysis, src_place: &Place<'tcx>)
+    fn local_copy(mir: &Body<'tcx>, def_use_analysis: &DefUseAnalysis, src_place: &Place<'tcx>)
                   -> Option<Action<'tcx>> {
         // The source must be a local.
         let src_local = if let Place::Base(PlaceBase::Local(local)) = *src_place {
@@ -232,7 +232,7 @@ impl<'tcx> Action<'tcx> {
     }
 
     fn perform(self,
-               mir: &mut Mir<'tcx>,
+               mir: &mut Body<'tcx>,
                def_use_analysis: &DefUseAnalysis,
                dest_local: Local,
                location: Location)
diff --git a/src/librustc_mir/transform/deaggregator.rs b/src/librustc_mir/transform/deaggregator.rs
index 9215356daa484..7da37f956cedd 100644
--- a/src/librustc_mir/transform/deaggregator.rs
+++ b/src/librustc_mir/transform/deaggregator.rs
@@ -10,7 +10,7 @@ impl MirPass for Deaggregator {
     fn run_pass<'a, 'tcx>(&self,
                           tcx: TyCtxt<'a, 'tcx, 'tcx>,
                           _source: MirSource<'tcx>,
-                          mir: &mut Mir<'tcx>) {
+                          mir: &mut Body<'tcx>) {
         let (basic_blocks, local_decls) = mir.basic_blocks_and_local_decls_mut();
         let local_decls = &*local_decls;
         for bb in basic_blocks {
diff --git a/src/librustc_mir/transform/dump_mir.rs b/src/librustc_mir/transform/dump_mir.rs
index 81e48fe2dbe3b..ebb65094a306d 100644
--- a/src/librustc_mir/transform/dump_mir.rs
+++ b/src/librustc_mir/transform/dump_mir.rs
@@ -5,7 +5,7 @@ use std::fmt;
 use std::fs::File;
 use std::io;
 
-use rustc::mir::Mir;
+use rustc::mir::Body;
 use rustc::session::config::{OutputFilenames, OutputType};
 use rustc::ty::TyCtxt;
 use crate::transform::{MirPass, MirSource};
@@ -21,7 +21,7 @@ impl MirPass for Marker {
     fn run_pass<'a, 'tcx>(&self,
                           _tcx: TyCtxt<'a, 'tcx, 'tcx>,
                           _source: MirSource<'tcx>,
-                          _mir: &mut Mir<'tcx>)
+                          _mir: &mut Body<'tcx>)
     {
     }
 }
@@ -42,7 +42,7 @@ pub fn on_mir_pass<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                              pass_num: &dyn fmt::Display,
                              pass_name: &str,
                              source: MirSource<'tcx>,
-                             mir: &Mir<'tcx>,
+                             mir: &Body<'tcx>,
                              is_after: bool) {
     if mir_util::dump_enabled(tcx, pass_name, source) {
         mir_util::dump_mir(tcx,
diff --git a/src/librustc_mir/transform/elaborate_drops.rs b/src/librustc_mir/transform/elaborate_drops.rs
index 023a61588c42e..2f190d2cacade 100644
--- a/src/librustc_mir/transform/elaborate_drops.rs
+++ b/src/librustc_mir/transform/elaborate_drops.rs
@@ -24,7 +24,7 @@ impl MirPass for ElaborateDrops {
     fn run_pass<'a, 'tcx>(&self,
                           tcx: TyCtxt<'a, 'tcx, 'tcx>,
                           src: MirSource<'tcx>,
-                          mir: &mut Mir<'tcx>)
+                          mir: &mut Body<'tcx>)
     {
         debug!("elaborate_drops({:?} @ {:?})", src, mir.span);
 
@@ -79,7 +79,7 @@ impl MirPass for ElaborateDrops {
 /// that can't drop anything.
 fn find_dead_unwinds<'a, 'tcx>(
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
-    mir: &Mir<'tcx>,
+    mir: &Body<'tcx>,
     def_id: hir::def_id::DefId,
     env: &MoveDataParamEnv<'tcx, 'tcx>)
     -> BitSet<BasicBlock>
@@ -143,7 +143,7 @@ struct InitializationData {
 impl InitializationData {
     fn apply_location<'a,'tcx>(&mut self,
                                tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                               mir: &Mir<'tcx>,
+                               mir: &Body<'tcx>,
                                env: &MoveDataParamEnv<'tcx, 'tcx>,
                                loc: Location)
     {
@@ -186,7 +186,7 @@ impl<'a, 'b, 'tcx> DropElaborator<'a, 'tcx> for Elaborator<'a, 'b, 'tcx> {
         &mut self.ctxt.patch
     }
 
-    fn mir(&self) -> &'a Mir<'tcx> {
+    fn mir(&self) -> &'a Body<'tcx> {
         self.ctxt.mir
     }
 
@@ -291,7 +291,7 @@ impl<'a, 'b, 'tcx> DropElaborator<'a, 'tcx> for Elaborator<'a, 'b, 'tcx> {
 
 struct ElaborateDropsCtxt<'a, 'tcx: 'a> {
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
-    mir: &'a Mir<'tcx>,
+    mir: &'a Body<'tcx>,
     env: &'a MoveDataParamEnv<'tcx, 'tcx>,
     flow_inits: DataflowResults<'tcx, MaybeInitializedPlaces<'a, 'tcx, 'tcx>>,
     flow_uninits:  DataflowResults<'tcx, MaybeUninitializedPlaces<'a, 'tcx, 'tcx>>,
diff --git a/src/librustc_mir/transform/erase_regions.rs b/src/librustc_mir/transform/erase_regions.rs
index 7c2ff94b75d86..ffc5bba6d6086 100644
--- a/src/librustc_mir/transform/erase_regions.rs
+++ b/src/librustc_mir/transform/erase_regions.rs
@@ -53,7 +53,7 @@ impl MirPass for EraseRegions {
     fn run_pass<'a, 'tcx>(&self,
                           tcx: TyCtxt<'a, 'tcx, 'tcx>,
                           _: MirSource<'tcx>,
-                          mir: &mut Mir<'tcx>) {
-        EraseRegionsVisitor::new(tcx).visit_mir(mir);
+                          mir: &mut Body<'tcx>) {
+        EraseRegionsVisitor::new(tcx).visit_body(mir);
     }
 }
diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs
index 780b3c9686b6a..40a43aeac9f4b 100644
--- a/src/librustc_mir/transform/generator.rs
+++ b/src/librustc_mir/transform/generator.rs
@@ -210,7 +210,7 @@ impl<'a, 'tcx> TransformVisitor<'a, 'tcx> {
     }
 
     // Create a statement which reads the discriminant into a temporary
-    fn get_discr(&self, mir: &mut Mir<'tcx>) -> (Statement<'tcx>, Place<'tcx>) {
+    fn get_discr(&self, mir: &mut Body<'tcx>) -> (Statement<'tcx>, Place<'tcx>) {
         let temp_decl = LocalDecl::new_internal(self.tcx.types.isize, mir.span);
         let local_decls_len = mir.local_decls.push(temp_decl);
         let temp = Place::Base(PlaceBase::Local(local_decls_len));
@@ -304,7 +304,7 @@ impl<'a, 'tcx> MutVisitor<'tcx> for TransformVisitor<'a, 'tcx> {
 fn make_generator_state_argument_indirect<'a, 'tcx>(
                 tcx: TyCtxt<'a, 'tcx, 'tcx>,
                 def_id: DefId,
-                mir: &mut Mir<'tcx>) {
+                mir: &mut Body<'tcx>) {
     let gen_ty = mir.local_decls.raw[1].ty;
 
     let region = ty::ReFree(ty::FreeRegion {
@@ -323,12 +323,12 @@ fn make_generator_state_argument_indirect<'a, 'tcx>(
     mir.local_decls.raw[1].ty = ref_gen_ty;
 
     // Add a deref to accesses of the generator state
-    DerefArgVisitor.visit_mir(mir);
+    DerefArgVisitor.visit_body(mir);
 }
 
 fn make_generator_state_argument_pinned<'a, 'tcx>(
                 tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                mir: &mut Mir<'tcx>) {
+                mir: &mut Body<'tcx>) {
     let ref_gen_ty = mir.local_decls.raw[1].ty;
 
     let pin_did = tcx.lang_items().pin_type().unwrap();
@@ -340,12 +340,12 @@ fn make_generator_state_argument_pinned<'a, 'tcx>(
     mir.local_decls.raw[1].ty = pin_ref_gen_ty;
 
     // Add the Pin field access to accesses of the generator state
-    PinArgVisitor { ref_gen_ty }.visit_mir(mir);
+    PinArgVisitor { ref_gen_ty }.visit_body(mir);
 }
 
 fn replace_result_variable<'tcx>(
     ret_ty: Ty<'tcx>,
-    mir: &mut Mir<'tcx>,
+    mir: &mut Body<'tcx>,
 ) -> Local {
     let source_info = source_info(mir);
     let new_ret = LocalDecl {
@@ -366,7 +366,7 @@ fn replace_result_variable<'tcx>(
     RenameLocalVisitor {
         from: RETURN_PLACE,
         to: new_ret_local,
-    }.visit_mir(mir);
+    }.visit_body(mir);
 
     new_ret_local
 }
@@ -387,7 +387,7 @@ impl<'tcx> Visitor<'tcx> for StorageIgnored {
 
 fn locals_live_across_suspend_points(
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
-    mir: &Mir<'tcx>,
+    mir: &Body<'tcx>,
     source: MirSource<'tcx>,
     movable: bool,
 ) -> (
@@ -408,7 +408,7 @@ fn locals_live_across_suspend_points(
     // Find the MIR locals which do not use StorageLive/StorageDead statements.
     // The storage of these locals are always live.
     let mut ignored = StorageIgnored(BitSet::new_filled(mir.local_decls.len()));
-    ignored.visit_mir(mir);
+    ignored.visit_body(mir);
 
     // Calculate the MIR locals which have been previously
     // borrowed (even if they are still active).
@@ -503,7 +503,7 @@ fn compute_layout<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                             upvars: &Vec<Ty<'tcx>>,
                             interior: Ty<'tcx>,
                             movable: bool,
-                            mir: &mut Mir<'tcx>)
+                            mir: &mut Body<'tcx>)
     -> (FxHashMap<Local, (Ty<'tcx>, VariantIdx, usize)>,
         GeneratorLayout<'tcx>,
         FxHashMap<BasicBlock, liveness::LiveVarSet>)
@@ -576,7 +576,7 @@ fn compute_layout<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     (remap, layout, storage_liveness)
 }
 
-fn insert_switch<'a, 'tcx>(mir: &mut Mir<'tcx>,
+fn insert_switch<'a, 'tcx>(mir: &mut Body<'tcx>,
                            cases: Vec<(usize, BasicBlock)>,
                            transform: &TransformVisitor<'a, 'tcx>,
                            default: TerminatorKind<'tcx>) {
@@ -608,7 +608,7 @@ fn insert_switch<'a, 'tcx>(mir: &mut Mir<'tcx>,
 
 fn elaborate_generator_drops<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                        def_id: DefId,
-                                       mir: &mut Mir<'tcx>) {
+                                       mir: &mut Body<'tcx>) {
     use crate::util::elaborate_drops::{elaborate_drop, Unwind};
     use crate::util::patch::MirPatch;
     use crate::shim::DropShimElaborator;
@@ -663,8 +663,8 @@ fn create_generator_drop_shim<'a, 'tcx>(
                 def_id: DefId,
                 source: MirSource<'tcx>,
                 gen_ty: Ty<'tcx>,
-                mir: &Mir<'tcx>,
-                drop_clean: BasicBlock) -> Mir<'tcx> {
+                mir: &Body<'tcx>,
+                drop_clean: BasicBlock) -> Body<'tcx> {
     let mut mir = mir.clone();
 
     let source_info = source_info(&mir);
@@ -734,7 +734,7 @@ fn create_generator_drop_shim<'a, 'tcx>(
     mir
 }
 
-fn insert_term_block<'tcx>(mir: &mut Mir<'tcx>, kind: TerminatorKind<'tcx>) -> BasicBlock {
+fn insert_term_block<'tcx>(mir: &mut Body<'tcx>, kind: TerminatorKind<'tcx>) -> BasicBlock {
     let term_block = BasicBlock::new(mir.basic_blocks().len());
     let source_info = source_info(mir);
     mir.basic_blocks_mut().push(BasicBlockData {
@@ -749,7 +749,7 @@ fn insert_term_block<'tcx>(mir: &mut Mir<'tcx>, kind: TerminatorKind<'tcx>) -> B
 }
 
 fn insert_panic_block<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                                mir: &mut Mir<'tcx>,
+                                mir: &mut Body<'tcx>,
                                 message: AssertMessage<'tcx>) -> BasicBlock {
     let assert_block = BasicBlock::new(mir.basic_blocks().len());
     let term = TerminatorKind::Assert {
@@ -785,7 +785,7 @@ fn create_generator_resume_function<'a, 'tcx>(
         transform: TransformVisitor<'a, 'tcx>,
         def_id: DefId,
         source: MirSource<'tcx>,
-        mir: &mut Mir<'tcx>) {
+        mir: &mut Body<'tcx>) {
     // Poison the generator when it unwinds
     for block in mir.basic_blocks_mut() {
         let source_info = block.terminator().source_info;
@@ -823,14 +823,14 @@ fn create_generator_resume_function<'a, 'tcx>(
     dump_mir(tcx, None, "generator_resume", &0, source, mir, |_, _| Ok(()) );
 }
 
-fn source_info<'a, 'tcx>(mir: &Mir<'tcx>) -> SourceInfo {
+fn source_info<'a, 'tcx>(mir: &Body<'tcx>) -> SourceInfo {
     SourceInfo {
         span: mir.span,
         scope: OUTERMOST_SOURCE_SCOPE,
     }
 }
 
-fn insert_clean_drop<'a, 'tcx>(mir: &mut Mir<'tcx>) -> BasicBlock {
+fn insert_clean_drop<'a, 'tcx>(mir: &mut Body<'tcx>) -> BasicBlock {
     let return_block = insert_term_block(mir, TerminatorKind::Return);
 
     // Create a block to destroy an unresumed generators. This can only destroy upvars.
@@ -853,7 +853,7 @@ fn insert_clean_drop<'a, 'tcx>(mir: &mut Mir<'tcx>) -> BasicBlock {
     drop_clean
 }
 
-fn create_cases<'a, 'tcx, F>(mir: &mut Mir<'tcx>,
+fn create_cases<'a, 'tcx, F>(mir: &mut Body<'tcx>,
                           transform: &TransformVisitor<'a, 'tcx>,
                           target: F) -> Vec<(usize, BasicBlock)>
     where F: Fn(&SuspensionPoint) -> Option<BasicBlock> {
@@ -897,7 +897,7 @@ impl MirPass for StateTransform {
     fn run_pass<'a, 'tcx>(&self,
                     tcx: TyCtxt<'a, 'tcx, 'tcx>,
                     source: MirSource<'tcx>,
-                    mir: &mut Mir<'tcx>) {
+                    mir: &mut Body<'tcx>) {
         let yield_ty = if let Some(yield_ty) = mir.yield_ty {
             yield_ty
         } else {
@@ -961,7 +961,7 @@ impl MirPass for StateTransform {
             new_ret_local,
             discr_ty,
         };
-        transform.visit_mir(mir);
+        transform.visit_body(mir);
 
         // Update our MIR struct to reflect the changed we've made
         mir.yield_ty = None;
diff --git a/src/librustc_mir/transform/inline.rs b/src/librustc_mir/transform/inline.rs
index 24ec3219a2e7b..18bf67e2a1d30 100644
--- a/src/librustc_mir/transform/inline.rs
+++ b/src/librustc_mir/transform/inline.rs
@@ -41,7 +41,7 @@ impl MirPass for Inline {
     fn run_pass<'a, 'tcx>(&self,
                           tcx: TyCtxt<'a, 'tcx, 'tcx>,
                           source: MirSource<'tcx>,
-                          mir: &mut Mir<'tcx>) {
+                          mir: &mut Body<'tcx>) {
         if tcx.sess.opts.debugging_opts.mir_opt_level >= 2 {
             Inliner { tcx, source }.run_pass(mir);
         }
@@ -54,7 +54,7 @@ struct Inliner<'a, 'tcx: 'a> {
 }
 
 impl<'a, 'tcx> Inliner<'a, 'tcx> {
-    fn run_pass(&self, caller_mir: &mut Mir<'tcx>) {
+    fn run_pass(&self, caller_mir: &mut Body<'tcx>) {
         // Keep a queue of callsites to try inlining on. We take
         // advantage of the fact that queries detect cycles here to
         // allow us to try and fetch the fully optimized MIR of a
@@ -171,7 +171,7 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> {
     fn get_valid_function_call(&self,
                                bb: BasicBlock,
                                bb_data: &BasicBlockData<'tcx>,
-                               caller_mir: &Mir<'tcx>,
+                               caller_mir: &Body<'tcx>,
                                param_env: ParamEnv<'tcx>,
     ) -> Option<CallSite<'tcx>> {
         // Don't inline calls that are in cleanup blocks.
@@ -204,7 +204,7 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> {
 
     fn consider_optimizing(&self,
                            callsite: CallSite<'tcx>,
-                           callee_mir: &Mir<'tcx>)
+                           callee_mir: &Body<'tcx>)
                            -> bool
     {
         debug!("consider_optimizing({:?})", callsite);
@@ -216,7 +216,7 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> {
 
     fn should_inline(&self,
                      callsite: CallSite<'tcx>,
-                     callee_mir: &Mir<'tcx>)
+                     callee_mir: &Body<'tcx>)
                      -> bool
     {
         debug!("should_inline({:?})", callsite);
@@ -394,8 +394,8 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> {
 
     fn inline_call(&self,
                    callsite: CallSite<'tcx>,
-                   caller_mir: &mut Mir<'tcx>,
-                   mut callee_mir: Mir<'tcx>) -> bool {
+                   caller_mir: &mut Body<'tcx>,
+                   mut callee_mir: Body<'tcx>) -> bool {
         let terminator = caller_mir[callsite.bb].terminator.take().unwrap();
         match terminator.kind {
             // FIXME: Handle inlining of diverging calls
@@ -528,7 +528,7 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> {
         &self,
         args: Vec<Operand<'tcx>>,
         callsite: &CallSite<'tcx>,
-        caller_mir: &mut Mir<'tcx>,
+        caller_mir: &mut Body<'tcx>,
     ) -> Vec<Local> {
         let tcx = self.tcx;
 
@@ -598,7 +598,7 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> {
         &self,
         arg: Operand<'tcx>,
         callsite: &CallSite<'tcx>,
-        caller_mir: &mut Mir<'tcx>,
+        caller_mir: &mut Body<'tcx>,
     ) -> Local {
         // FIXME: Analysis of the usage of the arguments to avoid
         // unnecessary temporaries.
diff --git a/src/librustc_mir/transform/instcombine.rs b/src/librustc_mir/transform/instcombine.rs
index 8187a81f0edab..1b92b1acac55d 100644
--- a/src/librustc_mir/transform/instcombine.rs
+++ b/src/librustc_mir/transform/instcombine.rs
@@ -1,6 +1,7 @@
 //! Performs various peephole optimizations.
 
-use rustc::mir::{Constant, Location, Place, PlaceBase, Mir, Operand, ProjectionElem, Rvalue, Local};
+use rustc::mir::{Constant, Location, Place, PlaceBase, Body, Operand, ProjectionElem, Rvalue,
+    Local};
 use rustc::mir::visit::{MutVisitor, Visitor};
 use rustc::ty::{self, TyCtxt};
 use rustc::util::nodemap::{FxHashMap, FxHashSet};
@@ -14,7 +15,7 @@ impl MirPass for InstCombine {
     fn run_pass<'a, 'tcx>(&self,
                           tcx: TyCtxt<'a, 'tcx, 'tcx>,
                           _: MirSource<'tcx>,
-                          mir: &mut Mir<'tcx>) {
+                          mir: &mut Body<'tcx>) {
         // We only run when optimizing MIR (at any level).
         if tcx.sess.opts.debugging_opts.mir_opt_level == 0 {
             return
@@ -25,12 +26,12 @@ impl MirPass for InstCombine {
         // `Place::ty()`).
         let optimizations = {
             let mut optimization_finder = OptimizationFinder::new(mir, tcx);
-            optimization_finder.visit_mir(mir);
+            optimization_finder.visit_body(mir);
             optimization_finder.optimizations
         };
 
         // Then carry out those optimizations.
-        MutVisitor::visit_mir(&mut InstCombineVisitor { optimizations }, mir);
+        MutVisitor::visit_body(&mut InstCombineVisitor { optimizations }, mir);
     }
 }
 
@@ -63,13 +64,13 @@ impl<'tcx> MutVisitor<'tcx> for InstCombineVisitor<'tcx> {
 
 /// Finds optimization opportunities on the MIR.
 struct OptimizationFinder<'b, 'a, 'tcx:'a+'b> {
-    mir: &'b Mir<'tcx>,
+    mir: &'b Body<'tcx>,
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     optimizations: OptimizationList<'tcx>,
 }
 
 impl<'b, 'a, 'tcx:'b> OptimizationFinder<'b, 'a, 'tcx> {
-    fn new(mir: &'b Mir<'tcx>, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> OptimizationFinder<'b, 'a, 'tcx> {
+    fn new(mir: &'b Body<'tcx>, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> OptimizationFinder<'b, 'a, 'tcx> {
         OptimizationFinder {
             mir,
             tcx,
diff --git a/src/librustc_mir/transform/lower_128bit.rs b/src/librustc_mir/transform/lower_128bit.rs
index fd9d6bb5760b1..8c19637a955f1 100644
--- a/src/librustc_mir/transform/lower_128bit.rs
+++ b/src/librustc_mir/transform/lower_128bit.rs
@@ -13,7 +13,7 @@ impl MirPass for Lower128Bit {
     fn run_pass<'a, 'tcx>(&self,
                           tcx: TyCtxt<'a, 'tcx, 'tcx>,
                           _src: MirSource<'tcx>,
-                          mir: &mut Mir<'tcx>) {
+                          mir: &mut Body<'tcx>) {
         let debugging_override = tcx.sess.opts.debugging_opts.lower_128bit_ops;
         let target_default = tcx.sess.host.options.i128_lowering;
         if !debugging_override.unwrap_or(target_default) {
@@ -25,7 +25,7 @@ impl MirPass for Lower128Bit {
 }
 
 impl Lower128Bit {
-    fn lower_128bit_ops<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, mir: &mut Mir<'tcx>) {
+    fn lower_128bit_ops<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, mir: &mut Body<'tcx>) {
         let mut new_blocks = Vec::new();
         let cur_len = mir.basic_blocks().len();
 
diff --git a/src/librustc_mir/transform/mod.rs b/src/librustc_mir/transform/mod.rs
index b609164415717..3fd4e6044af74 100644
--- a/src/librustc_mir/transform/mod.rs
+++ b/src/librustc_mir/transform/mod.rs
@@ -1,6 +1,6 @@
 use crate::build;
 use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
-use rustc::mir::{Mir, MirPhase, Promoted};
+use rustc::mir::{Body, MirPhase, Promoted};
 use rustc::ty::{TyCtxt, InstanceDef};
 use rustc::ty::query::Providers;
 use rustc::ty::steal::Steal;
@@ -95,7 +95,7 @@ fn mir_keys<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, krate: CrateNum)
     tcx.arena.alloc(set)
 }
 
-fn mir_built<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx Steal<Mir<'tcx>> {
+fn mir_built<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx Steal<Body<'tcx>> {
     let mir = build::mir_build(tcx, def_id);
     tcx.alloc_steal_mir(mir)
 }
@@ -145,19 +145,19 @@ pub trait MirPass {
     fn run_pass<'a, 'tcx>(&self,
                           tcx: TyCtxt<'a, 'tcx, 'tcx>,
                           source: MirSource<'tcx>,
-                          mir: &mut Mir<'tcx>);
+                          mir: &mut Body<'tcx>);
 }
 
 pub fn run_passes(
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
-    mir: &mut Mir<'tcx>,
+    mir: &mut Body<'tcx>,
     instance: InstanceDef<'tcx>,
     mir_phase: MirPhase,
     passes: &[&dyn MirPass],
 ) {
     let phase_index = mir_phase.phase_index();
 
-    let run_passes = |mir: &mut Mir<'tcx>, promoted| {
+    let run_passes = |mir: &mut Body<'tcx>, promoted| {
         if mir.phase >= mir_phase {
             return;
         }
@@ -196,7 +196,7 @@ pub fn run_passes(
     }
 }
 
-fn mir_const<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx Steal<Mir<'tcx>> {
+fn mir_const<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx Steal<Body<'tcx>> {
     // Unsafety check uses the raw mir, so make sure it is run
     let _ = tcx.unsafety_check_result(def_id);
 
@@ -210,7 +210,7 @@ fn mir_const<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx Stea
     tcx.alloc_steal_mir(mir)
 }
 
-fn mir_validated<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx Steal<Mir<'tcx>> {
+fn mir_validated<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx Steal<Body<'tcx>> {
     let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap();
     if let hir::BodyOwnerKind::Const = tcx.hir().body_owner_kind_by_hir_id(hir_id) {
         // Ensure that we compute the `mir_const_qualif` for constants at
@@ -227,7 +227,7 @@ fn mir_validated<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx
     tcx.alloc_steal_mir(mir)
 }
 
-fn optimized_mir<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx Mir<'tcx> {
+fn optimized_mir<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx Body<'tcx> {
     // (Mir-)Borrowck uses `mir_validated`, so we have to force it to
     // execute before we can steal.
     tcx.ensure().mir_borrowck(def_id);
diff --git a/src/librustc_mir/transform/no_landing_pads.rs b/src/librustc_mir/transform/no_landing_pads.rs
index 648f4e65b0d07..719e22ca15023 100644
--- a/src/librustc_mir/transform/no_landing_pads.rs
+++ b/src/librustc_mir/transform/no_landing_pads.rs
@@ -12,14 +12,14 @@ impl MirPass for NoLandingPads {
     fn run_pass<'a, 'tcx>(&self,
                           tcx: TyCtxt<'a, 'tcx, 'tcx>,
                           _: MirSource<'tcx>,
-                          mir: &mut Mir<'tcx>) {
+                          mir: &mut Body<'tcx>) {
         no_landing_pads(tcx, mir)
     }
 }
 
-pub fn no_landing_pads<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, mir: &mut Mir<'tcx>) {
+pub fn no_landing_pads<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, mir: &mut Body<'tcx>) {
     if tcx.sess.no_landing_pads() {
-        NoLandingPads.visit_mir(mir);
+        NoLandingPads.visit_body(mir);
     }
 }
 
diff --git a/src/librustc_mir/transform/promote_consts.rs b/src/librustc_mir/transform/promote_consts.rs
index 0bf96c689176b..24f810cceaf86 100644
--- a/src/librustc_mir/transform/promote_consts.rs
+++ b/src/librustc_mir/transform/promote_consts.rs
@@ -71,7 +71,7 @@ pub enum Candidate {
 struct TempCollector<'tcx> {
     temps: IndexVec<Local, TempState>,
     span: Span,
-    mir: &'tcx Mir<'tcx>,
+    mir: &'tcx Body<'tcx>,
 }
 
 impl<'tcx> Visitor<'tcx> for TempCollector<'tcx> {
@@ -134,7 +134,7 @@ impl<'tcx> Visitor<'tcx> for TempCollector<'tcx> {
     }
 }
 
-pub fn collect_temps(mir: &Mir<'_>,
+pub fn collect_temps(mir: &Body<'_>,
                      rpo: &mut ReversePostorder<'_, '_>) -> IndexVec<Local, TempState> {
     let mut collector = TempCollector {
         temps: IndexVec::from_elem(TempState::Undefined, &mir.local_decls),
@@ -149,8 +149,8 @@ pub fn collect_temps(mir: &Mir<'_>,
 
 struct Promoter<'a, 'tcx: 'a> {
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
-    source: &'a mut Mir<'tcx>,
-    promoted: Mir<'tcx>,
+    source: &'a mut Body<'tcx>,
+    promoted: Body<'tcx>,
     temps: &'a mut IndexVec<Local, TempState>,
 
     /// If true, all nested temps are also kept in the
@@ -369,7 +369,7 @@ impl<'a, 'tcx> MutVisitor<'tcx> for Promoter<'a, 'tcx> {
     }
 }
 
-pub fn promote_candidates<'a, 'tcx>(mir: &mut Mir<'tcx>,
+pub fn promote_candidates<'a, 'tcx>(mir: &mut Body<'tcx>,
                                     tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                     mut temps: IndexVec<Local, TempState>,
                                     candidates: Vec<Candidate>) {
@@ -393,13 +393,13 @@ pub fn promote_candidates<'a, 'tcx>(mir: &mut Mir<'tcx>,
         }
 
 
-        // Declare return place local so that `Mir::new` doesn't complain.
+        // Declare return place local so that `Body::new` doesn't complain.
         let initial_locals = iter::once(
             LocalDecl::new_return_place(tcx.types.never, mir.span)
         ).collect();
 
         let promoter = Promoter {
-            promoted: Mir::new(
+            promoted: Body::new(
                 IndexVec::new(),
                 // FIXME: maybe try to filter this to avoid blowing up
                 // memory usage?
diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs
index 12357cb10a991..1d7deb11cd46f 100644
--- a/src/librustc_mir/transform/qualify_consts.rs
+++ b/src/librustc_mir/transform/qualify_consts.rs
@@ -113,7 +113,7 @@ struct ConstCx<'a, 'tcx> {
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     param_env: ty::ParamEnv<'tcx>,
     mode: Mode,
-    mir: &'a Mir<'tcx>,
+    mir: &'a Body<'tcx>,
 
     per_local: PerQualif<BitSet<Local>>,
 }
@@ -619,7 +619,7 @@ impl Deref for Checker<'a, 'tcx> {
 impl<'a, 'tcx> Checker<'a, 'tcx> {
     fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>,
            def_id: DefId,
-           mir: &'a Mir<'tcx>,
+           mir: &'a Body<'tcx>,
            mode: Mode)
            -> Self {
         assert!(def_id.is_local());
@@ -1444,7 +1444,7 @@ impl MirPass for QualifyAndPromoteConstants {
     fn run_pass<'a, 'tcx>(&self,
                           tcx: TyCtxt<'a, 'tcx, 'tcx>,
                           src: MirSource<'tcx>,
-                          mir: &mut Mir<'tcx>) {
+                          mir: &mut Body<'tcx>) {
         // There's not really any point in promoting errorful MIR.
         if mir.return_ty().references_error() {
             tcx.sess.delay_span_bug(mir.span, "QualifyAndPromoteConstants: Mir had errors");
diff --git a/src/librustc_mir/transform/qualify_min_const_fn.rs b/src/librustc_mir/transform/qualify_min_const_fn.rs
index e1d41ba4fc509..23418ef3353fe 100644
--- a/src/librustc_mir/transform/qualify_min_const_fn.rs
+++ b/src/librustc_mir/transform/qualify_min_const_fn.rs
@@ -11,7 +11,7 @@ type McfResult = Result<(), (Span, Cow<'static, str>)>;
 pub fn is_min_const_fn(
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     def_id: DefId,
-    mir: &'a Mir<'tcx>,
+    mir: &'a Body<'tcx>,
 ) -> McfResult {
     let mut current = def_id;
     loop {
@@ -130,7 +130,7 @@ fn check_ty(
 
 fn check_rvalue(
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
-    mir: &'a Mir<'tcx>,
+    mir: &'a Body<'tcx>,
     rvalue: &Rvalue<'tcx>,
     span: Span,
 ) -> McfResult {
@@ -210,7 +210,7 @@ fn check_rvalue(
 
 fn check_statement(
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
-    mir: &'a Mir<'tcx>,
+    mir: &'a Body<'tcx>,
     statement: &Statement<'tcx>,
 ) -> McfResult {
     let span = statement.source_info.span;
@@ -240,7 +240,7 @@ fn check_statement(
 
 fn check_operand(
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
-    mir: &'a Mir<'tcx>,
+    mir: &'a Body<'tcx>,
     operand: &Operand<'tcx>,
     span: Span,
 ) -> McfResult {
@@ -254,7 +254,7 @@ fn check_operand(
 
 fn check_place(
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
-    mir: &'a Mir<'tcx>,
+    mir: &'a Body<'tcx>,
     place: &Place<'tcx>,
     span: Span,
 ) -> McfResult {
@@ -280,7 +280,7 @@ fn check_place(
 
 fn check_terminator(
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
-    mir: &'a Mir<'tcx>,
+    mir: &'a Body<'tcx>,
     terminator: &Terminator<'tcx>,
 ) -> McfResult {
     let span = terminator.source_info.span;
diff --git a/src/librustc_mir/transform/remove_noop_landing_pads.rs b/src/librustc_mir/transform/remove_noop_landing_pads.rs
index b7493b25d4650..42818a571151e 100644
--- a/src/librustc_mir/transform/remove_noop_landing_pads.rs
+++ b/src/librustc_mir/transform/remove_noop_landing_pads.rs
@@ -11,7 +11,7 @@ pub struct RemoveNoopLandingPads;
 
 pub fn remove_noop_landing_pads<'a, 'tcx>(
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
-    mir: &mut Mir<'tcx>)
+    mir: &mut Body<'tcx>)
 {
     if tcx.sess.no_landing_pads() {
         return
@@ -25,7 +25,7 @@ impl MirPass for RemoveNoopLandingPads {
     fn run_pass<'a, 'tcx>(&self,
                           tcx: TyCtxt<'a, 'tcx, 'tcx>,
                           _src: MirSource<'tcx>,
-                          mir: &mut Mir<'tcx>) {
+                          mir: &mut Body<'tcx>) {
         remove_noop_landing_pads(tcx, mir);
     }
 }
@@ -34,7 +34,7 @@ impl RemoveNoopLandingPads {
     fn is_nop_landing_pad(
         &self,
         bb: BasicBlock,
-        mir: &Mir<'_>,
+        mir: &Body<'_>,
         nop_landing_pads: &BitSet<BasicBlock>,
     ) -> bool {
         for stmt in &mir[bb].statements {
@@ -86,7 +86,7 @@ impl RemoveNoopLandingPads {
         }
     }
 
-    fn remove_nop_landing_pads(&self, mir: &mut Mir<'_>) {
+    fn remove_nop_landing_pads(&self, mir: &mut Body<'_>) {
         // make sure there's a single resume block
         let resume_block = {
             let patch = MirPatch::new(mir);
diff --git a/src/librustc_mir/transform/rustc_peek.rs b/src/librustc_mir/transform/rustc_peek.rs
index 7d2dbff996d08..2b3eb9e1edf30 100644
--- a/src/librustc_mir/transform/rustc_peek.rs
+++ b/src/librustc_mir/transform/rustc_peek.rs
@@ -5,7 +5,7 @@ use syntax_pos::Span;
 
 use rustc::ty::{self, TyCtxt};
 use rustc::hir::def_id::DefId;
-use rustc::mir::{self, Mir, Location};
+use rustc::mir::{self, Body, Location};
 use rustc_data_structures::bit_set::BitSet;
 use crate::transform::{MirPass, MirSource};
 
@@ -26,7 +26,7 @@ pub struct SanityCheck;
 
 impl MirPass for SanityCheck {
     fn run_pass<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                          src: MirSource<'tcx>, mir: &mut Mir<'tcx>) {
+                          src: MirSource<'tcx>, mir: &mut Body<'tcx>) {
         let def_id = src.def_id();
         if !tcx.has_attr(def_id, sym::rustc_mir) {
             debug!("skipping rustc_peek::SanityCheck on {}", tcx.def_path_str(def_id));
@@ -85,7 +85,7 @@ impl MirPass for SanityCheck {
 /// expression form above, then that emits an error as well, but those
 /// errors are not intended to be used for unit tests.)
 pub fn sanity_check_via_rustc_peek<'a, 'tcx, O>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                                                mir: &Mir<'tcx>,
+                                                mir: &Body<'tcx>,
                                                 def_id: DefId,
                                                 _attributes: &[ast::Attribute],
                                                 results: &DataflowResults<'tcx, O>)
@@ -102,7 +102,7 @@ pub fn sanity_check_via_rustc_peek<'a, 'tcx, O>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 }
 
 fn each_block<'a, 'tcx, O>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                           mir: &Mir<'tcx>,
+                           mir: &Body<'tcx>,
                            results: &DataflowResults<'tcx, O>,
                            bb: mir::BasicBlock) where
     O: BitDenotation<'tcx, Idx=MovePathIndex> + HasMoveData<'tcx>
diff --git a/src/librustc_mir/transform/simplify.rs b/src/librustc_mir/transform/simplify.rs
index ee16ec7b41cf5..e7be238e850f2 100644
--- a/src/librustc_mir/transform/simplify.rs
+++ b/src/librustc_mir/transform/simplify.rs
@@ -44,7 +44,7 @@ impl SimplifyCfg {
     }
 }
 
-pub fn simplify_cfg(mir: &mut Mir<'_>) {
+pub fn simplify_cfg(mir: &mut Body<'_>) {
     CfgSimplifier::new(mir).simplify();
     remove_dead_blocks(mir);
 
@@ -60,7 +60,7 @@ impl MirPass for SimplifyCfg {
     fn run_pass<'a, 'tcx>(&self,
                           _tcx: TyCtxt<'a, 'tcx, 'tcx>,
                           _src: MirSource<'tcx>,
-                          mir: &mut Mir<'tcx>) {
+                          mir: &mut Body<'tcx>) {
         debug!("SimplifyCfg({:?}) - simplifying {:?}", self.label, mir);
         simplify_cfg(mir);
     }
@@ -72,7 +72,7 @@ pub struct CfgSimplifier<'a, 'tcx: 'a> {
 }
 
 impl<'a, 'tcx: 'a> CfgSimplifier<'a, 'tcx> {
-    pub fn new(mir: &'a mut Mir<'tcx>) -> Self {
+    pub fn new(mir: &'a mut Body<'tcx>) -> Self {
         let mut pred_count = IndexVec::from_elem(0u32, mir.basic_blocks());
 
         // we can't use mir.predecessors() here because that counts
@@ -263,7 +263,7 @@ impl<'a, 'tcx: 'a> CfgSimplifier<'a, 'tcx> {
     }
 }
 
-pub fn remove_dead_blocks(mir: &mut Mir<'_>) {
+pub fn remove_dead_blocks(mir: &mut Body<'_>) {
     let mut seen = BitSet::new_empty(mir.basic_blocks().len());
     for (bb, _) in traversal::preorder(mir) {
         seen.insert(bb.index());
@@ -299,9 +299,9 @@ impl MirPass for SimplifyLocals {
     fn run_pass<'a, 'tcx>(&self,
                           tcx: TyCtxt<'a, 'tcx, 'tcx>,
                           _: MirSource<'tcx>,
-                          mir: &mut Mir<'tcx>) {
+                          mir: &mut Body<'tcx>) {
         let mut marker = DeclMarker { locals: BitSet::new_empty(mir.local_decls.len()) };
-        marker.visit_mir(mir);
+        marker.visit_body(mir);
         // Return pointer and arguments are always live
         marker.locals.insert(RETURN_PLACE);
         for arg in mir.args_iter() {
@@ -317,7 +317,7 @@ impl MirPass for SimplifyLocals {
 
         let map = make_local_map(&mut mir.local_decls, marker.locals);
         // Update references to all vars and tmps now
-        LocalUpdater { map }.visit_mir(mir);
+        LocalUpdater { map }.visit_body(mir);
         mir.local_decls.shrink_to_fit();
     }
 }
diff --git a/src/librustc_mir/transform/simplify_branches.rs b/src/librustc_mir/transform/simplify_branches.rs
index db73e829c53a7..53949bcfcd707 100644
--- a/src/librustc_mir/transform/simplify_branches.rs
+++ b/src/librustc_mir/transform/simplify_branches.rs
@@ -22,7 +22,7 @@ impl MirPass for SimplifyBranches {
     fn run_pass<'a, 'tcx>(&self,
                           tcx: TyCtxt<'a, 'tcx, 'tcx>,
                           _src: MirSource<'tcx>,
-                          mir: &mut Mir<'tcx>) {
+                          mir: &mut Body<'tcx>) {
         for block in mir.basic_blocks_mut() {
             let terminator = block.terminator_mut();
             terminator.kind = match terminator.kind {
diff --git a/src/librustc_mir/transform/uniform_array_move_out.rs b/src/librustc_mir/transform/uniform_array_move_out.rs
index 4eee0640d78cd..70ea244ac9003 100644
--- a/src/librustc_mir/transform/uniform_array_move_out.rs
+++ b/src/librustc_mir/transform/uniform_array_move_out.rs
@@ -40,18 +40,18 @@ impl MirPass for UniformArrayMoveOut {
     fn run_pass<'a, 'tcx>(&self,
                           tcx: TyCtxt<'a, 'tcx, 'tcx>,
                           _src: MirSource<'tcx>,
-                          mir: &mut Mir<'tcx>) {
+                          mir: &mut Body<'tcx>) {
         let mut patch = MirPatch::new(mir);
         {
             let mut visitor = UniformArrayMoveOutVisitor{mir, patch: &mut patch, tcx};
-            visitor.visit_mir(mir);
+            visitor.visit_body(mir);
         }
         patch.apply(mir);
     }
 }
 
 struct UniformArrayMoveOutVisitor<'a, 'tcx: 'a> {
-    mir: &'a Mir<'tcx>,
+    mir: &'a Body<'tcx>,
     patch: &'a mut MirPatch<'tcx>,
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
 }
@@ -165,14 +165,14 @@ impl MirPass for RestoreSubsliceArrayMoveOut {
     fn run_pass<'a, 'tcx>(&self,
                           tcx: TyCtxt<'a, 'tcx, 'tcx>,
                           _src: MirSource<'tcx>,
-                          mir: &mut Mir<'tcx>) {
+                          mir: &mut Body<'tcx>) {
         let mut patch = MirPatch::new(mir);
         {
             let mut visitor = RestoreDataCollector {
                 locals_use: IndexVec::from_elem(LocalUse::new(), &mir.local_decls),
                 candidates: vec![],
             };
-            visitor.visit_mir(mir);
+            visitor.visit_body(mir);
 
             for candidate in &visitor.candidates {
                 let statement = &mir[candidate.block].statements[candidate.statement_index];
@@ -254,7 +254,7 @@ impl RestoreSubsliceArrayMoveOut {
     }
 
     fn try_get_item_source<'a, 'tcx>(local_use: &LocalUse,
-                                     mir: &'a Mir<'tcx>) -> Option<(u32, &'a Place<'tcx>)> {
+                                     mir: &'a Body<'tcx>) -> Option<(u32, &'a Place<'tcx>)> {
         if let Some(location) = local_use.first_use {
             let block = &mir[location.block];
             if block.statements.len() > location.statement_index {
diff --git a/src/librustc_mir/util/collect_writes.rs b/src/librustc_mir/util/collect_writes.rs
index 7bd61c3a59c94..c8804dfbaf261 100644
--- a/src/librustc_mir/util/collect_writes.rs
+++ b/src/librustc_mir/util/collect_writes.rs
@@ -1,5 +1,5 @@
 use rustc::mir::{Local, Location};
-use rustc::mir::Mir;
+use rustc::mir::Body;
 use rustc::mir::visit::PlaceContext;
 use rustc::mir::visit::Visitor;
 
@@ -9,10 +9,10 @@ crate trait FindAssignments {
     fn find_assignments(&self, local: Local) -> Vec<Location>;
 }
 
-impl<'tcx> FindAssignments for Mir<'tcx>{
+impl<'tcx> FindAssignments for Body<'tcx>{
     fn find_assignments(&self, local: Local) -> Vec<Location>{
             let mut visitor = FindLocalAssignmentVisitor{ needle: local, locations: vec![]};
-            visitor.visit_mir(self);
+            visitor.visit_body(self);
             visitor.locations
     }
 }
diff --git a/src/librustc_mir/util/def_use.rs b/src/librustc_mir/util/def_use.rs
index 2925005b6674d..ba0190756c542 100644
--- a/src/librustc_mir/util/def_use.rs
+++ b/src/librustc_mir/util/def_use.rs
@@ -1,6 +1,6 @@
 //! Def-use analysis.
 
-use rustc::mir::{Local, Location, Mir};
+use rustc::mir::{Local, Location, Body};
 use rustc::mir::visit::{PlaceContext, MutVisitor, Visitor};
 use rustc_data_structures::indexed_vec::IndexVec;
 use std::mem;
@@ -21,19 +21,19 @@ pub struct Use {
 }
 
 impl DefUseAnalysis {
-    pub fn new(mir: &Mir<'_>) -> DefUseAnalysis {
+    pub fn new(mir: &Body<'_>) -> DefUseAnalysis {
         DefUseAnalysis {
             info: IndexVec::from_elem_n(Info::new(), mir.local_decls.len()),
         }
     }
 
-    pub fn analyze(&mut self, mir: &Mir<'_>) {
+    pub fn analyze(&mut self, mir: &Body<'_>) {
         self.clear();
 
         let mut finder = DefUseFinder {
             info: mem::replace(&mut self.info, IndexVec::new()),
         };
-        finder.visit_mir(mir);
+        finder.visit_body(mir);
         self.info = finder.info
     }
 
@@ -47,7 +47,7 @@ impl DefUseAnalysis {
         &self.info[local]
     }
 
-    fn mutate_defs_and_uses<F>(&self, local: Local, mir: &mut Mir<'_>, mut callback: F)
+    fn mutate_defs_and_uses<F>(&self, local: Local, mir: &mut Body<'_>, mut callback: F)
                                where F: for<'a> FnMut(&'a mut Local,
                                                       PlaceContext,
                                                       Location) {
@@ -61,7 +61,7 @@ impl DefUseAnalysis {
     // FIXME(pcwalton): this should update the def-use chains.
     pub fn replace_all_defs_and_uses_with(&self,
                                           local: Local,
-                                          mir: &mut Mir<'_>,
+                                          mir: &mut Body<'_>,
                                           new_local: Local) {
         self.mutate_defs_and_uses(local, mir, |local, _, _| *local = new_local)
     }
@@ -123,7 +123,7 @@ struct MutateUseVisitor<F> {
 }
 
 impl<F> MutateUseVisitor<F> {
-    fn new(query: Local, callback: F, _: &Mir<'_>)
+    fn new(query: Local, callback: F, _: &Body<'_>)
            -> MutateUseVisitor<F>
            where F: for<'a> FnMut(&'a mut Local, PlaceContext, Location) {
         MutateUseVisitor {
diff --git a/src/librustc_mir/util/elaborate_drops.rs b/src/librustc_mir/util/elaborate_drops.rs
index 98ca7c32675c8..c5c74cc0b2964 100644
--- a/src/librustc_mir/util/elaborate_drops.rs
+++ b/src/librustc_mir/util/elaborate_drops.rs
@@ -74,7 +74,7 @@ pub trait DropElaborator<'a, 'tcx: 'a> : fmt::Debug {
     type Path : Copy + fmt::Debug;
 
     fn patch(&mut self) -> &mut MirPatch<'tcx>;
-    fn mir(&self) -> &'a Mir<'tcx>;
+    fn mir(&self) -> &'a Body<'tcx>;
     fn tcx(&self) -> TyCtxt<'a, 'tcx, 'tcx>;
     fn param_env(&self) -> ty::ParamEnv<'tcx>;
 
diff --git a/src/librustc_mir/util/graphviz.rs b/src/librustc_mir/util/graphviz.rs
index fc4c6b3fd3f24..20d92da9ba330 100644
--- a/src/librustc_mir/util/graphviz.rs
+++ b/src/librustc_mir/util/graphviz.rs
@@ -34,7 +34,7 @@ pub fn graphviz_safe_def_name(def_id: DefId) -> String {
 /// Write a graphviz DOT graph of the MIR.
 pub fn write_mir_fn_graphviz<'tcx, W>(tcx: TyCtxt<'_, '_, 'tcx>,
                                       def_id: DefId,
-                                      mir: &Mir<'_>,
+                                      mir: &Body<'_>,
                                       w: &mut W) -> io::Result<()>
     where W: Write
 {
@@ -68,7 +68,7 @@ pub fn write_mir_fn_graphviz<'tcx, W>(tcx: TyCtxt<'_, '_, 'tcx>,
 /// `init` and `fini` are callbacks for emitting additional rows of
 /// data (using HTML enclosed with `<tr>` in the emitted text).
 pub fn write_node_label<W: Write, INIT, FINI>(block: BasicBlock,
-                                              mir: &Mir<'_>,
+                                              mir: &Body<'_>,
                                               w: &mut W,
                                               num_cols: u32,
                                               init: INIT,
@@ -110,7 +110,7 @@ pub fn write_node_label<W: Write, INIT, FINI>(block: BasicBlock,
 }
 
 /// Write a graphviz DOT node for the given basic block.
-fn write_node<W: Write>(block: BasicBlock, mir: &Mir<'_>, w: &mut W) -> io::Result<()> {
+fn write_node<W: Write>(block: BasicBlock, mir: &Body<'_>, w: &mut W) -> io::Result<()> {
     // Start a new node with the label to follow, in one of DOT's pseudo-HTML tables.
     write!(w, r#"    {} [shape="none", label=<"#, node(block))?;
     write_node_label(block, mir, w, 1, |_| Ok(()), |_| Ok(()))?;
@@ -119,7 +119,7 @@ fn write_node<W: Write>(block: BasicBlock, mir: &Mir<'_>, w: &mut W) -> io::Resu
 }
 
 /// Write graphviz DOT edges with labels between the given basic block and all of its successors.
-fn write_edges<W: Write>(source: BasicBlock, mir: &Mir<'_>, w: &mut W) -> io::Result<()> {
+fn write_edges<W: Write>(source: BasicBlock, mir: &Body<'_>, w: &mut W) -> io::Result<()> {
     let terminator = mir[source].terminator();
     let labels = terminator.kind.fmt_successor_labels();
 
@@ -135,7 +135,7 @@ fn write_edges<W: Write>(source: BasicBlock, mir: &Mir<'_>, w: &mut W) -> io::Re
 /// all the variables and temporaries.
 fn write_graph_label<'a, 'gcx, 'tcx, W: Write>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
                                                def_id: DefId,
-                                               mir: &Mir<'_>,
+                                               mir: &Body<'_>,
                                                w: &mut W)
                                                -> io::Result<()> {
     write!(w, "    label=<fn {}(", dot::escape_html(&tcx.def_path_str(def_id)))?;
diff --git a/src/librustc_mir/util/liveness.rs b/src/librustc_mir/util/liveness.rs
index 8d9a878fc9e37..a3317d3956be4 100644
--- a/src/librustc_mir/util/liveness.rs
+++ b/src/librustc_mir/util/liveness.rs
@@ -57,7 +57,7 @@ pub struct LivenessResult {
 /// Computes which local variables are live within the given function
 /// `mir`, including drops.
 pub fn liveness_of_locals<'tcx>(
-    mir: &Mir<'tcx>,
+    mir: &Body<'tcx>,
 ) -> LivenessResult {
     let num_live_vars = mir.local_decls.len();
 
@@ -258,7 +258,7 @@ pub fn dump_mir<'a, 'tcx>(
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     pass_name: &str,
     source: MirSource<'tcx>,
-    mir: &Mir<'tcx>,
+    mir: &Body<'tcx>,
     result: &LivenessResult,
 ) {
     if !dump_enabled(tcx, pass_name, source) {
@@ -276,7 +276,7 @@ fn dump_matched_mir_node<'a, 'tcx>(
     pass_name: &str,
     node_path: &str,
     source: MirSource<'tcx>,
-    mir: &Mir<'tcx>,
+    mir: &Body<'tcx>,
     result: &LivenessResult,
 ) {
     let mut file_path = PathBuf::new();
@@ -297,7 +297,7 @@ fn dump_matched_mir_node<'a, 'tcx>(
 pub fn write_mir_fn<'a, 'tcx>(
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     src: MirSource<'tcx>,
-    mir: &Mir<'tcx>,
+    mir: &Body<'tcx>,
     w: &mut dyn Write,
     result: &LivenessResult,
 ) -> io::Result<()> {
diff --git a/src/librustc_mir/util/patch.rs b/src/librustc_mir/util/patch.rs
index 366cd71f6d4e9..974dda867bc9d 100644
--- a/src/librustc_mir/util/patch.rs
+++ b/src/librustc_mir/util/patch.rs
@@ -17,7 +17,7 @@ pub struct MirPatch<'tcx> {
 }
 
 impl<'tcx> MirPatch<'tcx> {
-    pub fn new(mir: &Mir<'tcx>) -> Self {
+    pub fn new(mir: &Body<'tcx>) -> Self {
         let mut result = MirPatch {
             patch_map: IndexVec::from_elem(None, mir.basic_blocks()),
             new_blocks: vec![],
@@ -75,7 +75,7 @@ impl<'tcx> MirPatch<'tcx> {
         self.patch_map[bb].is_some()
     }
 
-    pub fn terminator_loc(&self, mir: &Mir<'tcx>, bb: BasicBlock) -> Location {
+    pub fn terminator_loc(&self, mir: &Body<'tcx>, bb: BasicBlock) -> Location {
         let offset = match bb.index().checked_sub(mir.basic_blocks().len()) {
             Some(index) => self.new_blocks[index].statements.len(),
             None => mir[bb].statements.len()
@@ -127,7 +127,7 @@ impl<'tcx> MirPatch<'tcx> {
         self.make_nop.push(loc);
     }
 
-    pub fn apply(self, mir: &mut Mir<'tcx>) {
+    pub fn apply(self, mir: &mut Body<'tcx>) {
         debug!("MirPatch: make nops at: {:?}", self.make_nop);
         for loc in self.make_nop {
             mir.make_statement_nop(loc);
@@ -177,7 +177,7 @@ impl<'tcx> MirPatch<'tcx> {
         }
     }
 
-    pub fn source_info_for_location(&self, mir: &Mir<'_>, loc: Location) -> SourceInfo {
+    pub fn source_info_for_location(&self, mir: &Body<'_>, loc: Location) -> SourceInfo {
         let data = match loc.block.index().checked_sub(mir.basic_blocks().len()) {
             Some(new) => &self.new_blocks[new],
             None => &mir[loc.block]
diff --git a/src/librustc_mir/util/pretty.rs b/src/librustc_mir/util/pretty.rs
index 94259fa523ccd..911fe3ea8bbbd 100644
--- a/src/librustc_mir/util/pretty.rs
+++ b/src/librustc_mir/util/pretty.rs
@@ -68,7 +68,7 @@ pub fn dump_mir<'a, 'gcx, 'tcx, F>(
     pass_name: &str,
     disambiguator: &dyn Display,
     source: MirSource<'tcx>,
-    mir: &Mir<'tcx>,
+    mir: &Body<'tcx>,
     extra_data: F,
 ) where
     F: FnMut(PassWhere, &mut dyn Write) -> io::Result<()>,
@@ -124,7 +124,7 @@ fn dump_matched_mir_node<'a, 'gcx, 'tcx, F>(
     node_path: &str,
     disambiguator: &dyn Display,
     source: MirSource<'tcx>,
-    mir: &Mir<'tcx>,
+    mir: &Body<'tcx>,
     mut extra_data: F,
 ) where
     F: FnMut(PassWhere, &mut dyn Write) -> io::Result<()>,
@@ -282,7 +282,7 @@ pub fn write_mir_pretty<'a, 'gcx, 'tcx>(
 pub fn write_mir_fn<'a, 'gcx, 'tcx, F>(
     tcx: TyCtxt<'a, 'gcx, 'tcx>,
     src: MirSource<'tcx>,
-    mir: &Mir<'tcx>,
+    mir: &Body<'tcx>,
     extra_data: &mut F,
     w: &mut dyn Write,
 ) -> io::Result<()>
@@ -306,7 +306,7 @@ where
 pub fn write_basic_block<'cx, 'gcx, 'tcx, F>(
     tcx: TyCtxt<'cx, 'gcx, 'tcx>,
     block: BasicBlock,
-    mir: &Mir<'tcx>,
+    mir: &Body<'tcx>,
     extra_data: &mut F,
     w: &mut dyn Write,
 ) -> io::Result<()>
@@ -464,7 +464,7 @@ fn comment(tcx: TyCtxt<'_, '_, '_>, SourceInfo { span, scope }: SourceInfo) -> S
 /// Prints local variables in a scope tree.
 fn write_scope_tree(
     tcx: TyCtxt<'_, '_, '_>,
-    mir: &Mir<'_>,
+    mir: &Body<'_>,
     scope_tree: &FxHashMap<SourceScope, Vec<SourceScope>>,
     w: &mut dyn Write,
     parent: SourceScope,
@@ -541,7 +541,7 @@ fn write_scope_tree(
 pub fn write_mir_intro<'a, 'gcx, 'tcx>(
     tcx: TyCtxt<'a, 'gcx, 'tcx>,
     src: MirSource<'tcx>,
-    mir: &Mir<'_>,
+    mir: &Body<'_>,
     w: &mut dyn Write,
 ) -> io::Result<()> {
     write_mir_sig(tcx, src, mir, w)?;
@@ -572,7 +572,7 @@ pub fn write_mir_intro<'a, 'gcx, 'tcx>(
 fn write_mir_sig(
     tcx: TyCtxt<'_, '_, '_>,
     src: MirSource<'tcx>,
-    mir: &Mir<'_>,
+    mir: &Body<'_>,
     w: &mut dyn Write,
 ) -> io::Result<()> {
     use rustc::hir::def::DefKind;
@@ -629,7 +629,7 @@ fn write_mir_sig(
     Ok(())
 }
 
-fn write_user_type_annotations(mir: &Mir<'_>, w: &mut dyn Write) -> io::Result<()> {
+fn write_user_type_annotations(mir: &Body<'_>, w: &mut dyn Write) -> io::Result<()> {
     if !mir.user_type_annotations.is_empty() {
         writeln!(w, "| User Type Annotations")?;
     }
diff --git a/src/librustc_target/Cargo.toml b/src/librustc_target/Cargo.toml
index ecea15a992250..3ab25146331c1 100644
--- a/src/librustc_target/Cargo.toml
+++ b/src/librustc_target/Cargo.toml
@@ -15,3 +15,4 @@ log = "0.4"
 rustc_cratesio_shim = { path = "../librustc_cratesio_shim" }
 rustc_data_structures = { path = "../librustc_data_structures" }
 serialize = { path = "../libserialize" }
+syntax_pos = { path = "../libsyntax_pos" }
diff --git a/src/librustc_target/abi/mod.rs b/src/librustc_target/abi/mod.rs
index 4b61057e5cf6c..8fc5e6aae34d4 100644
--- a/src/librustc_target/abi/mod.rs
+++ b/src/librustc_target/abi/mod.rs
@@ -7,6 +7,7 @@ use std::fmt;
 use std::ops::{Add, Deref, Sub, Mul, AddAssign, Range, RangeInclusive};
 
 use rustc_data_structures::indexed_vec::{Idx, IndexVec};
+use syntax_pos::symbol::{sym, Symbol};
 
 pub mod call;
 
@@ -552,6 +553,13 @@ impl FloatTy {
         }
     }
 
+    pub fn to_symbol(self) -> Symbol {
+        match self {
+            FloatTy::F32 => sym::f32,
+            FloatTy::F64 => sym::f64,
+        }
+    }
+
     pub fn bit_width(self) -> usize {
         match self {
             FloatTy::F32 => 32,
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index 655bf5722ae5a..6c339515e73f8 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -2697,16 +2697,12 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
 
     fn resolve_place_op(&self, op: PlaceOp, is_mut: bool) -> (Option<DefId>, ast::Ident) {
         let (tr, name) = match (op, is_mut) {
-            (PlaceOp::Deref, false) =>
-                (self.tcx.lang_items().deref_trait(), "deref"),
-            (PlaceOp::Deref, true) =>
-                (self.tcx.lang_items().deref_mut_trait(), "deref_mut"),
-            (PlaceOp::Index, false) =>
-                (self.tcx.lang_items().index_trait(), "index"),
-            (PlaceOp::Index, true) =>
-                (self.tcx.lang_items().index_mut_trait(), "index_mut"),
+            (PlaceOp::Deref, false) => (self.tcx.lang_items().deref_trait(), sym::deref),
+            (PlaceOp::Deref, true) => (self.tcx.lang_items().deref_mut_trait(), sym::deref_mut),
+            (PlaceOp::Index, false) => (self.tcx.lang_items().index_trait(), sym::index),
+            (PlaceOp::Index, true) => (self.tcx.lang_items().index_mut_trait(), sym::index_mut),
         };
-        (tr, ast::Ident::from_str(name))
+        (tr, ast::Ident::with_empty_ctxt(name))
     }
 
     fn try_overloaded_place_op(&self,
@@ -4948,7 +4944,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                 // This is less than ideal, it will not suggest a return type span on any
                 // method called `main`, regardless of whether it is actually the entry point,
                 // but it will still present it as the reason for the expected type.
-                Some((decl, ident, ident.name != Symbol::intern("main")))
+                Some((decl, ident, ident.name != sym::main))
             }),
             Node::TraitItem(&hir::TraitItem {
                 ident, node: hir::TraitItemKind::Method(hir::MethodSig {
diff --git a/src/libstd/env.rs b/src/libstd/env.rs
index 9058ea93d6de0..00e840a53e9c0 100644
--- a/src/libstd/env.rs
+++ b/src/libstd/env.rs
@@ -465,7 +465,7 @@ pub struct JoinPathsError {
 /// # }
 /// ```
 ///
-/// Using `env::join_paths` with `env::spit_paths` to append an item to the `PATH` environment
+/// Using `env::join_paths` with [`env::split_paths`] to append an item to the `PATH` environment
 /// variable:
 ///
 /// ```
@@ -483,6 +483,8 @@ pub struct JoinPathsError {
 ///     Ok(())
 /// }
 /// ```
+///
+/// [`env::split_paths`]: fn.split_paths.html
 #[stable(feature = "env", since = "1.0.0")]
 pub fn join_paths<I, T>(paths: I) -> Result<OsString, JoinPathsError>
     where I: IntoIterator<Item=T>, T: AsRef<OsStr>
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index 3276f152575f7..75e83bd9f9c74 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -10,7 +10,7 @@ use crate::parse::token;
 use crate::print::pprust;
 use crate::ptr::P;
 use crate::source_map::{dummy_spanned, respan, Spanned};
-use crate::symbol::{kw, Symbol};
+use crate::symbol::{kw, sym, Symbol};
 use crate::tokenstream::TokenStream;
 use crate::ThinVec;
 
@@ -1531,6 +1531,17 @@ impl IntTy {
         }
     }
 
+    pub fn to_symbol(&self) -> Symbol {
+        match *self {
+            IntTy::Isize => sym::isize,
+            IntTy::I8 => sym::i8,
+            IntTy::I16 => sym::i16,
+            IntTy::I32 => sym::i32,
+            IntTy::I64 => sym::i64,
+            IntTy::I128 => sym::i128,
+        }
+    }
+
     pub fn val_to_string(&self, val: i128) -> String {
         // Cast to a `u128` so we can correctly print `INT128_MIN`. All integral types
         // are parsed as `u128`, so we wouldn't want to print an extra negative
@@ -1572,6 +1583,17 @@ impl UintTy {
         }
     }
 
+    pub fn to_symbol(&self) -> Symbol {
+        match *self {
+            UintTy::Usize => sym::usize,
+            UintTy::U8 => sym::u8,
+            UintTy::U16 => sym::u16,
+            UintTy::U32 => sym::u32,
+            UintTy::U64 => sym::u64,
+            UintTy::U128 => sym::u128,
+        }
+    }
+
     pub fn val_to_string(&self, val: u128) -> String {
         format!("{}{}", val, self.ty_to_string())
     }
diff --git a/src/libsyntax/attr/mod.rs b/src/libsyntax/attr/mod.rs
index 2f75a8c9db57e..48948e4d0d79c 100644
--- a/src/libsyntax/attr/mod.rs
+++ b/src/libsyntax/attr/mod.rs
@@ -278,7 +278,14 @@ impl Attribute {
     pub fn parse<'a, T, F>(&self, sess: &'a ParseSess, mut f: F) -> PResult<'a, T>
         where F: FnMut(&mut Parser<'a>) -> PResult<'a, T>,
     {
-        let mut parser = Parser::new(sess, self.tokens.clone(), None, false, false);
+        let mut parser = Parser::new(
+            sess,
+            self.tokens.clone(),
+            None,
+            false,
+            false,
+            Some("attribute"),
+        );
         let result = f(&mut parser)?;
         if parser.token != token::Eof {
             parser.unexpected()?;
diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs
index f1a20d5406574..d72193ffe1205 100644
--- a/src/libsyntax/ext/base.rs
+++ b/src/libsyntax/ext/base.rs
@@ -11,7 +11,7 @@ use crate::parse::{self, parser, DirectoryOwnership};
 use crate::parse::token;
 use crate::ptr::P;
 use crate::symbol::{kw, sym, Ident, Symbol};
-use crate::ThinVec;
+use crate::{ThinVec, MACRO_ARGUMENTS};
 use crate::tokenstream::{self, TokenStream};
 
 use errors::{DiagnosticBuilder, DiagnosticId};
@@ -850,7 +850,7 @@ impl<'a> ExtCtxt<'a> {
     }
 
     pub fn new_parser_from_tts(&self, tts: &[tokenstream::TokenTree]) -> parser::Parser<'a> {
-        parse::stream_to_parser(self.parse_sess, tts.iter().cloned().collect())
+        parse::stream_to_parser(self.parse_sess, tts.iter().cloned().collect(), MACRO_ARGUMENTS)
     }
     pub fn source_map(&self) -> &'a SourceMap { self.parse_sess.source_map() }
     pub fn parse_sess(&self) -> &'a parse::ParseSess { self.parse_sess }
@@ -969,10 +969,10 @@ impl<'a> ExtCtxt<'a> {
     pub fn ident_of(&self, st: &str) -> ast::Ident {
         ast::Ident::from_str(st)
     }
-    pub fn std_path(&self, components: &[&str]) -> Vec<ast::Ident> {
+    pub fn std_path(&self, components: &[Symbol]) -> Vec<ast::Ident> {
         let def_site = DUMMY_SP.apply_mark(self.current_expansion.mark);
         iter::once(Ident::new(kw::DollarCrate, def_site))
-            .chain(components.iter().map(|s| self.ident_of(s)))
+            .chain(components.iter().map(|&s| Ident::with_empty_ctxt(s)))
             .collect()
     }
     pub fn name_of(&self, st: &str) -> ast::Name {
diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs
index ad8fb12deb7f6..9c0ffc1f6e8cb 100644
--- a/src/libsyntax/ext/build.rs
+++ b/src/libsyntax/ext/build.rs
@@ -3,11 +3,11 @@ use crate::attr;
 use crate::source_map::{dummy_spanned, respan, Spanned};
 use crate::ext::base::ExtCtxt;
 use crate::ptr::P;
-use crate::symbol::{Symbol, kw};
+use crate::symbol::{kw, sym, Symbol};
 use crate::ThinVec;
 
 use rustc_target::spec::abi::Abi;
-use syntax_pos::{Pos, Span, DUMMY_SP};
+use syntax_pos::{Pos, Span};
 
 pub trait AstBuilder {
     // paths
@@ -49,7 +49,6 @@ pub trait AstBuilder {
               ty: P<ast::Ty>,
               mutbl: ast::Mutability) -> P<ast::Ty>;
 
-    fn ty_option(&self, ty: P<ast::Ty>) -> P<ast::Ty>;
     fn ty_infer(&self, sp: Span) -> P<ast::Ty>;
 
     fn typaram(&self,
@@ -425,15 +424,6 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
                 ast::TyKind::Ptr(self.ty_mt(ty, mutbl)))
     }
 
-    fn ty_option(&self, ty: P<ast::Ty>) -> P<ast::Ty> {
-        self.ty_path(
-            self.path_all(DUMMY_SP,
-                          true,
-                          self.std_path(&["option", "Option"]),
-                          vec![ast::GenericArg::Type(ty)],
-                          Vec::new()))
-    }
-
     fn ty_infer(&self, span: Span) -> P<ast::Ty> {
         self.ty(span, ast::TyKind::Infer)
     }
@@ -735,7 +725,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
         self.expr(sp, ast::ExprKind::Array(exprs))
     }
     fn expr_vec_ng(&self, sp: Span) -> P<ast::Expr> {
-        self.expr_call_global(sp, self.std_path(&["vec", "Vec", "new"]),
+        self.expr_call_global(sp, self.std_path(&[sym::vec, sym::Vec, sym::new]),
                               Vec::new())
     }
     fn expr_vec_slice(&self, sp: Span, exprs: Vec<P<ast::Expr>>) -> P<ast::Expr> {
@@ -751,12 +741,12 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
 
 
     fn expr_some(&self, sp: Span, expr: P<ast::Expr>) -> P<ast::Expr> {
-        let some = self.std_path(&["option", "Option", "Some"]);
+        let some = self.std_path(&[sym::option, sym::Option, sym::Some]);
         self.expr_call_global(sp, some, vec![expr])
     }
 
     fn expr_none(&self, sp: Span) -> P<ast::Expr> {
-        let none = self.std_path(&["option", "Option", "None"]);
+        let none = self.std_path(&[sym::option, sym::Option, sym::None]);
         let none = self.path_global(sp, none);
         self.expr_path(none)
     }
@@ -780,7 +770,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
         let expr_loc_ptr = self.expr_addr_of(span, expr_loc_tuple);
         self.expr_call_global(
             span,
-            self.std_path(&["rt", "begin_panic"]),
+            self.std_path(&[sym::rt, sym::begin_panic]),
             vec![
                 self.expr_str(span, msg),
                 expr_loc_ptr])
@@ -791,19 +781,19 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
     }
 
     fn expr_ok(&self, sp: Span, expr: P<ast::Expr>) -> P<ast::Expr> {
-        let ok = self.std_path(&["result", "Result", "Ok"]);
+        let ok = self.std_path(&[sym::result, sym::Result, sym::Ok]);
         self.expr_call_global(sp, ok, vec![expr])
     }
 
     fn expr_err(&self, sp: Span, expr: P<ast::Expr>) -> P<ast::Expr> {
-        let err = self.std_path(&["result", "Result", "Err"]);
+        let err = self.std_path(&[sym::result, sym::Result, sym::Err]);
         self.expr_call_global(sp, err, vec![expr])
     }
 
     fn expr_try(&self, sp: Span, head: P<ast::Expr>) -> P<ast::Expr> {
-        let ok = self.std_path(&["result", "Result", "Ok"]);
+        let ok = self.std_path(&[sym::result, sym::Result, sym::Ok]);
         let ok_path = self.path_global(sp, ok);
-        let err = self.std_path(&["result", "Result", "Err"]);
+        let err = self.std_path(&[sym::result, sym::Result, sym::Err]);
         let err_path = self.path_global(sp, err);
 
         let binding_variable = self.ident_of("__try_var");
@@ -867,25 +857,25 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
     }
 
     fn pat_some(&self, span: Span, pat: P<ast::Pat>) -> P<ast::Pat> {
-        let some = self.std_path(&["option", "Option", "Some"]);
+        let some = self.std_path(&[sym::option, sym::Option, sym::Some]);
         let path = self.path_global(span, some);
         self.pat_tuple_struct(span, path, vec![pat])
     }
 
     fn pat_none(&self, span: Span) -> P<ast::Pat> {
-        let some = self.std_path(&["option", "Option", "None"]);
+        let some = self.std_path(&[sym::option, sym::Option, sym::None]);
         let path = self.path_global(span, some);
         self.pat_path(span, path)
     }
 
     fn pat_ok(&self, span: Span, pat: P<ast::Pat>) -> P<ast::Pat> {
-        let some = self.std_path(&["result", "Result", "Ok"]);
+        let some = self.std_path(&[sym::result, sym::Result, sym::Ok]);
         let path = self.path_global(span, some);
         self.pat_tuple_struct(span, path, vec![pat])
     }
 
     fn pat_err(&self, span: Span, pat: P<ast::Pat>) -> P<ast::Pat> {
-        let some = self.std_path(&["result", "Result", "Err"]);
+        let some = self.std_path(&[sym::result, sym::Result, sym::Err]);
         let path = self.path_global(span, some);
         self.pat_tuple_struct(span, path, vec![pat])
     }
diff --git a/src/libsyntax/ext/derive.rs b/src/libsyntax/ext/derive.rs
index 6e789c4c7086b..c47224ca0ce3f 100644
--- a/src/libsyntax/ext/derive.rs
+++ b/src/libsyntax/ext/derive.rs
@@ -58,10 +58,7 @@ pub fn add_derived_markers<T>(cx: &mut ExtCtxt<'_>, span: Span, traits: &[ast::P
         call_site: span,
         def_site: None,
         format: ExpnFormat::MacroAttribute(Symbol::intern(&pretty_name)),
-        allow_internal_unstable: Some(vec![
-            Symbol::intern("rustc_attrs"),
-            Symbol::intern("structural_match"),
-        ].into()),
+        allow_internal_unstable: Some(vec![sym::rustc_attrs, sym::structural_match].into()),
         allow_internal_unsafe: false,
         local_inner_macros: false,
         edition: cx.parse_sess.edition,
@@ -74,7 +71,7 @@ pub fn add_derived_markers<T>(cx: &mut ExtCtxt<'_>, span: Span, traits: &[ast::P
             attrs.push(cx.attribute(span, meta));
         }
         if names.contains(&Symbol::intern("Copy")) {
-            let meta = cx.meta_word(span, Symbol::intern("rustc_copy_clone_marker"));
+            let meta = cx.meta_word(span, sym::rustc_copy_clone_marker);
             attrs.push(cx.attribute(span, meta));
         }
     });
diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs
index fbe052252a114..c2a73b662c680 100644
--- a/src/libsyntax/ext/expand.rs
+++ b/src/libsyntax/ext/expand.rs
@@ -938,7 +938,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
             }
             BuiltinDerive(func) => {
                 expn_info.allow_internal_unstable = Some(vec![
-                    Symbol::intern("rustc_attrs"),
+                    sym::rustc_attrs,
                     Symbol::intern("derive_clone_copy"),
                     Symbol::intern("derive_eq"),
                     Symbol::intern("libstd_sys_internals"), // RustcDeserialize and RustcSerialize
diff --git a/src/libsyntax/ext/tt/macro_parser.rs b/src/libsyntax/ext/tt/macro_parser.rs
index fa1f85c0e7b57..7b7cf80760f5c 100644
--- a/src/libsyntax/ext/tt/macro_parser.rs
+++ b/src/libsyntax/ext/tt/macro_parser.rs
@@ -80,7 +80,7 @@ use crate::parse::{Directory, ParseSess};
 use crate::parse::parser::{Parser, PathStyle};
 use crate::parse::token::{self, DocComment, Nonterminal, Token};
 use crate::print::pprust;
-use crate::symbol::kw;
+use crate::symbol::{kw, sym, Symbol};
 use crate::tokenstream::{DelimSpan, TokenStream};
 
 use errors::FatalError;
@@ -598,7 +598,7 @@ fn inner_parse_loop<'root, 'tt>(
                 TokenTree::MetaVarDecl(_, _, id) => {
                     // Built-in nonterminals never start with these tokens,
                     // so we can eliminate them from consideration.
-                    if may_begin_with(&*id.as_str(), token) {
+                    if may_begin_with(id.name, token) {
                         bb_items.push(item);
                     }
                 }
@@ -658,7 +658,14 @@ pub fn parse(
     recurse_into_modules: bool,
 ) -> NamedParseResult {
     // Create a parser that can be used for the "black box" parts.
-    let mut parser = Parser::new(sess, tts, directory, recurse_into_modules, true);
+    let mut parser = Parser::new(
+        sess,
+        tts,
+        directory,
+        recurse_into_modules,
+        true,
+        crate::MACRO_ARGUMENTS,
+    );
 
     // A queue of possible matcher positions. We initialize it with the matcher position in which
     // the "dot" is before the first token of the first token tree in `ms`. `inner_parse_loop` then
@@ -784,7 +791,7 @@ pub fn parse(
                 let match_cur = item.match_cur;
                 item.push_match(
                     match_cur,
-                    MatchedNonterminal(Lrc::new(parse_nt(&mut parser, span, &ident.as_str()))),
+                    MatchedNonterminal(Lrc::new(parse_nt(&mut parser, span, ident.name))),
                 );
                 item.idx += 1;
                 item.match_cur += 1;
@@ -812,7 +819,7 @@ fn get_macro_ident(token: &Token) -> Option<(Ident, bool)> {
 ///
 /// Returning `false` is a *stability guarantee* that such a matcher will *never* begin with that
 /// token. Be conservative (return true) if not sure.
-fn may_begin_with(name: &str, token: &Token) -> bool {
+fn may_begin_with(name: Symbol, token: &Token) -> bool {
     /// Checks whether the non-terminal may contain a single (non-keyword) identifier.
     fn may_be_ident(nt: &token::Nonterminal) -> bool {
         match *nt {
@@ -822,16 +829,16 @@ fn may_begin_with(name: &str, token: &Token) -> bool {
     }
 
     match name {
-        "expr" => token.can_begin_expr(),
-        "ty" => token.can_begin_type(),
-        "ident" => get_macro_ident(token).is_some(),
-        "literal" => token.can_begin_literal_or_bool(),
-        "vis" => match *token {
+        sym::expr => token.can_begin_expr(),
+        sym::ty => token.can_begin_type(),
+        sym::ident => get_macro_ident(token).is_some(),
+        sym::literal => token.can_begin_literal_or_bool(),
+        sym::vis => match *token {
             // The follow-set of :vis + "priv" keyword + interpolated
             Token::Comma | Token::Ident(..) | Token::Interpolated(_) => true,
             _ => token.can_begin_type(),
         },
-        "block" => match *token {
+        sym::block => match *token {
             Token::OpenDelim(token::Brace) => true,
             Token::Interpolated(ref nt) => match **nt {
                 token::NtItem(_)
@@ -845,7 +852,7 @@ fn may_begin_with(name: &str, token: &Token) -> bool {
             },
             _ => false,
         },
-        "path" | "meta" => match *token {
+        sym::path | sym::meta => match *token {
             Token::ModSep | Token::Ident(..) => true,
             Token::Interpolated(ref nt) => match **nt {
                 token::NtPath(_) | token::NtMeta(_) => true,
@@ -853,7 +860,7 @@ fn may_begin_with(name: &str, token: &Token) -> bool {
             },
             _ => false,
         },
-        "pat" => match *token {
+        sym::pat => match *token {
             Token::Ident(..) |               // box, ref, mut, and other identifiers (can stricten)
             Token::OpenDelim(token::Paren) |    // tuple pattern
             Token::OpenDelim(token::Bracket) |  // slice pattern
@@ -869,7 +876,7 @@ fn may_begin_with(name: &str, token: &Token) -> bool {
             Token::Interpolated(ref nt) => may_be_ident(nt),
             _ => false,
         },
-        "lifetime" => match *token {
+        sym::lifetime => match *token {
             Token::Lifetime(_) => true,
             Token::Interpolated(ref nt) => match **nt {
                 token::NtLifetime(_) | token::NtTT(_) => true,
@@ -896,34 +903,34 @@ fn may_begin_with(name: &str, token: &Token) -> bool {
 /// # Returns
 ///
 /// The parsed non-terminal.
-fn parse_nt<'a>(p: &mut Parser<'a>, sp: Span, name: &str) -> Nonterminal {
-    if name == "tt" {
+fn parse_nt<'a>(p: &mut Parser<'a>, sp: Span, name: Symbol) -> Nonterminal {
+    if name == sym::tt {
         return token::NtTT(p.parse_token_tree());
     }
     // check at the beginning and the parser checks after each bump
     p.process_potential_macro_variable();
     match name {
-        "item" => match panictry!(p.parse_item()) {
+        sym::item => match panictry!(p.parse_item()) {
             Some(i) => token::NtItem(i),
             None => {
                 p.fatal("expected an item keyword").emit();
                 FatalError.raise();
             }
         },
-        "block" => token::NtBlock(panictry!(p.parse_block())),
-        "stmt" => match panictry!(p.parse_stmt()) {
+        sym::block => token::NtBlock(panictry!(p.parse_block())),
+        sym::stmt => match panictry!(p.parse_stmt()) {
             Some(s) => token::NtStmt(s),
             None => {
                 p.fatal("expected a statement").emit();
                 FatalError.raise();
             }
         },
-        "pat" => token::NtPat(panictry!(p.parse_pat(None))),
-        "expr" => token::NtExpr(panictry!(p.parse_expr())),
-        "literal" => token::NtLiteral(panictry!(p.parse_literal_maybe_minus())),
-        "ty" => token::NtTy(panictry!(p.parse_ty())),
+        sym::pat => token::NtPat(panictry!(p.parse_pat(None))),
+        sym::expr => token::NtExpr(panictry!(p.parse_expr())),
+        sym::literal => token::NtLiteral(panictry!(p.parse_literal_maybe_minus())),
+        sym::ty => token::NtTy(panictry!(p.parse_ty())),
         // this could be handled like a token, since it is one
-        "ident" => if let Some((ident, is_raw)) = get_macro_ident(&p.token) {
+        sym::ident => if let Some((ident, is_raw)) = get_macro_ident(&p.token) {
             let span = p.span;
             p.bump();
             token::NtIdent(Ident::new(ident.name, span), is_raw)
@@ -932,10 +939,10 @@ fn parse_nt<'a>(p: &mut Parser<'a>, sp: Span, name: &str) -> Nonterminal {
             p.fatal(&format!("expected ident, found {}", &token_str)).emit();
             FatalError.raise()
         }
-        "path" => token::NtPath(panictry!(p.parse_path(PathStyle::Type))),
-        "meta" => token::NtMeta(panictry!(p.parse_meta_item())),
-        "vis" => token::NtVis(panictry!(p.parse_visibility(true))),
-        "lifetime" => if p.check_lifetime() {
+        sym::path => token::NtPath(panictry!(p.parse_path(PathStyle::Type))),
+        sym::meta => token::NtMeta(panictry!(p.parse_meta_item())),
+        sym::vis => token::NtVis(panictry!(p.parse_visibility(true))),
+        sym::lifetime => if p.check_lifetime() {
             token::NtLifetime(p.expect_lifetime().ident)
         } else {
             let token_str = pprust::token_to_string(&p.token);
diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs
index 37c49112dcaac..285c88357a6a8 100644
--- a/src/libsyntax/ext/tt/macro_rules.rs
+++ b/src/libsyntax/ext/tt/macro_rules.rs
@@ -172,7 +172,7 @@ fn generic_extension<'cx>(cx: &'cx mut ExtCtxt<'_>,
                     path: Cow::from(cx.current_expansion.module.directory.as_path()),
                     ownership: cx.current_expansion.directory_ownership,
                 };
-                let mut p = Parser::new(cx.parse_sess(), tts, Some(directory), true, false);
+                let mut p = Parser::new(cx.parse_sess(), tts, Some(directory), true, false, None);
                 p.root_module_name = cx.current_expansion.module.mod_path.last()
                     .map(|id| id.as_str().to_string());
 
@@ -396,7 +396,7 @@ pub fn compile(
                         future this will become a hard error. Please use `allow_internal_unstable(\
                         foo, bar)` to only allow the `foo` and `bar` features",
                     );
-                    vec![Symbol::intern("allow_internal_unstable_backcompat_hack")].into()
+                    vec![sym::allow_internal_unstable_backcompat_hack].into()
                 })
             );
         let allow_internal_unsafe = attr::contains_name(&def.attrs, sym::allow_internal_unsafe);
diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs
index 5eda975bc9ee4..4229121b3d075 100644
--- a/src/libsyntax/lib.rs
+++ b/src/libsyntax/lib.rs
@@ -31,6 +31,8 @@ pub use rustc_data_structures::thin_vec::ThinVec;
 use ast::AttrId;
 use syntax_pos::edition::Edition;
 
+const MACRO_ARGUMENTS: Option<&'static str> = Some("macro arguments");
+
 // A variant of 'try!' that panics on an Err. This is used as a crutch on the
 // way towards a non-panic!-prone parser. It should be used for fatal parsing
 // errors; eventually we plan to convert all code using panictry to just use
diff --git a/src/libsyntax/parse/diagnostics.rs b/src/libsyntax/parse/diagnostics.rs
index 8ac5beb21b530..810acc9cc923e 100644
--- a/src/libsyntax/parse/diagnostics.rs
+++ b/src/libsyntax/parse/diagnostics.rs
@@ -13,7 +13,7 @@ use crate::symbol::kw;
 use crate::ThinVec;
 use errors::{Applicability, DiagnosticBuilder};
 use log::debug;
-use syntax_pos::Span;
+use syntax_pos::{Span, DUMMY_SP};
 
 pub trait RecoverQPath: Sized + 'static {
     const PATH_STYLE: PathStyle = PathStyle::Expr;
@@ -201,7 +201,7 @@ impl<'a> Parser<'a> {
 
         let mut path = ast::Path {
             segments: Vec::new(),
-            span: syntax_pos::DUMMY_SP,
+            span: DUMMY_SP,
         };
         self.parse_path_segments(&mut path.segments, T::PATH_STYLE)?;
         path.span = ty_span.to(self.prev_span);
@@ -267,6 +267,58 @@ impl<'a> Parser<'a> {
         }
     }
 
+    /// Create a `DiagnosticBuilder` for an unexpected token `t` and try to recover if it is a
+    /// closing delimiter.
+    pub fn unexpected_try_recover(
+        &mut self,
+        t: &token::Token,
+    ) -> PResult<'a, bool /* recovered */> {
+        let token_str = pprust::token_to_string(t);
+        let this_token_str = self.this_token_descr();
+        let (prev_sp, sp) = match (&self.token, self.subparser_name) {
+            // Point at the end of the macro call when reaching end of macro arguments.
+            (token::Token::Eof, Some(_)) => {
+                let sp = self.sess.source_map().next_point(self.span);
+                (sp, sp)
+            }
+            // We don't want to point at the following span after DUMMY_SP.
+            // This happens when the parser finds an empty TokenStream.
+            _ if self.prev_span == DUMMY_SP => (self.span, self.span),
+            // EOF, don't want to point at the following char, but rather the last token.
+            (token::Token::Eof, None) => (self.prev_span, self.span),
+            _ => (self.sess.source_map().next_point(self.prev_span), self.span),
+        };
+        let msg = format!(
+            "expected `{}`, found {}",
+            token_str,
+            match (&self.token, self.subparser_name) {
+                (token::Token::Eof, Some(origin)) => format!("end of {}", origin),
+                _ => this_token_str,
+            },
+        );
+        let mut err = self.struct_span_err(sp, &msg);
+        let label_exp = format!("expected `{}`", token_str);
+        match self.recover_closing_delimiter(&[t.clone()], err) {
+            Err(e) => err = e,
+            Ok(recovered) => {
+                return Ok(recovered);
+            }
+        }
+        let cm = self.sess.source_map();
+        match (cm.lookup_line(prev_sp.lo()), cm.lookup_line(sp.lo())) {
+            (Ok(ref a), Ok(ref b)) if a.line == b.line => {
+                // When the spans are in the same line, it means that the only content
+                // between them is whitespace, point only at the found token.
+                err.span_label(sp, label_exp);
+            }
+            _ => {
+                err.span_label(prev_sp, label_exp);
+                err.span_label(sp, "unexpected token");
+            }
+        }
+        Err(err)
+    }
+
     /// Consume alternative await syntaxes like `await <expr>`, `await? <expr>`, `await(<expr>)`
     /// and `await { <expr> }`.
     crate fn parse_incorrect_await_syntax(
@@ -562,4 +614,23 @@ impl<'a> Parser<'a> {
         }
     }
 
+    crate fn expected_expression_found(&self) -> DiagnosticBuilder<'a> {
+        let (span, msg) = match (&self.token, self.subparser_name) {
+            (&token::Token::Eof, Some(origin)) => {
+                let sp = self.sess.source_map().next_point(self.span);
+                (sp, format!("expected expression, found end of {}", origin))
+            }
+            _ => (self.span, format!(
+                "expected expression, found {}",
+                self.this_token_descr(),
+            )),
+        };
+        let mut err = self.struct_span_err(span, &msg);
+        let sp = self.sess.source_map().start_point(self.span);
+        if let Some(sp) = self.sess.ambiguous_block_expr_parse.borrow().get(&sp) {
+            self.sess.expr_parentheses_needed(&mut err, *sp, None);
+        }
+        err.span_label(span, "expected expression");
+        err
+    }
 }
diff --git a/src/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs
index deb76d6d70a33..a06a84f162a96 100644
--- a/src/libsyntax/parse/lexer/mod.rs
+++ b/src/libsyntax/parse/lexer/mod.rs
@@ -1,7 +1,7 @@
 use crate::ast::{self, Ident};
 use crate::parse::ParseSess;
 use crate::parse::token::{self, Token};
-use crate::symbol::Symbol;
+use crate::symbol::{sym, Symbol};
 use crate::parse::unescape;
 use crate::parse::unescape_error_reporting::{emit_unescape_error, push_escaped_char};
 
@@ -754,7 +754,7 @@ impl<'a> StringReader<'a> {
                 }
                 _ => {
                     // just a 0
-                    return (token::Integer, self.name_from(start_bpos));
+                    return (token::Integer, sym::integer(0));
                 }
             }
         } else if c.is_digit(10) {
diff --git a/src/libsyntax/parse/literal.rs b/src/libsyntax/parse/literal.rs
index 0305b1f59b946..18019a89130e7 100644
--- a/src/libsyntax/parse/literal.rs
+++ b/src/libsyntax/parse/literal.rs
@@ -171,12 +171,15 @@ impl LitKind {
     /// by an AST-based macro) or unavailable (e.g. from HIR pretty-printing).
     pub fn to_lit_token(&self) -> token::Lit {
         let (kind, symbol, suffix) = match *self {
-            LitKind::Str(string, ast::StrStyle::Cooked) => {
-                let escaped = string.as_str().escape_default().to_string();
-                (token::Str, Symbol::intern(&escaped), None)
+            LitKind::Str(symbol, ast::StrStyle::Cooked) => {
+                // Don't re-intern unless the escaped string is different.
+                let s = &symbol.as_str();
+                let escaped = s.escape_default().to_string();
+                let symbol = if escaped == *s { symbol } else { Symbol::intern(&escaped) };
+                (token::Str, symbol, None)
             }
-            LitKind::Str(string, ast::StrStyle::Raw(n)) => {
-                (token::StrRaw(n), string, None)
+            LitKind::Str(symbol, ast::StrStyle::Raw(n)) => {
+                (token::StrRaw(n), symbol, None)
             }
             LitKind::ByteStr(ref bytes) => {
                 let string = bytes.iter().cloned().flat_map(ascii::escape_default)
@@ -193,14 +196,14 @@ impl LitKind {
             }
             LitKind::Int(n, ty) => {
                 let suffix = match ty {
-                    ast::LitIntType::Unsigned(ty) => Some(Symbol::intern(ty.ty_to_string())),
-                    ast::LitIntType::Signed(ty) => Some(Symbol::intern(ty.ty_to_string())),
+                    ast::LitIntType::Unsigned(ty) => Some(ty.to_symbol()),
+                    ast::LitIntType::Signed(ty) => Some(ty.to_symbol()),
                     ast::LitIntType::Unsuffixed => None,
                 };
-                (token::Integer, Symbol::intern(&n.to_string()), suffix)
+                (token::Integer, sym::integer(n), suffix)
             }
             LitKind::Float(symbol, ty) => {
-                (token::Float, symbol, Some(Symbol::intern(ty.ty_to_string())))
+                (token::Float, symbol, Some(ty.to_symbol()))
             }
             LitKind::FloatUnsuffixed(symbol) => {
                 (token::Float, symbol, None)
diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs
index 1073fc6f3ab4d..f7a7aba9ecbaa 100644
--- a/src/libsyntax/parse/mod.rs
+++ b/src/libsyntax/parse/mod.rs
@@ -236,7 +236,7 @@ fn maybe_source_file_to_parser(
 ) -> Result<Parser<'_>, Vec<Diagnostic>> {
     let end_pos = source_file.end_pos;
     let (stream, unclosed_delims) = maybe_file_to_stream(sess, source_file, None)?;
-    let mut parser = stream_to_parser(sess, stream);
+    let mut parser = stream_to_parser(sess, stream, None);
     parser.unclosed_delims = unclosed_delims;
     if parser.token == token::Eof && parser.span.is_dummy() {
         parser.span = Span::new(end_pos, end_pos, parser.span.ctxt());
@@ -248,7 +248,7 @@ fn maybe_source_file_to_parser(
 // must preserve old name for now, because quote! from the *existing*
 // compiler expands into it
 pub fn new_parser_from_tts(sess: &ParseSess, tts: Vec<TokenTree>) -> Parser<'_> {
-    stream_to_parser(sess, tts.into_iter().collect())
+    stream_to_parser(sess, tts.into_iter().collect(), crate::MACRO_ARGUMENTS)
 }
 
 
@@ -328,8 +328,12 @@ pub fn maybe_file_to_stream(
 }
 
 /// Given stream and the `ParseSess`, produces a parser.
-pub fn stream_to_parser(sess: &ParseSess, stream: TokenStream) -> Parser<'_> {
-    Parser::new(sess, stream, None, true, false)
+pub fn stream_to_parser<'a>(
+    sess: &'a ParseSess,
+    stream: TokenStream,
+    subparser_name: Option<&'static str>,
+) -> Parser<'a> {
+    Parser::new(sess, stream, None, true, false, subparser_name)
 }
 
 /// Given stream, the `ParseSess` and the base directory, produces a parser.
@@ -343,10 +347,12 @@ pub fn stream_to_parser(sess: &ParseSess, stream: TokenStream) -> Parser<'_> {
 /// The main usage of this function is outside of rustc, for those who uses
 /// libsyntax as a library. Please do not remove this function while refactoring
 /// just because it is not used in rustc codebase!
-pub fn stream_to_parser_with_base_dir<'a>(sess: &'a ParseSess,
-                                          stream: TokenStream,
-                                          base_dir: Directory<'a>) -> Parser<'a> {
-    Parser::new(sess, stream, Some(base_dir), true, false)
+pub fn stream_to_parser_with_base_dir<'a>(
+    sess: &'a ParseSess,
+    stream: TokenStream,
+    base_dir: Directory<'a>,
+) -> Parser<'a> {
+    Parser::new(sess, stream, Some(base_dir), true, false, None)
 }
 
 /// A sequence separator.
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 11c566b65e50a..a49ac637b1bba 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -51,7 +51,7 @@ use crate::symbol::{kw, sym, Symbol};
 use errors::{Applicability, DiagnosticBuilder, DiagnosticId, FatalError};
 use rustc_target::spec::abi::{self, Abi};
 use syntax_pos::{
-    Span, MultiSpan, BytePos, FileName,
+    BytePos, DUMMY_SP, FileName, MultiSpan, Span,
     hygiene::CompilerDesugaringKind,
 };
 use log::{debug, trace};
@@ -233,6 +233,8 @@ pub struct Parser<'a> {
     /// error.
     crate unclosed_delims: Vec<UnmatchedBrace>,
     last_unexpected_token_span: Option<Span>,
+    /// If present, this `Parser` is not parsing Rust code but rather a macro call.
+    crate subparser_name: Option<&'static str>,
 }
 
 impl<'a> Drop for Parser<'a> {
@@ -309,7 +311,7 @@ impl TokenCursor {
                 self.frame = frame;
                 continue
             } else {
-                return TokenAndSpan { tok: token::Eof, sp: syntax_pos::DUMMY_SP }
+                return TokenAndSpan { tok: token::Eof, sp: DUMMY_SP }
             };
 
             match self.frame.last_token {
@@ -533,17 +535,19 @@ enum TokenExpectType {
 }
 
 impl<'a> Parser<'a> {
-    pub fn new(sess: &'a ParseSess,
-               tokens: TokenStream,
-               directory: Option<Directory<'a>>,
-               recurse_into_file_modules: bool,
-               desugar_doc_comments: bool)
-               -> Self {
+    pub fn new(
+        sess: &'a ParseSess,
+        tokens: TokenStream,
+        directory: Option<Directory<'a>>,
+        recurse_into_file_modules: bool,
+        desugar_doc_comments: bool,
+        subparser_name: Option<&'static str>,
+    ) -> Self {
         let mut parser = Parser {
             sess,
             token: token::Whitespace,
-            span: syntax_pos::DUMMY_SP,
-            prev_span: syntax_pos::DUMMY_SP,
+            span: DUMMY_SP,
+            prev_span: DUMMY_SP,
             meta_var_span: None,
             prev_token_kind: PrevTokenKind::Other,
             restrictions: Restrictions::empty(),
@@ -568,6 +572,7 @@ impl<'a> Parser<'a> {
             max_angle_bracket_count: 0,
             unclosed_delims: Vec::new(),
             last_unexpected_token_span: None,
+            subparser_name,
         };
 
         let tok = parser.next_tok();
@@ -631,44 +636,13 @@ impl<'a> Parser<'a> {
     }
 
     /// Expects and consumes the token `t`. Signals an error if the next token is not `t`.
-    pub fn expect(&mut self, t: &token::Token) -> PResult<'a,  bool /* recovered */> {
+    pub fn expect(&mut self, t: &token::Token) -> PResult<'a, bool /* recovered */> {
         if self.expected_tokens.is_empty() {
             if self.token == *t {
                 self.bump();
                 Ok(false)
             } else {
-                let token_str = pprust::token_to_string(t);
-                let this_token_str = self.this_token_descr();
-                let mut err = self.fatal(&format!("expected `{}`, found {}",
-                                                  token_str,
-                                                  this_token_str));
-
-                let sp = if self.token == token::Token::Eof {
-                    // EOF, don't want to point at the following char, but rather the last token
-                    self.prev_span
-                } else {
-                    self.sess.source_map().next_point(self.prev_span)
-                };
-                let label_exp = format!("expected `{}`", token_str);
-                match self.recover_closing_delimiter(&[t.clone()], err) {
-                    Err(e) => err = e,
-                    Ok(recovered) => {
-                        return Ok(recovered);
-                    }
-                }
-                let cm = self.sess.source_map();
-                match (cm.lookup_line(self.span.lo()), cm.lookup_line(sp.lo())) {
-                    (Ok(ref a), Ok(ref b)) if a.line == b.line => {
-                        // When the spans are in the same line, it means that the only content
-                        // between them is whitespace, point only at the found token.
-                        err.span_label(self.span, label_exp);
-                    }
-                    _ => {
-                        err.span_label(sp, label_exp);
-                        err.span_label(self.span, "unexpected token");
-                    }
-                }
-                Err(err)
+                self.unexpected_try_recover(t)
             }
         } else {
             self.expect_one_of(slice::from_ref(t), &[])
@@ -737,7 +711,7 @@ impl<'a> Parser<'a> {
             };
             self.last_unexpected_token_span = Some(self.span);
             let mut err = self.fatal(&msg_exp);
-            if self.token.is_ident_named("and") {
+            if self.token.is_ident_named(sym::and) {
                 err.span_suggestion_short(
                     self.span,
                     "use `&&` instead of `and` for the boolean operator",
@@ -745,7 +719,7 @@ impl<'a> Parser<'a> {
                     Applicability::MaybeIncorrect,
                 );
             }
-            if self.token.is_ident_named("or") {
+            if self.token.is_ident_named(sym::or) {
                 err.span_suggestion_short(
                     self.span,
                     "use `||` instead of `or` for the boolean operator",
@@ -812,7 +786,7 @@ impl<'a> Parser<'a> {
                     //   |                   expected one of 8 possible tokens here
                     err.span_label(self.span, label_exp);
                 }
-                _ if self.prev_span == syntax_pos::DUMMY_SP => {
+                _ if self.prev_span == DUMMY_SP => {
                     // Account for macro context where the previous span might not be
                     // available to avoid incorrect output (#54841).
                     err.span_label(self.span, "unexpected token");
@@ -2041,7 +2015,7 @@ impl<'a> Parser<'a> {
             path = self.parse_path(PathStyle::Type)?;
             path_span = path_lo.to(self.prev_span);
         } else {
-            path = ast::Path { segments: Vec::new(), span: syntax_pos::DUMMY_SP };
+            path = ast::Path { segments: Vec::new(), span: DUMMY_SP };
             path_span = self.span.to(self.span);
         }
 
@@ -2627,17 +2601,7 @@ impl<'a> Parser<'a> {
                         }
                         Err(mut err) => {
                             self.cancel(&mut err);
-                            let msg = format!("expected expression, found {}",
-                                              self.this_token_descr());
-                            let mut err = self.fatal(&msg);
-                            let sp = self.sess.source_map().start_point(self.span);
-                            if let Some(sp) = self.sess.ambiguous_block_expr_parse.borrow()
-                                .get(&sp)
-                            {
-                                self.sess.expr_parentheses_needed(&mut err, *sp, None);
-                            }
-                            err.span_label(self.span, "expected expression");
-                            return Err(err);
+                            return Err(self.expected_expression_found());
                         }
                     }
                 }
@@ -3258,7 +3222,7 @@ impl<'a> Parser<'a> {
                 let (span, e) = self.interpolated_or_expr_span(e)?;
                 (lo.to(span), ExprKind::Box(e))
             }
-            token::Ident(..) if self.token.is_ident_named("not") => {
+            token::Ident(..) if self.token.is_ident_named(sym::not) => {
                 // `not` is just an ordinary identifier in Rust-the-language,
                 // but as `rustc`-the-compiler, we can issue clever diagnostics
                 // for confused users who really want to say `!`
@@ -5131,7 +5095,7 @@ impl<'a> Parser<'a> {
             let do_not_suggest_help =
                 self.token.is_keyword(kw::In) || self.token == token::Colon;
 
-            if self.token.is_ident_named("and") {
+            if self.token.is_ident_named(sym::and) {
                 e.span_suggestion_short(
                     self.span,
                     "use `&&` instead of `and` for the boolean operator",
@@ -5139,7 +5103,7 @@ impl<'a> Parser<'a> {
                     Applicability::MaybeIncorrect,
                 );
             }
-            if self.token.is_ident_named("or") {
+            if self.token.is_ident_named(sym::or) {
                 e.span_suggestion_short(
                     self.span,
                     "use `||` instead of `or` for the boolean operator",
@@ -5592,7 +5556,7 @@ impl<'a> Parser<'a> {
                 where_clause: WhereClause {
                     id: ast::DUMMY_NODE_ID,
                     predicates: Vec::new(),
-                    span: syntax_pos::DUMMY_SP,
+                    span: DUMMY_SP,
                 },
                 span: span_lo.to(self.prev_span),
             })
@@ -5838,7 +5802,7 @@ impl<'a> Parser<'a> {
         let mut where_clause = WhereClause {
             id: ast::DUMMY_NODE_ID,
             predicates: Vec::new(),
-            span: syntax_pos::DUMMY_SP,
+            span: DUMMY_SP,
         };
 
         if !self.eat_keyword(kw::Where) {
@@ -6326,7 +6290,7 @@ impl<'a> Parser<'a> {
             VisibilityKind::Inherited => {}
             _ => {
                 let is_macro_rules: bool = match self.token {
-                    token::Ident(sid, _) => sid.name == Symbol::intern("macro_rules"),
+                    token::Ident(sid, _) => sid.name == sym::macro_rules,
                     _ => false,
                 };
                 let mut err = if is_macro_rules {
@@ -7005,7 +6969,7 @@ impl<'a> Parser<'a> {
                             Ident::with_empty_ctxt(sym::warn_directory_ownership)),
                         tokens: TokenStream::empty(),
                         is_sugared_doc: false,
-                        span: syntax_pos::DUMMY_SP,
+                        span: DUMMY_SP,
                     };
                     attr::mark_known(&attr);
                     attrs.push(attr);
@@ -7013,7 +6977,7 @@ impl<'a> Parser<'a> {
                 Ok((id, ItemKind::Mod(module), Some(attrs)))
             } else {
                 let placeholder = ast::Mod {
-                    inner: syntax_pos::DUMMY_SP,
+                    inner: DUMMY_SP,
                     items: Vec::new(),
                     inline: false
                 };
diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs
index e5361b2db4e9e..47185df8d6165 100644
--- a/src/libsyntax/parse/token.rs
+++ b/src/libsyntax/parse/token.rs
@@ -391,9 +391,9 @@ impl Token {
 
     /// Returns `true` if the token is a identifier whose name is the given
     /// string slice.
-    crate fn is_ident_named(&self, name: &str) -> bool {
+    crate fn is_ident_named(&self, name: Symbol) -> bool {
         match self.ident() {
-            Some((ident, _)) => ident.as_str() == name,
+            Some((ident, _)) => ident.name == name,
             None => false
         }
     }
diff --git a/src/libsyntax/std_inject.rs b/src/libsyntax/std_inject.rs
index 398705857bb7e..eea94f0d19458 100644
--- a/src/libsyntax/std_inject.rs
+++ b/src/libsyntax/std_inject.rs
@@ -20,9 +20,7 @@ fn ignored_span(sp: Span, edition: Edition) -> Span {
         call_site: DUMMY_SP,
         def_site: None,
         format: MacroAttribute(Symbol::intern("std_inject")),
-        allow_internal_unstable: Some(vec![
-            Symbol::intern("prelude_import"),
-        ].into()),
+        allow_internal_unstable: Some(vec![sym::prelude_import].into()),
         allow_internal_unsafe: false,
         local_inner_macros: false,
         edition,
@@ -98,7 +96,7 @@ pub fn maybe_inject_crates_ref(
     krate.module.items.insert(0, P(ast::Item {
         attrs: vec![ast::Attribute {
             style: ast::AttrStyle::Outer,
-            path: ast::Path::from_ident(ast::Ident::new(Symbol::intern("prelude_import"), span)),
+            path: ast::Path::from_ident(ast::Ident::new(sym::prelude_import, span)),
             tokens: TokenStream::empty(),
             id: attr::mk_attr_id(),
             is_sugared_doc: false,
diff --git a/src/libsyntax/test.rs b/src/libsyntax/test.rs
index d1e11da4e7cc2..1998ec19f13bf 100644
--- a/src/libsyntax/test.rs
+++ b/src/libsyntax/test.rs
@@ -283,12 +283,8 @@ fn generate_test_harness(sess: &ParseSess,
     mark.set_expn_info(ExpnInfo {
         call_site: DUMMY_SP,
         def_site: None,
-        format: MacroAttribute(Symbol::intern("test_case")),
-        allow_internal_unstable: Some(vec![
-            Symbol::intern("main"),
-            Symbol::intern("test"),
-            Symbol::intern("rustc_attrs"),
-        ].into()),
+        format: MacroAttribute(sym::test_case),
+        allow_internal_unstable: Some(vec![sym::main, sym::test, sym::rustc_attrs].into()),
         allow_internal_unsafe: false,
         local_inner_macros: false,
         edition: sess.edition,
@@ -347,14 +343,14 @@ fn mk_main(cx: &mut TestCtxt<'_>) -> P<ast::Item> {
     let call_test_main = ecx.stmt_expr(call_test_main);
 
     // #![main]
-    let main_meta = ecx.meta_word(sp, Symbol::intern("main"));
+    let main_meta = ecx.meta_word(sp, sym::main);
     let main_attr = ecx.attribute(sp, main_meta);
 
     // extern crate test as test_gensym
     let test_extern_stmt = ecx.stmt_item(sp, ecx.item(sp,
         test_id,
         vec![],
-        ast::ItemKind::ExternCrate(Some(Symbol::intern("test")))
+        ast::ItemKind::ExternCrate(Some(sym::test))
     ));
 
     // pub fn main() { ... }
diff --git a/src/libsyntax_ext/asm.rs b/src/libsyntax_ext/asm.rs
index b8e89c3ecf876..4d7083c1a790b 100644
--- a/src/libsyntax_ext/asm.rs
+++ b/src/libsyntax_ext/asm.rs
@@ -11,7 +11,7 @@ use syntax::ext::base::{self, *};
 use syntax::feature_gate;
 use syntax::parse::{self, token};
 use syntax::ptr::P;
-use syntax::symbol::{Symbol, sym};
+use syntax::symbol::{kw, sym, Symbol};
 use syntax::ast::AsmDialect;
 use syntax_pos::Span;
 use syntax::tokenstream;
@@ -93,7 +93,7 @@ fn parse_inline_asm<'a>(
         })
         .unwrap_or(tts.len());
     let mut p = cx.new_parser_from_tts(&tts[first_colon..]);
-    let mut asm = Symbol::intern("");
+    let mut asm = kw::Invalid;
     let mut asm_str_style = None;
     let mut outputs = Vec::new();
     let mut inputs = Vec::new();
@@ -138,7 +138,11 @@ fn parse_inline_asm<'a>(
                 if p2.token != token::Eof {
                     let mut extra_tts = p2.parse_all_token_trees()?;
                     extra_tts.extend(tts[first_colon..].iter().cloned());
-                    p = parse::stream_to_parser(cx.parse_sess, extra_tts.into_iter().collect());
+                    p = parse::stream_to_parser(
+                        cx.parse_sess,
+                        extra_tts.into_iter().collect(),
+                        Some("inline assembly"),
+                    );
                 }
 
                 asm = s;
diff --git a/src/libsyntax_ext/assert.rs b/src/libsyntax_ext/assert.rs
index a11cd9c6f761d..13342c8e28e2f 100644
--- a/src/libsyntax_ext/assert.rs
+++ b/src/libsyntax_ext/assert.rs
@@ -8,7 +8,7 @@ use syntax::parse::token::{self, Token};
 use syntax::parse::parser::Parser;
 use syntax::print::pprust;
 use syntax::ptr::P;
-use syntax::symbol::Symbol;
+use syntax::symbol::{sym, Symbol};
 use syntax::tokenstream::{TokenStream, TokenTree};
 use syntax_pos::{Span, DUMMY_SP};
 
@@ -27,7 +27,7 @@ pub fn expand_assert<'cx>(
 
     let sp = sp.apply_mark(cx.current_expansion.mark);
     let panic_call = Mac_ {
-        path: Path::from_ident(Ident::new(Symbol::intern("panic"), sp)),
+        path: Path::from_ident(Ident::new(sym::panic, sp)),
         tts: custom_message.unwrap_or_else(|| {
             TokenStream::from(TokenTree::Token(
                 DUMMY_SP,
diff --git a/src/libsyntax_ext/deriving/clone.rs b/src/libsyntax_ext/deriving/clone.rs
index a39e0a6e97303..b3b6328e2ca73 100644
--- a/src/libsyntax_ext/deriving/clone.rs
+++ b/src/libsyntax_ext/deriving/clone.rs
@@ -7,7 +7,7 @@ use syntax::attr;
 use syntax::ext::base::{Annotatable, ExtCtxt};
 use syntax::ext::build::AstBuilder;
 use syntax::ptr::P;
-use syntax::symbol::{Symbol, kw, sym};
+use syntax::symbol::{kw, sym, Symbol};
 use syntax_pos::Span;
 
 pub fn expand_deriving_clone(cx: &mut ExtCtxt<'_>,
@@ -76,7 +76,7 @@ pub fn expand_deriving_clone(cx: &mut ExtCtxt<'_>,
         _ => cx.span_bug(span, "#[derive(Clone)] on trait item or impl item"),
     }
 
-    let inline = cx.meta_word(span, Symbol::intern("inline"));
+    let inline = cx.meta_word(span, sym::inline);
     let attrs = vec![cx.attribute(span, inline)];
     let trait_def = TraitDef {
         span,
@@ -115,7 +115,7 @@ fn cs_clone_shallow(name: &str,
         // set the expn ID so we can use the unstable struct.
         let span = span.with_ctxt(cx.backtrace());
         let assert_path = cx.path_all(span, true,
-                                        cx.std_path(&["clone", helper_name]),
+                                        cx.std_path(&[sym::clone, Symbol::intern(helper_name)]),
                                         vec![GenericArg::Type(ty)], vec![]);
         stmts.push(cx.stmt_let_type_only(span, cx.ty_path(assert_path)));
     }
@@ -157,7 +157,7 @@ fn cs_clone(name: &str,
             -> P<Expr> {
     let ctor_path;
     let all_fields;
-    let fn_path = cx.std_path(&["clone", "Clone", "clone"]);
+    let fn_path = cx.std_path(&[sym::clone, sym::Clone, sym::clone]);
     let subcall = |cx: &mut ExtCtxt<'_>, field: &FieldInfo<'_>| {
         let args = vec![cx.expr_addr_of(field.span, field.self_.clone())];
         cx.expr_call_global(field.span, fn_path.clone(), args)
diff --git a/src/libsyntax_ext/deriving/cmp/eq.rs b/src/libsyntax_ext/deriving/cmp/eq.rs
index a1035ff641fa1..1d981e0ff7906 100644
--- a/src/libsyntax_ext/deriving/cmp/eq.rs
+++ b/src/libsyntax_ext/deriving/cmp/eq.rs
@@ -6,7 +6,7 @@ use syntax::ast::{self, Expr, MetaItem, GenericArg};
 use syntax::ext::base::{Annotatable, ExtCtxt};
 use syntax::ext::build::AstBuilder;
 use syntax::ptr::P;
-use syntax::symbol::Symbol;
+use syntax::symbol::{sym, Symbol};
 use syntax_pos::Span;
 
 pub fn expand_deriving_eq(cx: &mut ExtCtxt<'_>,
@@ -14,9 +14,9 @@ pub fn expand_deriving_eq(cx: &mut ExtCtxt<'_>,
                           mitem: &MetaItem,
                           item: &Annotatable,
                           push: &mut dyn FnMut(Annotatable)) {
-    let inline = cx.meta_word(span, Symbol::intern("inline"));
-    let hidden = cx.meta_list_item_word(span, Symbol::intern("hidden"));
-    let doc = cx.meta_list(span, Symbol::intern("doc"), vec![hidden]);
+    let inline = cx.meta_word(span, sym::inline);
+    let hidden = cx.meta_list_item_word(span, sym::hidden);
+    let doc = cx.meta_list(span, sym::doc, vec![hidden]);
     let attrs = vec![cx.attribute(span, inline), cx.attribute(span, doc)];
     let trait_def = TraitDef {
         span,
@@ -54,7 +54,7 @@ fn cs_total_eq_assert(cx: &mut ExtCtxt<'_>,
         // set the expn ID so we can use the unstable struct.
         let span = span.with_ctxt(cx.backtrace());
         let assert_path = cx.path_all(span, true,
-                                        cx.std_path(&["cmp", helper_name]),
+                                        cx.std_path(&[sym::cmp, Symbol::intern(helper_name)]),
                                         vec![GenericArg::Type(ty)], vec![]);
         stmts.push(cx.stmt_let_type_only(span, cx.ty_path(assert_path)));
     }
diff --git a/src/libsyntax_ext/deriving/cmp/ord.rs b/src/libsyntax_ext/deriving/cmp/ord.rs
index e4f939c151f3e..b25a9e4c50fbe 100644
--- a/src/libsyntax_ext/deriving/cmp/ord.rs
+++ b/src/libsyntax_ext/deriving/cmp/ord.rs
@@ -6,7 +6,7 @@ use syntax::ast::{self, Expr, MetaItem};
 use syntax::ext::base::{Annotatable, ExtCtxt};
 use syntax::ext::build::AstBuilder;
 use syntax::ptr::P;
-use syntax::symbol::Symbol;
+use syntax::symbol::sym;
 use syntax_pos::Span;
 
 pub fn expand_deriving_ord(cx: &mut ExtCtxt<'_>,
@@ -14,7 +14,7 @@ pub fn expand_deriving_ord(cx: &mut ExtCtxt<'_>,
                            mitem: &MetaItem,
                            item: &Annotatable,
                            push: &mut dyn FnMut(Annotatable)) {
-    let inline = cx.meta_word(span, Symbol::intern("inline"));
+    let inline = cx.meta_word(span, sym::inline);
     let attrs = vec![cx.attribute(span, inline)];
     let trait_def = TraitDef {
         span,
@@ -55,9 +55,9 @@ pub fn ordering_collapsed(cx: &mut ExtCtxt<'_>,
 
 pub fn cs_cmp(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> P<Expr> {
     let test_id = cx.ident_of("cmp").gensym();
-    let equals_path = cx.path_global(span, cx.std_path(&["cmp", "Ordering", "Equal"]));
+    let equals_path = cx.path_global(span, cx.std_path(&[sym::cmp, sym::Ordering, sym::Equal]));
 
-    let cmp_path = cx.std_path(&["cmp", "Ord", "cmp"]);
+    let cmp_path = cx.std_path(&[sym::cmp, sym::Ord, sym::cmp]);
 
     // Builds:
     //
diff --git a/src/libsyntax_ext/deriving/cmp/partial_eq.rs b/src/libsyntax_ext/deriving/cmp/partial_eq.rs
index 07026ae373919..6172f27261ecf 100644
--- a/src/libsyntax_ext/deriving/cmp/partial_eq.rs
+++ b/src/libsyntax_ext/deriving/cmp/partial_eq.rs
@@ -6,7 +6,7 @@ use syntax::ast::{BinOpKind, Expr, MetaItem};
 use syntax::ext::base::{Annotatable, ExtCtxt};
 use syntax::ext::build::AstBuilder;
 use syntax::ptr::P;
-use syntax::symbol::Symbol;
+use syntax::symbol::sym;
 use syntax_pos::Span;
 
 pub fn expand_deriving_partial_eq(cx: &mut ExtCtxt<'_>,
@@ -62,7 +62,7 @@ pub fn expand_deriving_partial_eq(cx: &mut ExtCtxt<'_>,
 
     macro_rules! md {
         ($name:expr, $f:ident) => { {
-            let inline = cx.meta_word(span, Symbol::intern("inline"));
+            let inline = cx.meta_word(span, sym::inline);
             let attrs = vec![cx.attribute(span, inline)];
             MethodDef {
                 name: $name,
diff --git a/src/libsyntax_ext/deriving/cmp/partial_ord.rs b/src/libsyntax_ext/deriving/cmp/partial_ord.rs
index e99abeb118ea2..3980741f252dd 100644
--- a/src/libsyntax_ext/deriving/cmp/partial_ord.rs
+++ b/src/libsyntax_ext/deriving/cmp/partial_ord.rs
@@ -8,7 +8,7 @@ use syntax::ast::{self, BinOpKind, Expr, MetaItem};
 use syntax::ext::base::{Annotatable, ExtCtxt};
 use syntax::ext::build::AstBuilder;
 use syntax::ptr::P;
-use syntax::symbol::Symbol;
+use syntax::symbol::{sym, Symbol};
 use syntax_pos::Span;
 
 pub fn expand_deriving_partial_ord(cx: &mut ExtCtxt<'_>,
@@ -18,7 +18,7 @@ pub fn expand_deriving_partial_ord(cx: &mut ExtCtxt<'_>,
                                    push: &mut dyn FnMut(Annotatable)) {
     macro_rules! md {
         ($name:expr, $op:expr, $equal:expr) => { {
-            let inline = cx.meta_word(span, Symbol::intern("inline"));
+            let inline = cx.meta_word(span, sym::inline);
             let attrs = vec![cx.attribute(span, inline)];
             MethodDef {
                 name: $name,
@@ -42,7 +42,7 @@ pub fn expand_deriving_partial_ord(cx: &mut ExtCtxt<'_>,
                                     vec![Box::new(ordering_ty)],
                                     PathKind::Std));
 
-    let inline = cx.meta_word(span, Symbol::intern("inline"));
+    let inline = cx.meta_word(span, sym::inline);
     let attrs = vec![cx.attribute(span, inline)];
 
     let partial_cmp_def = MethodDef {
@@ -114,11 +114,11 @@ pub fn some_ordering_collapsed(cx: &mut ExtCtxt<'_>,
 
 pub fn cs_partial_cmp(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> P<Expr> {
     let test_id = cx.ident_of("cmp").gensym();
-    let ordering = cx.path_global(span, cx.std_path(&["cmp", "Ordering", "Equal"]));
+    let ordering = cx.path_global(span, cx.std_path(&[sym::cmp, sym::Ordering, sym::Equal]));
     let ordering_expr = cx.expr_path(ordering.clone());
     let equals_expr = cx.expr_some(span, ordering_expr);
 
-    let partial_cmp_path = cx.std_path(&["cmp", "PartialOrd", "partial_cmp"]);
+    let partial_cmp_path = cx.std_path(&[sym::cmp, sym::PartialOrd, sym::partial_cmp]);
 
     // Builds:
     //
@@ -188,7 +188,8 @@ fn cs_op(less: bool,
          span: Span,
          substr: &Substructure<'_>) -> P<Expr> {
     let ordering_path = |cx: &mut ExtCtxt<'_>, name: &str| {
-        cx.expr_path(cx.path_global(span, cx.std_path(&["cmp", "Ordering", name])))
+        cx.expr_path(cx.path_global(
+            span, cx.std_path(&[sym::cmp, sym::Ordering, Symbol::intern(name)])))
     };
 
     let par_cmp = |cx: &mut ExtCtxt<'_>, span, self_f: P<Expr>, other_fs: &[P<Expr>], default| {
@@ -198,9 +199,9 @@ fn cs_op(less: bool,
         };
 
         // `PartialOrd::partial_cmp(self.fi, other.fi)`
-        let cmp_path = cx.expr_path(cx.path_global(span, cx.std_path(&["cmp",
-                                                                       "PartialOrd",
-                                                                       "partial_cmp"])));
+        let cmp_path = cx.expr_path(cx.path_global(span, cx.std_path(&[sym::cmp,
+                                                                       sym::PartialOrd,
+                                                                       sym::partial_cmp])));
         let cmp = cx.expr_call(span,
                                cmp_path,
                                vec![cx.expr_addr_of(span, self_f),
@@ -208,9 +209,9 @@ fn cs_op(less: bool,
 
         let default = ordering_path(cx, default);
         // `Option::unwrap_or(_, Ordering::Equal)`
-        let unwrap_path = cx.expr_path(cx.path_global(span, cx.std_path(&["option",
-                                                                          "Option",
-                                                                          "unwrap_or"])));
+        let unwrap_path = cx.expr_path(cx.path_global(span, cx.std_path(&[sym::option,
+                                                                          sym::Option,
+                                                                          sym::unwrap_or])));
         cx.expr_call(span, unwrap_path, vec![cmp, default])
     };
 
@@ -256,9 +257,9 @@ fn cs_op(less: bool,
 
             // `Ordering::then_with(Option::unwrap_or(..), ..)`
             let then_with_path = cx.expr_path(cx.path_global(span,
-                                                             cx.std_path(&["cmp",
-                                                                           "Ordering",
-                                                                           "then_with"])));
+                                                             cx.std_path(&[sym::cmp,
+                                                                           sym::Ordering,
+                                                                           sym::then_with])));
             cx.expr_call(span, then_with_path, vec![par_cmp, cx.lambda0(span, subexpr)])
         },
         |cx, args| {
diff --git a/src/libsyntax_ext/deriving/custom.rs b/src/libsyntax_ext/deriving/custom.rs
index e73110717e979..975d96951dc55 100644
--- a/src/libsyntax_ext/deriving/custom.rs
+++ b/src/libsyntax_ext/deriving/custom.rs
@@ -89,7 +89,7 @@ impl MultiItemModifier for ProcMacroDerive {
         let error_count_before = ecx.parse_sess.span_diagnostic.err_count();
         let msg = "proc-macro derive produced unparseable tokens";
 
-        let mut parser = parse::stream_to_parser(ecx.parse_sess, stream);
+        let mut parser = parse::stream_to_parser(ecx.parse_sess, stream, Some("proc-macro derive"));
         let mut items = vec![];
 
         loop {
diff --git a/src/libsyntax_ext/deriving/debug.rs b/src/libsyntax_ext/deriving/debug.rs
index 2fc1fc9140dc3..dec4c2dfc3b5e 100644
--- a/src/libsyntax_ext/deriving/debug.rs
+++ b/src/libsyntax_ext/deriving/debug.rs
@@ -9,6 +9,7 @@ use syntax::ast::{Expr, MetaItem};
 use syntax::ext::base::{Annotatable, ExtCtxt};
 use syntax::ext::build::AstBuilder;
 use syntax::ptr::P;
+use syntax::symbol::sym;
 use syntax_pos::{DUMMY_SP, Span};
 
 pub fn expand_deriving_debug(cx: &mut ExtCtxt<'_>,
@@ -82,7 +83,7 @@ fn show_substructure(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>
 
                 let expr = cx.expr_method_call(span,
                                                 builder_expr.clone(),
-                                                Ident::from_str("field"),
+                                                Ident::with_empty_ctxt(sym::field),
                                                 vec![field]);
 
                 // Use `let _ = expr;` to avoid triggering the
@@ -106,7 +107,7 @@ fn show_substructure(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>
                 let field = cx.expr_addr_of(field.span, field);
                 let expr = cx.expr_method_call(span,
                                                 builder_expr.clone(),
-                                                Ident::from_str("field"),
+                                                Ident::with_empty_ctxt(sym::field),
                                                 vec![name, field]);
                 stmts.push(stmt_let_undescore(cx, span, expr));
             }
diff --git a/src/libsyntax_ext/deriving/default.rs b/src/libsyntax_ext/deriving/default.rs
index 6db0a29165a4a..fd8e87e2fefd1 100644
--- a/src/libsyntax_ext/deriving/default.rs
+++ b/src/libsyntax_ext/deriving/default.rs
@@ -6,7 +6,7 @@ use syntax::ast::{Expr, MetaItem};
 use syntax::ext::base::{Annotatable, DummyResult, ExtCtxt};
 use syntax::ext::build::AstBuilder;
 use syntax::ptr::P;
-use syntax::symbol::Symbol;
+use syntax::symbol::{kw, sym};
 use syntax::span_err;
 use syntax_pos::Span;
 
@@ -15,7 +15,7 @@ pub fn expand_deriving_default(cx: &mut ExtCtxt<'_>,
                                mitem: &MetaItem,
                                item: &Annotatable,
                                push: &mut dyn FnMut(Annotatable)) {
-    let inline = cx.meta_word(span, Symbol::intern("inline"));
+    let inline = cx.meta_word(span, sym::inline);
     let attrs = vec![cx.attribute(span, inline)];
     let trait_def = TraitDef {
         span,
@@ -47,7 +47,8 @@ fn default_substructure(cx: &mut ExtCtxt<'_>,
                         trait_span: Span,
                         substr: &Substructure<'_>)
                         -> P<Expr> {
-    let default_ident = cx.std_path(&["default", "Default", "default"]);
+    // Note that `kw::Default` is "default" and `sym::Default` is "Default"!
+    let default_ident = cx.std_path(&[kw::Default, sym::Default, kw::Default]);
     let default_call = |span| cx.expr_call_global(span, default_ident.clone(), Vec::new());
 
     return match *substr.fields {
diff --git a/src/libsyntax_ext/deriving/generic/mod.rs b/src/libsyntax_ext/deriving/generic/mod.rs
index 0689eb50f9ca2..7e3082a87d992 100644
--- a/src/libsyntax_ext/deriving/generic/mod.rs
+++ b/src/libsyntax_ext/deriving/generic/mod.rs
@@ -666,14 +666,13 @@ impl<'a> TraitDef<'a> {
         let self_type = cx.ty_path(path);
 
         let attr = cx.attribute(self.span,
-                                cx.meta_word(self.span,
-                                             Symbol::intern("automatically_derived")));
+                                cx.meta_word(self.span, sym::automatically_derived));
         // Just mark it now since we know that it'll end up used downstream
         attr::mark_used(&attr);
         let opt_trait_ref = Some(trait_ref);
         let unused_qual = {
             let word = cx.meta_list_item_word(self.span, Symbol::intern("unused_qualifications"));
-            cx.attribute(self.span, cx.meta_list(self.span, Symbol::intern("allow"), vec![word]))
+            cx.attribute(self.span, cx.meta_list(self.span, sym::allow, vec![word]))
         };
 
         let mut a = vec![attr, unused_qual];
diff --git a/src/libsyntax_ext/deriving/hash.rs b/src/libsyntax_ext/deriving/hash.rs
index 0d4f2ddc3be7b..e7f99d4578226 100644
--- a/src/libsyntax_ext/deriving/hash.rs
+++ b/src/libsyntax_ext/deriving/hash.rs
@@ -6,6 +6,7 @@ use syntax::ast::{Expr, MetaItem, Mutability};
 use syntax::ext::base::{Annotatable, ExtCtxt};
 use syntax::ext::build::AstBuilder;
 use syntax::ptr::P;
+use syntax::symbol::sym;
 use syntax_pos::Span;
 
 pub fn expand_deriving_hash(cx: &mut ExtCtxt<'_>,
@@ -60,7 +61,7 @@ fn hash_substructure(cx: &mut ExtCtxt<'_>, trait_span: Span, substr: &Substructu
     };
     let call_hash = |span, thing_expr| {
         let hash_path = {
-            let strs = cx.std_path(&["hash", "Hash", "hash"]);
+            let strs = cx.std_path(&[sym::hash, sym::Hash, sym::hash]);
 
             cx.expr_path(cx.path_global(span, strs))
         };
diff --git a/src/libsyntax_ext/deriving/mod.rs b/src/libsyntax_ext/deriving/mod.rs
index c27de692d887c..ac41f30e6b39f 100644
--- a/src/libsyntax_ext/deriving/mod.rs
+++ b/src/libsyntax_ext/deriving/mod.rs
@@ -145,12 +145,12 @@ fn call_intrinsic(cx: &ExtCtxt<'_>,
         span = span.with_ctxt(cx.backtrace());
     } else { // Avoid instability errors with user defined curstom derives, cc #36316
         let mut info = cx.current_expansion.mark.expn_info().unwrap();
-        info.allow_internal_unstable = Some(vec![Symbol::intern("core_intrinsics")].into());
+        info.allow_internal_unstable = Some(vec![sym::core_intrinsics].into());
         let mark = Mark::fresh(Mark::root());
         mark.set_expn_info(info);
         span = span.with_ctxt(SyntaxContext::empty().apply_mark(mark));
     }
-    let path = cx.std_path(&["intrinsics", intrinsic]);
+    let path = cx.std_path(&[sym::intrinsics, Symbol::intern(intrinsic)]);
     let call = cx.expr_call_global(span, path, args);
 
     cx.expr_block(P(ast::Block {
diff --git a/src/libsyntax_ext/env.rs b/src/libsyntax_ext/env.rs
index 72a66ae3845d0..b7f2ecf0f9137 100644
--- a/src/libsyntax_ext/env.rs
+++ b/src/libsyntax_ext/env.rs
@@ -27,7 +27,7 @@ pub fn expand_option_env<'cx>(cx: &'cx mut ExtCtxt<'_>,
             let lt = cx.lifetime(sp, Ident::with_empty_ctxt(kw::StaticLifetime));
             cx.expr_path(cx.path_all(sp,
                                      true,
-                                     cx.std_path(&["option", "Option", "None"]),
+                                     cx.std_path(&[sym::option, sym::Option, sym::None]),
                                      vec![GenericArg::Type(cx.ty_rptr(sp,
                                                      cx.ty_ident(sp,
                                                                  Ident::with_empty_ctxt(sym::str)),
@@ -37,7 +37,7 @@ pub fn expand_option_env<'cx>(cx: &'cx mut ExtCtxt<'_>,
         }
         Ok(s) => {
             cx.expr_call_global(sp,
-                                cx.std_path(&["option", "Option", "Some"]),
+                                cx.std_path(&[sym::option, sym::Option, sym::Some]),
                                 vec![cx.expr_str(sp, Symbol::intern(&s))])
         }
     };
diff --git a/src/libsyntax_ext/format.rs b/src/libsyntax_ext/format.rs
index 9e54c0634b666..b5be45547cfbe 100644
--- a/src/libsyntax_ext/format.rs
+++ b/src/libsyntax_ext/format.rs
@@ -387,7 +387,7 @@ impl<'a, 'b> Context<'a, 'b> {
     }
 
     fn rtpath(ecx: &ExtCtxt<'_>, s: &str) -> Vec<ast::Ident> {
-        ecx.std_path(&["fmt", "rt", "v1", s])
+        ecx.std_path(&[sym::fmt, sym::rt, sym::v1, Symbol::intern(s)])
     }
 
     fn build_count(&self, c: parse::Count<'_>) -> P<ast::Expr> {
@@ -644,7 +644,7 @@ impl<'a, 'b> Context<'a, 'b> {
             ("new_v1_formatted", vec![pieces, args_slice, fmt])
         };
 
-        let path = self.ecx.std_path(&["fmt", "Arguments", fn_name]);
+        let path = self.ecx.std_path(&[sym::fmt, sym::Arguments, Symbol::intern(fn_name)]);
         self.ecx.expr_call_global(self.macsp, path, fn_args)
     }
 
@@ -675,14 +675,14 @@ impl<'a, 'b> Context<'a, 'b> {
                 }
             }
             Count => {
-                let path = ecx.std_path(&["fmt", "ArgumentV1", "from_usize"]);
+                let path = ecx.std_path(&[sym::fmt, sym::ArgumentV1, sym::from_usize]);
                 return ecx.expr_call_global(macsp, path, vec![arg]);
             }
         };
 
-        let path = ecx.std_path(&["fmt", trait_, "fmt"]);
+        let path = ecx.std_path(&[sym::fmt, Symbol::intern(trait_), sym::fmt]);
         let format_fn = ecx.path_global(sp, path);
-        let path = ecx.std_path(&["fmt", "ArgumentV1", "new"]);
+        let path = ecx.std_path(&[sym::fmt, sym::ArgumentV1, sym::new]);
         ecx.expr_call_global(macsp, path, vec![arg, ecx.expr_path(format_fn)])
     }
 }
diff --git a/src/libsyntax_ext/lib.rs b/src/libsyntax_ext/lib.rs
index e5fc7aab61db4..fc00154427501 100644
--- a/src/libsyntax_ext/lib.rs
+++ b/src/libsyntax_ext/lib.rs
@@ -42,8 +42,8 @@ pub mod proc_macro_impl;
 use rustc_data_structures::sync::Lrc;
 use syntax::ast;
 use syntax::ext::base::{MacroExpanderFn, NormalTT, NamedSyntaxExtension, MultiModifier};
-use syntax::symbol::Symbol;
 use syntax::edition::Edition;
+use syntax::symbol::{sym, Symbol};
 
 pub fn register_builtins(resolver: &mut dyn syntax::ext::base::Resolver,
                          user_exts: Vec<NamedSyntaxExtension>,
@@ -93,30 +93,26 @@ pub fn register_builtins(resolver: &mut dyn syntax::ext::base::Resolver,
         assert: assert::expand_assert,
     }
 
-    register(Symbol::intern("test_case"), MultiModifier(Box::new(test_case::expand)));
-    register(Symbol::intern("test"), MultiModifier(Box::new(test::expand_test)));
-    register(Symbol::intern("bench"), MultiModifier(Box::new(test::expand_bench)));
+    register(sym::test_case, MultiModifier(Box::new(test_case::expand)));
+    register(sym::test, MultiModifier(Box::new(test::expand_test)));
+    register(sym::bench, MultiModifier(Box::new(test::expand_bench)));
 
     // format_args uses `unstable` things internally.
     register(Symbol::intern("format_args"),
              NormalTT {
                 expander: Box::new(format::expand_format_args),
                 def_info: None,
-                allow_internal_unstable: Some(vec![
-                    Symbol::intern("fmt_internals"),
-                ].into()),
+                allow_internal_unstable: Some(vec![sym::fmt_internals].into()),
                 allow_internal_unsafe: false,
                 local_inner_macros: false,
                 unstable_feature: None,
                 edition,
             });
-    register(Symbol::intern("format_args_nl"),
+    register(sym::format_args_nl,
              NormalTT {
                  expander: Box::new(format::expand_format_args_nl),
                  def_info: None,
-                 allow_internal_unstable: Some(vec![
-                     Symbol::intern("fmt_internals"),
-                 ].into()),
+                 allow_internal_unstable: Some(vec![sym::fmt_internals].into()),
                  allow_internal_unsafe: false,
                  local_inner_macros: false,
                  unstable_feature: None,
diff --git a/src/libsyntax_ext/proc_macro_decls.rs b/src/libsyntax_ext/proc_macro_decls.rs
index a485bb19808db..5b8f4f35f2dd1 100644
--- a/src/libsyntax_ext/proc_macro_decls.rs
+++ b/src/libsyntax_ext/proc_macro_decls.rs
@@ -351,9 +351,9 @@ fn mk_decls(
     mark.set_expn_info(ExpnInfo {
         call_site: DUMMY_SP,
         def_site: None,
-        format: MacroAttribute(Symbol::intern("proc_macro")),
+        format: MacroAttribute(sym::proc_macro),
         allow_internal_unstable: Some(vec![
-            Symbol::intern("rustc_attrs"),
+            sym::rustc_attrs,
             Symbol::intern("proc_macro_internals"),
         ].into()),
         allow_internal_unsafe: false,
@@ -420,7 +420,7 @@ fn mk_decls(
         ast::Mutability::Immutable,
         cx.expr_vec_slice(span, decls),
     ).map(|mut i| {
-        let attr = cx.meta_word(span, Symbol::intern("rustc_proc_macro_decls"));
+        let attr = cx.meta_word(span, sym::rustc_proc_macro_decls);
         i.attrs.push(cx.attribute(span, attr));
         i.vis = respan(span, ast::VisibilityKind::Public);
         i
diff --git a/src/libsyntax_ext/proc_macro_server.rs b/src/libsyntax_ext/proc_macro_server.rs
index beac92894b77a..53730d2d08022 100644
--- a/src/libsyntax_ext/proc_macro_server.rs
+++ b/src/libsyntax_ext/proc_macro_server.rs
@@ -14,7 +14,7 @@ use syntax::parse::lexer::comments;
 use syntax::parse::{self, token, ParseSess};
 use syntax::tokenstream::{self, DelimSpan, IsJoint::*, TokenStream, TreeAndJoint};
 use syntax_pos::hygiene::{SyntaxContext, Transparency};
-use syntax_pos::symbol::{kw, Symbol};
+use syntax_pos::symbol::{kw, sym, Symbol};
 use syntax_pos::{BytePos, FileName, MultiSpan, Pos, SourceFile, Span};
 
 trait FromInternal<T> {
@@ -159,7 +159,7 @@ impl FromInternal<(TreeAndJoint, &'_ ParseSess, &'_ mut Vec<Self>)>
                     escaped.extend(ch.escape_debug());
                 }
                 let stream = vec![
-                    Ident(ast::Ident::new(Symbol::intern("doc"), span), false),
+                    Ident(ast::Ident::new(sym::doc, span), false),
                     Eq,
                     Token::lit(token::Str, Symbol::intern(&escaped), None),
                 ]
diff --git a/src/libsyntax_ext/test.rs b/src/libsyntax_ext/test.rs
index 8ee61a3f67f59..c20dc6cb2d7cd 100644
--- a/src/libsyntax_ext/test.rs
+++ b/src/libsyntax_ext/test.rs
@@ -65,11 +65,8 @@ pub fn expand_test_or_bench(
         mark.set_expn_info(ExpnInfo {
             call_site: DUMMY_SP,
             def_site: None,
-            format: MacroAttribute(Symbol::intern("test")),
-            allow_internal_unstable: Some(vec![
-                Symbol::intern("rustc_attrs"),
-                Symbol::intern("test"),
-            ].into()),
+            format: MacroAttribute(sym::test),
+            allow_internal_unstable: Some(vec![sym::rustc_attrs, sym::test].into()),
             allow_internal_unsafe: false,
             local_inner_macros: false,
             edition: cx.parse_sess.edition,
@@ -130,11 +127,11 @@ pub fn expand_test_or_bench(
     let mut test_const = cx.item(sp, ast::Ident::new(item.ident.name, sp).gensym(),
         vec![
             // #[cfg(test)]
-            cx.attribute(attr_sp, cx.meta_list(attr_sp, Symbol::intern("cfg"), vec![
-                cx.meta_list_item_word(attr_sp, Symbol::intern("test"))
+            cx.attribute(attr_sp, cx.meta_list(attr_sp, sym::cfg, vec![
+                cx.meta_list_item_word(attr_sp, sym::test)
             ])),
             // #[rustc_test_marker]
-            cx.attribute(attr_sp, cx.meta_word(attr_sp, Symbol::intern("rustc_test_marker"))),
+            cx.attribute(attr_sp, cx.meta_word(attr_sp, sym::rustc_test_marker)),
         ],
         // const $ident: test::TestDescAndFn =
         ast::ItemKind::Const(cx.ty(sp, ast::TyKind::Path(None, test_path("TestDescAndFn"))),
@@ -180,7 +177,7 @@ pub fn expand_test_or_bench(
     let test_extern = cx.item(sp,
         test_id,
         vec![],
-        ast::ItemKind::ExternCrate(Some(Symbol::intern("test")))
+        ast::ItemKind::ExternCrate(Some(sym::test))
     );
 
     log::debug!("Synthetic test item:\n{}\n", pprust::item_to_string(&test_const));
diff --git a/src/libsyntax_ext/test_case.rs b/src/libsyntax_ext/test_case.rs
index 5b1ae167ce315..cffecdd0f18e7 100644
--- a/src/libsyntax_ext/test_case.rs
+++ b/src/libsyntax_ext/test_case.rs
@@ -14,7 +14,7 @@ use syntax::ext::build::AstBuilder;
 use syntax::ext::hygiene::{Mark, SyntaxContext};
 use syntax::ast;
 use syntax::source_map::respan;
-use syntax::symbol::{Symbol, sym};
+use syntax::symbol::sym;
 use syntax_pos::{DUMMY_SP, Span};
 use syntax::source_map::{ExpnInfo, MacroAttribute};
 use syntax::feature_gate;
@@ -40,11 +40,8 @@ pub fn expand(
         mark.set_expn_info(ExpnInfo {
             call_site: DUMMY_SP,
             def_site: None,
-            format: MacroAttribute(Symbol::intern("test_case")),
-            allow_internal_unstable: Some(vec![
-                Symbol::intern("test"),
-                Symbol::intern("rustc_attrs"),
-            ].into()),
+            format: MacroAttribute(sym::test_case),
+            allow_internal_unstable: Some(vec![sym::test, sym::rustc_attrs].into()),
             allow_internal_unsafe: false,
             local_inner_macros: false,
             edition: ecx.parse_sess.edition,
@@ -59,7 +56,7 @@ pub fn expand(
         item.ident = item.ident.gensym();
         item.attrs.push(
             ecx.attribute(sp,
-                ecx.meta_word(sp, Symbol::intern("rustc_test_marker")))
+                ecx.meta_word(sp, sym::rustc_test_marker))
         );
         item
     });
diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs
index b1e1a056db4ad..60f87783b3e11 100644
--- a/src/libsyntax_pos/symbol.rs
+++ b/src/libsyntax_pos/symbol.rs
@@ -9,10 +9,10 @@ use rustc_data_structures::newtype_index;
 use rustc_macros::symbols;
 use serialize::{Decodable, Decoder, Encodable, Encoder};
 
-use std::fmt;
-use std::str;
 use std::cmp::{PartialEq, Ordering, PartialOrd, Ord};
+use std::fmt;
 use std::hash::{Hash, Hasher};
+use std::str;
 
 use crate::hygiene::SyntaxContext;
 use crate::{Span, DUMMY_SP, GLOBALS};
@@ -102,6 +102,9 @@ symbols! {
     // Symbols that can be referred to with syntax_pos::sym::*. The symbol is
     // the stringified identifier unless otherwise specified (e.g.
     // `proc_dash_macro` represents "proc-macro").
+    //
+    // As well as the symbols listed, there are symbols for the the strings
+    // "0", "1", ..., "9", which are accessible via `sym::integer`.
     Symbols {
         aarch64_target_feature,
         abi,
@@ -130,8 +133,11 @@ symbols! {
         allow_internal_unstable,
         allow_internal_unstable_backcompat_hack,
         always,
+        and,
         any,
         arbitrary_self_types,
+        Arguments,
+        ArgumentV1,
         arm_target_feature,
         asm,
         associated_consts,
@@ -145,6 +151,8 @@ symbols! {
         automatically_derived,
         avx512_target_feature,
         await_macro,
+        begin_panic,
+        bench,
         bin,
         bind_by_move_pattern_guards,
         block,
@@ -163,9 +171,11 @@ symbols! {
         cfg_target_thread_local,
         cfg_target_vendor,
         clone,
+        Clone,
         clone_closures,
         clone_from,
         closure_to_fn_coercion,
+        cmp,
         cmpxchg16b_target_feature,
         cold,
         compile_error,
@@ -199,11 +209,14 @@ symbols! {
         custom_test_frameworks,
         c_variadic,
         decl_macro,
+        Default,
         default_lib_allocator,
         default_type_parameter_fallback,
         default_type_params,
         deny,
         deprecated,
+        deref,
+        deref_mut,
         derive,
         doc,
         doc_alias,
@@ -231,6 +244,7 @@ symbols! {
         enable,
         err,
         Err,
+        Equal,
         except,
         exclusive_range_pattern,
         exhaustive_integer_patterns,
@@ -238,6 +252,7 @@ symbols! {
         existential_type,
         expected,
         export_name,
+        expr,
         extern_absolute_paths,
         external_doc,
         extern_crate_item_prelude,
@@ -250,8 +265,11 @@ symbols! {
         f64,
         feature,
         ffi_returns_twice,
+        field,
         field_init_shorthand,
         file,
+        fmt,
+        fmt_internals,
         fn_must_use,
         forbid,
         format_args_nl,
@@ -260,6 +278,7 @@ symbols! {
         from_error,
         from_generator,
         from_ok,
+        from_usize,
         fundamental,
         future,
         Future,
@@ -270,6 +289,8 @@ symbols! {
         global_allocator,
         global_asm,
         globs,
+        hash,
+        Hash,
         hexagon_target_feature,
         hidden,
         homogeneous_aggregate,
@@ -291,6 +312,8 @@ symbols! {
         impl_header_lifetime_elision,
         impl_trait_in_bindings,
         import_shadowing,
+        index,
+        index_mut,
         in_band_lifetimes,
         include,
         inclusive_range_syntax,
@@ -307,6 +330,7 @@ symbols! {
         issue,
         issue_5723_bootstrap,
         issue_tracker_base_url,
+        item,
         item_like_imports,
         iter,
         Iterator,
@@ -317,6 +341,7 @@ symbols! {
         lang,
         lang_items,
         lib,
+        lifetime,
         link,
         linkage,
         link_args,
@@ -325,6 +350,7 @@ symbols! {
         link_name,
         link_section,
         lint_reasons,
+        literal,
         local_inner_macros,
         log_syntax,
         loop_break_value,
@@ -364,6 +390,7 @@ symbols! {
         negate_unsigned,
         never,
         never_type,
+        new,
         next,
         __next,
         nll,
@@ -398,14 +425,21 @@ symbols! {
         option,
         Option,
         opt_out_copy,
+        or,
+        Ord,
+        Ordering,
         Output,
         overlapping_marker_traits,
         packed,
+        panic,
         panic_handler,
         panic_impl,
         panic_implementation,
         panic_runtime,
+        partial_cmp,
+        PartialOrd,
         passes,
+        pat,
         path,
         pattern_parentheses,
         Pending,
@@ -426,6 +460,7 @@ symbols! {
         proc_dash_macro: "proc-macro",
         proc_macro,
         proc_macro_attribute,
+        proc_macro_def_site,
         proc_macro_derive,
         proc_macro_expr,
         proc_macro_gen,
@@ -464,6 +499,7 @@ symbols! {
         Result,
         Return,
         rlib,
+        rt,
         rtm_target_feature,
         rust,
         rust_2015_preview,
@@ -547,6 +583,7 @@ symbols! {
         static_recursion,
         std,
         str,
+        stmt,
         stmt_expr_attributes,
         stop_after_dataflow,
         struct_field_attributes,
@@ -564,8 +601,10 @@ symbols! {
         test,
         test_2018_feature,
         test_accepted_feature,
+        test_case,
         test_removed_feature,
         test_runner,
+        then_with,
         thread_local,
         tool_attributes,
         tool_lints,
@@ -577,6 +616,7 @@ symbols! {
         Try,
         try_blocks,
         try_trait,
+        tt,
         tuple_indexing,
         ty,
         type_alias_enum_variants,
@@ -605,12 +645,15 @@ symbols! {
         untagged_unions,
         unwind,
         unwind_attributes,
+        unwrap_or,
         used,
         use_extern_macros,
         use_nested_groups,
         usize,
         v1,
         val,
+        vec,
+        Vec,
         vis,
         visible_private_types,
         volatile,
@@ -866,20 +909,13 @@ pub struct Interner {
 }
 
 impl Interner {
-    fn prefill(init: &[&str]) -> Self {
-        let mut this = Interner::default();
-        this.names.reserve(init.len());
-        this.strings.reserve(init.len());
-
-        // We can't allocate empty strings in the arena, so handle this here.
-        assert!(kw::Invalid.as_u32() == 0 && init[0].is_empty());
-        this.names.insert("", kw::Invalid);
-        this.strings.push("");
-
-        for string in &init[1..] {
-            this.intern(string);
+    fn prefill(init: &[&'static str]) -> Self {
+        let symbols = (0 .. init.len() as u32).map(Symbol::new);
+        Interner {
+            strings: init.to_vec(),
+            names: init.iter().copied().zip(symbols).collect(),
+            ..Default::default()
         }
-        this
     }
 
     pub fn intern(&mut self, string: &str) -> Symbol {
@@ -942,8 +978,21 @@ pub mod kw {
 
 // This module has a very short name because it's used a lot.
 pub mod sym {
+    use std::convert::TryInto;
     use super::Symbol;
+
     symbols!();
+
+    // Get the symbol for an integer. The first few non-negative integers each
+    // have a static symbol and therefore are fast.
+    pub fn integer<N: TryInto<usize> + Copy + ToString>(n: N) -> Symbol {
+        if let Result::Ok(idx) = n.try_into() {
+            if let Option::Some(&sym) = digits_array.get(idx) {
+                return sym;
+            }
+        }
+        Symbol::intern(&n.to_string())
+    }
 }
 
 impl Symbol {
diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs
index 7f7db2a21251a..8bd0d74cd1710 100644
--- a/src/libtest/lib.rs
+++ b/src/libtest/lib.rs
@@ -22,7 +22,6 @@
 #![unstable(feature = "test", issue = "27812")]
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/", test(attr(deny(warnings))))]
 #![feature(asm)]
-#![feature(fnbox)]
 #![cfg_attr(any(unix, target_os = "cloudabi"), feature(libc, rustc_private))]
 #![feature(nll)]
 #![feature(set_stdio)]
@@ -56,7 +55,6 @@ pub use self::TestResult::*;
 
 use std::any::Any;
 use std::borrow::Cow;
-use std::boxed::FnBox;
 use std::cmp;
 use std::collections::BTreeMap;
 use std::env;
@@ -174,7 +172,7 @@ pub trait TDynBenchFn: Send {
 pub enum TestFn {
     StaticTestFn(fn()),
     StaticBenchFn(fn(&mut Bencher)),
-    DynTestFn(Box<dyn FnBox() + Send>),
+    DynTestFn(Box<dyn FnOnce() + Send>),
     DynBenchFn(Box<dyn TDynBenchFn + 'static>),
 }
 
@@ -1447,7 +1445,7 @@ pub fn run_test(
         desc: TestDesc,
         monitor_ch: Sender<MonitorMsg>,
         nocapture: bool,
-        testfn: Box<dyn FnBox() + Send>,
+        testfn: Box<dyn FnOnce() + Send>,
         concurrency: Concurrent,
     ) {
         // Buffer for capturing standard I/O
diff --git a/src/test/run-make-fulldeps/cross-lang-lto-pgo-smoketest/Makefile b/src/test/run-make-fulldeps/cross-lang-lto-pgo-smoketest/Makefile
new file mode 100644
index 0000000000000..59a7d61892ffb
--- /dev/null
+++ b/src/test/run-make-fulldeps/cross-lang-lto-pgo-smoketest/Makefile
@@ -0,0 +1,87 @@
+# needs-matching-clang
+
+# This test makes sure that cross-language inlining can be used in conjunction
+# with profile-guided optimization. The test only tests that the whole workflow
+# can be executed without anything crashing. It does not test whether PGO or
+# xLTO have any specific effect on the generated code.
+
+-include ../tools.mk
+
+COMMON_FLAGS=-Copt-level=3 -Ccodegen-units=1
+
+# LLVM doesn't support instrumenting binaries that use SEH:
+# https://bugs.llvm.org/show_bug.cgi?id=41279
+#
+# Things work fine with -Cpanic=abort though.
+ifdef IS_MSVC
+COMMON_FLAGS+= -Cpanic=abort
+endif
+
+all: cpp-executable rust-executable
+
+cpp-executable:
+	$(RUSTC) -Clinker-plugin-lto=on \
+	         -Zpgo-gen="$(TMPDIR)"/cpp-profdata \
+	         -o "$(TMPDIR)"/librustlib-xlto.a \
+	         $(COMMON_FLAGS) \
+	         ./rustlib.rs
+	$(CLANG) -flto=thin \
+	         -fprofile-generate="$(TMPDIR)"/cpp-profdata \
+	         -fuse-ld=lld \
+	         -L "$(TMPDIR)" \
+	         -lrustlib-xlto \
+	         -o "$(TMPDIR)"/cmain \
+	         -O3 \
+	         ./cmain.c
+	$(TMPDIR)/cmain
+	# Postprocess the profiling data so it can be used by the compiler
+	"$(LLVM_BIN_DIR)"/llvm-profdata merge \
+		-o "$(TMPDIR)"/cpp-profdata/merged.profdata \
+		"$(TMPDIR)"/cpp-profdata/default_*.profraw
+	$(RUSTC) -Clinker-plugin-lto=on \
+	         -Zpgo-use="$(TMPDIR)"/cpp-profdata/merged.profdata \
+	         -o "$(TMPDIR)"/librustlib-xlto.a \
+	         $(COMMON_FLAGS) \
+	         ./rustlib.rs
+	$(CLANG) -flto=thin \
+	         -fprofile-use="$(TMPDIR)"/cpp-profdata/merged.profdata \
+	         -fuse-ld=lld \
+	         -L "$(TMPDIR)" \
+	         -lrustlib-xlto \
+	         -o "$(TMPDIR)"/cmain \
+	         -O3 \
+	         ./cmain.c
+
+rust-executable:
+	exit
+	$(CLANG) ./clib.c -fprofile-generate="$(TMPDIR)"/rs-profdata -flto=thin -c -o $(TMPDIR)/clib.o -O3
+	(cd $(TMPDIR); $(AR) crus ./libxyz.a ./clib.o)
+	$(RUSTC) -Clinker-plugin-lto=on \
+	         -Zpgo-gen="$(TMPDIR)"/rs-profdata \
+	         -L$(TMPDIR) \
+	         $(COMMON_FLAGS) \
+	         -Clinker=$(CLANG) \
+	         -Clink-arg=-fuse-ld=lld \
+	         -o $(TMPDIR)/rsmain \
+	         ./main.rs
+	$(TMPDIR)/rsmain
+	# Postprocess the profiling data so it can be used by the compiler
+	"$(LLVM_BIN_DIR)"/llvm-profdata merge \
+		-o "$(TMPDIR)"/rs-profdata/merged.profdata \
+		"$(TMPDIR)"/rs-profdata/default_*.profraw
+	$(CLANG) ./clib.c \
+	         -fprofile-use="$(TMPDIR)"/rs-profdata/merged.profdata \
+	         -flto=thin \
+	         -c \
+	         -o $(TMPDIR)/clib.o \
+	         -O3
+	rm "$(TMPDIR)"/libxyz.a
+	(cd $(TMPDIR); $(AR) crus ./libxyz.a ./clib.o)
+	$(RUSTC) -Clinker-plugin-lto=on \
+	         -Zpgo-use="$(TMPDIR)"/rs-profdata/merged.profdata \
+	         -L$(TMPDIR) \
+	         $(COMMON_FLAGS) \
+	         -Clinker=$(CLANG) \
+	         -Clink-arg=-fuse-ld=lld \
+	         -o $(TMPDIR)/rsmain \
+	         ./main.rs
diff --git a/src/test/run-make-fulldeps/cross-lang-lto-pgo-smoketest/clib.c b/src/test/run-make-fulldeps/cross-lang-lto-pgo-smoketest/clib.c
new file mode 100644
index 0000000000000..90f33f24dc424
--- /dev/null
+++ b/src/test/run-make-fulldeps/cross-lang-lto-pgo-smoketest/clib.c
@@ -0,0 +1,9 @@
+#include <stdint.h>
+
+uint32_t c_always_inlined() {
+    return 1234;
+}
+
+__attribute__((noinline)) uint32_t c_never_inlined() {
+    return 12345;
+}
diff --git a/src/test/run-make-fulldeps/cross-lang-lto-pgo-smoketest/cmain.c b/src/test/run-make-fulldeps/cross-lang-lto-pgo-smoketest/cmain.c
new file mode 100644
index 0000000000000..e3f24828be371
--- /dev/null
+++ b/src/test/run-make-fulldeps/cross-lang-lto-pgo-smoketest/cmain.c
@@ -0,0 +1,12 @@
+#include <stdint.h>
+
+// A trivial function defined in Rust, returning a constant value. This should
+// always be inlined.
+uint32_t rust_always_inlined();
+
+
+uint32_t rust_never_inlined();
+
+int main(int argc, char** argv) {
+    return (rust_never_inlined() + rust_always_inlined()) * 0;
+}
diff --git a/src/test/run-make-fulldeps/cross-lang-lto-pgo-smoketest/main.rs b/src/test/run-make-fulldeps/cross-lang-lto-pgo-smoketest/main.rs
new file mode 100644
index 0000000000000..8129dcb85d96a
--- /dev/null
+++ b/src/test/run-make-fulldeps/cross-lang-lto-pgo-smoketest/main.rs
@@ -0,0 +1,11 @@
+#[link(name = "xyz")]
+extern "C" {
+    fn c_always_inlined() -> u32;
+    fn c_never_inlined() -> u32;
+}
+
+fn main() {
+    unsafe {
+        println!("blub: {}", c_always_inlined() + c_never_inlined());
+    }
+}
diff --git a/src/test/run-make-fulldeps/cross-lang-lto-pgo-smoketest/rustlib.rs b/src/test/run-make-fulldeps/cross-lang-lto-pgo-smoketest/rustlib.rs
new file mode 100644
index 0000000000000..8a74d74a420bd
--- /dev/null
+++ b/src/test/run-make-fulldeps/cross-lang-lto-pgo-smoketest/rustlib.rs
@@ -0,0 +1,12 @@
+#![crate_type="staticlib"]
+
+#[no_mangle]
+pub extern "C" fn rust_always_inlined() -> u32 {
+    42
+}
+
+#[no_mangle]
+#[inline(never)]
+pub extern "C" fn rust_never_inlined() -> u32 {
+    421
+}
diff --git a/src/test/run-pass/regions/regions-lub-ref-ref-rc.rs b/src/test/run-pass/regions/regions-lub-ref-ref-rc.rs
index cd095f6f3a4a3..96c71b084b13e 100644
--- a/src/test/run-pass/regions/regions-lub-ref-ref-rc.rs
+++ b/src/test/run-pass/regions/regions-lub-ref-ref-rc.rs
@@ -11,16 +11,16 @@
 use std::rc::Rc;
 
 #[derive(Clone)]
-enum CachedMir<'mir> {
+enum Cached<'mir> {
     Ref(&'mir String),
     Owned(Rc<String>),
 }
 
-impl<'mir> CachedMir<'mir> {
+impl<'mir> Cached<'mir> {
     fn get_ref<'a>(&'a self) -> &'a String {
         match *self {
-            CachedMir::Ref(r) => r,
-            CachedMir::Owned(ref rc) => &rc,
+            Cached::Ref(r) => r,
+            Cached::Owned(ref rc) => &rc,
         }
     }
 }
diff --git a/src/test/run-pass/unsized-locals/fnbox-compat.rs b/src/test/run-pass/unsized-locals/fnbox-compat.rs
index 5ec54ada13bb0..74a4dd5d8515b 100644
--- a/src/test/run-pass/unsized-locals/fnbox-compat.rs
+++ b/src/test/run-pass/unsized-locals/fnbox-compat.rs
@@ -1,4 +1,5 @@
 #![feature(fnbox)]
+#![allow(deprecated, deprecated_in_future)]
 
 use std::boxed::FnBox;
 
diff --git a/src/test/run-pass/async-await.rs b/src/test/ui/async-await/async-await.rs
similarity index 99%
rename from src/test/run-pass/async-await.rs
rename to src/test/ui/async-await/async-await.rs
index 49fd8b8b1ce27..6fa013e5c54ca 100644
--- a/src/test/run-pass/async-await.rs
+++ b/src/test/ui/async-await/async-await.rs
@@ -1,3 +1,5 @@
+// run-pass
+
 // edition:2018
 // aux-build:arc_wake.rs
 
diff --git a/src/test/ui/async-fn-multiple-lifetimes.rs b/src/test/ui/async-await/async-fn-multiple-lifetimes.rs
similarity index 100%
rename from src/test/ui/async-fn-multiple-lifetimes.rs
rename to src/test/ui/async-await/async-fn-multiple-lifetimes.rs
diff --git a/src/test/ui/async-fn-multiple-lifetimes.stderr b/src/test/ui/async-await/async-fn-multiple-lifetimes.stderr
similarity index 100%
rename from src/test/ui/async-fn-multiple-lifetimes.stderr
rename to src/test/ui/async-await/async-fn-multiple-lifetimes.stderr
diff --git a/src/test/ui/async-fn-path-elision.rs b/src/test/ui/async-await/async-fn-path-elision.rs
similarity index 100%
rename from src/test/ui/async-fn-path-elision.rs
rename to src/test/ui/async-await/async-fn-path-elision.rs
diff --git a/src/test/ui/async-fn-path-elision.stderr b/src/test/ui/async-await/async-fn-path-elision.stderr
similarity index 100%
rename from src/test/ui/async-fn-path-elision.stderr
rename to src/test/ui/async-await/async-fn-path-elision.stderr
diff --git a/src/test/ui/async-matches-expr.rs b/src/test/ui/async-await/async-matches-expr.rs
similarity index 100%
rename from src/test/ui/async-matches-expr.rs
rename to src/test/ui/async-await/async-matches-expr.rs
diff --git a/src/test/ui/async-with-closure.rs b/src/test/ui/async-await/async-with-closure.rs
similarity index 100%
rename from src/test/ui/async-with-closure.rs
rename to src/test/ui/async-await/async-with-closure.rs
diff --git a/src/test/ui/await-keyword/2015-edition-error-in-non-macro-position.rs b/src/test/ui/async-await/await-keyword/2015-edition-error-in-non-macro-position.rs
similarity index 100%
rename from src/test/ui/await-keyword/2015-edition-error-in-non-macro-position.rs
rename to src/test/ui/async-await/await-keyword/2015-edition-error-in-non-macro-position.rs
diff --git a/src/test/ui/await-keyword/2015-edition-error-in-non-macro-position.stderr b/src/test/ui/async-await/await-keyword/2015-edition-error-in-non-macro-position.stderr
similarity index 100%
rename from src/test/ui/await-keyword/2015-edition-error-in-non-macro-position.stderr
rename to src/test/ui/async-await/await-keyword/2015-edition-error-in-non-macro-position.stderr
diff --git a/src/test/ui/await-keyword/2015-edition-warning.fixed b/src/test/ui/async-await/await-keyword/2015-edition-warning.fixed
similarity index 100%
rename from src/test/ui/await-keyword/2015-edition-warning.fixed
rename to src/test/ui/async-await/await-keyword/2015-edition-warning.fixed
diff --git a/src/test/ui/await-keyword/2015-edition-warning.rs b/src/test/ui/async-await/await-keyword/2015-edition-warning.rs
similarity index 100%
rename from src/test/ui/await-keyword/2015-edition-warning.rs
rename to src/test/ui/async-await/await-keyword/2015-edition-warning.rs
diff --git a/src/test/ui/await-keyword/2015-edition-warning.stderr b/src/test/ui/async-await/await-keyword/2015-edition-warning.stderr
similarity index 100%
rename from src/test/ui/await-keyword/2015-edition-warning.stderr
rename to src/test/ui/async-await/await-keyword/2015-edition-warning.stderr
diff --git a/src/test/ui/await-keyword/2018-edition-error-in-non-macro-position.rs b/src/test/ui/async-await/await-keyword/2018-edition-error-in-non-macro-position.rs
similarity index 100%
rename from src/test/ui/await-keyword/2018-edition-error-in-non-macro-position.rs
rename to src/test/ui/async-await/await-keyword/2018-edition-error-in-non-macro-position.rs
diff --git a/src/test/ui/await-keyword/2018-edition-error-in-non-macro-position.stderr b/src/test/ui/async-await/await-keyword/2018-edition-error-in-non-macro-position.stderr
similarity index 100%
rename from src/test/ui/await-keyword/2018-edition-error-in-non-macro-position.stderr
rename to src/test/ui/async-await/await-keyword/2018-edition-error-in-non-macro-position.stderr
diff --git a/src/test/ui/await-keyword/2018-edition-error.rs b/src/test/ui/async-await/await-keyword/2018-edition-error.rs
similarity index 100%
rename from src/test/ui/await-keyword/2018-edition-error.rs
rename to src/test/ui/async-await/await-keyword/2018-edition-error.rs
diff --git a/src/test/ui/await-keyword/2018-edition-error.stderr b/src/test/ui/async-await/await-keyword/2018-edition-error.stderr
similarity index 100%
rename from src/test/ui/await-keyword/2018-edition-error.stderr
rename to src/test/ui/async-await/await-keyword/2018-edition-error.stderr
diff --git a/src/test/ui/await-keyword/incorrect-syntax-suggestions.rs b/src/test/ui/async-await/await-keyword/incorrect-syntax-suggestions.rs
similarity index 100%
rename from src/test/ui/await-keyword/incorrect-syntax-suggestions.rs
rename to src/test/ui/async-await/await-keyword/incorrect-syntax-suggestions.rs
diff --git a/src/test/ui/await-keyword/incorrect-syntax-suggestions.stderr b/src/test/ui/async-await/await-keyword/incorrect-syntax-suggestions.stderr
similarity index 100%
rename from src/test/ui/await-keyword/incorrect-syntax-suggestions.stderr
rename to src/test/ui/async-await/await-keyword/incorrect-syntax-suggestions.stderr
diff --git a/src/test/ui/await-keyword/post_expansion_error.rs b/src/test/ui/async-await/await-keyword/post_expansion_error.rs
similarity index 100%
rename from src/test/ui/await-keyword/post_expansion_error.rs
rename to src/test/ui/async-await/await-keyword/post_expansion_error.rs
diff --git a/src/test/ui/await-keyword/post_expansion_error.stderr b/src/test/ui/async-await/await-keyword/post_expansion_error.stderr
similarity index 100%
rename from src/test/ui/await-keyword/post_expansion_error.stderr
rename to src/test/ui/async-await/await-keyword/post_expansion_error.stderr
diff --git a/src/test/run-pass/await-macro.rs b/src/test/ui/async-await/await-macro.rs
similarity index 99%
rename from src/test/run-pass/await-macro.rs
rename to src/test/ui/async-await/await-macro.rs
index e1b4328debd9a..1b807588d6ac2 100644
--- a/src/test/run-pass/await-macro.rs
+++ b/src/test/ui/async-await/await-macro.rs
@@ -1,3 +1,5 @@
+// run-pass
+
 // edition:2018
 // aux-build:arc_wake.rs
 
diff --git a/src/test/ui/nll/dont-print-desugared-async.rs b/src/test/ui/async-await/dont-print-desugared-async.rs
similarity index 100%
rename from src/test/ui/nll/dont-print-desugared-async.rs
rename to src/test/ui/async-await/dont-print-desugared-async.rs
diff --git a/src/test/ui/nll/dont-print-desugared-async.stderr b/src/test/ui/async-await/dont-print-desugared-async.stderr
similarity index 100%
rename from src/test/ui/nll/dont-print-desugared-async.stderr
rename to src/test/ui/async-await/dont-print-desugared-async.stderr
diff --git a/src/test/ui/async-await/drop-order/auxiliary/arc_wake.rs b/src/test/ui/async-await/drop-order/auxiliary/arc_wake.rs
new file mode 100644
index 0000000000000..c21886f26f467
--- /dev/null
+++ b/src/test/ui/async-await/drop-order/auxiliary/arc_wake.rs
@@ -0,0 +1,64 @@
+// edition:2018
+
+use std::sync::Arc;
+use std::task::{
+    Waker, RawWaker, RawWakerVTable,
+};
+
+macro_rules! waker_vtable {
+    ($ty:ident) => {
+        &RawWakerVTable::new(
+            clone_arc_raw::<$ty>,
+            wake_arc_raw::<$ty>,
+            wake_by_ref_arc_raw::<$ty>,
+            drop_arc_raw::<$ty>,
+        )
+    };
+}
+
+pub trait ArcWake {
+    fn wake(self: Arc<Self>);
+
+    fn wake_by_ref(arc_self: &Arc<Self>) {
+        arc_self.clone().wake()
+    }
+
+    fn into_waker(wake: Arc<Self>) -> Waker where Self: Sized
+    {
+        let ptr = Arc::into_raw(wake) as *const ();
+
+        unsafe {
+            Waker::from_raw(RawWaker::new(ptr, waker_vtable!(Self)))
+        }
+    }
+}
+
+unsafe fn increase_refcount<T: ArcWake>(data: *const ()) {
+    // Retain Arc by creating a copy
+    let arc: Arc<T> = Arc::from_raw(data as *const T);
+    let arc_clone = arc.clone();
+    // Forget the Arcs again, so that the refcount isn't decrased
+    let _ = Arc::into_raw(arc);
+    let _ = Arc::into_raw(arc_clone);
+}
+
+unsafe fn clone_arc_raw<T: ArcWake>(data: *const ()) -> RawWaker {
+    increase_refcount::<T>(data);
+    RawWaker::new(data, waker_vtable!(T))
+}
+
+unsafe fn drop_arc_raw<T: ArcWake>(data: *const ()) {
+    // Drop Arc
+    let _: Arc<T> = Arc::from_raw(data as *const T);
+}
+
+unsafe fn wake_arc_raw<T: ArcWake>(data: *const ()) {
+    let arc: Arc<T> = Arc::from_raw(data as *const T);
+    ArcWake::wake(arc);
+}
+
+unsafe fn wake_by_ref_arc_raw<T: ArcWake>(data: *const ()) {
+    let arc: Arc<T> = Arc::from_raw(data as *const T);
+    ArcWake::wake_by_ref(&arc);
+    let _ = Arc::into_raw(arc);
+}
diff --git a/src/test/ui/async-await/drop-order-for-async-fn-parameters-by-ref-binding.rs b/src/test/ui/async-await/drop-order/drop-order-for-async-fn-parameters-by-ref-binding.rs
similarity index 100%
rename from src/test/ui/async-await/drop-order-for-async-fn-parameters-by-ref-binding.rs
rename to src/test/ui/async-await/drop-order/drop-order-for-async-fn-parameters-by-ref-binding.rs
diff --git a/src/test/ui/async-await/drop-order-for-async-fn-parameters.rs b/src/test/ui/async-await/drop-order/drop-order-for-async-fn-parameters.rs
similarity index 100%
rename from src/test/ui/async-await/drop-order-for-async-fn-parameters.rs
rename to src/test/ui/async-await/drop-order/drop-order-for-async-fn-parameters.rs
diff --git a/src/test/ui/async-await/drop-order-locals-are-hidden.rs b/src/test/ui/async-await/drop-order/drop-order-locals-are-hidden.rs
similarity index 100%
rename from src/test/ui/async-await/drop-order-locals-are-hidden.rs
rename to src/test/ui/async-await/drop-order/drop-order-locals-are-hidden.rs
diff --git a/src/test/ui/async-await/drop-order-locals-are-hidden.stderr b/src/test/ui/async-await/drop-order/drop-order-locals-are-hidden.stderr
similarity index 100%
rename from src/test/ui/async-await/drop-order-locals-are-hidden.stderr
rename to src/test/ui/async-await/drop-order/drop-order-locals-are-hidden.stderr
diff --git a/src/test/ui/editions/edition-deny-async-fns-2015.rs b/src/test/ui/async-await/edition-deny-async-fns-2015.rs
similarity index 100%
rename from src/test/ui/editions/edition-deny-async-fns-2015.rs
rename to src/test/ui/async-await/edition-deny-async-fns-2015.rs
diff --git a/src/test/ui/editions/edition-deny-async-fns-2015.stderr b/src/test/ui/async-await/edition-deny-async-fns-2015.stderr
similarity index 100%
rename from src/test/ui/editions/edition-deny-async-fns-2015.stderr
rename to src/test/ui/async-await/edition-deny-async-fns-2015.stderr
diff --git a/src/test/ui/async-await/auxiliary/issue-60674.rs b/src/test/ui/async-await/issues/auxiliary/issue-60674.rs
similarity index 100%
rename from src/test/ui/async-await/auxiliary/issue-60674.rs
rename to src/test/ui/async-await/issues/auxiliary/issue-60674.rs
diff --git a/src/test/ui/issues/issue-51719.rs b/src/test/ui/async-await/issues/issue-51719.rs
similarity index 100%
rename from src/test/ui/issues/issue-51719.rs
rename to src/test/ui/async-await/issues/issue-51719.rs
diff --git a/src/test/ui/issues/issue-51719.stderr b/src/test/ui/async-await/issues/issue-51719.stderr
similarity index 100%
rename from src/test/ui/issues/issue-51719.stderr
rename to src/test/ui/async-await/issues/issue-51719.stderr
diff --git a/src/test/ui/issues/issue-51751.rs b/src/test/ui/async-await/issues/issue-51751.rs
similarity index 100%
rename from src/test/ui/issues/issue-51751.rs
rename to src/test/ui/async-await/issues/issue-51751.rs
diff --git a/src/test/ui/issues/issue-51751.stderr b/src/test/ui/async-await/issues/issue-51751.stderr
similarity index 100%
rename from src/test/ui/issues/issue-51751.stderr
rename to src/test/ui/async-await/issues/issue-51751.stderr
diff --git a/src/test/ui/issue-53249.rs b/src/test/ui/async-await/issues/issue-53249.rs
similarity index 100%
rename from src/test/ui/issue-53249.rs
rename to src/test/ui/async-await/issues/issue-53249.rs
diff --git a/src/test/pretty/issue-54752-async-block.rs b/src/test/ui/async-await/issues/issue-54752-async-block.rs
similarity index 90%
rename from src/test/pretty/issue-54752-async-block.rs
rename to src/test/ui/async-await/issues/issue-54752-async-block.rs
index 6930ee1a386fe..0036de90b2579 100644
--- a/src/test/pretty/issue-54752-async-block.rs
+++ b/src/test/ui/async-await/issues/issue-54752-async-block.rs
@@ -1,7 +1,9 @@
-#![feature(async_await)]
-#![allow(unused_parens)]
+// run-pass
 
 // edition:2018
 // pp-exact
 
+#![feature(async_await)]
+#![allow(unused_parens)]
+
 fn main() { let _a = (async  { }); }
diff --git a/src/test/ui/issues/issue-54974.rs b/src/test/ui/async-await/issues/issue-54974.rs
similarity index 100%
rename from src/test/ui/issues/issue-54974.rs
rename to src/test/ui/async-await/issues/issue-54974.rs
diff --git a/src/test/ui/issues/issue-55324.rs b/src/test/ui/async-await/issues/issue-55324.rs
similarity index 100%
rename from src/test/ui/issues/issue-55324.rs
rename to src/test/ui/async-await/issues/issue-55324.rs
diff --git a/src/test/run-pass/issue-55809.rs b/src/test/ui/async-await/issues/issue-55809.rs
similarity index 100%
rename from src/test/run-pass/issue-55809.rs
rename to src/test/ui/async-await/issues/issue-55809.rs
diff --git a/src/test/ui/issues/issue-58885.rs b/src/test/ui/async-await/issues/issue-58885.rs
similarity index 100%
rename from src/test/ui/issues/issue-58885.rs
rename to src/test/ui/async-await/issues/issue-58885.rs
diff --git a/src/test/ui/issues/issue-59001.rs b/src/test/ui/async-await/issues/issue-59001.rs
similarity index 100%
rename from src/test/ui/issues/issue-59001.rs
rename to src/test/ui/async-await/issues/issue-59001.rs
diff --git a/src/test/run-pass/generator/issue-59972.rs b/src/test/ui/async-await/issues/issue-59972.rs
similarity index 96%
rename from src/test/run-pass/generator/issue-59972.rs
rename to src/test/ui/async-await/issues/issue-59972.rs
index 995da4fb3ff3c..31e7a65dc98e3 100644
--- a/src/test/run-pass/generator/issue-59972.rs
+++ b/src/test/ui/async-await/issues/issue-59972.rs
@@ -1,3 +1,5 @@
+// run-pass
+
 // compile-flags: --edition=2018
 
 #![feature(async_await, await_macro)]
diff --git a/src/test/ui/async-await/issue-60518.rs b/src/test/ui/async-await/issues/issue-60518.rs
similarity index 100%
rename from src/test/ui/async-await/issue-60518.rs
rename to src/test/ui/async-await/issues/issue-60518.rs
diff --git a/src/test/ui/existential_types/issue-60655-latebound-regions.rs b/src/test/ui/async-await/issues/issue-60655-latebound-regions.rs
similarity index 100%
rename from src/test/ui/existential_types/issue-60655-latebound-regions.rs
rename to src/test/ui/async-await/issues/issue-60655-latebound-regions.rs
diff --git a/src/test/ui/async-await/issue-60674.rs b/src/test/ui/async-await/issues/issue-60674.rs
similarity index 100%
rename from src/test/ui/async-await/issue-60674.rs
rename to src/test/ui/async-await/issues/issue-60674.rs
diff --git a/src/test/ui/async-await/issue-60674.stdout b/src/test/ui/async-await/issues/issue-60674.stdout
similarity index 100%
rename from src/test/ui/async-await/issue-60674.stdout
rename to src/test/ui/async-await/issues/issue-60674.stdout
diff --git a/src/test/ui/no-args-non-move-async-closure.rs b/src/test/ui/async-await/no-args-non-move-async-closure.rs
similarity index 100%
rename from src/test/ui/no-args-non-move-async-closure.rs
rename to src/test/ui/async-await/no-args-non-move-async-closure.rs
diff --git a/src/test/ui/no-args-non-move-async-closure.stderr b/src/test/ui/async-await/no-args-non-move-async-closure.stderr
similarity index 100%
rename from src/test/ui/no-args-non-move-async-closure.stderr
rename to src/test/ui/async-await/no-args-non-move-async-closure.stderr
diff --git a/src/test/ui/impl-trait/recursive-async-impl-trait-type.rs b/src/test/ui/async-await/recursive-async-impl-trait-type.rs
similarity index 100%
rename from src/test/ui/impl-trait/recursive-async-impl-trait-type.rs
rename to src/test/ui/async-await/recursive-async-impl-trait-type.rs
diff --git a/src/test/ui/impl-trait/recursive-async-impl-trait-type.stderr b/src/test/ui/async-await/recursive-async-impl-trait-type.stderr
similarity index 100%
rename from src/test/ui/impl-trait/recursive-async-impl-trait-type.stderr
rename to src/test/ui/async-await/recursive-async-impl-trait-type.stderr
diff --git a/src/test/ui/generator/unresolved_type_param.rs b/src/test/ui/async-await/unresolved_type_param.rs
similarity index 100%
rename from src/test/ui/generator/unresolved_type_param.rs
rename to src/test/ui/async-await/unresolved_type_param.rs
diff --git a/src/test/ui/generator/unresolved_type_param.stderr b/src/test/ui/async-await/unresolved_type_param.stderr
similarity index 100%
rename from src/test/ui/generator/unresolved_type_param.stderr
rename to src/test/ui/async-await/unresolved_type_param.stderr
diff --git a/src/test/ui/confuse-field-and-method/issue-2392.rs b/src/test/ui/confuse-field-and-method/issue-2392.rs
index 41287c2591497..c242b6c2c20a2 100644
--- a/src/test/ui/confuse-field-and-method/issue-2392.rs
+++ b/src/test/ui/confuse-field-and-method/issue-2392.rs
@@ -1,7 +1,3 @@
-#![feature(core, fnbox)]
-
-use std::boxed::FnBox;
-
 struct FuncContainer {
     f1: fn(data: u8),
     f2: extern "C" fn(data: u8),
@@ -18,7 +14,7 @@ struct Obj<F> where F: FnOnce() -> u32 {
 }
 
 struct BoxedObj {
-    boxed_closure: Box<FnBox() -> u32>,
+    boxed_closure: Box<FnOnce() -> u32>,
 }
 
 struct Wrapper<F> where F: FnMut() -> u32 {
@@ -29,8 +25,8 @@ fn func() -> u32 {
     0
 }
 
-fn check_expression() -> Obj<Box<FnBox() -> u32>> {
-    Obj { closure: Box::new(|| 42_u32) as Box<FnBox() -> u32>, not_closure: 42 }
+fn check_expression() -> Obj<Box<FnOnce() -> u32>> {
+    Obj { closure: Box::new(|| 42_u32) as Box<FnOnce() -> u32>, not_closure: 42 }
 }
 
 fn main() {
@@ -48,7 +44,7 @@ fn main() {
     let boxed_fn = BoxedObj { boxed_closure: Box::new(func) };
     boxed_fn.boxed_closure();//~ ERROR no method named `boxed_closure` found
 
-    let boxed_closure = BoxedObj { boxed_closure: Box::new(|| 42_u32) as Box<FnBox() -> u32> };
+    let boxed_closure = BoxedObj { boxed_closure: Box::new(|| 42_u32) as Box<FnOnce() -> u32> };
     boxed_closure.boxed_closure();//~ ERROR no method named `boxed_closure` found
 
     // test expression writing in the notes
diff --git a/src/test/ui/confuse-field-and-method/issue-2392.stderr b/src/test/ui/confuse-field-and-method/issue-2392.stderr
index 2107318d87b5b..351cfef1b53ea 100644
--- a/src/test/ui/confuse-field-and-method/issue-2392.stderr
+++ b/src/test/ui/confuse-field-and-method/issue-2392.stderr
@@ -1,5 +1,5 @@
-error[E0599]: no method named `closure` found for type `Obj<[closure@$DIR/issue-2392.rs:39:36: 39:41]>` in the current scope
-  --> $DIR/issue-2392.rs:40:15
+error[E0599]: no method named `closure` found for type `Obj<[closure@$DIR/issue-2392.rs:35:36: 35:41]>` in the current scope
+  --> $DIR/issue-2392.rs:36:15
    |
 LL | struct Obj<F> where F: FnOnce() -> u32 {
    | -------------------------------------- method `closure` not found for this
@@ -11,8 +11,8 @@ help: to call the function stored in `closure`, surround the field access with p
 LL |     (o_closure.closure)();
    |     ^                 ^
 
-error[E0599]: no method named `not_closure` found for type `Obj<[closure@$DIR/issue-2392.rs:39:36: 39:41]>` in the current scope
-  --> $DIR/issue-2392.rs:42:15
+error[E0599]: no method named `not_closure` found for type `Obj<[closure@$DIR/issue-2392.rs:35:36: 35:41]>` in the current scope
+  --> $DIR/issue-2392.rs:38:15
    |
 LL | struct Obj<F> where F: FnOnce() -> u32 {
    | -------------------------------------- method `not_closure` not found for this
@@ -23,7 +23,7 @@ LL |     o_closure.not_closure();
    |               field, not a method
 
 error[E0599]: no method named `closure` found for type `Obj<fn() -> u32 {func}>` in the current scope
-  --> $DIR/issue-2392.rs:46:12
+  --> $DIR/issue-2392.rs:42:12
    |
 LL | struct Obj<F> where F: FnOnce() -> u32 {
    | -------------------------------------- method `closure` not found for this
@@ -36,7 +36,7 @@ LL |     (o_func.closure)();
    |     ^              ^
 
 error[E0599]: no method named `boxed_closure` found for type `BoxedObj` in the current scope
-  --> $DIR/issue-2392.rs:49:14
+  --> $DIR/issue-2392.rs:45:14
    |
 LL | struct BoxedObj {
    | --------------- method `boxed_closure` not found for this
@@ -49,7 +49,7 @@ LL |     (boxed_fn.boxed_closure)();
    |     ^                      ^
 
 error[E0599]: no method named `boxed_closure` found for type `BoxedObj` in the current scope
-  --> $DIR/issue-2392.rs:52:19
+  --> $DIR/issue-2392.rs:48:19
    |
 LL | struct BoxedObj {
    | --------------- method `boxed_closure` not found for this
@@ -62,7 +62,7 @@ LL |     (boxed_closure.boxed_closure)();
    |     ^                           ^
 
 error[E0599]: no method named `closure` found for type `Obj<fn() -> u32 {func}>` in the current scope
-  --> $DIR/issue-2392.rs:57:12
+  --> $DIR/issue-2392.rs:53:12
    |
 LL | struct Obj<F> where F: FnOnce() -> u32 {
    | -------------------------------------- method `closure` not found for this
@@ -75,7 +75,7 @@ LL |     (w.wrap.closure)();
    |     ^              ^
 
 error[E0599]: no method named `not_closure` found for type `Obj<fn() -> u32 {func}>` in the current scope
-  --> $DIR/issue-2392.rs:59:12
+  --> $DIR/issue-2392.rs:55:12
    |
 LL | struct Obj<F> where F: FnOnce() -> u32 {
    | -------------------------------------- method `not_closure` not found for this
@@ -85,8 +85,8 @@ LL |     w.wrap.not_closure();
    |            |
    |            field, not a method
 
-error[E0599]: no method named `closure` found for type `Obj<std::boxed::Box<(dyn std::boxed::FnBox<(), Output = u32> + 'static)>>` in the current scope
-  --> $DIR/issue-2392.rs:62:24
+error[E0599]: no method named `closure` found for type `Obj<std::boxed::Box<(dyn std::ops::FnOnce() -> u32 + 'static)>>` in the current scope
+  --> $DIR/issue-2392.rs:58:24
    |
 LL | struct Obj<F> where F: FnOnce() -> u32 {
    | -------------------------------------- method `closure` not found for this
@@ -99,7 +99,7 @@ LL |     (check_expression().closure)();
    |     ^                          ^
 
 error[E0599]: no method named `f1` found for type `FuncContainer` in the current scope
-  --> $DIR/issue-2392.rs:68:31
+  --> $DIR/issue-2392.rs:64:31
    |
 LL | struct FuncContainer {
    | -------------------- method `f1` not found for this
@@ -112,7 +112,7 @@ LL |             ((*self.container).f1)(1);
    |             ^                    ^
 
 error[E0599]: no method named `f2` found for type `FuncContainer` in the current scope
-  --> $DIR/issue-2392.rs:69:31
+  --> $DIR/issue-2392.rs:65:31
    |
 LL | struct FuncContainer {
    | -------------------- method `f2` not found for this
@@ -125,7 +125,7 @@ LL |             ((*self.container).f2)(1);
    |             ^                    ^
 
 error[E0599]: no method named `f3` found for type `FuncContainer` in the current scope
-  --> $DIR/issue-2392.rs:70:31
+  --> $DIR/issue-2392.rs:66:31
    |
 LL | struct FuncContainer {
    | -------------------- method `f3` not found for this
diff --git a/src/test/ui/E0501.rs b/src/test/ui/error-codes/E0501.rs
similarity index 100%
rename from src/test/ui/E0501.rs
rename to src/test/ui/error-codes/E0501.rs
diff --git a/src/test/ui/E0501.stderr b/src/test/ui/error-codes/E0501.stderr
similarity index 100%
rename from src/test/ui/E0501.stderr
rename to src/test/ui/error-codes/E0501.stderr
diff --git a/src/test/ui/E0506.rs b/src/test/ui/error-codes/E0506.rs
similarity index 100%
rename from src/test/ui/E0506.rs
rename to src/test/ui/error-codes/E0506.rs
diff --git a/src/test/ui/E0506.stderr b/src/test/ui/error-codes/E0506.stderr
similarity index 100%
rename from src/test/ui/E0506.stderr
rename to src/test/ui/error-codes/E0506.stderr
diff --git a/src/test/ui/E0508-fail.rs b/src/test/ui/error-codes/E0508-fail.rs
similarity index 100%
rename from src/test/ui/E0508-fail.rs
rename to src/test/ui/error-codes/E0508-fail.rs
diff --git a/src/test/ui/E0508-fail.stderr b/src/test/ui/error-codes/E0508-fail.stderr
similarity index 100%
rename from src/test/ui/E0508-fail.stderr
rename to src/test/ui/error-codes/E0508-fail.stderr
diff --git a/src/test/ui/E0508.rs b/src/test/ui/error-codes/E0508.rs
similarity index 100%
rename from src/test/ui/E0508.rs
rename to src/test/ui/error-codes/E0508.rs
diff --git a/src/test/ui/E0508.stderr b/src/test/ui/error-codes/E0508.stderr
similarity index 100%
rename from src/test/ui/E0508.stderr
rename to src/test/ui/error-codes/E0508.stderr
diff --git a/src/test/ui/E0583.rs b/src/test/ui/error-codes/E0583.rs
similarity index 100%
rename from src/test/ui/E0583.rs
rename to src/test/ui/error-codes/E0583.rs
diff --git a/src/test/ui/E0583.stderr b/src/test/ui/error-codes/E0583.stderr
similarity index 100%
rename from src/test/ui/E0583.stderr
rename to src/test/ui/error-codes/E0583.stderr
diff --git a/src/test/ui/E0594.rs b/src/test/ui/error-codes/E0594.rs
similarity index 100%
rename from src/test/ui/E0594.rs
rename to src/test/ui/error-codes/E0594.rs
diff --git a/src/test/ui/E0594.stderr b/src/test/ui/error-codes/E0594.stderr
similarity index 100%
rename from src/test/ui/E0594.stderr
rename to src/test/ui/error-codes/E0594.stderr
diff --git a/src/test/ui/E0596.rs b/src/test/ui/error-codes/E0596.rs
similarity index 100%
rename from src/test/ui/E0596.rs
rename to src/test/ui/error-codes/E0596.rs
diff --git a/src/test/ui/E0596.stderr b/src/test/ui/error-codes/E0596.stderr
similarity index 100%
rename from src/test/ui/E0596.stderr
rename to src/test/ui/error-codes/E0596.stderr
diff --git a/src/test/ui/E0642.rs b/src/test/ui/error-codes/E0642.rs
similarity index 100%
rename from src/test/ui/E0642.rs
rename to src/test/ui/error-codes/E0642.rs
diff --git a/src/test/ui/E0642.stderr b/src/test/ui/error-codes/E0642.stderr
similarity index 100%
rename from src/test/ui/E0642.stderr
rename to src/test/ui/error-codes/E0642.stderr
diff --git a/src/test/ui/E0660.rs b/src/test/ui/error-codes/E0660.rs
similarity index 100%
rename from src/test/ui/E0660.rs
rename to src/test/ui/error-codes/E0660.rs
diff --git a/src/test/ui/E0660.stderr b/src/test/ui/error-codes/E0660.stderr
similarity index 100%
rename from src/test/ui/E0660.stderr
rename to src/test/ui/error-codes/E0660.stderr
diff --git a/src/test/ui/E0661.rs b/src/test/ui/error-codes/E0661.rs
similarity index 100%
rename from src/test/ui/E0661.rs
rename to src/test/ui/error-codes/E0661.rs
diff --git a/src/test/ui/E0661.stderr b/src/test/ui/error-codes/E0661.stderr
similarity index 100%
rename from src/test/ui/E0661.stderr
rename to src/test/ui/error-codes/E0661.stderr
diff --git a/src/test/ui/E0662.rs b/src/test/ui/error-codes/E0662.rs
similarity index 100%
rename from src/test/ui/E0662.rs
rename to src/test/ui/error-codes/E0662.rs
diff --git a/src/test/ui/E0662.stderr b/src/test/ui/error-codes/E0662.stderr
similarity index 100%
rename from src/test/ui/E0662.stderr
rename to src/test/ui/error-codes/E0662.stderr
diff --git a/src/test/ui/E0663.rs b/src/test/ui/error-codes/E0663.rs
similarity index 100%
rename from src/test/ui/E0663.rs
rename to src/test/ui/error-codes/E0663.rs
diff --git a/src/test/ui/E0663.stderr b/src/test/ui/error-codes/E0663.stderr
similarity index 100%
rename from src/test/ui/E0663.stderr
rename to src/test/ui/error-codes/E0663.stderr
diff --git a/src/test/ui/E0664.rs b/src/test/ui/error-codes/E0664.rs
similarity index 100%
rename from src/test/ui/E0664.rs
rename to src/test/ui/error-codes/E0664.rs
diff --git a/src/test/ui/E0664.stderr b/src/test/ui/error-codes/E0664.stderr
similarity index 100%
rename from src/test/ui/E0664.stderr
rename to src/test/ui/error-codes/E0664.stderr
diff --git a/src/test/ui/E0665.rs b/src/test/ui/error-codes/E0665.rs
similarity index 100%
rename from src/test/ui/E0665.rs
rename to src/test/ui/error-codes/E0665.rs
diff --git a/src/test/ui/E0665.stderr b/src/test/ui/error-codes/E0665.stderr
similarity index 100%
rename from src/test/ui/E0665.stderr
rename to src/test/ui/error-codes/E0665.stderr
diff --git a/src/test/ui/E0705.rs b/src/test/ui/error-codes/E0705.rs
similarity index 100%
rename from src/test/ui/E0705.rs
rename to src/test/ui/error-codes/E0705.rs
diff --git a/src/test/ui/E0705.stderr b/src/test/ui/error-codes/E0705.stderr
similarity index 100%
rename from src/test/ui/E0705.stderr
rename to src/test/ui/error-codes/E0705.stderr
diff --git a/src/test/ui/e0119/auxiliary/complex_impl_support.rs b/src/test/ui/error-codes/e0119/auxiliary/complex_impl_support.rs
similarity index 100%
rename from src/test/ui/e0119/auxiliary/complex_impl_support.rs
rename to src/test/ui/error-codes/e0119/auxiliary/complex_impl_support.rs
diff --git a/src/test/ui/e0119/auxiliary/issue-23563-a.rs b/src/test/ui/error-codes/e0119/auxiliary/issue-23563-a.rs
similarity index 100%
rename from src/test/ui/e0119/auxiliary/issue-23563-a.rs
rename to src/test/ui/error-codes/e0119/auxiliary/issue-23563-a.rs
diff --git a/src/test/ui/e0119/complex-impl.rs b/src/test/ui/error-codes/e0119/complex-impl.rs
similarity index 100%
rename from src/test/ui/e0119/complex-impl.rs
rename to src/test/ui/error-codes/e0119/complex-impl.rs
diff --git a/src/test/ui/e0119/complex-impl.stderr b/src/test/ui/error-codes/e0119/complex-impl.stderr
similarity index 100%
rename from src/test/ui/e0119/complex-impl.stderr
rename to src/test/ui/error-codes/e0119/complex-impl.stderr
diff --git a/src/test/ui/e0119/conflict-with-std.rs b/src/test/ui/error-codes/e0119/conflict-with-std.rs
similarity index 100%
rename from src/test/ui/e0119/conflict-with-std.rs
rename to src/test/ui/error-codes/e0119/conflict-with-std.rs
diff --git a/src/test/ui/e0119/conflict-with-std.stderr b/src/test/ui/error-codes/e0119/conflict-with-std.stderr
similarity index 100%
rename from src/test/ui/e0119/conflict-with-std.stderr
rename to src/test/ui/error-codes/e0119/conflict-with-std.stderr
diff --git a/src/test/ui/e0119/issue-23563.rs b/src/test/ui/error-codes/e0119/issue-23563.rs
similarity index 100%
rename from src/test/ui/e0119/issue-23563.rs
rename to src/test/ui/error-codes/e0119/issue-23563.rs
diff --git a/src/test/ui/e0119/issue-23563.stderr b/src/test/ui/error-codes/e0119/issue-23563.stderr
similarity index 100%
rename from src/test/ui/e0119/issue-23563.stderr
rename to src/test/ui/error-codes/e0119/issue-23563.stderr
diff --git a/src/test/ui/e0119/issue-27403.rs b/src/test/ui/error-codes/e0119/issue-27403.rs
similarity index 100%
rename from src/test/ui/e0119/issue-27403.rs
rename to src/test/ui/error-codes/e0119/issue-27403.rs
diff --git a/src/test/ui/e0119/issue-27403.stderr b/src/test/ui/error-codes/e0119/issue-27403.stderr
similarity index 100%
rename from src/test/ui/e0119/issue-27403.stderr
rename to src/test/ui/error-codes/e0119/issue-27403.stderr
diff --git a/src/test/ui/e0119/issue-28981.rs b/src/test/ui/error-codes/e0119/issue-28981.rs
similarity index 100%
rename from src/test/ui/e0119/issue-28981.rs
rename to src/test/ui/error-codes/e0119/issue-28981.rs
diff --git a/src/test/ui/e0119/issue-28981.stderr b/src/test/ui/error-codes/e0119/issue-28981.stderr
similarity index 100%
rename from src/test/ui/e0119/issue-28981.stderr
rename to src/test/ui/error-codes/e0119/issue-28981.stderr
diff --git a/src/test/ui/e0119/so-37347311.rs b/src/test/ui/error-codes/e0119/so-37347311.rs
similarity index 100%
rename from src/test/ui/e0119/so-37347311.rs
rename to src/test/ui/error-codes/e0119/so-37347311.rs
diff --git a/src/test/ui/e0119/so-37347311.stderr b/src/test/ui/error-codes/e0119/so-37347311.stderr
similarity index 100%
rename from src/test/ui/e0119/so-37347311.stderr
rename to src/test/ui/error-codes/e0119/so-37347311.stderr
diff --git a/src/test/ui/auxiliary/issue-59764.rs b/src/test/ui/issues/auxiliary/issue-59764.rs
similarity index 100%
rename from src/test/ui/auxiliary/issue-59764.rs
rename to src/test/ui/issues/auxiliary/issue-59764.rs
diff --git a/src/test/ui/issue-59508-1.rs b/src/test/ui/issues/issue-59508-1.rs
similarity index 100%
rename from src/test/ui/issue-59508-1.rs
rename to src/test/ui/issues/issue-59508-1.rs
diff --git a/src/test/ui/issue-59508-1.stderr b/src/test/ui/issues/issue-59508-1.stderr
similarity index 100%
rename from src/test/ui/issue-59508-1.stderr
rename to src/test/ui/issues/issue-59508-1.stderr
diff --git a/src/test/ui/issue-59508.fixed b/src/test/ui/issues/issue-59508.fixed
similarity index 100%
rename from src/test/ui/issue-59508.fixed
rename to src/test/ui/issues/issue-59508.fixed
diff --git a/src/test/ui/issue-59508.rs b/src/test/ui/issues/issue-59508.rs
similarity index 100%
rename from src/test/ui/issue-59508.rs
rename to src/test/ui/issues/issue-59508.rs
diff --git a/src/test/ui/issue-59508.stderr b/src/test/ui/issues/issue-59508.stderr
similarity index 100%
rename from src/test/ui/issue-59508.stderr
rename to src/test/ui/issues/issue-59508.stderr
diff --git a/src/test/ui/issue-59756.fixed b/src/test/ui/issues/issue-59756.fixed
similarity index 100%
rename from src/test/ui/issue-59756.fixed
rename to src/test/ui/issues/issue-59756.fixed
diff --git a/src/test/ui/issue-59756.rs b/src/test/ui/issues/issue-59756.rs
similarity index 100%
rename from src/test/ui/issue-59756.rs
rename to src/test/ui/issues/issue-59756.rs
diff --git a/src/test/ui/issue-59756.stderr b/src/test/ui/issues/issue-59756.stderr
similarity index 100%
rename from src/test/ui/issue-59756.stderr
rename to src/test/ui/issues/issue-59756.stderr
diff --git a/src/test/ui/issue-59764.rs b/src/test/ui/issues/issue-59764.rs
similarity index 100%
rename from src/test/ui/issue-59764.rs
rename to src/test/ui/issues/issue-59764.rs
diff --git a/src/test/ui/issue-59764.stderr b/src/test/ui/issues/issue-59764.stderr
similarity index 100%
rename from src/test/ui/issue-59764.stderr
rename to src/test/ui/issues/issue-59764.stderr
diff --git a/src/test/ui/issue-60075.rs b/src/test/ui/issues/issue-60075.rs
similarity index 100%
rename from src/test/ui/issue-60075.rs
rename to src/test/ui/issues/issue-60075.rs
diff --git a/src/test/ui/issue-60075.stderr b/src/test/ui/issues/issue-60075.stderr
similarity index 100%
rename from src/test/ui/issue-60075.stderr
rename to src/test/ui/issues/issue-60075.stderr
diff --git a/src/test/ui/issue-60622.rs b/src/test/ui/issues/issue-60622.rs
similarity index 100%
rename from src/test/ui/issue-60622.rs
rename to src/test/ui/issues/issue-60622.rs
diff --git a/src/test/ui/issue-60622.stderr b/src/test/ui/issues/issue-60622.stderr
similarity index 100%
rename from src/test/ui/issue-60622.stderr
rename to src/test/ui/issues/issue-60622.stderr
diff --git a/src/test/ui/macros/format-parse-errors.stderr b/src/test/ui/macros/format-parse-errors.stderr
index b634cf2d9944c..fd4f93091944c 100644
--- a/src/test/ui/macros/format-parse-errors.stderr
+++ b/src/test/ui/macros/format-parse-errors.stderr
@@ -12,17 +12,17 @@ error: expected expression, found keyword `struct`
 LL |     format!(struct);
    |             ^^^^^^ expected expression
 
-error: expected expression, found `<eof>`
-  --> $DIR/format-parse-errors.rs:4:23
+error: expected expression, found end of macro arguments
+  --> $DIR/format-parse-errors.rs:4:24
    |
 LL |     format!("s", name =);
-   |                       ^ expected expression
+   |                        ^ expected expression
 
-error: expected `=`, found `<eof>`
-  --> $DIR/format-parse-errors.rs:5:29
+error: expected `=`, found end of macro arguments
+  --> $DIR/format-parse-errors.rs:5:32
    |
 LL |     format!("s", foo = foo, bar);
-   |                             ^^^ expected `=`
+   |                                ^ expected `=`
 
 error: expected expression, found keyword `struct`
   --> $DIR/format-parse-errors.rs:6:24
diff --git a/src/test/ui/malformed/malformed-derive-entry.rs b/src/test/ui/malformed/malformed-derive-entry.rs
index 74d22102c664d..36cc58f7e268e 100644
--- a/src/test/ui/malformed/malformed-derive-entry.rs
+++ b/src/test/ui/malformed/malformed-derive-entry.rs
@@ -1,17 +1,13 @@
-#[derive(Copy(Bad))]
-//~^ ERROR expected one of `)`, `,`, or `::`, found `(`
+#[derive(Copy(Bad))] //~ ERROR expected one of `)`, `,`, or `::`, found `(`
 struct Test1;
 
-#[derive(Copy="bad")]
-//~^ ERROR expected one of `)`, `,`, or `::`, found `=`
+#[derive(Copy="bad")] //~ ERROR expected one of `)`, `,`, or `::`, found `=`
 struct Test2;
 
-#[derive()]
-//~^ WARNING empty trait list
+#[derive()] //~ WARNING empty trait list
 struct Test3;
 
-#[derive]
-//~^ ERROR attribute must be of the form
+#[derive] //~ ERROR attribute must be of the form `#[derive(Trait1, Trait2, ...)]`
 struct Test4;
 
 fn main() {}
diff --git a/src/test/ui/malformed/malformed-derive-entry.stderr b/src/test/ui/malformed/malformed-derive-entry.stderr
index f546f74220a1c..0dc18f6811117 100644
--- a/src/test/ui/malformed/malformed-derive-entry.stderr
+++ b/src/test/ui/malformed/malformed-derive-entry.stderr
@@ -5,19 +5,19 @@ LL | #[derive(Copy(Bad))]
    |              ^ expected one of `)`, `,`, or `::` here
 
 error: expected one of `)`, `,`, or `::`, found `=`
-  --> $DIR/malformed-derive-entry.rs:5:14
+  --> $DIR/malformed-derive-entry.rs:4:14
    |
 LL | #[derive(Copy="bad")]
    |              ^ expected one of `)`, `,`, or `::` here
 
 warning: empty trait list in `derive`
-  --> $DIR/malformed-derive-entry.rs:9:1
+  --> $DIR/malformed-derive-entry.rs:7:1
    |
 LL | #[derive()]
    | ^^^^^^^^^^^
 
 error: attribute must be of the form `#[derive(Trait1, Trait2, ...)]`
-  --> $DIR/malformed-derive-entry.rs:13:1
+  --> $DIR/malformed-derive-entry.rs:10:1
    |
 LL | #[derive]
    | ^^^^^^^^^
diff --git a/src/test/ui/malformed/malformed-special-attrs.rs b/src/test/ui/malformed/malformed-special-attrs.rs
index f91c6bedb2b21..4d00755aea09d 100644
--- a/src/test/ui/malformed/malformed-special-attrs.rs
+++ b/src/test/ui/malformed/malformed-special-attrs.rs
@@ -1,4 +1,4 @@
-#[cfg_attr] //~ ERROR expected `(`, found `<eof>`
+#[cfg_attr] //~ ERROR expected `(`, found end of attribute
 struct S1;
 
 #[cfg_attr = ""] //~ ERROR expected `(`, found `=`
diff --git a/src/test/ui/malformed/malformed-special-attrs.stderr b/src/test/ui/malformed/malformed-special-attrs.stderr
index 8c23424087c04..a93f03589e383 100644
--- a/src/test/ui/malformed/malformed-special-attrs.stderr
+++ b/src/test/ui/malformed/malformed-special-attrs.stderr
@@ -1,13 +1,14 @@
-error: expected `(`, found `<eof>`
+error: expected `(`, found end of attribute
+  --> $DIR/malformed-special-attrs.rs:1:1
+   |
+LL | #[cfg_attr]
+   | ^ expected `(`
 
 error: expected `(`, found `=`
   --> $DIR/malformed-special-attrs.rs:4:12
    |
-LL | #[cfg_attr]
-   | - expected `(`
-...
 LL | #[cfg_attr = ""]
-   |            ^ unexpected token
+   |            ^ expected `(`
 
 error: attribute must be of the form `#[derive(Trait1, Trait2, ...)]`
   --> $DIR/malformed-special-attrs.rs:7:1
diff --git a/src/test/ui/parser/macro/bad-macro-argument.rs b/src/test/ui/parser/macro/bad-macro-argument.rs
new file mode 100644
index 0000000000000..4b6d23890653d
--- /dev/null
+++ b/src/test/ui/parser/macro/bad-macro-argument.rs
@@ -0,0 +1,4 @@
+fn main() {
+    let message = "world";
+    println!("Hello, {}", message/); //~ ERROR expected expression
+}
diff --git a/src/test/ui/parser/macro/bad-macro-argument.stderr b/src/test/ui/parser/macro/bad-macro-argument.stderr
new file mode 100644
index 0000000000000..3cd8accb66294
--- /dev/null
+++ b/src/test/ui/parser/macro/bad-macro-argument.stderr
@@ -0,0 +1,8 @@
+error: expected expression, found end of macro arguments
+  --> $DIR/bad-macro-argument.rs:3:35
+   |
+LL |     println!("Hello, {}", message/);
+   |                                   ^ expected expression
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/proc-macro/attr-invalid-exprs.rs b/src/test/ui/proc-macro/attr-invalid-exprs.rs
index c609cae90240c..fab98f0ce5ebe 100644
--- a/src/test/ui/proc-macro/attr-invalid-exprs.rs
+++ b/src/test/ui/proc-macro/attr-invalid-exprs.rs
@@ -9,7 +9,7 @@ use attr_stmt_expr::{duplicate, no_output};
 
 fn main() {
     let _ = #[no_output] "Hello, world!";
-    //~^ ERROR expected expression, found `<eof>`
+    //~^ ERROR expected expression, found end of macro arguments
 
     let _ = #[duplicate] "Hello, world!";
     //~^ ERROR macro expansion ignores token `,` and any following
diff --git a/src/test/ui/proc-macro/attr-invalid-exprs.stderr b/src/test/ui/proc-macro/attr-invalid-exprs.stderr
index 5d2fb59ff1f66..49fe0bd0fcfe2 100644
--- a/src/test/ui/proc-macro/attr-invalid-exprs.stderr
+++ b/src/test/ui/proc-macro/attr-invalid-exprs.stderr
@@ -1,4 +1,4 @@
-error: expected expression, found `<eof>`
+error: expected expression, found end of macro arguments
   --> $DIR/attr-invalid-exprs.rs:11:13
    |
 LL |     let _ = #[no_output] "Hello, world!";
diff --git a/src/test/ui/rfc1598-generic-associated-types/gat-dont-ice-on-absent-feature.rs b/src/test/ui/rfc1598-generic-associated-types/gat-dont-ice-on-absent-feature.rs
new file mode 100644
index 0000000000000..84fbb47301f04
--- /dev/null
+++ b/src/test/ui/rfc1598-generic-associated-types/gat-dont-ice-on-absent-feature.rs
@@ -0,0 +1,14 @@
+// rust-lang/rust#60654: Do not ICE on an attempt to use GATs that is
+// missing the feature gate.
+
+struct Foo;
+
+impl Iterator for Foo {
+    type Item<'b> = &'b Foo; //~ ERROR generic associated types are unstable [E0658]
+
+    fn next(&mut self) -> Option<Self::Item> {
+        None
+    }
+}
+
+fn main() { }
diff --git a/src/test/ui/rfc1598-generic-associated-types/gat-dont-ice-on-absent-feature.stderr b/src/test/ui/rfc1598-generic-associated-types/gat-dont-ice-on-absent-feature.stderr
new file mode 100644
index 0000000000000..27b1d73d0434a
--- /dev/null
+++ b/src/test/ui/rfc1598-generic-associated-types/gat-dont-ice-on-absent-feature.stderr
@@ -0,0 +1,12 @@
+error[E0658]: generic associated types are unstable
+  --> $DIR/gat-dont-ice-on-absent-feature.rs:7:5
+   |
+LL |     type Item<'b> = &'b Foo;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/44265
+   = help: add #![feature(generic_associated_types)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/tools/cargo b/src/tools/cargo
index c4fcfb725b4be..545f354259be4 160000
--- a/src/tools/cargo
+++ b/src/tools/cargo
@@ -1 +1 @@
-Subproject commit c4fcfb725b4be00c72eb9cf30c7d8b095577c280
+Subproject commit 545f354259be4e9745ea00a524c0e4c51df01aa6
diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs
index 8626ba060bf71..edef26e6b02c0 100644
--- a/src/tools/tidy/src/deps.rs
+++ b/src/tools/tidy/src/deps.rs
@@ -47,6 +47,9 @@ const EXCEPTIONS: &[&str] = &[
     "adler32",            // BSD-3-Clause AND Zlib, cargo dep that isn't used
     "fortanix-sgx-abi",   // MPL-2.0+, libstd but only for `sgx` target
     "constant_time_eq",   // CC0-1.0, rustfmt
+    "utf8parse",          // Apache-2.0 OR MIT, cargo via strip-ansi-escapes
+    "vte",                // Apache-2.0 OR MIT, cargo via strip-ansi-escapes
+    "sized-chunks",       // MPL-2.0+, cargo via im-rc
 ];
 
 /// Which crates to check against the whitelist?
@@ -241,7 +244,7 @@ pub fn check(path: &Path, bad: &mut bool) {
         }
 
         let toml = dir.path().join("Cargo.toml");
-        *bad = *bad || !check_license(&toml);
+        *bad = !check_license(&toml) || *bad;
     }
     assert!(saw_dir, "no vendored source");
 }