about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2020-07-01 14:45:56 +0000
committerbors <bors@rust-lang.org>2020-07-01 14:45:56 +0000
commitf781babf87dea29c44f93842b7ac9eb809549d29 (patch)
treefcb575eda0c6d0e786d9b42d1b6559b4865f3ff6
parent1505c1239554fd8c9a5f7a6f4823c7384a0c29e3 (diff)
parentc9b3e869771e7944719e139a327422726f7529de (diff)
downloadrust-f781babf87dea29c44f93842b7ac9eb809549d29.tar.gz
rust-f781babf87dea29c44f93842b7ac9eb809549d29.zip
Auto merge of #73924 - Manishearth:rollup-8r51ld9, r=Manishearth
Rollup of 17 pull requests

Successful merges:

 - #72071 (Added detailed error code explanation for issue E0687 in Rust compiler.)
 - #72369 (Bring net/parser.rs up to modern up to date with modern rust patterns)
 - #72445 (Stabilize `#[track_caller]`.)
 - #73466 (impl From<char> for String)
 - #73548 (remove rustdoc warnings)
 - #73649 (Fix sentence structure)
 - #73678 (Update Box::from_raw example to generalize better)
 - #73705 (stop taking references in Relate)
 - #73716 (Document the static keyword)
 - #73752 (Remap Windows ERROR_INVALID_PARAMETER to ErrorKind::InvalidInput from Other)
 - #73776 (Move terminator to new module)
 - #73778 (Make `likely` and `unlikely` const, gated by feature `const_unlikely`)
 - #73805 (Document the type keyword)
 - #73806 (Use an 'approximate' universal upper bound when reporting region errors)
 - #73828 (Fix wording for anonymous parameter name help)
 - #73846 (Fix comma in debug_assert! docs)
 - #73847 (Edit cursor.prev() method docs in lexer)

Failed merges:

r? @ghost
-rw-r--r--README.md21
-rw-r--r--src/doc/unstable-book/src/language-features/track-caller.md5
-rw-r--r--src/liballoc/boxed.rs5
-rw-r--r--src/liballoc/string.rs8
-rw-r--r--src/liballoc/tests/string.rs7
-rw-r--r--src/libcore/intrinsics.rs2
-rw-r--r--src/libcore/lib.rs3
-rw-r--r--src/libcore/macros/mod.rs4
-rw-r--r--src/libcore/panic.rs14
-rw-r--r--src/librustc_error_codes/error_codes.rs2
-rw-r--r--src/librustc_error_codes/error_codes/E0687.md36
-rw-r--r--src/librustc_error_codes/error_codes/E0736.md2
-rw-r--r--src/librustc_error_codes/error_codes/E0737.md2
-rw-r--r--src/librustc_error_codes/error_codes/E0739.md1
-rw-r--r--src/librustc_errors/lib.rs2
-rw-r--r--src/librustc_feature/accepted.rs3
-rw-r--r--src/librustc_feature/active.rs4
-rw-r--r--src/librustc_feature/builtin_attrs.rs2
-rw-r--r--src/librustc_infer/infer/at.rs18
-rw-r--r--src/librustc_infer/infer/canonical/query_response.rs8
-rw-r--r--src/librustc_infer/infer/combine.rs20
-rw-r--r--src/librustc_infer/infer/equate.rs10
-rw-r--r--src/librustc_infer/infer/glb.rs12
-rw-r--r--src/librustc_infer/infer/higher_ranked/mod.rs10
-rw-r--r--src/librustc_infer/infer/lub.rs14
-rw-r--r--src/librustc_infer/infer/nll_relate/mod.rs31
-rw-r--r--src/librustc_infer/infer/sub.rs8
-rw-r--r--src/librustc_lexer/src/cursor.rs4
-rw-r--r--src/librustc_lint/builtin.rs2
-rw-r--r--src/librustc_middle/ich/impls_ty.rs2
-rw-r--r--src/librustc_middle/lib.rs2
-rw-r--r--src/librustc_middle/mir/mod.rs494
-rw-r--r--src/librustc_middle/mir/terminator/mod.rs507
-rw-r--r--src/librustc_middle/ty/_match.rs8
-rw-r--r--src/librustc_middle/ty/error.rs9
-rw-r--r--src/librustc_middle/ty/flags.rs12
-rw-r--r--src/librustc_middle/ty/fold.rs8
-rw-r--r--src/librustc_middle/ty/layout.rs2
-rw-r--r--src/librustc_middle/ty/print/pretty.rs2
-rw-r--r--src/librustc_middle/ty/relate.rs226
-rw-r--r--src/librustc_middle/ty/structural_impls.rs5
-rw-r--r--src/librustc_middle/ty/sty.rs16
-rw-r--r--src/librustc_middle/ty/walk.rs2
-rw-r--r--src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs4
-rw-r--r--src/librustc_mir/borrow_check/diagnostics/region_errors.rs4
-rw-r--r--src/librustc_mir/borrow_check/region_infer/mod.rs34
-rw-r--r--src/librustc_mir/borrow_check/region_infer/opaque_types.rs3
-rw-r--r--src/librustc_mir/borrow_check/type_check/relate_tys.rs2
-rw-r--r--src/librustc_mir/interpret/intrinsics.rs4
-rw-r--r--src/librustc_mir/transform/check_consts/validation.rs7
-rw-r--r--src/librustc_mir/transform/qualify_min_const_fn.rs37
-rw-r--r--src/librustc_mir/transform/validate.rs10
-rw-r--r--src/librustc_mir_build/hair/pattern/_match.rs197
-rw-r--r--src/librustc_parse/parser/diagnostics.rs2
-rw-r--r--src/librustc_passes/intrinsicck.rs2
-rw-r--r--src/librustc_privacy/lib.rs10
-rw-r--r--src/librustc_span/symbol.rs2
-rw-r--r--src/librustc_symbol_mangling/v0.rs2
-rw-r--r--src/librustc_trait_selection/opaque_types.rs2
-rw-r--r--src/librustc_trait_selection/traits/error_reporting/mod.rs2
-rw-r--r--src/librustc_trait_selection/traits/error_reporting/on_unimplemented.rs4
-rw-r--r--src/librustc_trait_selection/traits/error_reporting/suggestions.rs4
-rw-r--r--src/librustc_trait_selection/traits/select/candidate_assembly.rs8
-rw-r--r--src/librustc_trait_selection/traits/select/confirmation.rs8
-rw-r--r--src/librustc_trait_selection/traits/select/mod.rs8
-rw-r--r--src/librustc_trait_selection/traits/wf.rs2
-rw-r--r--src/librustc_traits/chalk/lowering.rs4
-rw-r--r--src/librustc_typeck/astconv.rs4
-rw-r--r--src/librustc_typeck/check/closure.rs4
-rw-r--r--src/librustc_typeck/check/coercion.rs2
-rw-r--r--src/librustc_typeck/check/compare_method.rs2
-rw-r--r--src/librustc_typeck/check/dropck.rs16
-rw-r--r--src/librustc_typeck/check/method/suggest.rs2
-rw-r--r--src/librustc_typeck/check/mod.rs2
-rw-r--r--src/librustc_typeck/check/op.rs2
-rw-r--r--src/librustc_typeck/coherence/mod.rs2
-rw-r--r--src/librustc_typeck/collect.rs4
-rw-r--r--src/librustdoc/clean/mod.rs8
-rw-r--r--src/libstd/keyword_docs.rs118
-rw-r--r--src/libstd/lib.rs2
-rw-r--r--src/libstd/net/parser.rs482
-rw-r--r--src/libstd/sys/windows/mod.rs1
-rw-r--r--src/test/ui/anon-params/anon-params-denied-2018.stderr8
-rw-r--r--src/test/ui/asm/sym.rs2
-rw-r--r--src/test/ui/async-await/issue-67765-async-diagnostic.rs16
-rw-r--r--src/test/ui/async-await/issue-67765-async-diagnostic.stderr12
-rw-r--r--src/test/ui/feature-gates/feature-gate-track_caller.rs5
-rw-r--r--src/test/ui/feature-gates/feature-gate-track_caller.stderr12
-rw-r--r--src/test/ui/in-band-lifetimes/E0687.stderr1
-rw-r--r--src/test/ui/in-band-lifetimes/E0687_where.stderr1
-rw-r--r--src/test/ui/lifetimes/unnamed-closure-doesnt-life-long-enough-issue-67634.rs2
-rw-r--r--src/test/ui/lifetimes/unnamed-closure-doesnt-life-long-enough-issue-67634.stderr24
-rw-r--r--src/test/ui/macros/issue-68060.rs2
-rw-r--r--src/test/ui/macros/issue-68060.stderr6
-rw-r--r--src/test/ui/numbers-arithmetic/saturating-float-casts.rs1
-rw-r--r--src/test/ui/parser/inverted-parameters.rs2
-rw-r--r--src/test/ui/parser/inverted-parameters.stderr2
-rw-r--r--src/test/ui/parser/omitted-arg-in-item-fn.stderr2
-rw-r--r--src/test/ui/return-disjoint-regions.rs7
-rw-r--r--src/test/ui/return-disjoint-regions.stderr11
-rw-r--r--src/test/ui/rfc-2091-track-caller/call-chain.rs2
-rw-r--r--src/test/ui/rfc-2091-track-caller/caller-location-fnptr-rt-ctfe-equiv.rs2
-rw-r--r--src/test/ui/rfc-2091-track-caller/caller-location-intrinsic.rs6
-rw-r--r--src/test/ui/rfc-2091-track-caller/const-caller-location.rs2
-rw-r--r--src/test/ui/rfc-2091-track-caller/diverging-caller-location.rs2
-rw-r--r--src/test/ui/rfc-2091-track-caller/error-odd-syntax.rs2
-rw-r--r--src/test/ui/rfc-2091-track-caller/error-odd-syntax.stderr2
-rw-r--r--src/test/ui/rfc-2091-track-caller/error-with-invalid-abi.rs2
-rw-r--r--src/test/ui/rfc-2091-track-caller/error-with-invalid-abi.stderr4
-rw-r--r--src/test/ui/rfc-2091-track-caller/error-with-naked.rs2
-rw-r--r--src/test/ui/rfc-2091-track-caller/intrinsic-wrapper.rs6
-rw-r--r--src/test/ui/rfc-2091-track-caller/only-for-fns.rs2
-rw-r--r--src/test/ui/rfc-2091-track-caller/only-for-fns.stderr2
-rw-r--r--src/test/ui/rfc-2091-track-caller/pass.rs2
-rw-r--r--src/test/ui/rfc-2091-track-caller/track-caller-attribute.rs10
-rw-r--r--src/test/ui/rfc-2091-track-caller/track-caller-ffi.rs10
-rw-r--r--src/test/ui/rfc-2091-track-caller/tracked-fn-ptr-with-arg.rs2
-rw-r--r--src/test/ui/rfc-2091-track-caller/tracked-fn-ptr.rs2
-rw-r--r--src/test/ui/rfc-2091-track-caller/tracked-trait-impls.rs2
-rw-r--r--src/test/ui/rfc-2565-param-attrs/param-attrs-2018.stderr2
-rw-r--r--src/test/ui/span/issue-34264.stderr4
121 files changed, 1520 insertions, 1234 deletions
diff --git a/README.md b/README.md
index 42fc0a63c0f..c2ded10f05a 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,9 @@
-# The Rust Programming Language
+<a href = "https://www.rust-lang.org/"> 
+<img width = "90%" height = "auto" src = "https://img.shields.io/badge/Rust-Programming%20Language-black?style=flat&logo=rust" alt = "The Rust Programming Language">
+</a>
 
 This is the main source code repository for [Rust]. It contains the compiler,
-standard library, and documentation.
+standard library, and documentation. 
 
 [Rust]: https://www.rust-lang.org
 
@@ -17,9 +19,9 @@ Read ["Installation"] from [The Book].
 _Note: If you wish to contribute to the compiler, you should read [this
 chapter][rustcguidebuild] of the rustc-dev-guide instead of this section._
 
-The Rust build system has a Python script called `x.py` to bootstrap building
-the compiler. More information about it may be found by running `./x.py --help`
-or reading the [rustc dev guide][rustcguidebuild].
+The Rust build system uses a Python script called `x.py` to build the compiler,
+which manages the bootstrapping process. More information about it can be found 
+by running `./x.py --help` or reading the [rustc dev guide][rustcguidebuild].
 
 [rustcguidebuild]: https://rustc-dev-guide.rust-lang.org/building/how-to-build-and-run.html
 
@@ -54,9 +56,8 @@ or reading the [rustc dev guide][rustcguidebuild].
     $ cp config.toml.example config.toml
     ```
 
-    It is recommended that if you plan to use the Rust build system to create
-    an installation (using `./x.py install`) that you set the `prefix` value
-    in the `[install]` section to a directory that you have write permissions.
+    If you plan to use `x.py install` to create an installation, it is recommended
+    that you set the `prefix` value in the `[install]` section to a directory.
 
     Create install directory if you are not installing in default directory
 
@@ -143,8 +144,8 @@ shell with:
 ```
 
 Currently, building Rust only works with some known versions of Visual Studio. If
-you have a more recent version installed the build system doesn't understand
-then you may need to force rustbuild to use an older version. This can be done
+you have a more recent version installed and the build system doesn't understand,
+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
diff --git a/src/doc/unstable-book/src/language-features/track-caller.md b/src/doc/unstable-book/src/language-features/track-caller.md
deleted file mode 100644
index afc11a2b949..00000000000
--- a/src/doc/unstable-book/src/language-features/track-caller.md
+++ /dev/null
@@ -1,5 +0,0 @@
-# `track_caller`
-
-The tracking issue for this feature is: [#47809](https://github.com/rust-lang/rust/issues/47809).
-
-------------------------
diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs
index f1b560b9b96..3320ebdf821 100644
--- a/src/liballoc/boxed.rs
+++ b/src/liballoc/boxed.rs
@@ -384,7 +384,10 @@ impl<T: ?Sized> Box<T> {
     ///
     /// unsafe {
     ///     let ptr = alloc(Layout::new::<i32>()) as *mut i32;
-    ///     *ptr = 5;
+    ///     // In general .write is required to avoid attempting to destruct
+    ///     // the (uninitialized) previous contents of `ptr`, though for this
+    ///     // simple example `*ptr = 5` would have worked as well.
+    ///     ptr.write(5);
     ///     let x = Box::from_raw(ptr);
     /// }
     /// ```
diff --git a/src/liballoc/string.rs b/src/liballoc/string.rs
index 64d9692244d..13ef94dee23 100644
--- a/src/liballoc/string.rs
+++ b/src/liballoc/string.rs
@@ -2518,3 +2518,11 @@ impl DoubleEndedIterator for Drain<'_> {
 
 #[stable(feature = "fused", since = "1.26.0")]
 impl FusedIterator for Drain<'_> {}
+
+#[stable(feature = "from_char_for_string", since = "1.46.0")]
+impl From<char> for String {
+    #[inline]
+    fn from(c: char) -> Self {
+        c.to_string()
+    }
+}
diff --git a/src/liballoc/tests/string.rs b/src/liballoc/tests/string.rs
index 9ea020d2d19..d38655af78c 100644
--- a/src/liballoc/tests/string.rs
+++ b/src/liballoc/tests/string.rs
@@ -714,3 +714,10 @@ fn test_try_reserve_exact() {
         }
     }
 }
+
+#[test]
+fn test_from_char() {
+    assert_eq!(String::from('a'), 'a'.to_string());
+    let s: String = 'x'.into();
+    assert_eq!(s, 'x'.to_string());
+}
diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs
index 5d090187591..57ffed19c00 100644
--- a/src/libcore/intrinsics.rs
+++ b/src/libcore/intrinsics.rs
@@ -952,6 +952,7 @@ extern "rust-intrinsic" {
     /// Any use other than with `if` statements will probably not have an effect.
     ///
     /// This intrinsic does not have a stable counterpart.
+    #[rustc_const_unstable(feature = "const_likely", issue = "none")]
     pub fn likely(b: bool) -> bool;
 
     /// Hints to the compiler that branch condition is likely to be false.
@@ -960,6 +961,7 @@ extern "rust-intrinsic" {
     /// Any use other than with `if` statements will probably not have an effect.
     ///
     /// This intrinsic does not have a stable counterpart.
+    #[rustc_const_unstable(feature = "const_likely", issue = "none")]
     pub fn unlikely(b: bool) -> bool;
 
     /// Executes a breakpoint trap, for inspection by a debugger.
diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs
index aeb52bffbf2..63ddd97eed3 100644
--- a/src/libcore/lib.rs
+++ b/src/libcore/lib.rs
@@ -92,6 +92,7 @@
 #![feature(const_slice_from_raw_parts)]
 #![feature(const_slice_ptr_len)]
 #![feature(const_type_name)]
+#![feature(const_likely)]
 #![feature(custom_inner_attributes)]
 #![feature(decl_macro)]
 #![feature(doc_cfg)]
@@ -118,7 +119,7 @@
 #![feature(staged_api)]
 #![feature(std_internals)]
 #![feature(stmt_expr_attributes)]
-#![feature(track_caller)]
+#![cfg_attr(bootstrap, feature(track_caller))]
 #![feature(transparent_unions)]
 #![feature(unboxed_closures)]
 #![feature(unsized_locals)]
diff --git a/src/libcore/macros/mod.rs b/src/libcore/macros/mod.rs
index 3cfdde60135..17f7349bac2 100644
--- a/src/libcore/macros/mod.rs
+++ b/src/libcore/macros/mod.rs
@@ -1,6 +1,6 @@
 #[doc(include = "panic.md")]
 #[macro_export]
-#[allow_internal_unstable(core_panic, track_caller)]
+#[allow_internal_unstable(core_panic, const_caller_location)]
 #[stable(feature = "core", since = "1.6.0")]
 macro_rules! panic {
     () => (
@@ -151,7 +151,7 @@ macro_rules! assert_ne {
 /// An unchecked assertion allows a program in an inconsistent state to keep
 /// running, which might have unexpected consequences but does not introduce
 /// unsafety as long as this only happens in safe code. The performance cost
-/// of assertions, is however, not measurable in general. Replacing [`assert!`]
+/// of assertions, however, is not measurable in general. Replacing [`assert!`]
 /// with `debug_assert!` is thus only encouraged after thorough profiling, and
 /// more importantly, only in safe code!
 ///
diff --git a/src/libcore/panic.rs b/src/libcore/panic.rs
index c7009b76e81..543aa969330 100644
--- a/src/libcore/panic.rs
+++ b/src/libcore/panic.rs
@@ -190,7 +190,6 @@ impl<'a> Location<'a> {
     /// # Examples
     ///
     /// ```
-    /// #![feature(track_caller)]
     /// use core::panic::Location;
     ///
     /// /// Returns the [`Location`] at which it is called.
@@ -206,7 +205,7 @@ impl<'a> Location<'a> {
     ///
     /// let fixed_location = get_just_one_location();
     /// assert_eq!(fixed_location.file(), file!());
-    /// assert_eq!(fixed_location.line(), 15);
+    /// assert_eq!(fixed_location.line(), 14);
     /// assert_eq!(fixed_location.column(), 5);
     ///
     /// // running the same untracked function in a different location gives us the same result
@@ -217,7 +216,7 @@ impl<'a> Location<'a> {
     ///
     /// let this_location = get_caller_location();
     /// assert_eq!(this_location.file(), file!());
-    /// assert_eq!(this_location.line(), 29);
+    /// assert_eq!(this_location.line(), 28);
     /// assert_eq!(this_location.column(), 21);
     ///
     /// // running the tracked function in a different location produces a different value
@@ -226,13 +225,8 @@ impl<'a> Location<'a> {
     /// assert_ne!(this_location.line(), another_location.line());
     /// assert_ne!(this_location.column(), another_location.column());
     /// ```
-    // FIXME: When stabilizing this method, please also update the documentation
-    // of `intrinsics::caller_location`.
-    #[unstable(
-        feature = "track_caller",
-        reason = "uses #[track_caller] which is not yet stable",
-        issue = "47809"
-    )]
+    #[stable(feature = "track_caller", since = "1.46.0")]
+    #[rustc_const_unstable(feature = "const_caller_location", issue = "47809")]
     #[track_caller]
     pub const fn caller() -> &'static Location<'static> {
         crate::intrinsics::caller_location()
diff --git a/src/librustc_error_codes/error_codes.rs b/src/librustc_error_codes/error_codes.rs
index 162585360fb..a5527158aab 100644
--- a/src/librustc_error_codes/error_codes.rs
+++ b/src/librustc_error_codes/error_codes.rs
@@ -382,6 +382,7 @@ E0668: include_str!("./error_codes/E0668.md"),
 E0669: include_str!("./error_codes/E0669.md"),
 E0670: include_str!("./error_codes/E0670.md"),
 E0671: include_str!("./error_codes/E0671.md"),
+E0687: include_str!("./error_codes/E0687.md"),
 E0689: include_str!("./error_codes/E0689.md"),
 E0690: include_str!("./error_codes/E0690.md"),
 E0691: include_str!("./error_codes/E0691.md"),
@@ -613,7 +614,6 @@ E0766: include_str!("./error_codes/E0766.md"),
     E0640, // infer outlives requirements
 //  E0645, // trait aliases not finished
     E0667, // `impl Trait` in projections
-    E0687, // in-band lifetimes cannot be used in `fn`/`Fn` syntax
     E0688, // in-band lifetimes cannot be mixed with explicit lifetime binders
 //  E0694, // an unknown tool name found in scoped attributes
 //  E0702, // replaced with a generic attribute input check
diff --git a/src/librustc_error_codes/error_codes/E0687.md b/src/librustc_error_codes/error_codes/E0687.md
new file mode 100644
index 00000000000..67b7db2d31f
--- /dev/null
+++ b/src/librustc_error_codes/error_codes/E0687.md
@@ -0,0 +1,36 @@
+In-band lifetimes cannot be used in `fn`/`Fn` syntax.
+
+Erroneous code examples:
+
+```compile_fail,E0687
+#![feature(in_band_lifetimes)]
+
+fn foo(x: fn(&'a u32)) {} // error!
+
+fn bar(x: &Fn(&'a u32)) {} // error!
+
+fn baz(x: fn(&'a u32), y: &'a u32) {} // error!
+
+struct Foo<'a> { x: &'a u32 }
+
+impl Foo<'a> {
+    fn bar(&self, x: fn(&'a u32)) {} // error!
+}
+```
+
+Lifetimes used in `fn` or `Fn` syntax must be explicitly
+declared using `<...>` binders. For example:
+
+```
+fn foo<'a>(x: fn(&'a u32)) {} // ok!
+
+fn bar<'a>(x: &Fn(&'a u32)) {} // ok!
+
+fn baz<'a>(x: fn(&'a u32), y: &'a u32) {} // ok!
+
+struct Foo<'a> { x: &'a u32 }
+
+impl<'a> Foo<'a> {
+    fn bar(&self, x: fn(&'a u32)) {} // ok!
+}
+```
diff --git a/src/librustc_error_codes/error_codes/E0736.md b/src/librustc_error_codes/error_codes/E0736.md
index 8a60dc32059..0f3d41ba66d 100644
--- a/src/librustc_error_codes/error_codes/E0736.md
+++ b/src/librustc_error_codes/error_codes/E0736.md
@@ -3,8 +3,6 @@
 Erroneous code example:
 
 ```compile_fail,E0736
-#![feature(track_caller)]
-
 #[naked]
 #[track_caller]
 fn foo() {}
diff --git a/src/librustc_error_codes/error_codes/E0737.md b/src/librustc_error_codes/error_codes/E0737.md
index c6553e97b7e..ab5e60692b4 100644
--- a/src/librustc_error_codes/error_codes/E0737.md
+++ b/src/librustc_error_codes/error_codes/E0737.md
@@ -5,8 +5,6 @@ restrictions.
 Erroneous code example:
 
 ```compile_fail,E0737
-#![feature(track_caller)]
-
 #[track_caller]
 extern "C" fn foo() {}
 ```
diff --git a/src/librustc_error_codes/error_codes/E0739.md b/src/librustc_error_codes/error_codes/E0739.md
index 707751066ed..8d9039bef93 100644
--- a/src/librustc_error_codes/error_codes/E0739.md
+++ b/src/librustc_error_codes/error_codes/E0739.md
@@ -3,7 +3,6 @@
 Erroneous code example:
 
 ```compile_fail,E0739
-#![feature(track_caller)]
 #[track_caller]
 struct Bar {
     a: u8,
diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs
index 0c1418d3cad..362913ceadf 100644
--- a/src/librustc_errors/lib.rs
+++ b/src/librustc_errors/lib.rs
@@ -5,7 +5,7 @@
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
 #![feature(crate_visibility_modifier)]
 #![feature(nll)]
-#![feature(track_caller)]
+#![cfg_attr(bootstrap, feature(track_caller))]
 
 pub use emitter::ColorConfig;
 
diff --git a/src/librustc_feature/accepted.rs b/src/librustc_feature/accepted.rs
index b164b21913d..d93c17b05b4 100644
--- a/src/librustc_feature/accepted.rs
+++ b/src/librustc_feature/accepted.rs
@@ -265,6 +265,9 @@ declare_features! (
     (accepted, const_if_match, "1.45.0", Some(49146), None),
     /// Allows the use of `loop` and `while` in constants.
     (accepted, const_loop, "1.45.0", Some(52000), None),
+    /// Allows `#[track_caller]` to be used which provides
+    /// accurate caller location reporting during panic (RFC 2091).
+    (accepted, track_caller, "1.46.0", Some(47809), None),
 
     // -------------------------------------------------------------------------
     // feature-group-end: accepted features
diff --git a/src/librustc_feature/active.rs b/src/librustc_feature/active.rs
index 8660d6a8d64..b9a55377949 100644
--- a/src/librustc_feature/active.rs
+++ b/src/librustc_feature/active.rs
@@ -494,10 +494,6 @@ declare_features! (
     /// Allows the use of raw-dylibs (RFC 2627).
     (active, raw_dylib, "1.40.0", Some(58713), None),
 
-    /// Allows `#[track_caller]` to be used which provides
-    /// accurate caller location reporting during panic (RFC 2091).
-    (active, track_caller, "1.40.0", Some(47809), None),
-
     /// Allows making `dyn Trait` well-formed even if `Trait` is not object safe.
     /// In that case, `dyn Trait: Trait` does not hold. Moreover, coercions and
     /// casts in safe Rust to `dyn Trait` for such a `Trait` is also forbidden.
diff --git a/src/librustc_feature/builtin_attrs.rs b/src/librustc_feature/builtin_attrs.rs
index 524a3579710..c9a34f03375 100644
--- a/src/librustc_feature/builtin_attrs.rs
+++ b/src/librustc_feature/builtin_attrs.rs
@@ -260,6 +260,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
     ungated!(cold, Whitelisted, template!(Word)),
     ungated!(no_builtins, Whitelisted, template!(Word)),
     ungated!(target_feature, Whitelisted, template!(List: r#"enable = "name""#)),
+    ungated!(track_caller, Whitelisted, template!(Word)),
     gated!(
         no_sanitize, Whitelisted,
         template!(List: "address, memory, thread"),
@@ -333,7 +334,6 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
     gated!(ffi_returns_twice, Whitelisted, template!(Word), experimental!(ffi_returns_twice)),
     gated!(ffi_pure, Whitelisted, template!(Word), experimental!(ffi_pure)),
     gated!(ffi_const, Whitelisted, template!(Word), experimental!(ffi_const)),
-    gated!(track_caller, Whitelisted, template!(Word), experimental!(track_caller)),
     gated!(
         register_attr, CrateLevel, template!(List: "attr1, attr2, ..."),
         experimental!(register_attr),
diff --git a/src/librustc_infer/infer/at.rs b/src/librustc_infer/infer/at.rs
index d44b8f55414..a7749d33b7c 100644
--- a/src/librustc_infer/infer/at.rs
+++ b/src/librustc_infer/infer/at.rs
@@ -82,7 +82,7 @@ impl<'a, 'tcx> At<'a, 'tcx> {
     where
         T: ToTrace<'tcx>,
     {
-        self.trace_exp(a_is_expected, a, b).sub(&a, &b)
+        self.trace_exp(a_is_expected, a, b).sub(a, b)
     }
 
     /// Makes `actual <: expected`. For example, if type-checking a
@@ -109,7 +109,7 @@ impl<'a, 'tcx> At<'a, 'tcx> {
     where
         T: ToTrace<'tcx>,
     {
-        self.trace_exp(a_is_expected, a, b).eq(&a, &b)
+        self.trace_exp(a_is_expected, a, b).eq(a, b)
     }
 
     /// Makes `expected <: actual`.
@@ -117,7 +117,7 @@ impl<'a, 'tcx> At<'a, 'tcx> {
     where
         T: ToTrace<'tcx>,
     {
-        self.trace(expected, actual).eq(&expected, &actual)
+        self.trace(expected, actual).eq(expected, actual)
     }
 
     pub fn relate<T>(self, expected: T, variance: ty::Variance, actual: T) -> InferResult<'tcx, ()>
@@ -147,7 +147,7 @@ impl<'a, 'tcx> At<'a, 'tcx> {
     where
         T: ToTrace<'tcx>,
     {
-        self.trace(expected, actual).lub(&expected, &actual)
+        self.trace(expected, actual).lub(expected, actual)
     }
 
     /// Computes the greatest-lower-bound, or mutual subtype, of two
@@ -157,7 +157,7 @@ impl<'a, 'tcx> At<'a, 'tcx> {
     where
         T: ToTrace<'tcx>,
     {
-        self.trace(expected, actual).glb(&expected, &actual)
+        self.trace(expected, actual).glb(expected, actual)
     }
 
     /// Sets the "trace" values that will be used for
@@ -186,7 +186,7 @@ impl<'a, 'tcx> At<'a, 'tcx> {
 impl<'a, 'tcx> Trace<'a, 'tcx> {
     /// Makes `a <: b` where `a` may or may not be expected (if
     /// `a_is_expected` is true, then `a` is expected).
-    pub fn sub<T>(self, a: &T, b: &T) -> InferResult<'tcx, ()>
+    pub fn sub<T>(self, a: T, b: T) -> InferResult<'tcx, ()>
     where
         T: Relate<'tcx>,
     {
@@ -203,7 +203,7 @@ impl<'a, 'tcx> Trace<'a, 'tcx> {
 
     /// Makes `a == b`; the expectation is set by the call to
     /// `trace()`.
-    pub fn eq<T>(self, a: &T, b: &T) -> InferResult<'tcx, ()>
+    pub fn eq<T>(self, a: T, b: T) -> InferResult<'tcx, ()>
     where
         T: Relate<'tcx>,
     {
@@ -218,7 +218,7 @@ impl<'a, 'tcx> Trace<'a, 'tcx> {
         })
     }
 
-    pub fn lub<T>(self, a: &T, b: &T) -> InferResult<'tcx, T>
+    pub fn lub<T>(self, a: T, b: T) -> InferResult<'tcx, T>
     where
         T: Relate<'tcx>,
     {
@@ -233,7 +233,7 @@ impl<'a, 'tcx> Trace<'a, 'tcx> {
         })
     }
 
-    pub fn glb<T>(self, a: &T, b: &T) -> InferResult<'tcx, T>
+    pub fn glb<T>(self, a: T, b: T) -> InferResult<'tcx, T>
     where
         T: Relate<'tcx>,
     {
diff --git a/src/librustc_infer/infer/canonical/query_response.rs b/src/librustc_infer/infer/canonical/query_response.rs
index 8af526e3ad3..5cba581b9df 100644
--- a/src/librustc_infer/infer/canonical/query_response.rs
+++ b/src/librustc_infer/infer/canonical/query_response.rs
@@ -271,7 +271,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
                         },
                         ty::Variance::Invariant,
                     )
-                    .relate(&v1, &v2)?;
+                    .relate(v1, v2)?;
                 }
 
                 (GenericArgKind::Const(v1), GenericArgKind::Const(v2)) => {
@@ -285,7 +285,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
                         },
                         ty::Variance::Invariant,
                     )
-                    .relate(&v1, &v2)?;
+                    .relate(v1, v2)?;
                 }
 
                 _ => {
@@ -302,7 +302,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
                 // Screen out `'a: 'a` cases -- we skip the binder here but
                 // only compare the inner values to one another, so they are still at
                 // consistent binding levels.
-                let &ty::OutlivesPredicate(k1, r2) = r_c.skip_binder();
+                let ty::OutlivesPredicate(k1, r2) = r_c.skip_binder();
                 if k1 != r2.into() { Some(r_c) } else { None }
             }),
         );
@@ -526,7 +526,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
     ) -> impl Iterator<Item = PredicateObligation<'tcx>> + 'a + Captures<'tcx> {
         unsubstituted_region_constraints.iter().map(move |constraint| {
             let constraint = substitute_value(self.tcx, result_subst, constraint);
-            let &ty::OutlivesPredicate(k1, r2) = constraint.skip_binder(); // restored below
+            let ty::OutlivesPredicate(k1, r2) = constraint.skip_binder(); // restored below
 
             Obligation::new(
                 cause.clone(),
diff --git a/src/librustc_infer/infer/combine.rs b/src/librustc_infer/infer/combine.rs
index 4ef4ed47cb1..c8d4e9f0e14 100644
--- a/src/librustc_infer/infer/combine.rs
+++ b/src/librustc_infer/infer/combine.rs
@@ -318,10 +318,10 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> {
         // to associate causes/spans with each of the relations in
         // the stack to get this right.
         match dir {
-            EqTo => self.equate(a_is_expected).relate(&a_ty, &b_ty),
-            SubtypeOf => self.sub(a_is_expected).relate(&a_ty, &b_ty),
+            EqTo => self.equate(a_is_expected).relate(a_ty, b_ty),
+            SubtypeOf => self.sub(a_is_expected).relate(a_ty, b_ty),
             SupertypeOf => {
-                self.sub(a_is_expected).relate_with_variance(ty::Contravariant, &a_ty, &b_ty)
+                self.sub(a_is_expected).relate_with_variance(ty::Contravariant, a_ty, b_ty)
             }
         }?;
 
@@ -379,7 +379,7 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> {
             param_env: self.param_env,
         };
 
-        let ty = match generalize.relate(&ty, &ty) {
+        let ty = match generalize.relate(ty, ty) {
             Ok(ty) => ty,
             Err(e) => {
                 debug!("generalize: failure {:?}", e);
@@ -490,8 +490,8 @@ impl TypeRelation<'tcx> for Generalizer<'_, 'tcx> {
 
     fn binders<T>(
         &mut self,
-        a: &ty::Binder<T>,
-        b: &ty::Binder<T>,
+        a: ty::Binder<T>,
+        b: ty::Binder<T>,
     ) -> RelateResult<'tcx, ty::Binder<T>>
     where
         T: Relate<'tcx>,
@@ -519,8 +519,8 @@ impl TypeRelation<'tcx> for Generalizer<'_, 'tcx> {
     fn relate_with_variance<T: Relate<'tcx>>(
         &mut self,
         variance: ty::Variance,
-        a: &T,
-        b: &T,
+        a: T,
+        b: T,
     ) -> RelateResult<'tcx, T> {
         let old_ambient_variance = self.ambient_variance;
         self.ambient_variance = self.ambient_variance.xform(variance);
@@ -552,7 +552,7 @@ impl TypeRelation<'tcx> for Generalizer<'_, 'tcx> {
                     match probe {
                         TypeVariableValue::Known { value: u } => {
                             debug!("generalize: known value {:?}", u);
-                            self.relate(&u, &u)
+                            self.relate(u, u)
                         }
                         TypeVariableValue::Unknown { universe } => {
                             match self.ambient_variance {
@@ -655,7 +655,7 @@ impl TypeRelation<'tcx> for Generalizer<'_, 'tcx> {
                 let variable_table = &mut inner.const_unification_table();
                 let var_value = variable_table.probe_value(vid);
                 match var_value.val {
-                    ConstVariableValue::Known { value: u } => self.relate(&u, &u),
+                    ConstVariableValue::Known { value: u } => self.relate(u, u),
                     ConstVariableValue::Unknown { universe } => {
                         if self.for_universe.can_name(universe) {
                             Ok(c)
diff --git a/src/librustc_infer/infer/equate.rs b/src/librustc_infer/infer/equate.rs
index e3cafb82719..7de752d1de0 100644
--- a/src/librustc_infer/infer/equate.rs
+++ b/src/librustc_infer/infer/equate.rs
@@ -59,8 +59,8 @@ impl TypeRelation<'tcx> for Equate<'combine, 'infcx, 'tcx> {
     fn relate_with_variance<T: Relate<'tcx>>(
         &mut self,
         _: ty::Variance,
-        a: &T,
-        b: &T,
+        a: T,
+        b: T,
     ) -> RelateResult<'tcx, T> {
         self.relate(a, b)
     }
@@ -124,8 +124,8 @@ impl TypeRelation<'tcx> for Equate<'combine, 'infcx, 'tcx> {
 
     fn binders<T>(
         &mut self,
-        a: &ty::Binder<T>,
-        b: &ty::Binder<T>,
+        a: ty::Binder<T>,
+        b: ty::Binder<T>,
     ) -> RelateResult<'tcx, ty::Binder<T>>
     where
         T: Relate<'tcx>,
@@ -136,7 +136,7 @@ impl TypeRelation<'tcx> for Equate<'combine, 'infcx, 'tcx> {
         } else {
             // Fast path for the common case.
             self.relate(a.skip_binder(), b.skip_binder())?;
-            Ok(a.clone())
+            Ok(a)
         }
     }
 }
diff --git a/src/librustc_infer/infer/glb.rs b/src/librustc_infer/infer/glb.rs
index ec219a95b94..8a0ab52f383 100644
--- a/src/librustc_infer/infer/glb.rs
+++ b/src/librustc_infer/infer/glb.rs
@@ -43,8 +43,8 @@ impl TypeRelation<'tcx> for Glb<'combine, 'infcx, 'tcx> {
     fn relate_with_variance<T: Relate<'tcx>>(
         &mut self,
         variance: ty::Variance,
-        a: &T,
-        b: &T,
+        a: T,
+        b: T,
     ) -> RelateResult<'tcx, T> {
         match variance {
             ty::Invariant => self.fields.equate(self.a_is_expected).relate(a, b),
@@ -85,8 +85,8 @@ impl TypeRelation<'tcx> for Glb<'combine, 'infcx, 'tcx> {
 
     fn binders<T>(
         &mut self,
-        a: &ty::Binder<T>,
-        b: &ty::Binder<T>,
+        a: ty::Binder<T>,
+        b: ty::Binder<T>,
     ) -> RelateResult<'tcx, ty::Binder<T>>
     where
         T: Relate<'tcx>,
@@ -112,8 +112,8 @@ impl<'combine, 'infcx, 'tcx> LatticeDir<'infcx, 'tcx> for Glb<'combine, 'infcx,
 
     fn relate_bound(&mut self, v: Ty<'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, ()> {
         let mut sub = self.fields.sub(self.a_is_expected);
-        sub.relate(&v, &a)?;
-        sub.relate(&v, &b)?;
+        sub.relate(v, a)?;
+        sub.relate(v, b)?;
         Ok(())
     }
 }
diff --git a/src/librustc_infer/infer/higher_ranked/mod.rs b/src/librustc_infer/infer/higher_ranked/mod.rs
index b6251e34008..ea19dff7db1 100644
--- a/src/librustc_infer/infer/higher_ranked/mod.rs
+++ b/src/librustc_infer/infer/higher_ranked/mod.rs
@@ -11,8 +11,8 @@ use rustc_middle::ty::{self, Binder, TypeFoldable};
 impl<'a, 'tcx> CombineFields<'a, 'tcx> {
     pub fn higher_ranked_sub<T>(
         &mut self,
-        a: &Binder<T>,
-        b: &Binder<T>,
+        a: Binder<T>,
+        b: Binder<T>,
         a_is_expected: bool,
     ) -> RelateResult<'tcx, Binder<T>>
     where
@@ -33,20 +33,20 @@ impl<'a, 'tcx> CombineFields<'a, 'tcx> {
         self.infcx.commit_if_ok(|_| {
             // First, we instantiate each bound region in the supertype with a
             // fresh placeholder region.
-            let (b_prime, _) = self.infcx.replace_bound_vars_with_placeholders(b);
+            let (b_prime, _) = self.infcx.replace_bound_vars_with_placeholders(&b);
 
             // Next, we instantiate each bound region in the subtype
             // with a fresh region variable. These region variables --
             // but no other pre-existing region variables -- can name
             // the placeholders.
             let (a_prime, _) =
-                self.infcx.replace_bound_vars_with_fresh_vars(span, HigherRankedType, a);
+                self.infcx.replace_bound_vars_with_fresh_vars(span, HigherRankedType, &a);
 
             debug!("a_prime={:?}", a_prime);
             debug!("b_prime={:?}", b_prime);
 
             // Compare types now that bound regions have been replaced.
-            let result = self.sub(a_is_expected).relate(&a_prime, &b_prime)?;
+            let result = self.sub(a_is_expected).relate(a_prime, b_prime)?;
 
             debug!("higher_ranked_sub: OK result={:?}", result);
 
diff --git a/src/librustc_infer/infer/lub.rs b/src/librustc_infer/infer/lub.rs
index a0453db2cb4..3e2ea3d0f8f 100644
--- a/src/librustc_infer/infer/lub.rs
+++ b/src/librustc_infer/infer/lub.rs
@@ -43,8 +43,8 @@ impl TypeRelation<'tcx> for Lub<'combine, 'infcx, 'tcx> {
     fn relate_with_variance<T: Relate<'tcx>>(
         &mut self,
         variance: ty::Variance,
-        a: &T,
-        b: &T,
+        a: T,
+        b: T,
     ) -> RelateResult<'tcx, T> {
         match variance {
             ty::Invariant => self.fields.equate(self.a_is_expected).relate(a, b),
@@ -85,8 +85,8 @@ impl TypeRelation<'tcx> for Lub<'combine, 'infcx, 'tcx> {
 
     fn binders<T>(
         &mut self,
-        a: &ty::Binder<T>,
-        b: &ty::Binder<T>,
+        a: ty::Binder<T>,
+        b: ty::Binder<T>,
     ) -> RelateResult<'tcx, ty::Binder<T>>
     where
         T: Relate<'tcx>,
@@ -97,7 +97,7 @@ impl TypeRelation<'tcx> for Lub<'combine, 'infcx, 'tcx> {
         // very challenging, switch to invariance. This is obviously
         // overly conservative but works ok in practice.
         self.relate_with_variance(ty::Variance::Invariant, a, b)?;
-        Ok(a.clone())
+        Ok(a)
     }
 }
 
@@ -118,8 +118,8 @@ impl<'combine, 'infcx, 'tcx> LatticeDir<'infcx, 'tcx> for Lub<'combine, 'infcx,
 
     fn relate_bound(&mut self, v: Ty<'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, ()> {
         let mut sub = self.fields.sub(self.a_is_expected);
-        sub.relate(&a, &v)?;
-        sub.relate(&b, &v)?;
+        sub.relate(a, v)?;
+        sub.relate(b, v)?;
         Ok(())
     }
 }
diff --git a/src/librustc_infer/infer/nll_relate/mod.rs b/src/librustc_infer/infer/nll_relate/mod.rs
index 2350c28dfaa..cb1f1c08d88 100644
--- a/src/librustc_infer/infer/nll_relate/mod.rs
+++ b/src/librustc_infer/infer/nll_relate/mod.rs
@@ -161,7 +161,7 @@ where
 
     fn create_scope(
         &mut self,
-        value: &ty::Binder<impl TypeFoldable<'tcx>>,
+        value: ty::Binder<impl Relate<'tcx>>,
         universally_quantified: UniversallyQuantified,
     ) -> BoundRegionScope<'tcx> {
         let mut scope = BoundRegionScope::default();
@@ -369,7 +369,7 @@ where
             universe,
         };
 
-        generalizer.relate(&value, &value)
+        generalizer.relate(value, value)
     }
 }
 
@@ -495,8 +495,8 @@ where
     fn relate_with_variance<T: Relate<'tcx>>(
         &mut self,
         variance: ty::Variance,
-        a: &T,
-        b: &T,
+        a: T,
+        b: T,
     ) -> RelateResult<'tcx, T> {
         debug!("relate_with_variance(variance={:?}, a={:?}, b={:?})", variance, a, b);
 
@@ -613,8 +613,8 @@ where
 
     fn binders<T>(
         &mut self,
-        a: &ty::Binder<T>,
-        b: &ty::Binder<T>,
+        a: ty::Binder<T>,
+        b: ty::Binder<T>,
     ) -> RelateResult<'tcx, ty::Binder<T>>
     where
         T: Relate<'tcx>,
@@ -640,11 +640,10 @@ where
 
         debug!("binders({:?}: {:?}, ambient_variance={:?})", a, b, self.ambient_variance);
 
-        if !a.skip_binder().has_escaping_bound_vars() && !b.skip_binder().has_escaping_bound_vars()
-        {
+        if let (Some(a), Some(b)) = (a.no_bound_vars(), b.no_bound_vars()) {
             // Fast path for the common case.
-            self.relate(a.skip_binder(), b.skip_binder())?;
-            return Ok(a.clone());
+            self.relate(a, b)?;
+            return Ok(ty::Binder::bind(a));
         }
 
         if self.ambient_covariance() {
@@ -839,8 +838,8 @@ where
     fn relate_with_variance<T: Relate<'tcx>>(
         &mut self,
         variance: ty::Variance,
-        a: &T,
-        b: &T,
+        a: T,
+        b: T,
     ) -> RelateResult<'tcx, T> {
         debug!(
             "TypeGeneralizer::relate_with_variance(variance={:?}, a={:?}, b={:?})",
@@ -890,7 +889,7 @@ where
                     match variables.probe(vid) {
                         TypeVariableValue::Known { value: u } => {
                             drop(variables);
-                            self.relate(&u, &u)
+                            self.relate(u, u)
                         }
                         TypeVariableValue::Unknown { universe: _universe } => {
                             if self.ambient_variance == ty::Bivariant {
@@ -984,7 +983,7 @@ where
                 let variable_table = &mut inner.const_unification_table();
                 let var_value = variable_table.probe_value(vid);
                 match var_value.val.known() {
-                    Some(u) => self.relate(&u, &u),
+                    Some(u) => self.relate(u, u),
                     None => {
                         let new_var_id = variable_table.new_key(ConstVarValue {
                             origin: var_value.origin,
@@ -1001,8 +1000,8 @@ where
 
     fn binders<T>(
         &mut self,
-        a: &ty::Binder<T>,
-        _: &ty::Binder<T>,
+        a: ty::Binder<T>,
+        _: ty::Binder<T>,
     ) -> RelateResult<'tcx, ty::Binder<T>>
     where
         T: Relate<'tcx>,
diff --git a/src/librustc_infer/infer/sub.rs b/src/librustc_infer/infer/sub.rs
index 90962d210b5..d190f7e4342 100644
--- a/src/librustc_infer/infer/sub.rs
+++ b/src/librustc_infer/infer/sub.rs
@@ -62,8 +62,8 @@ impl TypeRelation<'tcx> for Sub<'combine, 'infcx, 'tcx> {
     fn relate_with_variance<T: Relate<'tcx>>(
         &mut self,
         variance: ty::Variance,
-        a: &T,
-        b: &T,
+        a: T,
+        b: T,
     ) -> RelateResult<'tcx, T> {
         match variance {
             ty::Invariant => self.fields.equate(self.a_is_expected).relate(a, b),
@@ -162,8 +162,8 @@ impl TypeRelation<'tcx> for Sub<'combine, 'infcx, 'tcx> {
 
     fn binders<T>(
         &mut self,
-        a: &ty::Binder<T>,
-        b: &ty::Binder<T>,
+        a: ty::Binder<T>,
+        b: ty::Binder<T>,
     ) -> RelateResult<'tcx, ty::Binder<T>>
     where
         T: Relate<'tcx>,
diff --git a/src/librustc_lexer/src/cursor.rs b/src/librustc_lexer/src/cursor.rs
index ed0911379c4..c0045d3f79b 100644
--- a/src/librustc_lexer/src/cursor.rs
+++ b/src/librustc_lexer/src/cursor.rs
@@ -23,8 +23,8 @@ impl<'a> Cursor<'a> {
         }
     }
 
-    /// For debug assertions only
-    /// Returns the last eaten symbol (or '\0' in release builds).
+    /// Returns the last eaten symbol (or `'\0'` in release builds).
+    /// (For debug assertions only.)
     pub(crate) fn prev(&self) -> char {
         #[cfg(debug_assertions)]
         {
diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs
index 36d2954ac6e..d55cbbe19c2 100644
--- a/src/librustc_lint/builtin.rs
+++ b/src/librustc_lint/builtin.rs
@@ -911,7 +911,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MutableTransmutes {
                 }
                 let sig = cx.tables().node_type(expr.hir_id).fn_sig(cx.tcx);
                 let from = sig.inputs().skip_binder()[0];
-                let to = *sig.output().skip_binder();
+                let to = sig.output().skip_binder();
                 return Some((from, to));
             }
             None
diff --git a/src/librustc_middle/ich/impls_ty.rs b/src/librustc_middle/ich/impls_ty.rs
index ef6247881c0..8f15c99f951 100644
--- a/src/librustc_middle/ich/impls_ty.rs
+++ b/src/librustc_middle/ich/impls_ty.rs
@@ -123,7 +123,7 @@ where
     T: HashStable<StableHashingContext<'a>>,
 {
     fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
-        self.skip_binder().hash_stable(hcx, hasher);
+        self.as_ref().skip_binder().hash_stable(hcx, hasher);
     }
 }
 
diff --git a/src/librustc_middle/lib.rs b/src/librustc_middle/lib.rs
index 676346fbebd..96b8ca27183 100644
--- a/src/librustc_middle/lib.rs
+++ b/src/librustc_middle/lib.rs
@@ -42,7 +42,7 @@
 #![feature(or_patterns)]
 #![feature(range_is_empty)]
 #![feature(min_specialization)]
-#![feature(track_caller)]
+#![cfg_attr(bootstrap, feature(track_caller))]
 #![feature(trusted_len)]
 #![feature(stmt_expr_attributes)]
 #![feature(test)]
diff --git a/src/librustc_middle/mir/mod.rs b/src/librustc_middle/mir/mod.rs
index 0ed0d905007..ae59f8c542d 100644
--- a/src/librustc_middle/mir/mod.rs
+++ b/src/librustc_middle/mir/mod.rs
@@ -19,7 +19,6 @@ use rustc_target::abi::VariantIdx;
 
 use polonius_engine::Atom;
 pub use rustc_ast::ast::Mutability;
-use rustc_ast::ast::{InlineAsmOptions, InlineAsmTemplatePiece};
 use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::graph::dominators::{dominators, Dominators};
 use rustc_data_structures::graph::{self, GraphSuccessors};
@@ -45,6 +44,8 @@ pub mod mono;
 mod predecessors;
 mod query;
 pub mod tcx;
+pub mod terminator;
+pub use terminator::*;
 pub mod traversal;
 mod type_foldable;
 pub mod visit;
@@ -1046,191 +1047,6 @@ pub struct BasicBlockData<'tcx> {
     pub is_cleanup: bool,
 }
 
-#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
-pub struct Terminator<'tcx> {
-    pub source_info: SourceInfo,
-    pub kind: TerminatorKind<'tcx>,
-}
-
-#[derive(Clone, RustcEncodable, RustcDecodable, HashStable, PartialEq)]
-pub enum TerminatorKind<'tcx> {
-    /// Block should have one successor in the graph; we jump there.
-    Goto { target: BasicBlock },
-
-    /// Operand evaluates to an integer; jump depending on its value
-    /// to one of the targets, and otherwise fallback to `otherwise`.
-    SwitchInt {
-        /// The discriminant value being tested.
-        discr: Operand<'tcx>,
-
-        /// The type of value being tested.
-        /// This is always the same as the type of `discr`.
-        /// FIXME: remove this redundant information. Currently, it is relied on by pretty-printing.
-        switch_ty: Ty<'tcx>,
-
-        /// Possible values. The locations to branch to in each case
-        /// are found in the corresponding indices from the `targets` vector.
-        values: Cow<'tcx, [u128]>,
-
-        /// Possible branch sites. The last element of this vector is used
-        /// for the otherwise branch, so targets.len() == values.len() + 1
-        /// should hold.
-        //
-        // This invariant is quite non-obvious and also could be improved.
-        // One way to make this invariant is to have something like this instead:
-        //
-        // branches: Vec<(ConstInt, BasicBlock)>,
-        // otherwise: Option<BasicBlock> // exhaustive if None
-        //
-        // However we’ve decided to keep this as-is until we figure a case
-        // where some other approach seems to be strictly better than other.
-        targets: Vec<BasicBlock>,
-    },
-
-    /// Indicates that the landing pad is finished and unwinding should
-    /// continue. Emitted by `build::scope::diverge_cleanup`.
-    Resume,
-
-    /// Indicates that the landing pad is finished and that the process
-    /// should abort. Used to prevent unwinding for foreign items.
-    Abort,
-
-    /// Indicates a normal return. The return place should have
-    /// been filled in before this executes. This can occur multiple times
-    /// in different basic blocks.
-    Return,
-
-    /// Indicates a terminator that can never be reached.
-    Unreachable,
-
-    /// Drop the `Place`.
-    Drop { place: Place<'tcx>, target: BasicBlock, unwind: Option<BasicBlock> },
-
-    /// Drop the `Place` and assign the new value over it. This ensures
-    /// that the assignment to `P` occurs *even if* the destructor for
-    /// place unwinds. Its semantics are best explained by the
-    /// elaboration:
-    ///
-    /// ```
-    /// BB0 {
-    ///   DropAndReplace(P <- V, goto BB1, unwind BB2)
-    /// }
-    /// ```
-    ///
-    /// becomes
-    ///
-    /// ```
-    /// BB0 {
-    ///   Drop(P, goto BB1, unwind BB2)
-    /// }
-    /// BB1 {
-    ///   // P is now uninitialized
-    ///   P <- V
-    /// }
-    /// BB2 {
-    ///   // P is now uninitialized -- its dtor panicked
-    ///   P <- V
-    /// }
-    /// ```
-    DropAndReplace {
-        place: Place<'tcx>,
-        value: Operand<'tcx>,
-        target: BasicBlock,
-        unwind: Option<BasicBlock>,
-    },
-
-    /// Block ends with a call of a converging function.
-    Call {
-        /// The function that’s being called.
-        func: Operand<'tcx>,
-        /// Arguments the function is called with.
-        /// These are owned by the callee, which is free to modify them.
-        /// This allows the memory occupied by "by-value" arguments to be
-        /// reused across function calls without duplicating the contents.
-        args: Vec<Operand<'tcx>>,
-        /// Destination for the return value. If some, the call is converging.
-        destination: Option<(Place<'tcx>, BasicBlock)>,
-        /// Cleanups to be done if the call unwinds.
-        cleanup: Option<BasicBlock>,
-        /// `true` if this is from a call in HIR rather than from an overloaded
-        /// operator. True for overloaded function call.
-        from_hir_call: bool,
-        /// This `Span` is the span of the function, without the dot and receiver
-        /// (e.g. `foo(a, b)` in `x.foo(a, b)`
-        fn_span: Span,
-    },
-
-    /// Jump to the target if the condition has the expected value,
-    /// otherwise panic with a message and a cleanup target.
-    Assert {
-        cond: Operand<'tcx>,
-        expected: bool,
-        msg: AssertMessage<'tcx>,
-        target: BasicBlock,
-        cleanup: Option<BasicBlock>,
-    },
-
-    /// A suspend point.
-    Yield {
-        /// The value to return.
-        value: Operand<'tcx>,
-        /// Where to resume to.
-        resume: BasicBlock,
-        /// The place to store the resume argument in.
-        resume_arg: Place<'tcx>,
-        /// Cleanup to be done if the generator is dropped at this suspend point.
-        drop: Option<BasicBlock>,
-    },
-
-    /// Indicates the end of the dropping of a generator.
-    GeneratorDrop,
-
-    /// A block where control flow only ever takes one real path, but borrowck
-    /// needs to be more conservative.
-    FalseEdge {
-        /// The target normal control flow will take.
-        real_target: BasicBlock,
-        /// A block control flow could conceptually jump to, but won't in
-        /// practice.
-        imaginary_target: BasicBlock,
-    },
-    /// A terminator for blocks that only take one path in reality, but where we
-    /// reserve the right to unwind in borrowck, even if it won't happen in practice.
-    /// This can arise in infinite loops with no function calls for example.
-    FalseUnwind {
-        /// The target normal control flow will take.
-        real_target: BasicBlock,
-        /// The imaginary cleanup block link. This particular path will never be taken
-        /// in practice, but in order to avoid fragility we want to always
-        /// consider it in borrowck. We don't want to accept programs which
-        /// pass borrowck only when `panic=abort` or some assertions are disabled
-        /// due to release vs. debug mode builds. This needs to be an `Option` because
-        /// of the `remove_noop_landing_pads` and `no_landing_pads` passes.
-        unwind: Option<BasicBlock>,
-    },
-
-    /// Block ends with an inline assembly block. This is a terminator since
-    /// inline assembly is allowed to diverge.
-    InlineAsm {
-        /// The template for the inline assembly, with placeholders.
-        template: &'tcx [InlineAsmTemplatePiece],
-
-        /// The operands for the inline assembly, as `Operand`s or `Place`s.
-        operands: Vec<InlineAsmOperand<'tcx>>,
-
-        /// Miscellaneous options for the inline assembly.
-        options: InlineAsmOptions,
-
-        /// Source spans for each line of the inline assembly code. These are
-        /// used to map assembler errors back to the line in the source code.
-        line_spans: &'tcx [Span],
-
-        /// Destination block after the inline assembly returns, unless it is
-        /// diverging (InlineAsmOptions::NORETURN).
-        destination: Option<BasicBlock>,
-    },
-}
-
 /// Information about an assertion failure.
 #[derive(Clone, RustcEncodable, RustcDecodable, HashStable, PartialEq)]
 pub enum AssertKind<O> {
@@ -1279,149 +1095,6 @@ pub type Successors<'a> =
 pub type SuccessorsMut<'a> =
     iter::Chain<option::IntoIter<&'a mut BasicBlock>, slice::IterMut<'a, BasicBlock>>;
 
-impl<'tcx> Terminator<'tcx> {
-    pub fn successors(&self) -> Successors<'_> {
-        self.kind.successors()
-    }
-
-    pub fn successors_mut(&mut self) -> SuccessorsMut<'_> {
-        self.kind.successors_mut()
-    }
-
-    pub fn unwind(&self) -> Option<&Option<BasicBlock>> {
-        self.kind.unwind()
-    }
-
-    pub fn unwind_mut(&mut self) -> Option<&mut Option<BasicBlock>> {
-        self.kind.unwind_mut()
-    }
-}
-
-impl<'tcx> TerminatorKind<'tcx> {
-    pub fn if_(
-        tcx: TyCtxt<'tcx>,
-        cond: Operand<'tcx>,
-        t: BasicBlock,
-        f: BasicBlock,
-    ) -> TerminatorKind<'tcx> {
-        static BOOL_SWITCH_FALSE: &[u128] = &[0];
-        TerminatorKind::SwitchInt {
-            discr: cond,
-            switch_ty: tcx.types.bool,
-            values: From::from(BOOL_SWITCH_FALSE),
-            targets: vec![f, t],
-        }
-    }
-
-    pub fn successors(&self) -> Successors<'_> {
-        use self::TerminatorKind::*;
-        match *self {
-            Resume
-            | Abort
-            | GeneratorDrop
-            | Return
-            | Unreachable
-            | Call { destination: None, cleanup: None, .. }
-            | InlineAsm { destination: None, .. } => None.into_iter().chain(&[]),
-            Goto { target: ref t }
-            | Call { destination: None, cleanup: Some(ref t), .. }
-            | Call { destination: Some((_, ref t)), cleanup: None, .. }
-            | Yield { resume: ref t, drop: None, .. }
-            | DropAndReplace { target: ref t, unwind: None, .. }
-            | Drop { target: ref t, unwind: None, .. }
-            | Assert { target: ref t, cleanup: None, .. }
-            | FalseUnwind { real_target: ref t, unwind: None }
-            | InlineAsm { destination: Some(ref t), .. } => Some(t).into_iter().chain(&[]),
-            Call { destination: Some((_, ref t)), cleanup: Some(ref u), .. }
-            | Yield { resume: ref t, drop: Some(ref u), .. }
-            | DropAndReplace { target: ref t, unwind: Some(ref u), .. }
-            | Drop { target: ref t, unwind: Some(ref u), .. }
-            | Assert { target: ref t, cleanup: Some(ref u), .. }
-            | FalseUnwind { real_target: ref t, unwind: Some(ref u) } => {
-                Some(t).into_iter().chain(slice::from_ref(u))
-            }
-            SwitchInt { ref targets, .. } => None.into_iter().chain(&targets[..]),
-            FalseEdge { ref real_target, ref imaginary_target } => {
-                Some(real_target).into_iter().chain(slice::from_ref(imaginary_target))
-            }
-        }
-    }
-
-    pub fn successors_mut(&mut self) -> SuccessorsMut<'_> {
-        use self::TerminatorKind::*;
-        match *self {
-            Resume
-            | Abort
-            | GeneratorDrop
-            | Return
-            | Unreachable
-            | Call { destination: None, cleanup: None, .. }
-            | InlineAsm { destination: None, .. } => None.into_iter().chain(&mut []),
-            Goto { target: ref mut t }
-            | Call { destination: None, cleanup: Some(ref mut t), .. }
-            | Call { destination: Some((_, ref mut t)), cleanup: None, .. }
-            | Yield { resume: ref mut t, drop: None, .. }
-            | DropAndReplace { target: ref mut t, unwind: None, .. }
-            | Drop { target: ref mut t, unwind: None, .. }
-            | Assert { target: ref mut t, cleanup: None, .. }
-            | FalseUnwind { real_target: ref mut t, unwind: None }
-            | InlineAsm { destination: Some(ref mut t), .. } => Some(t).into_iter().chain(&mut []),
-            Call { destination: Some((_, ref mut t)), cleanup: Some(ref mut u), .. }
-            | Yield { resume: ref mut t, drop: Some(ref mut u), .. }
-            | DropAndReplace { target: ref mut t, unwind: Some(ref mut u), .. }
-            | Drop { target: ref mut t, unwind: Some(ref mut u), .. }
-            | Assert { target: ref mut t, cleanup: Some(ref mut u), .. }
-            | FalseUnwind { real_target: ref mut t, unwind: Some(ref mut u) } => {
-                Some(t).into_iter().chain(slice::from_mut(u))
-            }
-            SwitchInt { ref mut targets, .. } => None.into_iter().chain(&mut targets[..]),
-            FalseEdge { ref mut real_target, ref mut imaginary_target } => {
-                Some(real_target).into_iter().chain(slice::from_mut(imaginary_target))
-            }
-        }
-    }
-
-    pub fn unwind(&self) -> Option<&Option<BasicBlock>> {
-        match *self {
-            TerminatorKind::Goto { .. }
-            | TerminatorKind::Resume
-            | TerminatorKind::Abort
-            | TerminatorKind::Return
-            | TerminatorKind::Unreachable
-            | TerminatorKind::GeneratorDrop
-            | TerminatorKind::Yield { .. }
-            | TerminatorKind::SwitchInt { .. }
-            | TerminatorKind::FalseEdge { .. }
-            | TerminatorKind::InlineAsm { .. } => None,
-            TerminatorKind::Call { cleanup: ref unwind, .. }
-            | TerminatorKind::Assert { cleanup: ref unwind, .. }
-            | TerminatorKind::DropAndReplace { ref unwind, .. }
-            | TerminatorKind::Drop { ref unwind, .. }
-            | TerminatorKind::FalseUnwind { ref unwind, .. } => Some(unwind),
-        }
-    }
-
-    pub fn unwind_mut(&mut self) -> Option<&mut Option<BasicBlock>> {
-        match *self {
-            TerminatorKind::Goto { .. }
-            | TerminatorKind::Resume
-            | TerminatorKind::Abort
-            | TerminatorKind::Return
-            | TerminatorKind::Unreachable
-            | TerminatorKind::GeneratorDrop
-            | TerminatorKind::Yield { .. }
-            | TerminatorKind::SwitchInt { .. }
-            | TerminatorKind::FalseEdge { .. }
-            | TerminatorKind::InlineAsm { .. } => None,
-            TerminatorKind::Call { cleanup: ref mut unwind, .. }
-            | TerminatorKind::Assert { cleanup: ref mut unwind, .. }
-            | TerminatorKind::DropAndReplace { ref mut unwind, .. }
-            | TerminatorKind::Drop { ref mut unwind, .. }
-            | TerminatorKind::FalseUnwind { ref mut unwind, .. } => Some(unwind),
-        }
-    }
-}
-
 impl<'tcx> BasicBlockData<'tcx> {
     pub fn new(terminator: Option<Terminator<'tcx>>) -> BasicBlockData<'tcx> {
         BasicBlockData { statements: vec![], terminator, is_cleanup: false }
@@ -1628,169 +1301,6 @@ impl<O: fmt::Debug> fmt::Debug for AssertKind<O> {
     }
 }
 
-impl<'tcx> Debug for TerminatorKind<'tcx> {
-    fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
-        self.fmt_head(fmt)?;
-        let successor_count = self.successors().count();
-        let labels = self.fmt_successor_labels();
-        assert_eq!(successor_count, labels.len());
-
-        match successor_count {
-            0 => Ok(()),
-
-            1 => write!(fmt, " -> {:?}", self.successors().next().unwrap()),
-
-            _ => {
-                write!(fmt, " -> [")?;
-                for (i, target) in self.successors().enumerate() {
-                    if i > 0 {
-                        write!(fmt, ", ")?;
-                    }
-                    write!(fmt, "{}: {:?}", labels[i], target)?;
-                }
-                write!(fmt, "]")
-            }
-        }
-    }
-}
-
-impl<'tcx> TerminatorKind<'tcx> {
-    /// Writes the "head" part of the terminator; that is, its name and the data it uses to pick the
-    /// successor basic block, if any. The only information not included is the list of possible
-    /// successors, which may be rendered differently between the text and the graphviz format.
-    pub fn fmt_head<W: Write>(&self, fmt: &mut W) -> fmt::Result {
-        use self::TerminatorKind::*;
-        match self {
-            Goto { .. } => write!(fmt, "goto"),
-            SwitchInt { discr, .. } => write!(fmt, "switchInt({:?})", discr),
-            Return => write!(fmt, "return"),
-            GeneratorDrop => write!(fmt, "generator_drop"),
-            Resume => write!(fmt, "resume"),
-            Abort => write!(fmt, "abort"),
-            Yield { value, resume_arg, .. } => write!(fmt, "{:?} = yield({:?})", resume_arg, value),
-            Unreachable => write!(fmt, "unreachable"),
-            Drop { place, .. } => write!(fmt, "drop({:?})", place),
-            DropAndReplace { place, value, .. } => {
-                write!(fmt, "replace({:?} <- {:?})", place, value)
-            }
-            Call { func, args, destination, .. } => {
-                if let Some((destination, _)) = destination {
-                    write!(fmt, "{:?} = ", destination)?;
-                }
-                write!(fmt, "{:?}(", func)?;
-                for (index, arg) in args.iter().enumerate() {
-                    if index > 0 {
-                        write!(fmt, ", ")?;
-                    }
-                    write!(fmt, "{:?}", arg)?;
-                }
-                write!(fmt, ")")
-            }
-            Assert { cond, expected, msg, .. } => {
-                write!(fmt, "assert(")?;
-                if !expected {
-                    write!(fmt, "!")?;
-                }
-                write!(fmt, "{:?}, ", cond)?;
-                msg.fmt_assert_args(fmt)?;
-                write!(fmt, ")")
-            }
-            FalseEdge { .. } => write!(fmt, "falseEdge"),
-            FalseUnwind { .. } => write!(fmt, "falseUnwind"),
-            InlineAsm { template, ref operands, options, .. } => {
-                write!(fmt, "asm!(\"{}\"", InlineAsmTemplatePiece::to_string(template))?;
-                for op in operands {
-                    write!(fmt, ", ")?;
-                    let print_late = |&late| if late { "late" } else { "" };
-                    match op {
-                        InlineAsmOperand::In { reg, value } => {
-                            write!(fmt, "in({}) {:?}", reg, value)?;
-                        }
-                        InlineAsmOperand::Out { reg, late, place: Some(place) } => {
-                            write!(fmt, "{}out({}) {:?}", print_late(late), reg, place)?;
-                        }
-                        InlineAsmOperand::Out { reg, late, place: None } => {
-                            write!(fmt, "{}out({}) _", print_late(late), reg)?;
-                        }
-                        InlineAsmOperand::InOut {
-                            reg,
-                            late,
-                            in_value,
-                            out_place: Some(out_place),
-                        } => {
-                            write!(
-                                fmt,
-                                "in{}out({}) {:?} => {:?}",
-                                print_late(late),
-                                reg,
-                                in_value,
-                                out_place
-                            )?;
-                        }
-                        InlineAsmOperand::InOut { reg, late, in_value, out_place: None } => {
-                            write!(fmt, "in{}out({}) {:?} => _", print_late(late), reg, in_value)?;
-                        }
-                        InlineAsmOperand::Const { value } => {
-                            write!(fmt, "const {:?}", value)?;
-                        }
-                        InlineAsmOperand::SymFn { value } => {
-                            write!(fmt, "sym_fn {:?}", value)?;
-                        }
-                        InlineAsmOperand::SymStatic { def_id } => {
-                            write!(fmt, "sym_static {:?}", def_id)?;
-                        }
-                    }
-                }
-                write!(fmt, ", options({:?}))", options)
-            }
-        }
-    }
-
-    /// Returns the list of labels for the edges to the successor basic blocks.
-    pub fn fmt_successor_labels(&self) -> Vec<Cow<'static, str>> {
-        use self::TerminatorKind::*;
-        match *self {
-            Return | Resume | Abort | Unreachable | GeneratorDrop => vec![],
-            Goto { .. } => vec!["".into()],
-            SwitchInt { ref values, switch_ty, .. } => ty::tls::with(|tcx| {
-                let param_env = ty::ParamEnv::empty();
-                let switch_ty = tcx.lift(&switch_ty).unwrap();
-                let size = tcx.layout_of(param_env.and(switch_ty)).unwrap().size;
-                values
-                    .iter()
-                    .map(|&u| {
-                        ty::Const::from_scalar(tcx, Scalar::from_uint(u, size), switch_ty)
-                            .to_string()
-                            .into()
-                    })
-                    .chain(iter::once("otherwise".into()))
-                    .collect()
-            }),
-            Call { destination: Some(_), cleanup: Some(_), .. } => {
-                vec!["return".into(), "unwind".into()]
-            }
-            Call { destination: Some(_), cleanup: None, .. } => vec!["return".into()],
-            Call { destination: None, cleanup: Some(_), .. } => vec!["unwind".into()],
-            Call { destination: None, cleanup: None, .. } => vec![],
-            Yield { drop: Some(_), .. } => vec!["resume".into(), "drop".into()],
-            Yield { drop: None, .. } => vec!["resume".into()],
-            DropAndReplace { unwind: None, .. } | Drop { unwind: None, .. } => {
-                vec!["return".into()]
-            }
-            DropAndReplace { unwind: Some(_), .. } | Drop { unwind: Some(_), .. } => {
-                vec!["return".into(), "unwind".into()]
-            }
-            Assert { cleanup: None, .. } => vec!["".into()],
-            Assert { .. } => vec!["success".into(), "unwind".into()],
-            FalseEdge { .. } => vec!["real".into(), "imaginary".into()],
-            FalseUnwind { unwind: Some(_), .. } => vec!["real".into(), "cleanup".into()],
-            FalseUnwind { unwind: None, .. } => vec!["real".into()],
-            InlineAsm { destination: Some(_), .. } => vec!["".into()],
-            InlineAsm { destination: None, .. } => vec![],
-        }
-    }
-}
-
 ///////////////////////////////////////////////////////////////////////////
 // Statements
 
diff --git a/src/librustc_middle/mir/terminator/mod.rs b/src/librustc_middle/mir/terminator/mod.rs
new file mode 100644
index 00000000000..1f5041141d5
--- /dev/null
+++ b/src/librustc_middle/mir/terminator/mod.rs
@@ -0,0 +1,507 @@
+use crate::mir::interpret::Scalar;
+use crate::ty::{self, Ty, TyCtxt};
+use rustc_ast::ast::{InlineAsmOptions, InlineAsmTemplatePiece};
+
+use super::{
+    AssertMessage, BasicBlock, InlineAsmOperand, Operand, Place, SourceInfo, Successors,
+    SuccessorsMut,
+};
+pub use rustc_ast::ast::Mutability;
+use rustc_macros::HashStable;
+use rustc_span::Span;
+use std::borrow::Cow;
+use std::fmt::{self, Debug, Formatter, Write};
+use std::iter;
+use std::slice;
+
+pub use super::query::*;
+
+#[derive(Clone, RustcEncodable, RustcDecodable, HashStable, PartialEq)]
+pub enum TerminatorKind<'tcx> {
+    /// Block should have one successor in the graph; we jump there.
+    Goto { target: BasicBlock },
+
+    /// Operand evaluates to an integer; jump depending on its value
+    /// to one of the targets, and otherwise fallback to `otherwise`.
+    SwitchInt {
+        /// The discriminant value being tested.
+        discr: Operand<'tcx>,
+
+        /// The type of value being tested.
+        /// This is always the same as the type of `discr`.
+        /// FIXME: remove this redundant information. Currently, it is relied on by pretty-printing.
+        switch_ty: Ty<'tcx>,
+
+        /// Possible values. The locations to branch to in each case
+        /// are found in the corresponding indices from the `targets` vector.
+        values: Cow<'tcx, [u128]>,
+
+        /// Possible branch sites. The last element of this vector is used
+        /// for the otherwise branch, so targets.len() == values.len() + 1
+        /// should hold.
+        //
+        // This invariant is quite non-obvious and also could be improved.
+        // One way to make this invariant is to have something like this instead:
+        //
+        // branches: Vec<(ConstInt, BasicBlock)>,
+        // otherwise: Option<BasicBlock> // exhaustive if None
+        //
+        // However we’ve decided to keep this as-is until we figure a case
+        // where some other approach seems to be strictly better than other.
+        targets: Vec<BasicBlock>,
+    },
+
+    /// Indicates that the landing pad is finished and unwinding should
+    /// continue. Emitted by `build::scope::diverge_cleanup`.
+    Resume,
+
+    /// Indicates that the landing pad is finished and that the process
+    /// should abort. Used to prevent unwinding for foreign items.
+    Abort,
+
+    /// Indicates a normal return. The return place should have
+    /// been filled in before this executes. This can occur multiple times
+    /// in different basic blocks.
+    Return,
+
+    /// Indicates a terminator that can never be reached.
+    Unreachable,
+
+    /// Drop the `Place`.
+    Drop { place: Place<'tcx>, target: BasicBlock, unwind: Option<BasicBlock> },
+
+    /// Drop the `Place` and assign the new value over it. This ensures
+    /// that the assignment to `P` occurs *even if* the destructor for
+    /// place unwinds. Its semantics are best explained by the
+    /// elaboration:
+    ///
+    /// ```
+    /// BB0 {
+    ///   DropAndReplace(P <- V, goto BB1, unwind BB2)
+    /// }
+    /// ```
+    ///
+    /// becomes
+    ///
+    /// ```
+    /// BB0 {
+    ///   Drop(P, goto BB1, unwind BB2)
+    /// }
+    /// BB1 {
+    ///   // P is now uninitialized
+    ///   P <- V
+    /// }
+    /// BB2 {
+    ///   // P is now uninitialized -- its dtor panicked
+    ///   P <- V
+    /// }
+    /// ```
+    DropAndReplace {
+        place: Place<'tcx>,
+        value: Operand<'tcx>,
+        target: BasicBlock,
+        unwind: Option<BasicBlock>,
+    },
+
+    /// Block ends with a call of a converging function.
+    Call {
+        /// The function that’s being called.
+        func: Operand<'tcx>,
+        /// Arguments the function is called with.
+        /// These are owned by the callee, which is free to modify them.
+        /// This allows the memory occupied by "by-value" arguments to be
+        /// reused across function calls without duplicating the contents.
+        args: Vec<Operand<'tcx>>,
+        /// Destination for the return value. If some, the call is converging.
+        destination: Option<(Place<'tcx>, BasicBlock)>,
+        /// Cleanups to be done if the call unwinds.
+        cleanup: Option<BasicBlock>,
+        /// `true` if this is from a call in HIR rather than from an overloaded
+        /// operator. True for overloaded function call.
+        from_hir_call: bool,
+        /// This `Span` is the span of the function, without the dot and receiver
+        /// (e.g. `foo(a, b)` in `x.foo(a, b)`
+        fn_span: Span,
+    },
+
+    /// Jump to the target if the condition has the expected value,
+    /// otherwise panic with a message and a cleanup target.
+    Assert {
+        cond: Operand<'tcx>,
+        expected: bool,
+        msg: AssertMessage<'tcx>,
+        target: BasicBlock,
+        cleanup: Option<BasicBlock>,
+    },
+
+    /// A suspend point.
+    Yield {
+        /// The value to return.
+        value: Operand<'tcx>,
+        /// Where to resume to.
+        resume: BasicBlock,
+        /// The place to store the resume argument in.
+        resume_arg: Place<'tcx>,
+        /// Cleanup to be done if the generator is dropped at this suspend point.
+        drop: Option<BasicBlock>,
+    },
+
+    /// Indicates the end of the dropping of a generator.
+    GeneratorDrop,
+
+    /// A block where control flow only ever takes one real path, but borrowck
+    /// needs to be more conservative.
+    FalseEdge {
+        /// The target normal control flow will take.
+        real_target: BasicBlock,
+        /// A block control flow could conceptually jump to, but won't in
+        /// practice.
+        imaginary_target: BasicBlock,
+    },
+    /// A terminator for blocks that only take one path in reality, but where we
+    /// reserve the right to unwind in borrowck, even if it won't happen in practice.
+    /// This can arise in infinite loops with no function calls for example.
+    FalseUnwind {
+        /// The target normal control flow will take.
+        real_target: BasicBlock,
+        /// The imaginary cleanup block link. This particular path will never be taken
+        /// in practice, but in order to avoid fragility we want to always
+        /// consider it in borrowck. We don't want to accept programs which
+        /// pass borrowck only when `panic=abort` or some assertions are disabled
+        /// due to release vs. debug mode builds. This needs to be an `Option` because
+        /// of the `remove_noop_landing_pads` and `no_landing_pads` passes.
+        unwind: Option<BasicBlock>,
+    },
+
+    /// Block ends with an inline assembly block. This is a terminator since
+    /// inline assembly is allowed to diverge.
+    InlineAsm {
+        /// The template for the inline assembly, with placeholders.
+        template: &'tcx [InlineAsmTemplatePiece],
+
+        /// The operands for the inline assembly, as `Operand`s or `Place`s.
+        operands: Vec<InlineAsmOperand<'tcx>>,
+
+        /// Miscellaneous options for the inline assembly.
+        options: InlineAsmOptions,
+
+        /// Source spans for each line of the inline assembly code. These are
+        /// used to map assembler errors back to the line in the source code.
+        line_spans: &'tcx [Span],
+
+        /// Destination block after the inline assembly returns, unless it is
+        /// diverging (InlineAsmOptions::NORETURN).
+        destination: Option<BasicBlock>,
+    },
+}
+#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
+pub struct Terminator<'tcx> {
+    pub source_info: SourceInfo,
+    pub kind: TerminatorKind<'tcx>,
+}
+
+impl<'tcx> Terminator<'tcx> {
+    pub fn successors(&self) -> Successors<'_> {
+        self.kind.successors()
+    }
+
+    pub fn successors_mut(&mut self) -> SuccessorsMut<'_> {
+        self.kind.successors_mut()
+    }
+
+    pub fn unwind(&self) -> Option<&Option<BasicBlock>> {
+        self.kind.unwind()
+    }
+
+    pub fn unwind_mut(&mut self) -> Option<&mut Option<BasicBlock>> {
+        self.kind.unwind_mut()
+    }
+}
+
+impl<'tcx> TerminatorKind<'tcx> {
+    pub fn if_(
+        tcx: TyCtxt<'tcx>,
+        cond: Operand<'tcx>,
+        t: BasicBlock,
+        f: BasicBlock,
+    ) -> TerminatorKind<'tcx> {
+        static BOOL_SWITCH_FALSE: &[u128] = &[0];
+        TerminatorKind::SwitchInt {
+            discr: cond,
+            switch_ty: tcx.types.bool,
+            values: From::from(BOOL_SWITCH_FALSE),
+            targets: vec![f, t],
+        }
+    }
+
+    pub fn successors(&self) -> Successors<'_> {
+        use self::TerminatorKind::*;
+        match *self {
+            Resume
+            | Abort
+            | GeneratorDrop
+            | Return
+            | Unreachable
+            | Call { destination: None, cleanup: None, .. }
+            | InlineAsm { destination: None, .. } => None.into_iter().chain(&[]),
+            Goto { target: ref t }
+            | Call { destination: None, cleanup: Some(ref t), .. }
+            | Call { destination: Some((_, ref t)), cleanup: None, .. }
+            | Yield { resume: ref t, drop: None, .. }
+            | DropAndReplace { target: ref t, unwind: None, .. }
+            | Drop { target: ref t, unwind: None, .. }
+            | Assert { target: ref t, cleanup: None, .. }
+            | FalseUnwind { real_target: ref t, unwind: None }
+            | InlineAsm { destination: Some(ref t), .. } => Some(t).into_iter().chain(&[]),
+            Call { destination: Some((_, ref t)), cleanup: Some(ref u), .. }
+            | Yield { resume: ref t, drop: Some(ref u), .. }
+            | DropAndReplace { target: ref t, unwind: Some(ref u), .. }
+            | Drop { target: ref t, unwind: Some(ref u), .. }
+            | Assert { target: ref t, cleanup: Some(ref u), .. }
+            | FalseUnwind { real_target: ref t, unwind: Some(ref u) } => {
+                Some(t).into_iter().chain(slice::from_ref(u))
+            }
+            SwitchInt { ref targets, .. } => None.into_iter().chain(&targets[..]),
+            FalseEdge { ref real_target, ref imaginary_target } => {
+                Some(real_target).into_iter().chain(slice::from_ref(imaginary_target))
+            }
+        }
+    }
+
+    pub fn successors_mut(&mut self) -> SuccessorsMut<'_> {
+        use self::TerminatorKind::*;
+        match *self {
+            Resume
+            | Abort
+            | GeneratorDrop
+            | Return
+            | Unreachable
+            | Call { destination: None, cleanup: None, .. }
+            | InlineAsm { destination: None, .. } => None.into_iter().chain(&mut []),
+            Goto { target: ref mut t }
+            | Call { destination: None, cleanup: Some(ref mut t), .. }
+            | Call { destination: Some((_, ref mut t)), cleanup: None, .. }
+            | Yield { resume: ref mut t, drop: None, .. }
+            | DropAndReplace { target: ref mut t, unwind: None, .. }
+            | Drop { target: ref mut t, unwind: None, .. }
+            | Assert { target: ref mut t, cleanup: None, .. }
+            | FalseUnwind { real_target: ref mut t, unwind: None }
+            | InlineAsm { destination: Some(ref mut t), .. } => Some(t).into_iter().chain(&mut []),
+            Call { destination: Some((_, ref mut t)), cleanup: Some(ref mut u), .. }
+            | Yield { resume: ref mut t, drop: Some(ref mut u), .. }
+            | DropAndReplace { target: ref mut t, unwind: Some(ref mut u), .. }
+            | Drop { target: ref mut t, unwind: Some(ref mut u), .. }
+            | Assert { target: ref mut t, cleanup: Some(ref mut u), .. }
+            | FalseUnwind { real_target: ref mut t, unwind: Some(ref mut u) } => {
+                Some(t).into_iter().chain(slice::from_mut(u))
+            }
+            SwitchInt { ref mut targets, .. } => None.into_iter().chain(&mut targets[..]),
+            FalseEdge { ref mut real_target, ref mut imaginary_target } => {
+                Some(real_target).into_iter().chain(slice::from_mut(imaginary_target))
+            }
+        }
+    }
+
+    pub fn unwind(&self) -> Option<&Option<BasicBlock>> {
+        match *self {
+            TerminatorKind::Goto { .. }
+            | TerminatorKind::Resume
+            | TerminatorKind::Abort
+            | TerminatorKind::Return
+            | TerminatorKind::Unreachable
+            | TerminatorKind::GeneratorDrop
+            | TerminatorKind::Yield { .. }
+            | TerminatorKind::SwitchInt { .. }
+            | TerminatorKind::FalseEdge { .. }
+            | TerminatorKind::InlineAsm { .. } => None,
+            TerminatorKind::Call { cleanup: ref unwind, .. }
+            | TerminatorKind::Assert { cleanup: ref unwind, .. }
+            | TerminatorKind::DropAndReplace { ref unwind, .. }
+            | TerminatorKind::Drop { ref unwind, .. }
+            | TerminatorKind::FalseUnwind { ref unwind, .. } => Some(unwind),
+        }
+    }
+
+    pub fn unwind_mut(&mut self) -> Option<&mut Option<BasicBlock>> {
+        match *self {
+            TerminatorKind::Goto { .. }
+            | TerminatorKind::Resume
+            | TerminatorKind::Abort
+            | TerminatorKind::Return
+            | TerminatorKind::Unreachable
+            | TerminatorKind::GeneratorDrop
+            | TerminatorKind::Yield { .. }
+            | TerminatorKind::SwitchInt { .. }
+            | TerminatorKind::FalseEdge { .. }
+            | TerminatorKind::InlineAsm { .. } => None,
+            TerminatorKind::Call { cleanup: ref mut unwind, .. }
+            | TerminatorKind::Assert { cleanup: ref mut unwind, .. }
+            | TerminatorKind::DropAndReplace { ref mut unwind, .. }
+            | TerminatorKind::Drop { ref mut unwind, .. }
+            | TerminatorKind::FalseUnwind { ref mut unwind, .. } => Some(unwind),
+        }
+    }
+}
+
+impl<'tcx> Debug for TerminatorKind<'tcx> {
+    fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
+        self.fmt_head(fmt)?;
+        let successor_count = self.successors().count();
+        let labels = self.fmt_successor_labels();
+        assert_eq!(successor_count, labels.len());
+
+        match successor_count {
+            0 => Ok(()),
+
+            1 => write!(fmt, " -> {:?}", self.successors().next().unwrap()),
+
+            _ => {
+                write!(fmt, " -> [")?;
+                for (i, target) in self.successors().enumerate() {
+                    if i > 0 {
+                        write!(fmt, ", ")?;
+                    }
+                    write!(fmt, "{}: {:?}", labels[i], target)?;
+                }
+                write!(fmt, "]")
+            }
+        }
+    }
+}
+
+impl<'tcx> TerminatorKind<'tcx> {
+    /// Writes the "head" part of the terminator; that is, its name and the data it uses to pick the
+    /// successor basic block, if any. The only information not included is the list of possible
+    /// successors, which may be rendered differently between the text and the graphviz format.
+    pub fn fmt_head<W: Write>(&self, fmt: &mut W) -> fmt::Result {
+        use self::TerminatorKind::*;
+        match self {
+            Goto { .. } => write!(fmt, "goto"),
+            SwitchInt { discr, .. } => write!(fmt, "switchInt({:?})", discr),
+            Return => write!(fmt, "return"),
+            GeneratorDrop => write!(fmt, "generator_drop"),
+            Resume => write!(fmt, "resume"),
+            Abort => write!(fmt, "abort"),
+            Yield { value, resume_arg, .. } => write!(fmt, "{:?} = yield({:?})", resume_arg, value),
+            Unreachable => write!(fmt, "unreachable"),
+            Drop { place, .. } => write!(fmt, "drop({:?})", place),
+            DropAndReplace { place, value, .. } => {
+                write!(fmt, "replace({:?} <- {:?})", place, value)
+            }
+            Call { func, args, destination, .. } => {
+                if let Some((destination, _)) = destination {
+                    write!(fmt, "{:?} = ", destination)?;
+                }
+                write!(fmt, "{:?}(", func)?;
+                for (index, arg) in args.iter().enumerate() {
+                    if index > 0 {
+                        write!(fmt, ", ")?;
+                    }
+                    write!(fmt, "{:?}", arg)?;
+                }
+                write!(fmt, ")")
+            }
+            Assert { cond, expected, msg, .. } => {
+                write!(fmt, "assert(")?;
+                if !expected {
+                    write!(fmt, "!")?;
+                }
+                write!(fmt, "{:?}, ", cond)?;
+                msg.fmt_assert_args(fmt)?;
+                write!(fmt, ")")
+            }
+            FalseEdge { .. } => write!(fmt, "falseEdge"),
+            FalseUnwind { .. } => write!(fmt, "falseUnwind"),
+            InlineAsm { template, ref operands, options, .. } => {
+                write!(fmt, "asm!(\"{}\"", InlineAsmTemplatePiece::to_string(template))?;
+                for op in operands {
+                    write!(fmt, ", ")?;
+                    let print_late = |&late| if late { "late" } else { "" };
+                    match op {
+                        InlineAsmOperand::In { reg, value } => {
+                            write!(fmt, "in({}) {:?}", reg, value)?;
+                        }
+                        InlineAsmOperand::Out { reg, late, place: Some(place) } => {
+                            write!(fmt, "{}out({}) {:?}", print_late(late), reg, place)?;
+                        }
+                        InlineAsmOperand::Out { reg, late, place: None } => {
+                            write!(fmt, "{}out({}) _", print_late(late), reg)?;
+                        }
+                        InlineAsmOperand::InOut {
+                            reg,
+                            late,
+                            in_value,
+                            out_place: Some(out_place),
+                        } => {
+                            write!(
+                                fmt,
+                                "in{}out({}) {:?} => {:?}",
+                                print_late(late),
+                                reg,
+                                in_value,
+                                out_place
+                            )?;
+                        }
+                        InlineAsmOperand::InOut { reg, late, in_value, out_place: None } => {
+                            write!(fmt, "in{}out({}) {:?} => _", print_late(late), reg, in_value)?;
+                        }
+                        InlineAsmOperand::Const { value } => {
+                            write!(fmt, "const {:?}", value)?;
+                        }
+                        InlineAsmOperand::SymFn { value } => {
+                            write!(fmt, "sym_fn {:?}", value)?;
+                        }
+                        InlineAsmOperand::SymStatic { def_id } => {
+                            write!(fmt, "sym_static {:?}", def_id)?;
+                        }
+                    }
+                }
+                write!(fmt, ", options({:?}))", options)
+            }
+        }
+    }
+
+    /// Returns the list of labels for the edges to the successor basic blocks.
+    pub fn fmt_successor_labels(&self) -> Vec<Cow<'static, str>> {
+        use self::TerminatorKind::*;
+        match *self {
+            Return | Resume | Abort | Unreachable | GeneratorDrop => vec![],
+            Goto { .. } => vec!["".into()],
+            SwitchInt { ref values, switch_ty, .. } => ty::tls::with(|tcx| {
+                let param_env = ty::ParamEnv::empty();
+                let switch_ty = tcx.lift(&switch_ty).unwrap();
+                let size = tcx.layout_of(param_env.and(switch_ty)).unwrap().size;
+                values
+                    .iter()
+                    .map(|&u| {
+                        ty::Const::from_scalar(tcx, Scalar::from_uint(u, size), switch_ty)
+                            .to_string()
+                            .into()
+                    })
+                    .chain(iter::once("otherwise".into()))
+                    .collect()
+            }),
+            Call { destination: Some(_), cleanup: Some(_), .. } => {
+                vec!["return".into(), "unwind".into()]
+            }
+            Call { destination: Some(_), cleanup: None, .. } => vec!["return".into()],
+            Call { destination: None, cleanup: Some(_), .. } => vec!["unwind".into()],
+            Call { destination: None, cleanup: None, .. } => vec![],
+            Yield { drop: Some(_), .. } => vec!["resume".into(), "drop".into()],
+            Yield { drop: None, .. } => vec!["resume".into()],
+            DropAndReplace { unwind: None, .. } | Drop { unwind: None, .. } => {
+                vec!["return".into()]
+            }
+            DropAndReplace { unwind: Some(_), .. } | Drop { unwind: Some(_), .. } => {
+                vec!["return".into(), "unwind".into()]
+            }
+            Assert { cleanup: None, .. } => vec!["".into()],
+            Assert { .. } => vec!["success".into(), "unwind".into()],
+            FalseEdge { .. } => vec!["real".into(), "imaginary".into()],
+            FalseUnwind { unwind: Some(_), .. } => vec!["real".into(), "cleanup".into()],
+            FalseUnwind { unwind: None, .. } => vec!["real".into()],
+            InlineAsm { destination: Some(_), .. } => vec!["".into()],
+            InlineAsm { destination: None, .. } => vec![],
+        }
+    }
+}
diff --git a/src/librustc_middle/ty/_match.rs b/src/librustc_middle/ty/_match.rs
index db9229ae3d2..4693a2f66fb 100644
--- a/src/librustc_middle/ty/_match.rs
+++ b/src/librustc_middle/ty/_match.rs
@@ -46,8 +46,8 @@ impl TypeRelation<'tcx> for Match<'tcx> {
     fn relate_with_variance<T: Relate<'tcx>>(
         &mut self,
         _: ty::Variance,
-        a: &T,
-        b: &T,
+        a: T,
+        b: T,
     ) -> RelateResult<'tcx, T> {
         self.relate(a, b)
     }
@@ -112,8 +112,8 @@ impl TypeRelation<'tcx> for Match<'tcx> {
 
     fn binders<T>(
         &mut self,
-        a: &ty::Binder<T>,
-        b: &ty::Binder<T>,
+        a: ty::Binder<T>,
+        b: ty::Binder<T>,
     ) -> RelateResult<'tcx, ty::Binder<T>>
     where
         T: Relate<'tcx>,
diff --git a/src/librustc_middle/ty/error.rs b/src/librustc_middle/ty/error.rs
index 6113359ca93..30ff5a2d9eb 100644
--- a/src/librustc_middle/ty/error.rs
+++ b/src/librustc_middle/ty/error.rs
@@ -57,7 +57,6 @@ pub enum TypeError<'tcx> {
     /// type).
     CyclicTy(Ty<'tcx>),
     ProjectionMismatched(ExpectedFound<DefId>),
-    ProjectionBoundsLength(ExpectedFound<usize>),
     ExistentialMismatch(ExpectedFound<&'tcx ty::List<ty::ExistentialPredicate<'tcx>>>),
     ObjectUnsafeCoercion(DefId),
     ConstMismatch(ExpectedFound<&'tcx ty::Const<'tcx>>),
@@ -174,13 +173,6 @@ impl<'tcx> fmt::Display for TypeError<'tcx> {
                     tcx.def_path_str(values.found)
                 )
             }),
-            ProjectionBoundsLength(ref values) => write!(
-                f,
-                "expected {} associated type binding{}, found {}",
-                values.expected,
-                pluralize!(values.expected),
-                values.found
-            ),
             ExistentialMismatch(ref values) => report_maybe_different(
                 f,
                 &format!("trait `{}`", values.expected),
@@ -216,7 +208,6 @@ impl<'tcx> TypeError<'tcx> {
             | RegionsPlaceholderMismatch
             | Traits(_)
             | ProjectionMismatched(_)
-            | ProjectionBoundsLength(_)
             | ExistentialMismatch(_)
             | ConstMismatch(_)
             | IntrinsicCast
diff --git a/src/librustc_middle/ty/flags.rs b/src/librustc_middle/ty/flags.rs
index c782eee9387..0e86fcf53b2 100644
--- a/src/librustc_middle/ty/flags.rs
+++ b/src/librustc_middle/ty/flags.rs
@@ -88,13 +88,13 @@ impl FlagComputation {
                 self.add_substs(substs);
             }
 
-            &ty::GeneratorWitness(ref ts) => {
+            &ty::GeneratorWitness(ts) => {
                 let mut computation = FlagComputation::new();
-                computation.add_tys(&ts.skip_binder()[..]);
+                computation.add_tys(ts.skip_binder());
                 self.add_bound_computation(computation);
             }
 
-            &ty::Closure(_, ref substs) => {
+            &ty::Closure(_, substs) => {
                 self.add_substs(substs);
             }
 
@@ -122,7 +122,7 @@ impl FlagComputation {
                 self.add_substs(substs);
             }
 
-            &ty::Projection(ref data) => {
+            &ty::Projection(data) => {
                 self.add_flags(TypeFlags::HAS_TY_PROJECTION);
                 self.add_projection_ty(data);
             }
@@ -211,7 +211,7 @@ impl FlagComputation {
 
                 self.add_bound_computation(computation);
             }
-            ty::PredicateKind::Projection(projection) => {
+            &ty::PredicateKind::Projection(projection) => {
                 let mut computation = FlagComputation::new();
                 let ty::ProjectionPredicate { projection_ty, ty } = projection.skip_binder();
                 computation.add_projection_ty(projection_ty);
@@ -298,7 +298,7 @@ impl FlagComputation {
         self.add_ty(projection.ty);
     }
 
-    fn add_projection_ty(&mut self, projection_ty: &ty::ProjectionTy<'_>) {
+    fn add_projection_ty(&mut self, projection_ty: ty::ProjectionTy<'_>) {
         self.add_substs(projection_ty.substs);
     }
 
diff --git a/src/librustc_middle/ty/fold.rs b/src/librustc_middle/ty/fold.rs
index 2d25c7c6ac9..492f8ce9ef1 100644
--- a/src/librustc_middle/ty/fold.rs
+++ b/src/librustc_middle/ty/fold.rs
@@ -336,7 +336,7 @@ impl<'tcx> TyCtxt<'tcx> {
         {
             fn visit_binder<T: TypeFoldable<'tcx>>(&mut self, t: &Binder<T>) -> bool {
                 self.outer_index.shift_in(1);
-                let result = t.skip_binder().visit_with(self);
+                let result = t.as_ref().skip_binder().visit_with(self);
                 self.outer_index.shift_out(1);
                 result
             }
@@ -558,7 +558,7 @@ impl<'tcx> TyCtxt<'tcx> {
         let fld_c = |bound_ct, ty| {
             self.mk_const(ty::Const { val: ty::ConstKind::Bound(ty::INNERMOST, bound_ct), ty })
         };
-        self.replace_escaping_bound_vars(value.skip_binder(), fld_r, fld_t, fld_c)
+        self.replace_escaping_bound_vars(value.as_ref().skip_binder(), fld_r, fld_t, fld_c)
     }
 
     /// Replaces all escaping bound vars. The `fld_r` closure replaces escaping
@@ -617,7 +617,7 @@ impl<'tcx> TyCtxt<'tcx> {
         H: FnMut(ty::BoundVar, Ty<'tcx>) -> &'tcx ty::Const<'tcx>,
         T: TypeFoldable<'tcx>,
     {
-        self.replace_escaping_bound_vars(value.skip_binder(), fld_r, fld_t, fld_c)
+        self.replace_escaping_bound_vars(value.as_ref().skip_binder(), fld_r, fld_t, fld_c)
     }
 
     /// Replaces any late-bound regions bound in `value` with
@@ -673,7 +673,7 @@ impl<'tcx> TyCtxt<'tcx> {
         T: TypeFoldable<'tcx>,
     {
         let mut collector = LateBoundRegionsCollector::new(just_constraint);
-        let result = value.skip_binder().visit_with(&mut collector);
+        let result = value.as_ref().skip_binder().visit_with(&mut collector);
         assert!(!result); // should never have stopped early
         collector.regions
     }
diff --git a/src/librustc_middle/ty/layout.rs b/src/librustc_middle/ty/layout.rs
index e4cc96dd83b..39b8566e7a8 100644
--- a/src/librustc_middle/ty/layout.rs
+++ b/src/librustc_middle/ty/layout.rs
@@ -2303,7 +2303,7 @@ impl<'tcx> ty::Instance<'tcx> {
 
                 let env_ty = tcx.closure_env_ty(def_id, substs).unwrap();
                 sig.map_bound(|sig| tcx.mk_fn_sig(
-                    iter::once(*env_ty.skip_binder()).chain(sig.inputs().iter().cloned()),
+                    iter::once(env_ty.skip_binder()).chain(sig.inputs().iter().cloned()),
                     sig.output(),
                     sig.c_variadic,
                     sig.unsafety,
diff --git a/src/librustc_middle/ty/print/pretty.rs b/src/librustc_middle/ty/print/pretty.rs
index 06121424971..9fa1260f64d 100644
--- a/src/librustc_middle/ty/print/pretty.rs
+++ b/src/librustc_middle/ty/print/pretty.rs
@@ -189,7 +189,7 @@ pub trait PrettyPrinter<'tcx>:
     where
         T: Print<'tcx, Self, Output = Self, Error = Self::Error> + TypeFoldable<'tcx>,
     {
-        value.skip_binder().print(self)
+        value.as_ref().skip_binder().print(self)
     }
 
     /// Prints comma-separated elements.
diff --git a/src/librustc_middle/ty/relate.rs b/src/librustc_middle/ty/relate.rs
index e9a8b9095bf..cee04ce8c6a 100644
--- a/src/librustc_middle/ty/relate.rs
+++ b/src/librustc_middle/ty/relate.rs
@@ -13,7 +13,6 @@ use rustc_hir::def_id::DefId;
 use rustc_span::DUMMY_SP;
 use rustc_target::spec::abi;
 use std::iter;
-use std::rc::Rc;
 
 pub type RelateResult<'tcx, T> = Result<T, TypeError<'tcx>>;
 
@@ -42,7 +41,7 @@ pub trait TypeRelation<'tcx>: Sized {
     }
 
     /// Generic relation routine suitable for most anything.
-    fn relate<T: Relate<'tcx>>(&mut self, a: &T, b: &T) -> RelateResult<'tcx, T> {
+    fn relate<T: Relate<'tcx>>(&mut self, a: T, b: T) -> RelateResult<'tcx, T> {
         Relate::relate(self, a, b)
     }
 
@@ -68,8 +67,8 @@ pub trait TypeRelation<'tcx>: Sized {
     fn relate_with_variance<T: Relate<'tcx>>(
         &mut self,
         variance: ty::Variance,
-        a: &T,
-        b: &T,
+        a: T,
+        b: T,
     ) -> RelateResult<'tcx, T>;
 
     // Overridable relations. You shouldn't typically call these
@@ -94,18 +93,18 @@ pub trait TypeRelation<'tcx>: Sized {
 
     fn binders<T>(
         &mut self,
-        a: &ty::Binder<T>,
-        b: &ty::Binder<T>,
+        a: ty::Binder<T>,
+        b: ty::Binder<T>,
     ) -> RelateResult<'tcx, ty::Binder<T>>
     where
         T: Relate<'tcx>;
 }
 
-pub trait Relate<'tcx>: TypeFoldable<'tcx> {
+pub trait Relate<'tcx>: TypeFoldable<'tcx> + Copy {
     fn relate<R: TypeRelation<'tcx>>(
         relation: &mut R,
-        a: &Self,
-        b: &Self,
+        a: Self,
+        b: Self,
     ) -> RelateResult<'tcx, Self>;
 }
 
@@ -115,8 +114,8 @@ pub trait Relate<'tcx>: TypeFoldable<'tcx> {
 impl<'tcx> Relate<'tcx> for ty::TypeAndMut<'tcx> {
     fn relate<R: TypeRelation<'tcx>>(
         relation: &mut R,
-        a: &ty::TypeAndMut<'tcx>,
-        b: &ty::TypeAndMut<'tcx>,
+        a: ty::TypeAndMut<'tcx>,
+        b: ty::TypeAndMut<'tcx>,
     ) -> RelateResult<'tcx, ty::TypeAndMut<'tcx>> {
         debug!("{}.mts({:?}, {:?})", relation.tag(), a, b);
         if a.mutbl != b.mutbl {
@@ -127,7 +126,7 @@ impl<'tcx> Relate<'tcx> for ty::TypeAndMut<'tcx> {
                 ast::Mutability::Not => ty::Covariant,
                 ast::Mutability::Mut => ty::Invariant,
             };
-            let ty = relation.relate_with_variance(variance, &a.ty, &b.ty)?;
+            let ty = relation.relate_with_variance(variance, a.ty, b.ty)?;
             Ok(ty::TypeAndMut { ty, mutbl })
         }
     }
@@ -143,7 +142,7 @@ pub fn relate_substs<R: TypeRelation<'tcx>>(
 
     let params = a_subst.iter().zip(b_subst).enumerate().map(|(i, (a, b))| {
         let variance = variances.map_or(ty::Invariant, |v| v[i]);
-        relation.relate_with_variance(variance, &a, &b)
+        relation.relate_with_variance(variance, a, b)
     });
 
     Ok(tcx.mk_substs(params)?)
@@ -152,8 +151,8 @@ pub fn relate_substs<R: TypeRelation<'tcx>>(
 impl<'tcx> Relate<'tcx> for ty::FnSig<'tcx> {
     fn relate<R: TypeRelation<'tcx>>(
         relation: &mut R,
-        a: &ty::FnSig<'tcx>,
-        b: &ty::FnSig<'tcx>,
+        a: ty::FnSig<'tcx>,
+        b: ty::FnSig<'tcx>,
     ) -> RelateResult<'tcx, ty::FnSig<'tcx>> {
         let tcx = relation.tcx();
 
@@ -164,8 +163,8 @@ impl<'tcx> Relate<'tcx> for ty::FnSig<'tcx> {
                 &b.c_variadic,
             )));
         }
-        let unsafety = relation.relate(&a.unsafety, &b.unsafety)?;
-        let abi = relation.relate(&a.abi, &b.abi)?;
+        let unsafety = relation.relate(a.unsafety, b.unsafety)?;
+        let abi = relation.relate(a.abi, b.abi)?;
 
         if a.inputs().len() != b.inputs().len() {
             return Err(TypeError::ArgCount);
@@ -180,9 +179,9 @@ impl<'tcx> Relate<'tcx> for ty::FnSig<'tcx> {
             .chain(iter::once(((a.output(), b.output()), true)))
             .map(|((a, b), is_output)| {
                 if is_output {
-                    relation.relate(&a, &b)
+                    relation.relate(a, b)
                 } else {
-                    relation.relate_with_variance(ty::Contravariant, &a, &b)
+                    relation.relate_with_variance(ty::Contravariant, a, b)
                 }
             });
         Ok(ty::FnSig {
@@ -197,13 +196,13 @@ impl<'tcx> Relate<'tcx> for ty::FnSig<'tcx> {
 impl<'tcx> Relate<'tcx> for ast::Unsafety {
     fn relate<R: TypeRelation<'tcx>>(
         relation: &mut R,
-        a: &ast::Unsafety,
-        b: &ast::Unsafety,
+        a: ast::Unsafety,
+        b: ast::Unsafety,
     ) -> RelateResult<'tcx, ast::Unsafety> {
         if a != b {
-            Err(TypeError::UnsafetyMismatch(expected_found(relation, a, b)))
+            Err(TypeError::UnsafetyMismatch(expected_found(relation, &a, &b)))
         } else {
-            Ok(*a)
+            Ok(a)
         }
     }
 }
@@ -211,18 +210,18 @@ impl<'tcx> Relate<'tcx> for ast::Unsafety {
 impl<'tcx> Relate<'tcx> for abi::Abi {
     fn relate<R: TypeRelation<'tcx>>(
         relation: &mut R,
-        a: &abi::Abi,
-        b: &abi::Abi,
+        a: abi::Abi,
+        b: abi::Abi,
     ) -> RelateResult<'tcx, abi::Abi> {
-        if a == b { Ok(*a) } else { Err(TypeError::AbiMismatch(expected_found(relation, a, b))) }
+        if a == b { Ok(a) } else { Err(TypeError::AbiMismatch(expected_found(relation, &a, &b))) }
     }
 }
 
 impl<'tcx> Relate<'tcx> for ty::ProjectionTy<'tcx> {
     fn relate<R: TypeRelation<'tcx>>(
         relation: &mut R,
-        a: &ty::ProjectionTy<'tcx>,
-        b: &ty::ProjectionTy<'tcx>,
+        a: ty::ProjectionTy<'tcx>,
+        b: ty::ProjectionTy<'tcx>,
     ) -> RelateResult<'tcx, ty::ProjectionTy<'tcx>> {
         if a.item_def_id != b.item_def_id {
             Err(TypeError::ProjectionMismatched(expected_found(
@@ -231,7 +230,7 @@ impl<'tcx> Relate<'tcx> for ty::ProjectionTy<'tcx> {
                 &b.item_def_id,
             )))
         } else {
-            let substs = relation.relate(&a.substs, &b.substs)?;
+            let substs = relation.relate(a.substs, b.substs)?;
             Ok(ty::ProjectionTy { item_def_id: a.item_def_id, substs: &substs })
         }
     }
@@ -240,8 +239,8 @@ impl<'tcx> Relate<'tcx> for ty::ProjectionTy<'tcx> {
 impl<'tcx> Relate<'tcx> for ty::ExistentialProjection<'tcx> {
     fn relate<R: TypeRelation<'tcx>>(
         relation: &mut R,
-        a: &ty::ExistentialProjection<'tcx>,
-        b: &ty::ExistentialProjection<'tcx>,
+        a: ty::ExistentialProjection<'tcx>,
+        b: ty::ExistentialProjection<'tcx>,
     ) -> RelateResult<'tcx, ty::ExistentialProjection<'tcx>> {
         if a.item_def_id != b.item_def_id {
             Err(TypeError::ProjectionMismatched(expected_found(
@@ -250,37 +249,18 @@ impl<'tcx> Relate<'tcx> for ty::ExistentialProjection<'tcx> {
                 &b.item_def_id,
             )))
         } else {
-            let ty = relation.relate_with_variance(ty::Invariant, &a.ty, &b.ty)?;
-            let substs = relation.relate_with_variance(ty::Invariant, &a.substs, &b.substs)?;
+            let ty = relation.relate_with_variance(ty::Invariant, a.ty, b.ty)?;
+            let substs = relation.relate_with_variance(ty::Invariant, a.substs, b.substs)?;
             Ok(ty::ExistentialProjection { item_def_id: a.item_def_id, substs, ty })
         }
     }
 }
 
-impl<'tcx> Relate<'tcx> for Vec<ty::PolyExistentialProjection<'tcx>> {
-    fn relate<R: TypeRelation<'tcx>>(
-        relation: &mut R,
-        a: &Vec<ty::PolyExistentialProjection<'tcx>>,
-        b: &Vec<ty::PolyExistentialProjection<'tcx>>,
-    ) -> RelateResult<'tcx, Vec<ty::PolyExistentialProjection<'tcx>>> {
-        // To be compatible, `a` and `b` must be for precisely the
-        // same set of traits and item names. We always require that
-        // projection bounds lists are sorted by trait-def-id and item-name,
-        // so we can just iterate through the lists pairwise, so long as they are the
-        // same length.
-        if a.len() != b.len() {
-            Err(TypeError::ProjectionBoundsLength(expected_found(relation, &a.len(), &b.len())))
-        } else {
-            a.iter().zip(b).map(|(a, b)| relation.relate(a, b)).collect()
-        }
-    }
-}
-
 impl<'tcx> Relate<'tcx> for ty::TraitRef<'tcx> {
     fn relate<R: TypeRelation<'tcx>>(
         relation: &mut R,
-        a: &ty::TraitRef<'tcx>,
-        b: &ty::TraitRef<'tcx>,
+        a: ty::TraitRef<'tcx>,
+        b: ty::TraitRef<'tcx>,
     ) -> RelateResult<'tcx, ty::TraitRef<'tcx>> {
         // Different traits cannot be related.
         if a.def_id != b.def_id {
@@ -295,8 +275,8 @@ impl<'tcx> Relate<'tcx> for ty::TraitRef<'tcx> {
 impl<'tcx> Relate<'tcx> for ty::ExistentialTraitRef<'tcx> {
     fn relate<R: TypeRelation<'tcx>>(
         relation: &mut R,
-        a: &ty::ExistentialTraitRef<'tcx>,
-        b: &ty::ExistentialTraitRef<'tcx>,
+        a: ty::ExistentialTraitRef<'tcx>,
+        b: ty::ExistentialTraitRef<'tcx>,
     ) -> RelateResult<'tcx, ty::ExistentialTraitRef<'tcx>> {
         // Different traits cannot be related.
         if a.def_id != b.def_id {
@@ -308,18 +288,18 @@ impl<'tcx> Relate<'tcx> for ty::ExistentialTraitRef<'tcx> {
     }
 }
 
-#[derive(Debug, Clone, TypeFoldable)]
+#[derive(Copy, Debug, Clone, TypeFoldable)]
 struct GeneratorWitness<'tcx>(&'tcx ty::List<Ty<'tcx>>);
 
 impl<'tcx> Relate<'tcx> for GeneratorWitness<'tcx> {
     fn relate<R: TypeRelation<'tcx>>(
         relation: &mut R,
-        a: &GeneratorWitness<'tcx>,
-        b: &GeneratorWitness<'tcx>,
+        a: GeneratorWitness<'tcx>,
+        b: GeneratorWitness<'tcx>,
     ) -> RelateResult<'tcx, GeneratorWitness<'tcx>> {
         assert_eq!(a.0.len(), b.0.len());
         let tcx = relation.tcx();
-        let types = tcx.mk_type_list(a.0.iter().zip(b.0).map(|(a, b)| relation.relate(&a, &b)))?;
+        let types = tcx.mk_type_list(a.0.iter().zip(b.0).map(|(a, b)| relation.relate(a, b)))?;
         Ok(GeneratorWitness(types))
     }
 }
@@ -327,8 +307,8 @@ impl<'tcx> Relate<'tcx> for GeneratorWitness<'tcx> {
 impl<'tcx> Relate<'tcx> for Ty<'tcx> {
     fn relate<R: TypeRelation<'tcx>>(
         relation: &mut R,
-        a: &Ty<'tcx>,
-        b: &Ty<'tcx>,
+        a: Ty<'tcx>,
+        b: Ty<'tcx>,
     ) -> RelateResult<'tcx, Ty<'tcx>> {
         relation.tys(a, b)
     }
@@ -379,7 +359,7 @@ pub fn super_relate_tys<R: TypeRelation<'tcx>>(
 
         (&ty::Foreign(a_id), &ty::Foreign(b_id)) if a_id == b_id => Ok(tcx.mk_foreign(a_id)),
 
-        (&ty::Dynamic(ref a_obj, ref a_region), &ty::Dynamic(ref b_obj, ref b_region)) => {
+        (&ty::Dynamic(a_obj, a_region), &ty::Dynamic(b_obj, b_region)) => {
             let region_bound = relation.with_cause(Cause::ExistentialRegionBound, |relation| {
                 relation.relate_with_variance(ty::Contravariant, a_region, b_region)
             })?;
@@ -392,7 +372,7 @@ pub fn super_relate_tys<R: TypeRelation<'tcx>>(
             // All Generator types with the same id represent
             // the (anonymous) type of the same generator expression. So
             // all of their regions should be equated.
-            let substs = relation.relate(&a_substs, &b_substs)?;
+            let substs = relation.relate(a_substs, b_substs)?;
             Ok(tcx.mk_generator(a_id, substs, movability))
         }
 
@@ -402,7 +382,7 @@ pub fn super_relate_tys<R: TypeRelation<'tcx>>(
             let a_types = a_types.map_bound(GeneratorWitness);
             let b_types = b_types.map_bound(GeneratorWitness);
             // Then remove the GeneratorWitness for the result
-            let types = relation.relate(&a_types, &b_types)?.map_bound(|witness| witness.0);
+            let types = relation.relate(a_types, b_types)?.map_bound(|witness| witness.0);
             Ok(tcx.mk_generator_witness(types))
         }
 
@@ -410,26 +390,26 @@ pub fn super_relate_tys<R: TypeRelation<'tcx>>(
             // All Closure types with the same id represent
             // the (anonymous) type of the same closure expression. So
             // all of their regions should be equated.
-            let substs = relation.relate(&a_substs, &b_substs)?;
+            let substs = relation.relate(a_substs, b_substs)?;
             Ok(tcx.mk_closure(a_id, &substs))
         }
 
-        (&ty::RawPtr(ref a_mt), &ty::RawPtr(ref b_mt)) => {
+        (&ty::RawPtr(a_mt), &ty::RawPtr(b_mt)) => {
             let mt = relation.relate(a_mt, b_mt)?;
             Ok(tcx.mk_ptr(mt))
         }
 
         (&ty::Ref(a_r, a_ty, a_mutbl), &ty::Ref(b_r, b_ty, b_mutbl)) => {
-            let r = relation.relate_with_variance(ty::Contravariant, &a_r, &b_r)?;
+            let r = relation.relate_with_variance(ty::Contravariant, a_r, b_r)?;
             let a_mt = ty::TypeAndMut { ty: a_ty, mutbl: a_mutbl };
             let b_mt = ty::TypeAndMut { ty: b_ty, mutbl: b_mutbl };
-            let mt = relation.relate(&a_mt, &b_mt)?;
+            let mt = relation.relate(a_mt, b_mt)?;
             Ok(tcx.mk_ref(r, mt))
         }
 
         (&ty::Array(a_t, sz_a), &ty::Array(b_t, sz_b)) => {
-            let t = relation.relate(&a_t, &b_t)?;
-            match relation.relate(&sz_a, &sz_b) {
+            let t = relation.relate(a_t, b_t)?;
+            match relation.relate(sz_a, sz_b) {
                 Ok(sz) => Ok(tcx.mk_ty(ty::Array(t, sz))),
                 // FIXME(#72219) Implement improved diagnostics for mismatched array
                 // length?
@@ -450,16 +430,14 @@ pub fn super_relate_tys<R: TypeRelation<'tcx>>(
         }
 
         (&ty::Slice(a_t), &ty::Slice(b_t)) => {
-            let t = relation.relate(&a_t, &b_t)?;
+            let t = relation.relate(a_t, b_t)?;
             Ok(tcx.mk_slice(t))
         }
 
         (&ty::Tuple(as_), &ty::Tuple(bs)) => {
             if as_.len() == bs.len() {
                 Ok(tcx.mk_tup(
-                    as_.iter()
-                        .zip(bs)
-                        .map(|(a, b)| relation.relate(&a.expect_ty(), &b.expect_ty())),
+                    as_.iter().zip(bs).map(|(a, b)| relation.relate(a.expect_ty(), b.expect_ty())),
                 )?)
             } else if !(as_.is_empty() || bs.is_empty()) {
                 Err(TypeError::TupleSize(expected_found(relation, &as_.len(), &bs.len())))
@@ -476,12 +454,12 @@ pub fn super_relate_tys<R: TypeRelation<'tcx>>(
         }
 
         (&ty::FnPtr(a_fty), &ty::FnPtr(b_fty)) => {
-            let fty = relation.relate(&a_fty, &b_fty)?;
+            let fty = relation.relate(a_fty, b_fty)?;
             Ok(tcx.mk_fn_ptr(fty))
         }
 
         // these two are already handled downstream in case of lazy normalization
-        (ty::Projection(a_data), ty::Projection(b_data)) => {
+        (&ty::Projection(a_data), &ty::Projection(b_data)) => {
             let projection_ty = relation.relate(a_data, b_data)?;
             Ok(tcx.mk_projection(projection_ty.item_def_id, projection_ty.substs))
         }
@@ -603,8 +581,8 @@ pub fn super_relate_consts<R: TypeRelation<'tcx>>(
             ty::ConstKind::Unevaluated(b_def_id, b_substs, b_promoted),
         ) if a_def_id == b_def_id && a_promoted == b_promoted => {
             let substs =
-                relation.relate_with_variance(ty::Variance::Invariant, &a_substs, &b_substs)?;
-            Ok(ty::ConstKind::Unevaluated(a_def_id, &substs, a_promoted))
+                relation.relate_with_variance(ty::Variance::Invariant, a_substs, b_substs)?;
+            Ok(ty::ConstKind::Unevaluated(a_def_id, substs, a_promoted))
         }
         _ => Err(TypeError::ConstMismatch(expected_found(relation, &a, &b))),
     };
@@ -614,8 +592,8 @@ pub fn super_relate_consts<R: TypeRelation<'tcx>>(
 impl<'tcx> Relate<'tcx> for &'tcx ty::List<ty::ExistentialPredicate<'tcx>> {
     fn relate<R: TypeRelation<'tcx>>(
         relation: &mut R,
-        a: &Self,
-        b: &Self,
+        a: Self,
+        b: Self,
     ) -> RelateResult<'tcx, Self> {
         let tcx = relation.tcx();
 
@@ -629,16 +607,16 @@ impl<'tcx> Relate<'tcx> for &'tcx ty::List<ty::ExistentialPredicate<'tcx>> {
         b_v.sort_by(|a, b| a.stable_cmp(tcx, b));
         b_v.dedup();
         if a_v.len() != b_v.len() {
-            return Err(TypeError::ExistentialMismatch(expected_found(relation, a, b)));
+            return Err(TypeError::ExistentialMismatch(expected_found(relation, &a, &b)));
         }
 
         let v = a_v.into_iter().zip(b_v.into_iter()).map(|(ep_a, ep_b)| {
             use crate::ty::ExistentialPredicate::*;
             match (ep_a, ep_b) {
-                (Trait(ref a), Trait(ref b)) => Ok(Trait(relation.relate(a, b)?)),
-                (Projection(ref a), Projection(ref b)) => Ok(Projection(relation.relate(a, b)?)),
-                (AutoTrait(ref a), AutoTrait(ref b)) if a == b => Ok(AutoTrait(*a)),
-                _ => Err(TypeError::ExistentialMismatch(expected_found(relation, a, b))),
+                (Trait(a), Trait(b)) => Ok(Trait(relation.relate(a, b)?)),
+                (Projection(a), Projection(b)) => Ok(Projection(relation.relate(a, b)?)),
+                (AutoTrait(a), AutoTrait(b)) if a == b => Ok(AutoTrait(a)),
+                _ => Err(TypeError::ExistentialMismatch(expected_found(relation, &a, &b))),
             }
         });
         Ok(tcx.mk_existential_predicates(v)?)
@@ -648,8 +626,8 @@ impl<'tcx> Relate<'tcx> for &'tcx ty::List<ty::ExistentialPredicate<'tcx>> {
 impl<'tcx> Relate<'tcx> for ty::ClosureSubsts<'tcx> {
     fn relate<R: TypeRelation<'tcx>>(
         relation: &mut R,
-        a: &ty::ClosureSubsts<'tcx>,
-        b: &ty::ClosureSubsts<'tcx>,
+        a: ty::ClosureSubsts<'tcx>,
+        b: ty::ClosureSubsts<'tcx>,
     ) -> RelateResult<'tcx, ty::ClosureSubsts<'tcx>> {
         let substs = relate_substs(relation, None, a.substs, b.substs)?;
         Ok(ty::ClosureSubsts { substs })
@@ -659,8 +637,8 @@ impl<'tcx> Relate<'tcx> for ty::ClosureSubsts<'tcx> {
 impl<'tcx> Relate<'tcx> for ty::GeneratorSubsts<'tcx> {
     fn relate<R: TypeRelation<'tcx>>(
         relation: &mut R,
-        a: &ty::GeneratorSubsts<'tcx>,
-        b: &ty::GeneratorSubsts<'tcx>,
+        a: ty::GeneratorSubsts<'tcx>,
+        b: ty::GeneratorSubsts<'tcx>,
     ) -> RelateResult<'tcx, ty::GeneratorSubsts<'tcx>> {
         let substs = relate_substs(relation, None, a.substs, b.substs)?;
         Ok(ty::GeneratorSubsts { substs })
@@ -670,8 +648,8 @@ impl<'tcx> Relate<'tcx> for ty::GeneratorSubsts<'tcx> {
 impl<'tcx> Relate<'tcx> for SubstsRef<'tcx> {
     fn relate<R: TypeRelation<'tcx>>(
         relation: &mut R,
-        a: &SubstsRef<'tcx>,
-        b: &SubstsRef<'tcx>,
+        a: SubstsRef<'tcx>,
+        b: SubstsRef<'tcx>,
     ) -> RelateResult<'tcx, SubstsRef<'tcx>> {
         relate_substs(relation, None, a, b)
     }
@@ -680,72 +658,48 @@ impl<'tcx> Relate<'tcx> for SubstsRef<'tcx> {
 impl<'tcx> Relate<'tcx> for ty::Region<'tcx> {
     fn relate<R: TypeRelation<'tcx>>(
         relation: &mut R,
-        a: &ty::Region<'tcx>,
-        b: &ty::Region<'tcx>,
+        a: ty::Region<'tcx>,
+        b: ty::Region<'tcx>,
     ) -> RelateResult<'tcx, ty::Region<'tcx>> {
-        relation.regions(*a, *b)
+        relation.regions(a, b)
     }
 }
 
 impl<'tcx> Relate<'tcx> for &'tcx ty::Const<'tcx> {
     fn relate<R: TypeRelation<'tcx>>(
         relation: &mut R,
-        a: &&'tcx ty::Const<'tcx>,
-        b: &&'tcx ty::Const<'tcx>,
+        a: &'tcx ty::Const<'tcx>,
+        b: &'tcx ty::Const<'tcx>,
     ) -> RelateResult<'tcx, &'tcx ty::Const<'tcx>> {
-        relation.consts(*a, *b)
+        relation.consts(a, b)
     }
 }
 
 impl<'tcx, T: Relate<'tcx>> Relate<'tcx> for ty::Binder<T> {
     fn relate<R: TypeRelation<'tcx>>(
         relation: &mut R,
-        a: &ty::Binder<T>,
-        b: &ty::Binder<T>,
+        a: ty::Binder<T>,
+        b: ty::Binder<T>,
     ) -> RelateResult<'tcx, ty::Binder<T>> {
         relation.binders(a, b)
     }
 }
 
-impl<'tcx, T: Relate<'tcx>> Relate<'tcx> for Rc<T> {
-    fn relate<R: TypeRelation<'tcx>>(
-        relation: &mut R,
-        a: &Rc<T>,
-        b: &Rc<T>,
-    ) -> RelateResult<'tcx, Rc<T>> {
-        let a: &T = a;
-        let b: &T = b;
-        Ok(Rc::new(relation.relate(a, b)?))
-    }
-}
-
-impl<'tcx, T: Relate<'tcx>> Relate<'tcx> for Box<T> {
-    fn relate<R: TypeRelation<'tcx>>(
-        relation: &mut R,
-        a: &Box<T>,
-        b: &Box<T>,
-    ) -> RelateResult<'tcx, Box<T>> {
-        let a: &T = a;
-        let b: &T = b;
-        Ok(Box::new(relation.relate(a, b)?))
-    }
-}
-
 impl<'tcx> Relate<'tcx> for GenericArg<'tcx> {
     fn relate<R: TypeRelation<'tcx>>(
         relation: &mut R,
-        a: &GenericArg<'tcx>,
-        b: &GenericArg<'tcx>,
+        a: GenericArg<'tcx>,
+        b: GenericArg<'tcx>,
     ) -> RelateResult<'tcx, GenericArg<'tcx>> {
         match (a.unpack(), b.unpack()) {
             (GenericArgKind::Lifetime(a_lt), GenericArgKind::Lifetime(b_lt)) => {
-                Ok(relation.relate(&a_lt, &b_lt)?.into())
+                Ok(relation.relate(a_lt, b_lt)?.into())
             }
             (GenericArgKind::Type(a_ty), GenericArgKind::Type(b_ty)) => {
-                Ok(relation.relate(&a_ty, &b_ty)?.into())
+                Ok(relation.relate(a_ty, b_ty)?.into())
             }
             (GenericArgKind::Const(a_ct), GenericArgKind::Const(b_ct)) => {
-                Ok(relation.relate(&a_ct, &b_ct)?.into())
+                Ok(relation.relate(a_ct, b_ct)?.into())
             }
             (GenericArgKind::Lifetime(unpacked), x) => {
                 bug!("impossible case reached: can't relate: {:?} with {:?}", unpacked, x)
@@ -763,22 +717,22 @@ impl<'tcx> Relate<'tcx> for GenericArg<'tcx> {
 impl<'tcx> Relate<'tcx> for ty::TraitPredicate<'tcx> {
     fn relate<R: TypeRelation<'tcx>>(
         relation: &mut R,
-        a: &ty::TraitPredicate<'tcx>,
-        b: &ty::TraitPredicate<'tcx>,
+        a: ty::TraitPredicate<'tcx>,
+        b: ty::TraitPredicate<'tcx>,
     ) -> RelateResult<'tcx, ty::TraitPredicate<'tcx>> {
-        Ok(ty::TraitPredicate { trait_ref: relation.relate(&a.trait_ref, &b.trait_ref)? })
+        Ok(ty::TraitPredicate { trait_ref: relation.relate(a.trait_ref, b.trait_ref)? })
     }
 }
 
 impl<'tcx> Relate<'tcx> for ty::ProjectionPredicate<'tcx> {
     fn relate<R: TypeRelation<'tcx>>(
         relation: &mut R,
-        a: &ty::ProjectionPredicate<'tcx>,
-        b: &ty::ProjectionPredicate<'tcx>,
+        a: ty::ProjectionPredicate<'tcx>,
+        b: ty::ProjectionPredicate<'tcx>,
     ) -> RelateResult<'tcx, ty::ProjectionPredicate<'tcx>> {
         Ok(ty::ProjectionPredicate {
-            projection_ty: relation.relate(&a.projection_ty, &b.projection_ty)?,
-            ty: relation.relate(&a.ty, &b.ty)?,
+            projection_ty: relation.relate(a.projection_ty, b.projection_ty)?,
+            ty: relation.relate(a.ty, b.ty)?,
         })
     }
 }
diff --git a/src/librustc_middle/ty/structural_impls.rs b/src/librustc_middle/ty/structural_impls.rs
index f736037b5c1..1d3607fe32f 100644
--- a/src/librustc_middle/ty/structural_impls.rs
+++ b/src/librustc_middle/ty/structural_impls.rs
@@ -514,7 +514,7 @@ impl<'a, 'tcx> Lift<'tcx> for ty::PredicateKind<'a> {
 impl<'tcx, T: Lift<'tcx>> Lift<'tcx> for ty::Binder<T> {
     type Lifted = ty::Binder<T::Lifted>;
     fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
-        tcx.lift(self.skip_binder()).map(ty::Binder::bind)
+        tcx.lift(self.as_ref().skip_binder()).map(ty::Binder::bind)
     }
 }
 
@@ -655,7 +655,6 @@ impl<'a, 'tcx> Lift<'tcx> for ty::error::TypeError<'a> {
             VariadicMismatch(x) => VariadicMismatch(x),
             CyclicTy(t) => return tcx.lift(&t).map(|t| CyclicTy(t)),
             ProjectionMismatched(x) => ProjectionMismatched(x),
-            ProjectionBoundsLength(x) => ProjectionBoundsLength(x),
             Sorts(ref x) => return tcx.lift(x).map(Sorts),
             ExistentialMismatch(ref x) => return tcx.lift(x).map(ExistentialMismatch),
             ConstMismatch(ref x) => return tcx.lift(x).map(ConstMismatch),
@@ -798,7 +797,7 @@ impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for ty::Binder<T> {
     }
 
     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
-        self.skip_binder().visit_with(visitor)
+        self.as_ref().skip_binder().visit_with(visitor)
     }
 
     fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
diff --git a/src/librustc_middle/ty/sty.rs b/src/librustc_middle/ty/sty.rs
index 8f86d2ef522..c7683cefd82 100644
--- a/src/librustc_middle/ty/sty.rs
+++ b/src/librustc_middle/ty/sty.rs
@@ -615,7 +615,7 @@ impl<'tcx> ExistentialPredicate<'tcx> {
 impl<'tcx> Binder<ExistentialPredicate<'tcx>> {
     pub fn with_self_ty(&self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> ty::Predicate<'tcx> {
         use crate::ty::ToPredicate;
-        match *self.skip_binder() {
+        match self.skip_binder() {
             ExistentialPredicate::Trait(tr) => {
                 Binder(tr).with_self_ty(tcx, self_ty).without_const().to_predicate(tcx)
             }
@@ -776,7 +776,7 @@ impl<'tcx> PolyTraitRef<'tcx> {
 
     pub fn to_poly_trait_predicate(&self) -> ty::PolyTraitPredicate<'tcx> {
         // Note that we preserve binding levels
-        Binder(ty::TraitPredicate { trait_ref: *self.skip_binder() })
+        Binder(ty::TraitPredicate { trait_ref: self.skip_binder() })
     }
 }
 
@@ -880,8 +880,8 @@ impl<T> Binder<T> {
     /// - extracting the `DefId` from a PolyTraitRef;
     /// - comparing the self type of a PolyTraitRef to see if it is equal to
     ///   a type parameter `X`, since the type `X` does not reference any regions
-    pub fn skip_binder(&self) -> &T {
-        &self.0
+    pub fn skip_binder(self) -> T {
+        self.0
     }
 
     pub fn as_ref(&self) -> Binder<&T> {
@@ -916,11 +916,7 @@ impl<T> Binder<T> {
     where
         T: TypeFoldable<'tcx>,
     {
-        if self.skip_binder().has_escaping_bound_vars() {
-            None
-        } else {
-            Some(self.skip_binder().clone())
-        }
+        if self.0.has_escaping_bound_vars() { None } else { Some(self.skip_binder()) }
     }
 
     /// Given two things that have the same binder level,
@@ -997,7 +993,7 @@ impl<'tcx> ProjectionTy<'tcx> {
     }
 }
 
-#[derive(Clone, Debug, TypeFoldable)]
+#[derive(Copy, Clone, Debug, TypeFoldable)]
 pub struct GenSig<'tcx> {
     pub resume_ty: Ty<'tcx>,
     pub yield_ty: Ty<'tcx>,
diff --git a/src/librustc_middle/ty/walk.rs b/src/librustc_middle/ty/walk.rs
index 633d4fda8a4..82c649b8f54 100644
--- a/src/librustc_middle/ty/walk.rs
+++ b/src/librustc_middle/ty/walk.rs
@@ -133,7 +133,7 @@ fn push_inner<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent: GenericArg<'tcx>)
             ty::Dynamic(obj, lt) => {
                 stack.push(lt.into());
                 stack.extend(obj.iter().rev().flat_map(|predicate| {
-                    let (substs, opt_ty) = match *predicate.skip_binder() {
+                    let (substs, opt_ty) = match predicate.skip_binder() {
                         ty::ExistentialPredicate::Trait(tr) => (tr.substs, None),
                         ty::ExistentialPredicate::Projection(p) => (p.substs, Some(p.ty)),
                         ty::ExistentialPredicate::AutoTrait(_) =>
diff --git a/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs b/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs
index e85f69554d0..17846055f6c 100644
--- a/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs
+++ b/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs
@@ -1923,7 +1923,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
 
                 // We use a mix of the HIR and the Ty types to get information
                 // as the HIR doesn't have full types for closure arguments.
-                let return_ty = *sig.output().skip_binder();
+                let return_ty = sig.output().skip_binder();
                 let mut return_span = fn_decl.output.span();
                 if let hir::FnRetTy::Return(ty) = &fn_decl.output {
                     if let hir::TyKind::Rptr(lifetime, _) = ty.kind {
@@ -1965,7 +1965,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                 let argument_ty = sig.inputs().skip_binder().first()?;
 
                 let return_span = fn_decl.output.span();
-                let return_ty = *sig.output().skip_binder();
+                let return_ty = sig.output().skip_binder();
 
                 // We expect the first argument to be a reference.
                 match argument_ty.kind {
diff --git a/src/librustc_mir/borrow_check/diagnostics/region_errors.rs b/src/librustc_mir/borrow_check/diagnostics/region_errors.rs
index 99b9788c20b..26c2aea41d5 100644
--- a/src/librustc_mir/borrow_check/diagnostics/region_errors.rs
+++ b/src/librustc_mir/borrow_check/diagnostics/region_errors.rs
@@ -122,7 +122,9 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
         if self.regioncx.universal_regions().is_universal_region(r) {
             Some(r)
         } else {
-            let upper_bound = self.regioncx.universal_upper_bound(r);
+            // We just want something nameable, even if it's not
+            // actually an upper bound.
+            let upper_bound = self.regioncx.approx_universal_upper_bound(r);
 
             if self.regioncx.upper_bound_in_region_scc(r, upper_bound) {
                 self.to_error_region_vid(upper_bound)
diff --git a/src/librustc_mir/borrow_check/region_infer/mod.rs b/src/librustc_mir/borrow_check/region_infer/mod.rs
index 3e459bd52f7..081125cb625 100644
--- a/src/librustc_mir/borrow_check/region_infer/mod.rs
+++ b/src/librustc_mir/borrow_check/region_infer/mod.rs
@@ -1114,6 +1114,40 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         lub
     }
 
+    /// Like `universal_upper_bound`, but returns an approximation more suitable
+    /// for diagnostics. If `r` contains multiple disjoint universal regions
+    /// (e.g. 'a and 'b in `fn foo<'a, 'b> { ... }`, we pick the lower-numbered region.
+    /// This corresponds to picking named regions over unnamed regions
+    /// (e.g. picking early-bound regions over a closure late-bound region).
+    ///
+    /// This means that the returned value may not be a true upper bound, since
+    /// only 'static is known to outlive disjoint universal regions.
+    /// Therefore, this method should only be used in diagnostic code,
+    /// where displaying *some* named universal region is better than
+    /// falling back to 'static.
+    pub(in crate::borrow_check) fn approx_universal_upper_bound(&self, r: RegionVid) -> RegionVid {
+        debug!("approx_universal_upper_bound(r={:?}={})", r, self.region_value_str(r));
+
+        // Find the smallest universal region that contains all other
+        // universal regions within `region`.
+        let mut lub = self.universal_regions.fr_fn_body;
+        let r_scc = self.constraint_sccs.scc(r);
+        let static_r = self.universal_regions.fr_static;
+        for ur in self.scc_values.universal_regions_outlived_by(r_scc) {
+            let new_lub = self.universal_region_relations.postdom_upper_bound(lub, ur);
+            debug!("approx_universal_upper_bound: ur={:?} lub={:?} new_lub={:?}", ur, lub, new_lub);
+            if ur != static_r && lub != static_r && new_lub == static_r {
+                lub = std::cmp::min(ur, lub);
+            } else {
+                lub = new_lub;
+            }
+        }
+
+        debug!("approx_universal_upper_bound: r={:?} lub={:?}", r, lub);
+
+        lub
+    }
+
     /// Tests if `test` is true when applied to `lower_bound` at
     /// `point`.
     fn eval_verify_bound(
diff --git a/src/librustc_mir/borrow_check/region_infer/opaque_types.rs b/src/librustc_mir/borrow_check/region_infer/opaque_types.rs
index 7e352bfba77..325dca8c8ca 100644
--- a/src/librustc_mir/borrow_check/region_infer/opaque_types.rs
+++ b/src/librustc_mir/borrow_check/region_infer/opaque_types.rs
@@ -141,7 +141,8 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     {
         tcx.fold_regions(&ty, &mut false, |region, _| match *region {
             ty::ReVar(vid) => {
-                let upper_bound = self.universal_upper_bound(vid);
+                // Find something that we can name
+                let upper_bound = self.approx_universal_upper_bound(vid);
                 self.definitions[upper_bound].external_name.unwrap_or(region)
             }
             _ => region,
diff --git a/src/librustc_mir/borrow_check/type_check/relate_tys.rs b/src/librustc_mir/borrow_check/type_check/relate_tys.rs
index 285d9ed6469..91b1a1fbd97 100644
--- a/src/librustc_mir/borrow_check/type_check/relate_tys.rs
+++ b/src/librustc_mir/borrow_check/type_check/relate_tys.rs
@@ -31,7 +31,7 @@ pub(super) fn relate_types<'tcx>(
         NllTypeRelatingDelegate::new(infcx, borrowck_context, locations, category),
         v,
     )
-    .relate(&a, &b)?;
+    .relate(a, b)?;
     Ok(())
 }
 
diff --git a/src/librustc_mir/interpret/intrinsics.rs b/src/librustc_mir/interpret/intrinsics.rs
index 88ba28dab82..01eb2d0b8e2 100644
--- a/src/librustc_mir/interpret/intrinsics.rs
+++ b/src/librustc_mir/interpret/intrinsics.rs
@@ -409,6 +409,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 );
                 self.copy_op(self.operand_index(args[0], index)?, dest)?;
             }
+            sym::likely | sym::unlikely => {
+                // These just return their argument
+                self.copy_op(args[0], dest)?;
+            }
             // FIXME(#73156): Handle source code coverage in const eval
             sym::count_code_region => (),
             _ => return Ok(false),
diff --git a/src/librustc_mir/transform/check_consts/validation.rs b/src/librustc_mir/transform/check_consts/validation.rs
index ca1f0aecd04..f00fc96e591 100644
--- a/src/librustc_mir/transform/check_consts/validation.rs
+++ b/src/librustc_mir/transform/check_consts/validation.rs
@@ -531,9 +531,12 @@ impl Visitor<'tcx> for Validator<'mir, 'tcx> {
                 if is_lang_panic_fn(self.tcx, def_id) {
                     self.check_op(ops::Panic);
                 } else if let Some(feature) = is_unstable_const_fn(self.tcx, def_id) {
-                    // Exempt unstable const fns inside of macros with
+                    // Exempt unstable const fns inside of macros or functions with
                     // `#[allow_internal_unstable]`.
-                    if !self.span.allows_unstable(feature) {
+                    use crate::transform::qualify_min_const_fn::lib_feature_allowed;
+                    if !self.span.allows_unstable(feature)
+                        && !lib_feature_allowed(self.tcx, self.def_id, feature)
+                    {
                         self.check_op(ops::FnCallUnstable(def_id, feature));
                     }
                 } else {
diff --git a/src/librustc_mir/transform/qualify_min_const_fn.rs b/src/librustc_mir/transform/qualify_min_const_fn.rs
index 5a3663384fb..2f5257080cd 100644
--- a/src/librustc_mir/transform/qualify_min_const_fn.rs
+++ b/src/librustc_mir/transform/qualify_min_const_fn.rs
@@ -328,6 +328,26 @@ fn feature_allowed(tcx: TyCtxt<'tcx>, def_id: DefId, feature_gate: Symbol) -> bo
         .map_or(false, |mut features| features.any(|name| name == feature_gate))
 }
 
+/// Returns `true` if the given library feature gate is allowed within the function with the given `DefId`.
+pub fn lib_feature_allowed(tcx: TyCtxt<'tcx>, def_id: DefId, feature_gate: Symbol) -> bool {
+    // All features require that the corresponding gate be enabled,
+    // even if the function has `#[allow_internal_unstable(the_gate)]`.
+    if !tcx.features().declared_lib_features.iter().any(|&(sym, _)| sym == feature_gate) {
+        return false;
+    }
+
+    // If this crate is not using stability attributes, or this function is not claiming to be a
+    // stable `const fn`, that is all that is required.
+    if !tcx.features().staged_api || tcx.has_attr(def_id, sym::rustc_const_unstable) {
+        return true;
+    }
+
+    // However, we cannot allow stable `const fn`s to use unstable features without an explicit
+    // opt-in via `allow_internal_unstable`.
+    attr::allow_internal_unstable(&tcx.get_attrs(def_id), &tcx.sess.diagnostic())
+        .map_or(false, |mut features| features.any(|name| name == feature_gate))
+}
+
 fn check_terminator(
     tcx: TyCtxt<'tcx>,
     body: &'a Body<'tcx>,
@@ -367,8 +387,17 @@ fn check_terminator(
             fn_span: _,
         } => {
             let fn_ty = func.ty(body, tcx);
-            if let ty::FnDef(def_id, _) = fn_ty.kind {
-                if !crate::const_eval::is_min_const_fn(tcx, def_id) {
+            if let ty::FnDef(fn_def_id, _) = fn_ty.kind {
+                // Allow unstable const if we opt in by using #[allow_internal_unstable]
+                // on function or macro declaration.
+                if !crate::const_eval::is_min_const_fn(tcx, fn_def_id)
+                    && !crate::const_eval::is_unstable_const_fn(tcx, fn_def_id)
+                        .map(|feature| {
+                            span.allows_unstable(feature)
+                                || lib_feature_allowed(tcx, def_id, feature)
+                        })
+                        .unwrap_or(false)
+                {
                     return Err((
                         span,
                         format!(
@@ -380,10 +409,10 @@ fn check_terminator(
                     ));
                 }
 
-                check_operand(tcx, func, span, def_id, body)?;
+                check_operand(tcx, func, span, fn_def_id, body)?;
 
                 for arg in args {
-                    check_operand(tcx, arg, span, def_id, body)?;
+                    check_operand(tcx, arg, span, fn_def_id, body)?;
                 }
                 Ok(())
             } else {
diff --git a/src/librustc_mir/transform/validate.rs b/src/librustc_mir/transform/validate.rs
index d3f486c815e..e794a6949d2 100644
--- a/src/librustc_mir/transform/validate.rs
+++ b/src/librustc_mir/transform/validate.rs
@@ -74,8 +74,8 @@ pub fn equal_up_to_regions(
         fn relate_with_variance<T: Relate<'tcx>>(
             &mut self,
             _: ty::Variance,
-            a: &T,
-            b: &T,
+            a: T,
+            b: T,
         ) -> RelateResult<'tcx, T> {
             // Ignore variance, require types to be exactly the same.
             self.relate(a, b)
@@ -108,8 +108,8 @@ pub fn equal_up_to_regions(
 
         fn binders<T>(
             &mut self,
-            a: &ty::Binder<T>,
-            b: &ty::Binder<T>,
+            a: ty::Binder<T>,
+            b: ty::Binder<T>,
         ) -> RelateResult<'tcx, ty::Binder<T>>
         where
             T: Relate<'tcx>,
@@ -121,7 +121,7 @@ pub fn equal_up_to_regions(
 
     // Instantiate and run relation.
     let mut relator: LifetimeIgnoreRelation<'tcx> = LifetimeIgnoreRelation { tcx: tcx, param_env };
-    relator.relate(&src, &dest).is_ok()
+    relator.relate(src, dest).is_ok()
 }
 
 struct TypeChecker<'a, 'tcx> {
diff --git a/src/librustc_mir_build/hair/pattern/_match.rs b/src/librustc_mir_build/hair/pattern/_match.rs
index 6ac5d41ec61..18b92bf29bf 100644
--- a/src/librustc_mir_build/hair/pattern/_match.rs
+++ b/src/librustc_mir_build/hair/pattern/_match.rs
@@ -4,8 +4,8 @@
 //! This file includes the logic for exhaustiveness and usefulness checking for
 //! pattern-matching. Specifically, given a list of patterns for a type, we can
 //! tell whether:
-//! (a) the patterns cover every possible constructor for the type [exhaustiveness]
-//! (b) each pattern is necessary [usefulness]
+//! (a) the patterns cover every possible constructor for the type (exhaustiveness)
+//! (b) each pattern is necessary (usefulness)
 //!
 //! The algorithm implemented here is a modified version of the one described in:
 //! http://moscova.inria.fr/~maranget/papers/warn/index.html
@@ -101,53 +101,54 @@
 //! To match the paper, the top of the stack is at the beginning / on the left.
 //!
 //! There are two important operations on pattern-stacks necessary to understand the algorithm:
-//!     1. We can pop a given constructor off the top of a stack. This operation is called
-//!        `specialize`, and is denoted `S(c, p)` where `c` is a constructor (like `Some` or
-//!        `None`) and `p` a pattern-stack.
-//!        If the pattern on top of the stack can cover `c`, this removes the constructor and
-//!        pushes its arguments onto the stack. It also expands OR-patterns into distinct patterns.
-//!        Otherwise the pattern-stack is discarded.
-//!        This essentially filters those pattern-stacks whose top covers the constructor `c` and
-//!        discards the others.
 //!
-//!        For example, the first pattern above initially gives a stack `[(Some(true), _)]`. If we
-//!        pop the tuple constructor, we are left with `[Some(true), _]`, and if we then pop the
-//!        `Some` constructor we get `[true, _]`. If we had popped `None` instead, we would get
-//!        nothing back.
+//! 1. We can pop a given constructor off the top of a stack. This operation is called
+//!    `specialize`, and is denoted `S(c, p)` where `c` is a constructor (like `Some` or
+//!    `None`) and `p` a pattern-stack.
+//!    If the pattern on top of the stack can cover `c`, this removes the constructor and
+//!    pushes its arguments onto the stack. It also expands OR-patterns into distinct patterns.
+//!    Otherwise the pattern-stack is discarded.
+//!    This essentially filters those pattern-stacks whose top covers the constructor `c` and
+//!    discards the others.
 //!
-//!        This returns zero or more new pattern-stacks, as follows. We look at the pattern `p_1`
-//!        on top of the stack, and we have four cases:
-//!             1.1. `p_1 = c(r_1, .., r_a)`, i.e. the top of the stack has constructor `c`. We
-//!                  push onto the stack the arguments of this constructor, and return the result:
-//!                     r_1, .., r_a, p_2, .., p_n
-//!             1.2. `p_1 = c'(r_1, .., r_a')` where `c ≠ c'`. We discard the current stack and
-//!                  return nothing.
-//!             1.3. `p_1 = _`. We push onto the stack as many wildcards as the constructor `c` has
-//!                  arguments (its arity), and return the resulting stack:
-//!                     _, .., _, p_2, .., p_n
-//!             1.4. `p_1 = r_1 | r_2`. We expand the OR-pattern and then recurse on each resulting
-//!                  stack:
-//!                     S(c, (r_1, p_2, .., p_n))
-//!                     S(c, (r_2, p_2, .., p_n))
+//!    For example, the first pattern above initially gives a stack `[(Some(true), _)]`. If we
+//!    pop the tuple constructor, we are left with `[Some(true), _]`, and if we then pop the
+//!    `Some` constructor we get `[true, _]`. If we had popped `None` instead, we would get
+//!    nothing back.
 //!
-//!     2. We can pop a wildcard off the top of the stack. This is called `D(p)`, where `p` is
-//!        a pattern-stack.
-//!        This is used when we know there are missing constructor cases, but there might be
-//!        existing wildcard patterns, so to check the usefulness of the matrix, we have to check
-//!        all its *other* components.
+//!    This returns zero or more new pattern-stacks, as follows. We look at the pattern `p_1`
+//!    on top of the stack, and we have four cases:
+//!         1.1. `p_1 = c(r_1, .., r_a)`, i.e. the top of the stack has constructor `c`. We
+//!              push onto the stack the arguments of this constructor, and return the result:
+//!                 r_1, .., r_a, p_2, .., p_n
+//!         1.2. `p_1 = c'(r_1, .., r_a')` where `c ≠ c'`. We discard the current stack and
+//!              return nothing.
+//!         1.3. `p_1 = _`. We push onto the stack as many wildcards as the constructor `c` has
+//!              arguments (its arity), and return the resulting stack:
+//!                 _, .., _, p_2, .., p_n
+//!         1.4. `p_1 = r_1 | r_2`. We expand the OR-pattern and then recurse on each resulting
+//!              stack:
+//!                 S(c, (r_1, p_2, .., p_n))
+//!                 S(c, (r_2, p_2, .., p_n))
 //!
-//!        It is computed as follows. We look at the pattern `p_1` on top of the stack,
-//!        and we have three cases:
-//!             1.1. `p_1 = c(r_1, .., r_a)`. We discard the current stack and return nothing.
-//!             1.2. `p_1 = _`. We return the rest of the stack:
-//!                     p_2, .., p_n
-//!             1.3. `p_1 = r_1 | r_2`. We expand the OR-pattern and then recurse on each resulting
-//!               stack.
-//!                     D((r_1, p_2, .., p_n))
-//!                     D((r_2, p_2, .., p_n))
+//! 2. We can pop a wildcard off the top of the stack. This is called `D(p)`, where `p` is
+//!    a pattern-stack.
+//!    This is used when we know there are missing constructor cases, but there might be
+//!    existing wildcard patterns, so to check the usefulness of the matrix, we have to check
+//!    all its *other* components.
 //!
-//!     Note that the OR-patterns are not always used directly in Rust, but are used to derive the
-//!     exhaustive integer matching rules, so they're written here for posterity.
+//!    It is computed as follows. We look at the pattern `p_1` on top of the stack,
+//!    and we have three cases:
+//!         1.1. `p_1 = c(r_1, .., r_a)`. We discard the current stack and return nothing.
+//!         1.2. `p_1 = _`. We return the rest of the stack:
+//!                 p_2, .., p_n
+//!         1.3. `p_1 = r_1 | r_2`. We expand the OR-pattern and then recurse on each resulting
+//!           stack.
+//!                 D((r_1, p_2, .., p_n))
+//!                 D((r_2, p_2, .., p_n))
+//!
+//! Note that the OR-patterns are not always used directly in Rust, but are used to derive the
+//! exhaustive integer matching rules, so they're written here for posterity.
 //!
 //! Both those operations extend straightforwardly to a list or pattern-stacks, i.e. a matrix, by
 //! working row-by-row. Popping a constructor ends up keeping only the matrix rows that start with
@@ -168,66 +169,66 @@
 //!
 //! Inductive step. (`n > 0`, i.e., whether there's at least one column
 //!                  [which may then be expanded into further columns later])
-//!     We're going to match on the top of the new pattern-stack, `p_1`.
-//!         - If `p_1 == c(r_1, .., r_a)`, i.e. we have a constructor pattern.
-//!           Then, the usefulness of `p_1` can be reduced to whether it is useful when
-//!           we ignore all the patterns in the first column of `P` that involve other constructors.
-//!           This is where `S(c, P)` comes in:
-//!           `U(P, p) := U(S(c, P), S(c, p))`
-//!           This special case is handled in `is_useful_specialized`.
+//! We're going to match on the top of the new pattern-stack, `p_1`.
+//!     - If `p_1 == c(r_1, .., r_a)`, i.e. we have a constructor pattern.
+//! Then, the usefulness of `p_1` can be reduced to whether it is useful when
+//! we ignore all the patterns in the first column of `P` that involve other constructors.
+//! This is where `S(c, P)` comes in:
+//! `U(P, p) := U(S(c, P), S(c, p))`
+//! This special case is handled in `is_useful_specialized`.
 //!
-//!           For example, if `P` is:
-//!           [
-//!               [Some(true), _],
-//!               [None, 0],
-//!           ]
-//!           and `p` is [Some(false), 0], then we don't care about row 2 since we know `p` only
-//!           matches values that row 2 doesn't. For row 1 however, we need to dig into the
-//!           arguments of `Some` to know whether some new value is covered. So we compute
-//!           `U([[true, _]], [false, 0])`.
+//! For example, if `P` is:
+//! [
+//! [Some(true), _],
+//! [None, 0],
+//! ]
+//! and `p` is [Some(false), 0], then we don't care about row 2 since we know `p` only
+//! matches values that row 2 doesn't. For row 1 however, we need to dig into the
+//! arguments of `Some` to know whether some new value is covered. So we compute
+//! `U([[true, _]], [false, 0])`.
 //!
-//!         - If `p_1 == _`, then we look at the list of constructors that appear in the first
-//!               component of the rows of `P`:
-//!             + If there are some constructors that aren't present, then we might think that the
-//!               wildcard `_` is useful, since it covers those constructors that weren't covered
-//!               before.
-//!               That's almost correct, but only works if there were no wildcards in those first
-//!               components. So we need to check that `p` is useful with respect to the rows that
-//!               start with a wildcard, if there are any. This is where `D` comes in:
-//!               `U(P, p) := U(D(P), D(p))`
+//!   - If `p_1 == _`, then we look at the list of constructors that appear in the first
+//! component of the rows of `P`:
+//!   + If there are some constructors that aren't present, then we might think that the
+//! wildcard `_` is useful, since it covers those constructors that weren't covered
+//! before.
+//! That's almost correct, but only works if there were no wildcards in those first
+//! components. So we need to check that `p` is useful with respect to the rows that
+//! start with a wildcard, if there are any. This is where `D` comes in:
+//! `U(P, p) := U(D(P), D(p))`
 //!
-//!               For example, if `P` is:
-//!               [
-//!                   [_, true, _],
-//!                   [None, false, 1],
-//!               ]
-//!               and `p` is [_, false, _], the `Some` constructor doesn't appear in `P`. So if we
-//!               only had row 2, we'd know that `p` is useful. However row 1 starts with a
-//!               wildcard, so we need to check whether `U([[true, _]], [false, 1])`.
+//! For example, if `P` is:
+//! [
+//!     [_, true, _],
+//!     [None, false, 1],
+//! ]
+//! and `p` is [_, false, _], the `Some` constructor doesn't appear in `P`. So if we
+//! only had row 2, we'd know that `p` is useful. However row 1 starts with a
+//! wildcard, so we need to check whether `U([[true, _]], [false, 1])`.
 //!
-//!             + Otherwise, all possible constructors (for the relevant type) are present. In this
-//!               case we must check whether the wildcard pattern covers any unmatched value. For
-//!               that, we can think of the `_` pattern as a big OR-pattern that covers all
-//!               possible constructors. For `Option`, that would mean `_ = None | Some(_)` for
-//!               example. The wildcard pattern is useful in this case if it is useful when
-//!               specialized to one of the possible constructors. So we compute:
-//!               `U(P, p) := ∃(k ϵ constructors) U(S(k, P), S(k, p))`
+//!   + Otherwise, all possible constructors (for the relevant type) are present. In this
+//! case we must check whether the wildcard pattern covers any unmatched value. For
+//! that, we can think of the `_` pattern as a big OR-pattern that covers all
+//! possible constructors. For `Option`, that would mean `_ = None | Some(_)` for
+//! example. The wildcard pattern is useful in this case if it is useful when
+//! specialized to one of the possible constructors. So we compute:
+//! `U(P, p) := ∃(k ϵ constructors) U(S(k, P), S(k, p))`
 //!
-//!               For example, if `P` is:
-//!               [
-//!                   [Some(true), _],
-//!                   [None, false],
-//!               ]
-//!               and `p` is [_, false], both `None` and `Some` constructors appear in the first
-//!               components of `P`. We will therefore try popping both constructors in turn: we
-//!               compute U([[true, _]], [_, false]) for the `Some` constructor, and U([[false]],
-//!               [false]) for the `None` constructor. The first case returns true, so we know that
-//!               `p` is useful for `P`. Indeed, it matches `[Some(false), _]` that wasn't matched
-//!               before.
+//! For example, if `P` is:
+//! [
+//!     [Some(true), _],
+//!     [None, false],
+//! ]
+//! and `p` is [_, false], both `None` and `Some` constructors appear in the first
+//! components of `P`. We will therefore try popping both constructors in turn: we
+//! compute `U([[true, _]], [_, false])` for the `Some` constructor, and `U([[false]],
+//! [false])` for the `None` constructor. The first case returns true, so we know that
+//! `p` is useful for `P`. Indeed, it matches `[Some(false), _]` that wasn't matched
+//! before.
 //!
-//!         - If `p_1 == r_1 | r_2`, then the usefulness depends on each `r_i` separately:
-//!           `U(P, p) := U(P, (r_1, p_2, .., p_n))
-//!                    || U(P, (r_2, p_2, .., p_n))`
+//!   - If `p_1 == r_1 | r_2`, then the usefulness depends on each `r_i` separately:
+//! `U(P, p) := U(P, (r_1, p_2, .., p_n))
+//!  || U(P, (r_2, p_2, .., p_n))`
 //!
 //! Modifications to the algorithm
 //! ------------------------------
diff --git a/src/librustc_parse/parser/diagnostics.rs b/src/librustc_parse/parser/diagnostics.rs
index fc9ffc30924..e27bbc532cf 100644
--- a/src/librustc_parse/parser/diagnostics.rs
+++ b/src/librustc_parse/parser/diagnostics.rs
@@ -1415,7 +1415,7 @@ impl<'a> Parser<'a> {
                 if self.token != token::Lt {
                     err.span_suggestion(
                         pat.span,
-                        "if this was a parameter name, give it a type",
+                        "if this is a parameter name, give it a type",
                         format!("{}: TypeName", ident),
                         Applicability::HasPlaceholders,
                     );
diff --git a/src/librustc_passes/intrinsicck.rs b/src/librustc_passes/intrinsicck.rs
index 683039df15a..e4f4885690f 100644
--- a/src/librustc_passes/intrinsicck.rs
+++ b/src/librustc_passes/intrinsicck.rs
@@ -422,7 +422,7 @@ impl Visitor<'tcx> for ExprVisitor<'tcx> {
                         let typ = self.tables.node_type(expr.hir_id);
                         let sig = typ.fn_sig(self.tcx);
                         let from = sig.inputs().skip_binder()[0];
-                        let to = *sig.output().skip_binder();
+                        let to = sig.output().skip_binder();
                         self.check_transmute(expr.span, from, to);
                     }
                 }
diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs
index 9e6e7ea962b..20f09ef52f0 100644
--- a/src/librustc_privacy/lib.rs
+++ b/src/librustc_privacy/lib.rs
@@ -92,14 +92,14 @@ where
         for (predicate, _span) in predicates {
             match predicate.kind() {
                 ty::PredicateKind::Trait(poly_predicate, _) => {
-                    let ty::TraitPredicate { trait_ref } = *poly_predicate.skip_binder();
+                    let ty::TraitPredicate { trait_ref } = poly_predicate.skip_binder();
                     if self.visit_trait(trait_ref) {
                         return true;
                     }
                 }
                 ty::PredicateKind::Projection(poly_predicate) => {
                     let ty::ProjectionPredicate { projection_ty, ty } =
-                        *poly_predicate.skip_binder();
+                        poly_predicate.skip_binder();
                     if ty.visit_with(self) {
                         return true;
                     }
@@ -108,7 +108,7 @@ where
                     }
                 }
                 ty::PredicateKind::TypeOutlives(poly_predicate) => {
-                    let ty::OutlivesPredicate(ty, _region) = *poly_predicate.skip_binder();
+                    let ty::OutlivesPredicate(ty, _region) = poly_predicate.skip_binder();
                     if ty.visit_with(self) {
                         return true;
                     }
@@ -175,7 +175,7 @@ where
             ty::Dynamic(predicates, ..) => {
                 // All traits in the list are considered the "primary" part of the type
                 // and are visited by shallow visitors.
-                for predicate in *predicates.skip_binder() {
+                for predicate in predicates.skip_binder() {
                     let trait_ref = match predicate {
                         ty::ExistentialPredicate::Trait(trait_ref) => trait_ref,
                         ty::ExistentialPredicate::Projection(proj) => proj.trait_ref(tcx),
@@ -1270,7 +1270,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> {
             );
 
             for (trait_predicate, _, _) in bounds.trait_bounds {
-                if self.visit_trait(*trait_predicate.skip_binder()) {
+                if self.visit_trait(trait_predicate.skip_binder()) {
                     return;
                 }
             }
diff --git a/src/librustc_span/symbol.rs b/src/librustc_span/symbol.rs
index 857734037af..e2f0d0b94c4 100644
--- a/src/librustc_span/symbol.rs
+++ b/src/librustc_span/symbol.rs
@@ -427,6 +427,7 @@ symbols! {
         lhs,
         lib,
         lifetime,
+        likely,
         line,
         link,
         linkage,
@@ -813,6 +814,7 @@ symbols! {
         underscore_lifetimes,
         uniform_paths,
         universal_impl_trait,
+        unlikely,
         unmarked_api,
         unreachable_code,
         unrestricted_attribute_tokens,
diff --git a/src/librustc_symbol_mangling/v0.rs b/src/librustc_symbol_mangling/v0.rs
index 7d117b77cf5..ecf27fbf542 100644
--- a/src/librustc_symbol_mangling/v0.rs
+++ b/src/librustc_symbol_mangling/v0.rs
@@ -219,7 +219,7 @@ impl SymbolMangler<'tcx> {
         lifetime_depths.end += lifetimes;
 
         self.binders.push(BinderLevel { lifetime_depths });
-        self = print_value(self, value.skip_binder())?;
+        self = print_value(self, value.as_ref().skip_binder())?;
         self.binders.pop();
 
         Ok(self)
diff --git a/src/librustc_trait_selection/opaque_types.rs b/src/librustc_trait_selection/opaque_types.rs
index adccdd0b261..ce478de7c75 100644
--- a/src/librustc_trait_selection/opaque_types.rs
+++ b/src/librustc_trait_selection/opaque_types.rs
@@ -691,7 +691,7 @@ where
     OP: FnMut(ty::Region<'tcx>),
 {
     fn visit_binder<T: TypeFoldable<'tcx>>(&mut self, t: &ty::Binder<T>) -> bool {
-        t.skip_binder().visit_with(self);
+        t.as_ref().skip_binder().visit_with(self);
         false // keep visiting
     }
 
diff --git a/src/librustc_trait_selection/traits/error_reporting/mod.rs b/src/librustc_trait_selection/traits/error_reporting/mod.rs
index fd0c1a54d27..49e43873df7 100644
--- a/src/librustc_trait_selection/traits/error_reporting/mod.rs
+++ b/src/librustc_trait_selection/traits/error_reporting/mod.rs
@@ -1569,7 +1569,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> {
                     // no need to overload user in such cases
                     return;
                 }
-                let &SubtypePredicate { a_is_expected: _, a, b } = data.skip_binder();
+                let SubtypePredicate { a_is_expected: _, a, b } = data.skip_binder();
                 // both must be type variables, or the other would've been instantiated
                 assert!(a.is_ty_var() && b.is_ty_var());
                 self.need_type_info_err(body_id, span, a, ErrorCode::E0282)
diff --git a/src/librustc_trait_selection/traits/error_reporting/on_unimplemented.rs b/src/librustc_trait_selection/traits/error_reporting/on_unimplemented.rs
index fd87759a762..ec51dddc2c8 100644
--- a/src/librustc_trait_selection/traits/error_reporting/on_unimplemented.rs
+++ b/src/librustc_trait_selection/traits/error_reporting/on_unimplemented.rs
@@ -122,7 +122,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
     ) -> OnUnimplementedNote {
         let def_id =
             self.impl_similar_to(trait_ref, obligation).unwrap_or_else(|| trait_ref.def_id());
-        let trait_ref = *trait_ref.skip_binder();
+        let trait_ref = trait_ref.skip_binder();
 
         let mut flags = vec![];
         flags.push((
@@ -219,7 +219,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
             }
         }
         if let ty::Dynamic(traits, _) = self_ty.kind {
-            for t in *traits.skip_binder() {
+            for t in traits.skip_binder() {
                 if let ty::ExistentialPredicate::Trait(trait_ref) = t {
                     flags.push((sym::_Self, Some(self.tcx.def_path_str(trait_ref.def_id))))
                 }
diff --git a/src/librustc_trait_selection/traits/error_reporting/suggestions.rs b/src/librustc_trait_selection/traits/error_reporting/suggestions.rs
index 176bd90303d..1fafa9ec035 100644
--- a/src/librustc_trait_selection/traits/error_reporting/suggestions.rs
+++ b/src/librustc_trait_selection/traits/error_reporting/suggestions.rs
@@ -1179,7 +1179,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
     ) -> DiagnosticBuilder<'tcx> {
         crate fn build_fn_sig_string<'tcx>(
             tcx: TyCtxt<'tcx>,
-            trait_ref: &ty::TraitRef<'tcx>,
+            trait_ref: ty::TraitRef<'tcx>,
         ) -> String {
             let inputs = trait_ref.substs.type_at(1);
             let sig = if let ty::Tuple(inputs) = inputs.kind {
@@ -1360,7 +1360,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
                         }
                         ty::GeneratorWitness(..) => {}
                         _ if generator.is_none() => {
-                            trait_ref = Some(*derived_obligation.parent_trait_ref.skip_binder());
+                            trait_ref = Some(derived_obligation.parent_trait_ref.skip_binder());
                             target_ty = Some(ty);
                         }
                         _ => {}
diff --git a/src/librustc_trait_selection/traits/select/candidate_assembly.rs b/src/librustc_trait_selection/traits/select/candidate_assembly.rs
index 4dab5814f7b..91c162872b2 100644
--- a/src/librustc_trait_selection/traits/select/candidate_assembly.rs
+++ b/src/librustc_trait_selection/traits/select/candidate_assembly.rs
@@ -220,7 +220,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         // Okay to skip binder because the substs on generator types never
         // touch bound regions, they just capture the in-scope
         // type/region parameters.
-        let self_ty = *obligation.self_ty().skip_binder();
+        let self_ty = obligation.self_ty().skip_binder();
         match self_ty.kind {
             ty::Generator(..) => {
                 debug!(
@@ -299,7 +299,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         }
 
         // Okay to skip binder because what we are inspecting doesn't involve bound regions.
-        let self_ty = *obligation.self_ty().skip_binder();
+        let self_ty = obligation.self_ty().skip_binder();
         match self_ty.kind {
             ty::Infer(ty::TyVar(_)) => {
                 debug!("assemble_fn_pointer_candidates: ambiguous self-type");
@@ -362,7 +362,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         candidates: &mut SelectionCandidateSet<'tcx>,
     ) -> Result<(), SelectionError<'tcx>> {
         // Okay to skip binder here because the tests we do below do not involve bound regions.
-        let self_ty = *obligation.self_ty().skip_binder();
+        let self_ty = obligation.self_ty().skip_binder();
         debug!("assemble_candidates_from_auto_impls(self_ty={:?})", self_ty);
 
         let def_id = obligation.predicate.def_id();
@@ -583,7 +583,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         candidates: &mut SelectionCandidateSet<'tcx>,
     ) -> Result<(), SelectionError<'tcx>> {
         // Okay to skip binder here because the tests we do below do not involve bound regions.
-        let self_ty = *obligation.self_ty().skip_binder();
+        let self_ty = obligation.self_ty().skip_binder();
         debug!("assemble_candidates_for_trait_alias(self_ty={:?})", self_ty);
 
         let def_id = obligation.predicate.def_id();
diff --git a/src/librustc_trait_selection/traits/select/confirmation.rs b/src/librustc_trait_selection/traits/select/confirmation.rs
index 834bf17227d..fa970589bbb 100644
--- a/src/librustc_trait_selection/traits/select/confirmation.rs
+++ b/src/librustc_trait_selection/traits/select/confirmation.rs
@@ -326,7 +326,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         // probably flatten the binder from the obligation and the binder
         // from the object. Have to try to make a broken test case that
         // results.
-        let self_ty = self.infcx.shallow_resolve(*obligation.self_ty().skip_binder());
+        let self_ty = self.infcx.shallow_resolve(obligation.self_ty().skip_binder());
         let poly_trait_ref = match self_ty.kind {
             ty::Dynamic(ref data, ..) => data
                 .principal()
@@ -379,7 +379,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         debug!("confirm_fn_pointer_candidate({:?})", obligation);
 
         // Okay to skip binder; it is reintroduced below.
-        let self_ty = self.infcx.shallow_resolve(*obligation.self_ty().skip_binder());
+        let self_ty = self.infcx.shallow_resolve(obligation.self_ty().skip_binder());
         let sig = self_ty.fn_sig(self.tcx());
         let trait_ref = closure_trait_ref_and_return_type(
             self.tcx(),
@@ -448,7 +448,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         // Okay to skip binder because the substs on generator types never
         // touch bound regions, they just capture the in-scope
         // type/region parameters.
-        let self_ty = self.infcx.shallow_resolve(*obligation.self_ty().skip_binder());
+        let self_ty = self.infcx.shallow_resolve(obligation.self_ty().skip_binder());
         let (generator_def_id, substs) = match self_ty.kind {
             ty::Generator(id, substs, _) => (id, substs),
             _ => bug!("closure candidate for non-closure {:?}", obligation),
@@ -497,7 +497,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         // Okay to skip binder because the substs on closure types never
         // touch bound regions, they just capture the in-scope
         // type/region parameters.
-        let self_ty = self.infcx.shallow_resolve(*obligation.self_ty().skip_binder());
+        let self_ty = self.infcx.shallow_resolve(obligation.self_ty().skip_binder());
         let (closure_def_id, substs) = match self_ty.kind {
             ty::Closure(id, substs) => (id, substs),
             _ => bug!("closure candidate for non-closure {:?}", obligation),
diff --git a/src/librustc_trait_selection/traits/select/mod.rs b/src/librustc_trait_selection/traits/select/mod.rs
index cff5efbfd0f..c41a27c6f43 100644
--- a/src/librustc_trait_selection/traits/select/mod.rs
+++ b/src/librustc_trait_selection/traits/select/mod.rs
@@ -748,8 +748,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             && stack.iter().skip(1).any(|prev| {
                 stack.obligation.param_env == prev.obligation.param_env
                     && self.match_fresh_trait_refs(
-                        &stack.fresh_trait_ref,
-                        &prev.fresh_trait_ref,
+                        stack.fresh_trait_ref,
+                        prev.fresh_trait_ref,
                         prev.obligation.param_env,
                     )
             })
@@ -1944,8 +1944,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
 
     fn match_fresh_trait_refs(
         &self,
-        previous: &ty::PolyTraitRef<'tcx>,
-        current: &ty::PolyTraitRef<'tcx>,
+        previous: ty::PolyTraitRef<'tcx>,
+        current: ty::PolyTraitRef<'tcx>,
         param_env: ty::ParamEnv<'tcx>,
     ) -> bool {
         let mut matcher = ty::_match::Match::new(self.tcx(), param_env);
diff --git a/src/librustc_trait_selection/traits/wf.rs b/src/librustc_trait_selection/traits/wf.rs
index 1825c159ff3..ebff2dd9b23 100644
--- a/src/librustc_trait_selection/traits/wf.rs
+++ b/src/librustc_trait_selection/traits/wf.rs
@@ -695,7 +695,7 @@ pub fn object_region_bounds<'tcx>(
     let open_ty = tcx.mk_ty_infer(ty::FreshTy(0));
 
     let predicates = existential_predicates.iter().filter_map(|predicate| {
-        if let ty::ExistentialPredicate::Projection(_) = *predicate.skip_binder() {
+        if let ty::ExistentialPredicate::Projection(_) = predicate.skip_binder() {
             None
         } else {
             Some(predicate.with_self_ty(tcx, open_ty))
diff --git a/src/librustc_traits/chalk/lowering.rs b/src/librustc_traits/chalk/lowering.rs
index e09359b8b3f..ed021e5b9de 100644
--- a/src/librustc_traits/chalk/lowering.rs
+++ b/src/librustc_traits/chalk/lowering.rs
@@ -615,7 +615,7 @@ crate fn collect_bound_vars<'a, 'tcx, T: TypeFoldable<'tcx>>(
     ty: &'a Binder<T>,
 ) -> (T, chalk_ir::VariableKinds<RustInterner<'tcx>>, BTreeMap<DefId, u32>) {
     let mut bound_vars_collector = BoundVarsCollector::new();
-    ty.skip_binder().visit_with(&mut bound_vars_collector);
+    ty.as_ref().skip_binder().visit_with(&mut bound_vars_collector);
     let mut parameters = bound_vars_collector.parameters;
     let named_parameters: BTreeMap<DefId, u32> = bound_vars_collector
         .named_parameters
@@ -625,7 +625,7 @@ crate fn collect_bound_vars<'a, 'tcx, T: TypeFoldable<'tcx>>(
         .collect();
 
     let mut bound_var_substitutor = NamedBoundVarSubstitutor::new(tcx, &named_parameters);
-    let new_ty = ty.skip_binder().fold_with(&mut bound_var_substitutor);
+    let new_ty = ty.as_ref().skip_binder().fold_with(&mut bound_var_substitutor);
 
     for var in named_parameters.values() {
         parameters.insert(*var, chalk_ir::VariableKind::Lifetime);
diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs
index 1b08bf2fc77..5d1949626dd 100644
--- a/src/librustc_typeck/astconv.rs
+++ b/src/librustc_typeck/astconv.rs
@@ -1802,7 +1802,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
 
         // Calling `skip_binder` is okay because the predicates are re-bound.
         let regular_trait_predicates = existential_trait_refs
-            .map(|trait_ref| ty::ExistentialPredicate::Trait(*trait_ref.skip_binder()));
+            .map(|trait_ref| ty::ExistentialPredicate::Trait(trait_ref.skip_binder()));
         let auto_trait_predicates = auto_traits
             .into_iter()
             .map(|trait_ref| ty::ExistentialPredicate::AutoTrait(trait_ref.trait_ref().def_id()));
@@ -1810,7 +1810,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
             .chain(auto_trait_predicates)
             .chain(
                 existential_projections
-                    .map(|x| ty::ExistentialPredicate::Projection(*x.skip_binder())),
+                    .map(|x| ty::ExistentialPredicate::Projection(x.skip_binder())),
             )
             .collect::<SmallVec<[_; 8]>>();
         v.sort_by(|a, b| a.stable_cmp(tcx, b));
diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs
index 6d09ddc925f..fce2b18b782 100644
--- a/src/librustc_typeck/check/closure.rs
+++ b/src/librustc_typeck/check/closure.rs
@@ -188,7 +188,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             }
             ty::Infer(ty::TyVar(vid)) => self.deduce_expectations_from_obligations(vid),
             ty::FnPtr(sig) => {
-                let expected_sig = ExpectedSig { cause_span: None, sig: *sig.skip_binder() };
+                let expected_sig = ExpectedSig { cause_span: None, sig: sig.skip_binder() };
                 (Some(expected_sig), Some(ty::ClosureKind::Fn))
             }
             _ => (None, None),
@@ -501,7 +501,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             for ((hir_ty, &supplied_ty), expected_ty) in decl
                 .inputs
                 .iter()
-                .zip(*supplied_sig.inputs().skip_binder()) // binder moved to (*) below
+                .zip(supplied_sig.inputs().skip_binder()) // binder moved to (*) below
                 .zip(expected_sigs.liberated_sig.inputs())
             // `liberated_sig` is E'.
             {
diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs
index b6cd8da2362..e6b3224050e 100644
--- a/src/librustc_typeck/check/coercion.rs
+++ b/src/librustc_typeck/check/coercion.rs
@@ -964,7 +964,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             let sig = self
                 .at(cause, self.param_env)
                 .trace(prev_ty, new_ty)
-                .lub(&a_sig, &b_sig)
+                .lub(a_sig, b_sig)
                 .map(|ok| self.register_infer_ok_obligations(ok))?;
 
             // Reify both sides and return the reified fn pointer type.
diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs
index 4e97ba41dcb..e6217e0cc1b 100644
--- a/src/librustc_typeck/check/compare_method.rs
+++ b/src/librustc_typeck/check/compare_method.rs
@@ -502,7 +502,7 @@ fn compare_self_type<'tcx>(
             ty::ImplContainer(_) => impl_trait_ref.self_ty(),
             ty::TraitContainer(_) => tcx.types.self_param,
         };
-        let self_arg_ty = *tcx.fn_sig(method.def_id).input(0).skip_binder();
+        let self_arg_ty = tcx.fn_sig(method.def_id).input(0).skip_binder();
         let param_env = ty::ParamEnv::reveal_all();
 
         tcx.infer_ctxt().enter(|infcx| {
diff --git a/src/librustc_typeck/check/dropck.rs b/src/librustc_typeck/check/dropck.rs
index e27c2e45039..f6991120f34 100644
--- a/src/librustc_typeck/check/dropck.rs
+++ b/src/librustc_typeck/check/dropck.rs
@@ -227,10 +227,10 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(
         let predicate_matches_closure = |p: Predicate<'tcx>| {
             let mut relator: SimpleEqRelation<'tcx> = SimpleEqRelation::new(tcx, self_param_env);
             match (predicate.kind(), p.kind()) {
-                (ty::PredicateKind::Trait(a, _), ty::PredicateKind::Trait(b, _)) => {
+                (&ty::PredicateKind::Trait(a, _), &ty::PredicateKind::Trait(b, _)) => {
                     relator.relate(a, b).is_ok()
                 }
-                (ty::PredicateKind::Projection(a), ty::PredicateKind::Projection(b)) => {
+                (&ty::PredicateKind::Projection(a), &ty::PredicateKind::Projection(b)) => {
                     relator.relate(a, b).is_ok()
                 }
                 _ => predicate == p,
@@ -310,8 +310,8 @@ impl TypeRelation<'tcx> for SimpleEqRelation<'tcx> {
     fn relate_with_variance<T: Relate<'tcx>>(
         &mut self,
         _: ty::Variance,
-        a: &T,
-        b: &T,
+        a: T,
+        b: T,
     ) -> RelateResult<'tcx, T> {
         // Here we ignore variance because we require drop impl's types
         // to be *exactly* the same as to the ones in the struct definition.
@@ -354,8 +354,8 @@ impl TypeRelation<'tcx> for SimpleEqRelation<'tcx> {
 
     fn binders<T>(
         &mut self,
-        a: &ty::Binder<T>,
-        b: &ty::Binder<T>,
+        a: ty::Binder<T>,
+        b: ty::Binder<T>,
     ) -> RelateResult<'tcx, ty::Binder<T>>
     where
         T: Relate<'tcx>,
@@ -364,8 +364,8 @@ impl TypeRelation<'tcx> for SimpleEqRelation<'tcx> {
 
         // Anonymizing the LBRs is necessary to solve (Issue #59497).
         // After we do so, it should be totally fine to skip the binders.
-        let anon_a = self.tcx.anonymize_late_bound_regions(a);
-        let anon_b = self.tcx.anonymize_late_bound_regions(b);
+        let anon_a = self.tcx.anonymize_late_bound_regions(&a);
+        let anon_b = self.tcx.anonymize_late_bound_regions(&b);
         self.relate(anon_a.skip_binder(), anon_b.skip_binder())?;
 
         Ok(a.clone())
diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs
index 67bdd04d371..b75dac52b93 100644
--- a/src/librustc_typeck/check/method/suggest.rs
+++ b/src/librustc_typeck/check/method/suggest.rs
@@ -608,7 +608,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             ty::Adt(def, _) => bound_spans.push((def_span(def.did), msg)),
                             // Point at the trait object that couldn't satisfy the bound.
                             ty::Dynamic(preds, _) => {
-                                for pred in *preds.skip_binder() {
+                                for pred in preds.skip_binder() {
                                     match pred {
                                         ty::ExistentialPredicate::Trait(tr) => {
                                             bound_spans.push((def_span(tr.def_id), msg.clone()))
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index 7c4048ab223..b617937d6bd 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -2446,7 +2446,7 @@ fn bounds_from_generic_predicates(
 /// Return placeholder code for the given function.
 fn fn_sig_suggestion(
     tcx: TyCtxt<'_>,
-    sig: &ty::FnSig<'_>,
+    sig: ty::FnSig<'_>,
     ident: Ident,
     predicates: ty::GenericPredicates<'_>,
     assoc: &ty::AssocItem,
diff --git a/src/librustc_typeck/check/op.rs b/src/librustc_typeck/check/op.rs
index 94a5685a992..a1e060b97ad 100644
--- a/src/librustc_typeck/check/op.rs
+++ b/src/librustc_typeck/check/op.rs
@@ -500,7 +500,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 return false;
             }
             // We're emitting a suggestion, so we can just ignore regions
-            let fn_sig = *self.tcx.fn_sig(def_id).skip_binder();
+            let fn_sig = self.tcx.fn_sig(def_id).skip_binder();
 
             let other_ty = if let FnDef(def_id, _) = other_ty.kind {
                 if !self.tcx.has_typeck_tables(def_id) {
diff --git a/src/librustc_typeck/coherence/mod.rs b/src/librustc_typeck/coherence/mod.rs
index a45a44a6801..3b203dd222a 100644
--- a/src/librustc_typeck/coherence/mod.rs
+++ b/src/librustc_typeck/coherence/mod.rs
@@ -216,7 +216,7 @@ fn check_object_overlap<'tcx>(
         let component_def_ids = data.iter().flat_map(|predicate| {
             match predicate.skip_binder() {
                 ty::ExistentialPredicate::Trait(tr) => Some(tr.def_id),
-                ty::ExistentialPredicate::AutoTrait(def_id) => Some(*def_id),
+                ty::ExistentialPredicate::AutoTrait(def_id) => Some(def_id),
                 // An associated type projection necessarily comes with
                 // an additional `Trait` requirement.
                 ty::ExistentialPredicate::Projection(..) => None,
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index b486e3d3536..8920203e6af 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -2102,11 +2102,11 @@ fn compute_sig_of_foreign_fn_decl<'tcx>(
                     .emit();
             }
         };
-        for (input, ty) in decl.inputs.iter().zip(*fty.inputs().skip_binder()) {
+        for (input, ty) in decl.inputs.iter().zip(fty.inputs().skip_binder()) {
             check(&input, ty)
         }
         if let hir::FnRetTy::Return(ref ty) = decl.output {
-            check(&ty, *fty.output().skip_binder())
+            check(&ty, fty.output().skip_binder())
         }
     }
 
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 73fe87b05d4..bfe8464347d 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -347,7 +347,7 @@ impl Clean<GenericBound> for (ty::PolyTraitRef<'_>, &[TypeBinding]) {
 
         GenericBound::TraitBound(
             PolyTrait {
-                trait_: (*poly_trait_ref.skip_binder(), bounds).clean(cx),
+                trait_: (poly_trait_ref.skip_binder(), bounds).clean(cx),
                 generic_params: late_bound_regions,
             },
             hir::TraitBoundModifier::None,
@@ -549,7 +549,7 @@ impl<'tcx> Clean<Option<WherePredicate>> for ty::PolyOutlivesPredicate<Ty<'tcx>,
 
 impl<'tcx> Clean<WherePredicate> for ty::PolyProjectionPredicate<'tcx> {
     fn clean(&self, cx: &DocContext<'_>) -> WherePredicate {
-        let ty::ProjectionPredicate { projection_ty, ty } = *self.skip_binder();
+        let ty::ProjectionPredicate { projection_ty, ty } = self.skip_binder();
         WherePredicate::EqPredicate { lhs: projection_ty.clean(cx), rhs: ty.clean(cx) }
     }
 }
@@ -1177,7 +1177,7 @@ impl Clean<Item> for ty::AssocItem {
                         ty::ImplContainer(def_id) => cx.tcx.type_of(def_id),
                         ty::TraitContainer(_) => cx.tcx.types.self_param,
                     };
-                    let self_arg_ty = *sig.input(0).skip_binder();
+                    let self_arg_ty = sig.input(0).skip_binder();
                     if self_arg_ty == self_ty {
                         decl.inputs.values[0].type_ = Generic(String::from("Self"));
                     } else if let ty::Ref(_, ty, _) = self_arg_ty.kind {
@@ -1679,7 +1679,7 @@ impl<'tcx> Clean<Type> for Ty<'tcx> {
                                 if let ty::PredicateKind::Projection(proj) = pred.kind() {
                                     let proj = proj.skip_binder();
                                     if proj.projection_ty.trait_ref(cx.tcx)
-                                        == *trait_ref.skip_binder()
+                                        == trait_ref.skip_binder()
                                     {
                                         Some(TypeBinding {
                                             name: cx
diff --git a/src/libstd/keyword_docs.rs b/src/libstd/keyword_docs.rs
index d972cf6db18..0b3386c05d5 100644
--- a/src/libstd/keyword_docs.rs
+++ b/src/libstd/keyword_docs.rs
@@ -1281,11 +1281,84 @@ mod self_upper_keyword {}
 
 #[doc(keyword = "static")]
 //
-/// A place that is valid for the duration of a program.
+/// A static item is a value which is valid for the entire duration of your
+/// program (a `'static` lifetime).
 ///
-/// The documentation for this keyword is [not yet complete]. Pull requests welcome!
+/// On the surface, `static` items seem very similar to [`const`]s: both contain
+/// a value, both require type annotations and both can only be initialized with
+/// constant functions and values. However, `static`s are notably different in
+/// that they represent a location in memory. That means that you can have
+/// references to `static` items and potentially even modify them, making them
+/// essentially global variables.
 ///
-/// [not yet complete]: https://github.com/rust-lang/rust/issues/34601
+/// Static items do not call [`drop`] at the end of the program.
+///
+/// There are two types of `static` items: those declared in association with
+/// the [`mut`] keyword and those without.
+///
+/// Static items cannot be moved:
+///
+/// ```rust,compile_fail,E0507
+/// static VEC: Vec<u32> = vec![];
+///
+/// fn move_vec(v: Vec<u32>) -> Vec<u32> {
+///     v
+/// }
+///
+/// // This line causes an error
+/// move_vec(VEC);
+/// ```
+///
+/// # Simple `static`s
+///
+/// Accessing non-[`mut`] `static` items is considered safe, but some
+/// restrictions apply. Most notably, the type of a `static` value needs to
+/// implement the [`Sync`] trait, ruling out interior mutability containers
+/// like [`RefCell`]. See the [Reference] for more information.
+///
+/// ```rust
+/// static FOO: [i32; 5] = [1, 2, 3, 4, 5];
+///
+/// let r1 = &FOO as *const _;
+/// let r2 = &FOO as *const _;
+/// // With a strictly read-only static, references will have the same adress
+/// assert_eq!(r1, r2);
+/// // A static item can be used just like a variable in many cases
+/// println!("{:?}", FOO);
+/// ```
+///
+/// # Mutable `static`s
+///
+/// If a `static` item is declared with the [`mut`] keyword, then it is allowed
+/// to be modified by the program. However, accessing mutable `static`s can
+/// cause undefined behavior in a number of ways, for example due to data races
+/// in a multithreaded context. As such, all accesses to mutable `static`s
+/// require an [`unsafe`] block.
+///
+/// Despite their unsafety, mutable `static`s are necessary in many contexts:
+/// they can be used to represent global state shared by the whole program or in
+/// [`extern`] blocks to bind to variables from C libraries.
+///
+/// In an [`extern`] block:
+///
+/// ```rust,no_run
+/// # #![allow(dead_code)]
+/// extern "C" {
+///     static mut ERROR_MESSAGE: *mut std::os::raw::c_char;
+/// }
+/// ```
+///
+/// Mutable `static`s, just like simple `static`s, have some restrictions that
+/// apply to them. See the [Reference] for more information.
+///
+/// [`const`]: keyword.const.html
+/// [`extern`]: keyword.extern.html
+/// [`mut`]: keyword.mut.html
+/// [`unsafe`]: keyword.unsafe.html
+/// [`drop`]: mem/fn.drop.html
+/// [`Sync`]: marker/trait.Sync.html
+/// [`RefCell`]: cell/struct.RefCell.html
+/// [Reference]: ../reference/items/static-items.html
 mod static_keyword {}
 
 #[doc(keyword = "struct")]
@@ -1463,9 +1536,44 @@ mod true_keyword {}
 //
 /// Define an alias for an existing type.
 ///
-/// The documentation for this keyword is [not yet complete]. Pull requests welcome!
+/// The syntax is `type Name = ExistingType;`.
 ///
-/// [not yet complete]: https://github.com/rust-lang/rust/issues/34601
+/// # Examples
+///
+/// `type` does **not** create a new type:
+///
+/// ```rust
+/// type Meters = u32;
+/// type Kilograms = u32;
+///
+/// let m: Meters = 3;
+/// let k: Kilograms = 3;
+///
+/// assert_eq!(m, k);
+/// ```
+///
+/// In traits, `type` is used to declare an [associated type]:
+///
+/// ```rust
+/// trait Iterator {
+///     // associated type declaration
+///     type Item;
+///     fn next(&mut self) -> Option<Self::Item>;
+/// }
+///
+/// struct Once<T>(Option<T>);
+///
+/// impl<T> Iterator for Once<T> {
+///     // associated type definition
+///     type Item = T;
+///     fn next(&mut self) -> Option<Self::Item> {
+///         self.0.take()
+///     }
+/// }
+/// ```
+///
+/// [`trait`]: keyword.trait.html
+/// [associated type]: ../reference/items/associated-items.html#associated-types
 mod type_keyword {}
 
 #[doc(keyword = "unsafe")]
diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs
index ef699ede2a1..372038df54f 100644
--- a/src/libstd/lib.rs
+++ b/src/libstd/lib.rs
@@ -316,7 +316,7 @@
 #![feature(toowned_clone_into)]
 #![feature(total_cmp)]
 #![feature(trace_macros)]
-#![feature(track_caller)]
+#![cfg_attr(bootstrap, feature(track_caller))]
 #![feature(try_reserve)]
 #![feature(unboxed_closures)]
 #![feature(untagged_unions)]
diff --git a/src/libstd/net/parser.rs b/src/libstd/net/parser.rs
index 3f38ee54710..12d3baf6333 100644
--- a/src/libstd/net/parser.rs
+++ b/src/libstd/net/parser.rs
@@ -10,163 +10,132 @@ use crate::str::FromStr;
 
 struct Parser<'a> {
     // parsing as ASCII, so can use byte array
-    s: &'a [u8],
-    pos: usize,
+    state: &'a [u8],
 }
 
 impl<'a> Parser<'a> {
-    fn new(s: &'a str) -> Parser<'a> {
-        Parser { s: s.as_bytes(), pos: 0 }
+    fn new(input: &'a str) -> Parser<'a> {
+        Parser { state: input.as_bytes() }
     }
 
     fn is_eof(&self) -> bool {
-        self.pos == self.s.len()
+        self.state.is_empty()
     }
 
-    // Commit only if parser returns Some
-    fn read_atomically<T, F>(&mut self, cb: F) -> Option<T>
+    /// Run a parser, and restore the pre-parse state if it fails
+    fn read_atomically<T, F>(&mut self, inner: F) -> Option<T>
     where
         F: FnOnce(&mut Parser<'_>) -> Option<T>,
     {
-        let pos = self.pos;
-        let r = cb(self);
-        if r.is_none() {
-            self.pos = pos;
+        let state = self.state;
+        let result = inner(self);
+        if result.is_none() {
+            self.state = state;
         }
-        r
+        result
     }
 
-    // Commit only if parser read till EOF
-    fn read_till_eof<T, F>(&mut self, cb: F) -> Option<T>
+    /// Run a parser, but fail if the entire input wasn't consumed.
+    /// Doesn't run atomically.
+    fn read_till_eof<T, F>(&mut self, inner: F) -> Option<T>
     where
         F: FnOnce(&mut Parser<'_>) -> Option<T>,
     {
-        self.read_atomically(move |p| cb(p).filter(|_| p.is_eof()))
+        inner(self).filter(|_| self.is_eof())
     }
 
-    // Apply 3 parsers sequentially
-    fn read_seq_3<A, B, C, PA, PB, PC>(&mut self, pa: PA, pb: PB, pc: PC) -> Option<(A, B, C)>
+    /// Same as read_till_eof, but returns a Result<AddrParseError> on failure
+    fn parse_with<T, F>(&mut self, inner: F) -> Result<T, AddrParseError>
     where
-        PA: FnOnce(&mut Parser<'_>) -> Option<A>,
-        PB: FnOnce(&mut Parser<'_>) -> Option<B>,
-        PC: FnOnce(&mut Parser<'_>) -> Option<C>,
+        F: FnOnce(&mut Parser<'_>) -> Option<T>,
     {
-        self.read_atomically(move |p| {
-            let a = pa(p);
-            let b = if a.is_some() { pb(p) } else { None };
-            let c = if b.is_some() { pc(p) } else { None };
-            match (a, b, c) {
-                (Some(a), Some(b), Some(c)) => Some((a, b, c)),
-                _ => None,
-            }
-        })
+        self.read_till_eof(inner).ok_or(AddrParseError(()))
     }
 
-    // Read next char
+    /// Read the next character from the input
     fn read_char(&mut self) -> Option<char> {
-        if self.is_eof() {
-            None
-        } else {
-            let r = self.s[self.pos] as char;
-            self.pos += 1;
-            Some(r)
-        }
-    }
-
-    // Return char and advance iff next char is equal to requested
-    fn read_given_char(&mut self, c: char) -> Option<char> {
-        self.read_atomically(|p| match p.read_char() {
-            Some(next) if next == c => Some(next),
-            _ => None,
+        self.state.split_first().map(|(&b, tail)| {
+            self.state = tail;
+            b as char
         })
     }
 
-    // Read digit
-    fn read_digit(&mut self, radix: u8) -> Option<u8> {
-        fn parse_digit(c: char, radix: u8) -> Option<u8> {
-            let c = c as u8;
-            // assuming radix is either 10 or 16
-            if c >= b'0' && c <= b'9' {
-                Some(c - b'0')
-            } else if radix > 10 && c >= b'a' && c < b'a' + (radix - 10) {
-                Some(c - b'a' + 10)
-            } else if radix > 10 && c >= b'A' && c < b'A' + (radix - 10) {
-                Some(c - b'A' + 10)
-            } else {
-                None
-            }
-        }
-
-        self.read_atomically(|p| p.read_char().and_then(|c| parse_digit(c, radix)))
+    /// Read the next character from the input if it matches the target
+    fn read_given_char(&mut self, target: char) -> Option<char> {
+        self.read_atomically(|p| p.read_char().filter(|&c| c == target))
     }
 
-    fn read_number_impl(&mut self, radix: u8, max_digits: u32, upto: u32) -> Option<u32> {
-        let mut r = 0;
-        let mut digit_count = 0;
-        loop {
-            match self.read_digit(radix) {
-                Some(d) => {
-                    r = r * (radix as u32) + (d as u32);
-                    digit_count += 1;
-                    if digit_count > max_digits || r >= upto {
-                        return None;
-                    }
-                }
-                None => {
-                    if digit_count == 0 {
-                        return None;
-                    } else {
-                        return Some(r);
-                    }
-                }
-            };
-        }
+    /// Helper for reading separators in an indexed loop. Reads the separator
+    /// character iff index > 0, then runs the parser. When used in a loop,
+    /// the separator character will only be read on index > 0 (see
+    /// read_ipv4_addr for an example)
+    fn read_separator<T, F>(&mut self, sep: char, index: usize, inner: F) -> Option<T>
+    where
+        F: FnOnce(&mut Parser<'_>) -> Option<T>,
+    {
+        self.read_atomically(move |p| {
+            if index > 0 {
+                let _ = p.read_given_char(sep)?;
+            }
+            inner(p)
+        })
     }
 
-    // Read number, failing if max_digits of number value exceeded
-    fn read_number(&mut self, radix: u8, max_digits: u32, upto: u32) -> Option<u32> {
-        self.read_atomically(|p| p.read_number_impl(radix, max_digits, upto))
+    // Read a single digit in the given radix. For instance, 0-9 in radix 10;
+    // 0-9A-F in radix 16.
+    fn read_digit(&mut self, radix: u32) -> Option<u32> {
+        self.read_atomically(move |p| p.read_char()?.to_digit(radix))
     }
 
-    fn read_ipv4_addr_impl(&mut self) -> Option<Ipv4Addr> {
-        let mut bs = [0; 4];
-        let mut i = 0;
-        while i < 4 {
-            if i != 0 && self.read_given_char('.').is_none() {
-                return None;
+    // Read a number off the front of the input in the given radix, stopping
+    // at the first non-digit character or eof. Fails if the number has more
+    // digits than max_digits, or the value is >= upto, or if there is no number.
+    fn read_number(&mut self, radix: u32, max_digits: u32, upto: u32) -> Option<u32> {
+        self.read_atomically(move |p| {
+            let mut result = 0;
+            let mut digit_count = 0;
+
+            while let Some(digit) = p.read_digit(radix) {
+                result = (result * radix) + digit;
+                digit_count += 1;
+                if digit_count > max_digits || result >= upto {
+                    return None;
+                }
             }
 
-            bs[i] = self.read_number(10, 3, 0x100).map(|n| n as u8)?;
-            i += 1;
-        }
-        Some(Ipv4Addr::new(bs[0], bs[1], bs[2], bs[3]))
+            if digit_count == 0 { None } else { Some(result) }
+        })
     }
 
-    // Read IPv4 address
+    /// Read an IPv4 address
     fn read_ipv4_addr(&mut self) -> Option<Ipv4Addr> {
-        self.read_atomically(|p| p.read_ipv4_addr_impl())
-    }
+        self.read_atomically(|p| {
+            let mut groups = [0; 4];
 
-    fn read_ipv6_addr_impl(&mut self) -> Option<Ipv6Addr> {
-        fn ipv6_addr_from_head_tail(head: &[u16], tail: &[u16]) -> Ipv6Addr {
-            assert!(head.len() + tail.len() <= 8);
-            let mut gs = [0; 8];
-            gs[..head.len()].copy_from_slice(head);
-            gs[(8 - tail.len())..8].copy_from_slice(tail);
-            Ipv6Addr::new(gs[0], gs[1], gs[2], gs[3], gs[4], gs[5], gs[6], gs[7])
-        }
+            for (i, slot) in groups.iter_mut().enumerate() {
+                *slot = p.read_separator('.', i, |p| p.read_number(10, 3, 0x100))? as u8;
+            }
+
+            Some(groups.into())
+        })
+    }
 
-        fn read_groups(p: &mut Parser<'_>, groups: &mut [u16; 8], limit: usize) -> (usize, bool) {
-            let mut i = 0;
-            while i < limit {
+    /// Read an IPV6 Address
+    fn read_ipv6_addr(&mut self) -> Option<Ipv6Addr> {
+        /// Read a chunk of an ipv6 address into `groups`. Returns the number
+        /// of groups read, along with a bool indicating if an embedded
+        /// trailing ipv4 address was read. Specifically, read a series of
+        /// colon-separated ipv6 groups (0x0000 - 0xFFFF), with an optional
+        /// trailing embedded ipv4 address.
+        fn read_groups(p: &mut Parser<'_>, groups: &mut [u16]) -> (usize, bool) {
+            let limit = groups.len();
+
+            for (i, slot) in groups.iter_mut().enumerate() {
+                // Try to read a trailing embedded ipv4 address. There must be
+                // at least two groups left.
                 if i < limit - 1 {
-                    let ipv4 = p.read_atomically(|p| {
-                        if i == 0 || p.read_given_char(':').is_some() {
-                            p.read_ipv4_addr()
-                        } else {
-                            None
-                        }
-                    });
+                    let ipv4 = p.read_separator(':', i, |p| p.read_ipv4_addr());
+
                     if let Some(v4_addr) = ipv4 {
                         let octets = v4_addr.octets();
                         groups[i + 0] = ((octets[0] as u16) << 8) | (octets[1] as u16);
@@ -175,83 +144,85 @@ impl<'a> Parser<'a> {
                     }
                 }
 
-                let group = p.read_atomically(|p| {
-                    if i == 0 || p.read_given_char(':').is_some() {
-                        p.read_number(16, 4, 0x10000).map(|n| n as u16)
-                    } else {
-                        None
-                    }
-                });
+                let group = p.read_separator(':', i, |p| p.read_number(16, 4, 0x10000));
+
                 match group {
-                    Some(g) => groups[i] = g,
+                    Some(g) => *slot = g as u16,
                     None => return (i, false),
                 }
-                i += 1;
             }
-            (i, false)
+            (groups.len(), false)
         }
 
-        let mut head = [0; 8];
-        let (head_size, head_ipv4) = read_groups(self, &mut head, 8);
+        self.read_atomically(|p| {
+            // Read the front part of the address; either the whole thing, or up
+            // to the first ::
+            let mut head = [0; 8];
+            let (head_size, head_ipv4) = read_groups(p, &mut head);
 
-        if head_size == 8 {
-            return Some(Ipv6Addr::new(
-                head[0], head[1], head[2], head[3], head[4], head[5], head[6], head[7],
-            ));
-        }
+            if head_size == 8 {
+                return Some(head.into());
+            }
 
-        // IPv4 part is not allowed before `::`
-        if head_ipv4 {
-            return None;
-        }
+            // IPv4 part is not allowed before `::`
+            if head_ipv4 {
+                return None;
+            }
 
-        // read `::` if previous code parsed less than 8 groups
-        if self.read_given_char(':').is_none() || self.read_given_char(':').is_none() {
-            return None;
-        }
+            // read `::` if previous code parsed less than 8 groups
+            // `::` indicates one or more groups of 16 bits of zeros
+            let _ = p.read_given_char(':')?;
+            let _ = p.read_given_char(':')?;
 
-        let mut tail = [0; 8];
-        // `::` indicates one or more groups of 16 bits of zeros
-        let limit = 8 - (head_size + 1);
-        let (tail_size, _) = read_groups(self, &mut tail, limit);
-        Some(ipv6_addr_from_head_tail(&head[..head_size], &tail[..tail_size]))
-    }
+            // Read the back part of the address. The :: must contain at least one
+            // set of zeroes, so our max length is 7.
+            let mut tail = [0; 7];
+            let limit = 8 - (head_size + 1);
+            let (tail_size, _) = read_groups(p, &mut tail[..limit]);
 
-    fn read_ipv6_addr(&mut self) -> Option<Ipv6Addr> {
-        self.read_atomically(|p| p.read_ipv6_addr_impl())
+            // Concat the head and tail of the IP address
+            head[(8 - tail_size)..8].copy_from_slice(&tail[..tail_size]);
+
+            Some(head.into())
+        })
     }
 
+    /// Read an IP Address, either IPV4 or IPV6.
     fn read_ip_addr(&mut self) -> Option<IpAddr> {
-        self.read_ipv4_addr().map(IpAddr::V4).or_else(|| self.read_ipv6_addr().map(IpAddr::V6))
+        self.read_ipv4_addr().map(IpAddr::V4).or_else(move || self.read_ipv6_addr().map(IpAddr::V6))
     }
 
-    fn read_socket_addr_v4(&mut self) -> Option<SocketAddrV4> {
-        let ip_addr = |p: &mut Parser<'_>| p.read_ipv4_addr();
-        let colon = |p: &mut Parser<'_>| p.read_given_char(':');
-        let port = |p: &mut Parser<'_>| p.read_number(10, 5, 0x10000).map(|n| n as u16);
+    /// Read a : followed by a port in base 10
+    fn read_port(&mut self) -> Option<u16> {
+        self.read_atomically(|p| {
+            let _ = p.read_given_char(':')?;
+            let port = p.read_number(10, 5, 0x10000)?;
+            Some(port as u16)
+        })
+    }
 
-        self.read_seq_3(ip_addr, colon, port).map(|t| {
-            let (ip, _, port): (Ipv4Addr, char, u16) = t;
-            SocketAddrV4::new(ip, port)
+    /// Read an IPV4 address with a port
+    fn read_socket_addr_v4(&mut self) -> Option<SocketAddrV4> {
+        self.read_atomically(|p| {
+            let ip = p.read_ipv4_addr()?;
+            let port = p.read_port()?;
+            Some(SocketAddrV4::new(ip, port))
         })
     }
 
+    /// Read an IPV6 address with a port
     fn read_socket_addr_v6(&mut self) -> Option<SocketAddrV6> {
-        let ip_addr = |p: &mut Parser<'_>| {
-            let open_br = |p: &mut Parser<'_>| p.read_given_char('[');
-            let ip_addr = |p: &mut Parser<'_>| p.read_ipv6_addr();
-            let clos_br = |p: &mut Parser<'_>| p.read_given_char(']');
-            p.read_seq_3(open_br, ip_addr, clos_br).map(|t| t.1)
-        };
-        let colon = |p: &mut Parser<'_>| p.read_given_char(':');
-        let port = |p: &mut Parser<'_>| p.read_number(10, 5, 0x10000).map(|n| n as u16);
-
-        self.read_seq_3(ip_addr, colon, port).map(|t| {
-            let (ip, _, port): (Ipv6Addr, char, u16) = t;
-            SocketAddrV6::new(ip, port, 0, 0)
+        self.read_atomically(|p| {
+            let _ = p.read_given_char('[')?;
+            let ip = p.read_ipv6_addr()?;
+            let _ = p.read_given_char(']')?;
+
+            let port = p.read_port()?;
+            Some(SocketAddrV6::new(ip, port, 0, 0))
         })
     }
 
+    /// Read an IP address with a port
     fn read_socket_addr(&mut self) -> Option<SocketAddr> {
         self.read_socket_addr_v4()
             .map(SocketAddr::V4)
@@ -263,10 +234,7 @@ impl<'a> Parser<'a> {
 impl FromStr for IpAddr {
     type Err = AddrParseError;
     fn from_str(s: &str) -> Result<IpAddr, AddrParseError> {
-        match Parser::new(s).read_till_eof(|p| p.read_ip_addr()) {
-            Some(s) => Ok(s),
-            None => Err(AddrParseError(())),
-        }
+        Parser::new(s).parse_with(|p| p.read_ip_addr())
     }
 }
 
@@ -274,10 +242,7 @@ impl FromStr for IpAddr {
 impl FromStr for Ipv4Addr {
     type Err = AddrParseError;
     fn from_str(s: &str) -> Result<Ipv4Addr, AddrParseError> {
-        match Parser::new(s).read_till_eof(|p| p.read_ipv4_addr()) {
-            Some(s) => Ok(s),
-            None => Err(AddrParseError(())),
-        }
+        Parser::new(s).parse_with(|p| p.read_ipv4_addr())
     }
 }
 
@@ -285,10 +250,7 @@ impl FromStr for Ipv4Addr {
 impl FromStr for Ipv6Addr {
     type Err = AddrParseError;
     fn from_str(s: &str) -> Result<Ipv6Addr, AddrParseError> {
-        match Parser::new(s).read_till_eof(|p| p.read_ipv6_addr()) {
-            Some(s) => Ok(s),
-            None => Err(AddrParseError(())),
-        }
+        Parser::new(s).parse_with(|p| p.read_ipv6_addr())
     }
 }
 
@@ -296,10 +258,7 @@ impl FromStr for Ipv6Addr {
 impl FromStr for SocketAddrV4 {
     type Err = AddrParseError;
     fn from_str(s: &str) -> Result<SocketAddrV4, AddrParseError> {
-        match Parser::new(s).read_till_eof(|p| p.read_socket_addr_v4()) {
-            Some(s) => Ok(s),
-            None => Err(AddrParseError(())),
-        }
+        Parser::new(s).parse_with(|p| p.read_socket_addr_v4())
     }
 }
 
@@ -307,10 +266,7 @@ impl FromStr for SocketAddrV4 {
 impl FromStr for SocketAddrV6 {
     type Err = AddrParseError;
     fn from_str(s: &str) -> Result<SocketAddrV6, AddrParseError> {
-        match Parser::new(s).read_till_eof(|p| p.read_socket_addr_v6()) {
-            Some(s) => Ok(s),
-            None => Err(AddrParseError(())),
-        }
+        Parser::new(s).parse_with(|p| p.read_socket_addr_v6())
     }
 }
 
@@ -318,10 +274,7 @@ impl FromStr for SocketAddrV6 {
 impl FromStr for SocketAddr {
     type Err = AddrParseError;
     fn from_str(s: &str) -> Result<SocketAddr, AddrParseError> {
-        match Parser::new(s).read_till_eof(|p| p.read_socket_addr()) {
-            Some(s) => Ok(s),
-            None => Err(AddrParseError(())),
-        }
+        Parser::new(s).parse_with(|p| p.read_socket_addr())
     }
 }
 
@@ -376,3 +329,146 @@ impl Error for AddrParseError {
         "invalid IP address syntax"
     }
 }
+
+#[cfg(test)]
+mod tests {
+    // FIXME: These tests are all excellent candidates for AFL fuzz testing
+    use crate::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6};
+    use crate::str::FromStr;
+
+    const PORT: u16 = 8080;
+
+    const IPV4: Ipv4Addr = Ipv4Addr::new(192, 168, 0, 1);
+    const IPV4_STR: &str = "192.168.0.1";
+    const IPV4_STR_PORT: &str = "192.168.0.1:8080";
+
+    const IPV6: Ipv6Addr = Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0xc0a8, 0x1);
+    const IPV6_STR_FULL: &str = "2001:db8:0:0:0:0:c0a8:1";
+    const IPV6_STR_COMPRESS: &str = "2001:db8::c0a8:1";
+    const IPV6_STR_V4: &str = "2001:db8::192.168.0.1";
+    const IPV6_STR_PORT: &str = "[2001:db8::c0a8:1]:8080";
+
+    #[test]
+    fn parse_ipv4() {
+        let result: Ipv4Addr = IPV4_STR.parse().unwrap();
+        assert_eq!(result, IPV4);
+
+        assert!(Ipv4Addr::from_str(IPV4_STR_PORT).is_err());
+        assert!(Ipv4Addr::from_str(IPV6_STR_FULL).is_err());
+        assert!(Ipv4Addr::from_str(IPV6_STR_COMPRESS).is_err());
+        assert!(Ipv4Addr::from_str(IPV6_STR_V4).is_err());
+        assert!(Ipv4Addr::from_str(IPV6_STR_PORT).is_err());
+    }
+
+    #[test]
+    fn parse_ipv6() {
+        let result: Ipv6Addr = IPV6_STR_FULL.parse().unwrap();
+        assert_eq!(result, IPV6);
+
+        let result: Ipv6Addr = IPV6_STR_COMPRESS.parse().unwrap();
+        assert_eq!(result, IPV6);
+
+        let result: Ipv6Addr = IPV6_STR_V4.parse().unwrap();
+        assert_eq!(result, IPV6);
+
+        assert!(Ipv6Addr::from_str(IPV4_STR).is_err());
+        assert!(Ipv6Addr::from_str(IPV4_STR_PORT).is_err());
+        assert!(Ipv6Addr::from_str(IPV6_STR_PORT).is_err());
+    }
+
+    #[test]
+    fn parse_ip() {
+        let result: IpAddr = IPV4_STR.parse().unwrap();
+        assert_eq!(result, IpAddr::from(IPV4));
+
+        let result: IpAddr = IPV6_STR_FULL.parse().unwrap();
+        assert_eq!(result, IpAddr::from(IPV6));
+
+        let result: IpAddr = IPV6_STR_COMPRESS.parse().unwrap();
+        assert_eq!(result, IpAddr::from(IPV6));
+
+        let result: IpAddr = IPV6_STR_V4.parse().unwrap();
+        assert_eq!(result, IpAddr::from(IPV6));
+
+        assert!(IpAddr::from_str(IPV4_STR_PORT).is_err());
+        assert!(IpAddr::from_str(IPV6_STR_PORT).is_err());
+    }
+
+    #[test]
+    fn parse_socket_v4() {
+        let result: SocketAddrV4 = IPV4_STR_PORT.parse().unwrap();
+        assert_eq!(result, SocketAddrV4::new(IPV4, PORT));
+
+        assert!(SocketAddrV4::from_str(IPV4_STR).is_err());
+        assert!(SocketAddrV4::from_str(IPV6_STR_FULL).is_err());
+        assert!(SocketAddrV4::from_str(IPV6_STR_COMPRESS).is_err());
+        assert!(SocketAddrV4::from_str(IPV6_STR_V4).is_err());
+        assert!(SocketAddrV4::from_str(IPV6_STR_PORT).is_err());
+    }
+
+    #[test]
+    fn parse_socket_v6() {
+        let result: SocketAddrV6 = IPV6_STR_PORT.parse().unwrap();
+        assert_eq!(result, SocketAddrV6::new(IPV6, PORT, 0, 0));
+
+        assert!(SocketAddrV6::from_str(IPV4_STR).is_err());
+        assert!(SocketAddrV6::from_str(IPV4_STR_PORT).is_err());
+        assert!(SocketAddrV6::from_str(IPV6_STR_FULL).is_err());
+        assert!(SocketAddrV6::from_str(IPV6_STR_COMPRESS).is_err());
+        assert!(SocketAddrV6::from_str(IPV6_STR_V4).is_err());
+    }
+
+    #[test]
+    fn parse_socket() {
+        let result: SocketAddr = IPV4_STR_PORT.parse().unwrap();
+        assert_eq!(result, SocketAddr::from((IPV4, PORT)));
+
+        let result: SocketAddr = IPV6_STR_PORT.parse().unwrap();
+        assert_eq!(result, SocketAddr::from((IPV6, PORT)));
+
+        assert!(SocketAddr::from_str(IPV4_STR).is_err());
+        assert!(SocketAddr::from_str(IPV6_STR_FULL).is_err());
+        assert!(SocketAddr::from_str(IPV6_STR_COMPRESS).is_err());
+        assert!(SocketAddr::from_str(IPV6_STR_V4).is_err());
+    }
+
+    #[test]
+    fn ipv6_corner_cases() {
+        let result: Ipv6Addr = "1::".parse().unwrap();
+        assert_eq!(result, Ipv6Addr::new(1, 0, 0, 0, 0, 0, 0, 0));
+
+        let result: Ipv6Addr = "1:1::".parse().unwrap();
+        assert_eq!(result, Ipv6Addr::new(1, 1, 0, 0, 0, 0, 0, 0));
+
+        let result: Ipv6Addr = "::1".parse().unwrap();
+        assert_eq!(result, Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1));
+
+        let result: Ipv6Addr = "::1:1".parse().unwrap();
+        assert_eq!(result, Ipv6Addr::new(0, 0, 0, 0, 0, 0, 1, 1));
+
+        let result: Ipv6Addr = "::".parse().unwrap();
+        assert_eq!(result, Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0));
+
+        let result: Ipv6Addr = "::192.168.0.1".parse().unwrap();
+        assert_eq!(result, Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0xc0a8, 0x1));
+
+        let result: Ipv6Addr = "::1:192.168.0.1".parse().unwrap();
+        assert_eq!(result, Ipv6Addr::new(0, 0, 0, 0, 0, 1, 0xc0a8, 0x1));
+
+        let result: Ipv6Addr = "1:1:1:1:1:1:192.168.0.1".parse().unwrap();
+        assert_eq!(result, Ipv6Addr::new(1, 1, 1, 1, 1, 1, 0xc0a8, 0x1));
+    }
+
+    // Things that might not seem like failures but are
+    #[test]
+    fn ipv6_corner_failures() {
+        // No IP address before the ::
+        assert!(Ipv6Addr::from_str("1:192.168.0.1::").is_err());
+
+        // :: must have at least 1 set of zeroes
+        assert!(Ipv6Addr::from_str("1:1:1:1::1:1:1:1").is_err());
+
+        // Need brackets for a port
+        assert!(SocketAddrV6::from_str("1:1:1:1:1:1:1:1:8080").is_err());
+    }
+}
diff --git a/src/libstd/sys/windows/mod.rs b/src/libstd/sys/windows/mod.rs
index 640c9f3636d..193ab5b47ef 100644
--- a/src/libstd/sys/windows/mod.rs
+++ b/src/libstd/sys/windows/mod.rs
@@ -61,6 +61,7 @@ pub fn decode_error_kind(errno: i32) -> ErrorKind {
         c::ERROR_FILE_NOT_FOUND => return ErrorKind::NotFound,
         c::ERROR_PATH_NOT_FOUND => return ErrorKind::NotFound,
         c::ERROR_NO_DATA => return ErrorKind::BrokenPipe,
+        c::ERROR_INVALID_PARAMETER => return ErrorKind::InvalidInput,
         c::ERROR_SEM_TIMEOUT
         | c::WAIT_TIMEOUT
         | c::ERROR_DRIVER_CANCEL_TIMEOUT
diff --git a/src/test/ui/anon-params/anon-params-denied-2018.stderr b/src/test/ui/anon-params/anon-params-denied-2018.stderr
index e7a806a8468..840294db083 100644
--- a/src/test/ui/anon-params/anon-params-denied-2018.stderr
+++ b/src/test/ui/anon-params/anon-params-denied-2018.stderr
@@ -9,7 +9,7 @@ help: if this is a `self` type, give it a parameter name
    |
 LL |     fn foo(self: i32);
    |            ^^^^^^^^^
-help: if this was a parameter name, give it a type
+help: if this is a parameter name, give it a type
    |
 LL |     fn foo(i32: TypeName);
    |            ^^^^^^^^^^^^^
@@ -29,7 +29,7 @@ help: if this is a `self` type, give it a parameter name
    |
 LL |     fn bar_with_default_impl(self: String, String) {}
    |                              ^^^^^^^^^^^^
-help: if this was a parameter name, give it a type
+help: if this is a parameter name, give it a type
    |
 LL |     fn bar_with_default_impl(String: TypeName, String) {}
    |                              ^^^^^^^^^^^^^^^^
@@ -45,7 +45,7 @@ LL |     fn bar_with_default_impl(String, String) {}
    |                                            ^ expected one of `:`, `@`, or `|`
    |
    = note: anonymous parameters are removed in the 2018 edition (see RFC 1685)
-help: if this was a parameter name, give it a type
+help: if this is a parameter name, give it a type
    |
 LL |     fn bar_with_default_impl(String, String: TypeName) {}
    |                                      ^^^^^^^^^^^^^^^^
@@ -61,7 +61,7 @@ LL |     fn baz(a:usize, b, c: usize) -> usize {
    |                      ^ expected one of `:`, `@`, or `|`
    |
    = note: anonymous parameters are removed in the 2018 edition (see RFC 1685)
-help: if this was a parameter name, give it a type
+help: if this is a parameter name, give it a type
    |
 LL |     fn baz(a:usize, b: TypeName, c: usize) -> usize {
    |                     ^^^^^^^^^^^
diff --git a/src/test/ui/asm/sym.rs b/src/test/ui/asm/sym.rs
index 8cff16aa75f..9931697e412 100644
--- a/src/test/ui/asm/sym.rs
+++ b/src/test/ui/asm/sym.rs
@@ -3,7 +3,7 @@
 // only-linux
 // run-pass
 
-#![feature(asm, track_caller, thread_local)]
+#![feature(asm, thread_local)]
 
 extern "C" fn f1() -> i32 {
     111
diff --git a/src/test/ui/async-await/issue-67765-async-diagnostic.rs b/src/test/ui/async-await/issue-67765-async-diagnostic.rs
new file mode 100644
index 00000000000..5093916e73a
--- /dev/null
+++ b/src/test/ui/async-await/issue-67765-async-diagnostic.rs
@@ -0,0 +1,16 @@
+// edition:2018
+//
+// Regression test for issue #67765
+// Tests that we point at the proper location when giving
+// a lifetime error.
+fn main() {}
+
+async fn func<'a>() -> Result<(), &'a str> {
+    let s = String::new();
+
+    let b = &s[..];
+
+    Err(b)?; //~ ERROR cannot return value referencing local variable `s`
+
+    Ok(())
+}
diff --git a/src/test/ui/async-await/issue-67765-async-diagnostic.stderr b/src/test/ui/async-await/issue-67765-async-diagnostic.stderr
new file mode 100644
index 00000000000..78253042bee
--- /dev/null
+++ b/src/test/ui/async-await/issue-67765-async-diagnostic.stderr
@@ -0,0 +1,12 @@
+error[E0515]: cannot return value referencing local variable `s`
+  --> $DIR/issue-67765-async-diagnostic.rs:13:11
+   |
+LL |     let b = &s[..];
+   |              - `s` is borrowed here
+LL | 
+LL |     Err(b)?;
+   |           ^ returns a value referencing data owned by the current function
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0515`.
diff --git a/src/test/ui/feature-gates/feature-gate-track_caller.rs b/src/test/ui/feature-gates/feature-gate-track_caller.rs
deleted file mode 100644
index 5865cf0a4f7..00000000000
--- a/src/test/ui/feature-gates/feature-gate-track_caller.rs
+++ /dev/null
@@ -1,5 +0,0 @@
-#[track_caller]
-fn f() {}
-//~^^ ERROR the `#[track_caller]` attribute is an experimental feature
-
-fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-track_caller.stderr b/src/test/ui/feature-gates/feature-gate-track_caller.stderr
deleted file mode 100644
index 8ceab501617..00000000000
--- a/src/test/ui/feature-gates/feature-gate-track_caller.stderr
+++ /dev/null
@@ -1,12 +0,0 @@
-error[E0658]: the `#[track_caller]` attribute is an experimental feature
-  --> $DIR/feature-gate-track_caller.rs:1:1
-   |
-LL | #[track_caller]
-   | ^^^^^^^^^^^^^^^
-   |
-   = note: see issue #47809 <https://github.com/rust-lang/rust/issues/47809> for more information
-   = help: add `#![feature(track_caller)]` 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/test/ui/in-band-lifetimes/E0687.stderr b/src/test/ui/in-band-lifetimes/E0687.stderr
index e8e5100e00e..7aea2f22046 100644
--- a/src/test/ui/in-band-lifetimes/E0687.stderr
+++ b/src/test/ui/in-band-lifetimes/E0687.stderr
@@ -24,3 +24,4 @@ LL |     fn bar(&self, x: fn(&'a u32)) {}
 
 error: aborting due to 4 previous errors
 
+For more information about this error, try `rustc --explain E0687`.
diff --git a/src/test/ui/in-band-lifetimes/E0687_where.stderr b/src/test/ui/in-band-lifetimes/E0687_where.stderr
index b422869c4db..af0f9665f5d 100644
--- a/src/test/ui/in-band-lifetimes/E0687_where.stderr
+++ b/src/test/ui/in-band-lifetimes/E0687_where.stderr
@@ -12,3 +12,4 @@ LL | fn baz(x: &impl Fn(&'a u32)) {}
 
 error: aborting due to 2 previous errors
 
+For more information about this error, try `rustc --explain E0687`.
diff --git a/src/test/ui/lifetimes/unnamed-closure-doesnt-life-long-enough-issue-67634.rs b/src/test/ui/lifetimes/unnamed-closure-doesnt-life-long-enough-issue-67634.rs
index 19d7f019047..8deb3655158 100644
--- a/src/test/ui/lifetimes/unnamed-closure-doesnt-life-long-enough-issue-67634.rs
+++ b/src/test/ui/lifetimes/unnamed-closure-doesnt-life-long-enough-issue-67634.rs
@@ -1,3 +1,3 @@
 fn main() {
-    [0].iter().flat_map(|a| [0].iter().map(|_| &a)); //~ ERROR `a` does not live long enough
+    [0].iter().flat_map(|a| [0].iter().map(|_| &a)); //~ ERROR closure may outlive
 }
diff --git a/src/test/ui/lifetimes/unnamed-closure-doesnt-life-long-enough-issue-67634.stderr b/src/test/ui/lifetimes/unnamed-closure-doesnt-life-long-enough-issue-67634.stderr
index cb0b481e748..34470119112 100644
--- a/src/test/ui/lifetimes/unnamed-closure-doesnt-life-long-enough-issue-67634.stderr
+++ b/src/test/ui/lifetimes/unnamed-closure-doesnt-life-long-enough-issue-67634.stderr
@@ -1,15 +1,21 @@
-error[E0597]: `a` does not live long enough
-  --> $DIR/unnamed-closure-doesnt-life-long-enough-issue-67634.rs:2:49
+error[E0373]: closure may outlive the current function, but it borrows `a`, which is owned by the current function
+  --> $DIR/unnamed-closure-doesnt-life-long-enough-issue-67634.rs:2:44
    |
 LL |     [0].iter().flat_map(|a| [0].iter().map(|_| &a));
-   |                                             -   ^- ...but `a` will be dropped here, when the enclosing closure returns
-   |                                             |   |
-   |                                             |   `a` would have to be valid for `'_`...
-   |                                             has type `&i32`
+   |                                            ^^^  - `a` is borrowed here
+   |                                            |
+   |                                            may outlive borrowed value `a`
    |
-   = note: functions cannot return a borrow to data owned within the function's scope, functions can only return borrows to data passed as arguments
-   = note: to learn more, visit <https://doc.rust-lang.org/book/ch04-02-references-and-borrowing.html#dangling-references>
+note: closure is returned here
+  --> $DIR/unnamed-closure-doesnt-life-long-enough-issue-67634.rs:2:29
+   |
+LL |     [0].iter().flat_map(|a| [0].iter().map(|_| &a));
+   |                             ^^^^^^^^^^^^^^^^^^^^^^
+help: to force the closure to take ownership of `a` (and any other referenced variables), use the `move` keyword
+   |
+LL |     [0].iter().flat_map(|a| [0].iter().map(move |_| &a));
+   |                                            ^^^^^^^^
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0597`.
+For more information about this error, try `rustc --explain E0373`.
diff --git a/src/test/ui/macros/issue-68060.rs b/src/test/ui/macros/issue-68060.rs
index bc70f8ffec2..8772e98b6e9 100644
--- a/src/test/ui/macros/issue-68060.rs
+++ b/src/test/ui/macros/issue-68060.rs
@@ -1,5 +1,3 @@
-#![feature(track_caller)]
-
 fn main() {
     (0..)
         .map(
diff --git a/src/test/ui/macros/issue-68060.stderr b/src/test/ui/macros/issue-68060.stderr
index 22187c4a409..b9b2f946c59 100644
--- a/src/test/ui/macros/issue-68060.stderr
+++ b/src/test/ui/macros/issue-68060.stderr
@@ -1,5 +1,5 @@
 error[E0658]: `#[target_feature(..)]` can only be applied to `unsafe` functions
-  --> $DIR/issue-68060.rs:6:13
+  --> $DIR/issue-68060.rs:4:13
    |
 LL |             #[target_feature(enable = "")]
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -11,13 +11,13 @@ LL |             |_| (),
    = help: add `#![feature(target_feature_11)]` to the crate attributes to enable
 
 error: the feature named `` is not valid for this target
-  --> $DIR/issue-68060.rs:6:30
+  --> $DIR/issue-68060.rs:4:30
    |
 LL |             #[target_feature(enable = "")]
    |                              ^^^^^^^^^^^ `` is not valid for this target
 
 error[E0737]: `#[track_caller]` requires Rust ABI
-  --> $DIR/issue-68060.rs:9:13
+  --> $DIR/issue-68060.rs:7:13
    |
 LL |             #[track_caller]
    |             ^^^^^^^^^^^^^^^
diff --git a/src/test/ui/numbers-arithmetic/saturating-float-casts.rs b/src/test/ui/numbers-arithmetic/saturating-float-casts.rs
index e6d0c94a02f..825a11972ae 100644
--- a/src/test/ui/numbers-arithmetic/saturating-float-casts.rs
+++ b/src/test/ui/numbers-arithmetic/saturating-float-casts.rs
@@ -9,7 +9,6 @@
 // merged.
 
 #![feature(test, stmt_expr_attributes)]
-#![feature(track_caller)]
 #![deny(overflowing_literals)]
 extern crate test;
 
diff --git a/src/test/ui/parser/inverted-parameters.rs b/src/test/ui/parser/inverted-parameters.rs
index 6f19ee9c7dc..5c4272504e0 100644
--- a/src/test/ui/parser/inverted-parameters.rs
+++ b/src/test/ui/parser/inverted-parameters.rs
@@ -20,7 +20,7 @@ fn pattern((i32, i32) (a, b)) {}
 
 fn fizz(i32) {}
 //~^ ERROR expected one of `:`, `@`
-//~| HELP if this was a parameter name, give it a type
+//~| HELP if this is a parameter name, give it a type
 //~| HELP if this is a `self` type, give it a parameter name
 //~| HELP if this is a type, explicitly ignore the parameter name
 
diff --git a/src/test/ui/parser/inverted-parameters.stderr b/src/test/ui/parser/inverted-parameters.stderr
index 043ff65f74e..ae180af93e3 100644
--- a/src/test/ui/parser/inverted-parameters.stderr
+++ b/src/test/ui/parser/inverted-parameters.stderr
@@ -39,7 +39,7 @@ help: if this is a `self` type, give it a parameter name
    |
 LL | fn fizz(self: i32) {}
    |         ^^^^^^^^^
-help: if this was a parameter name, give it a type
+help: if this is a parameter name, give it a type
    |
 LL | fn fizz(i32: TypeName) {}
    |         ^^^^^^^^^^^^^
diff --git a/src/test/ui/parser/omitted-arg-in-item-fn.stderr b/src/test/ui/parser/omitted-arg-in-item-fn.stderr
index 9f138bf84ce..bc3329dcbc2 100644
--- a/src/test/ui/parser/omitted-arg-in-item-fn.stderr
+++ b/src/test/ui/parser/omitted-arg-in-item-fn.stderr
@@ -9,7 +9,7 @@ help: if this is a `self` type, give it a parameter name
    |
 LL | fn foo(self: x) {
    |        ^^^^^^^
-help: if this was a parameter name, give it a type
+help: if this is a parameter name, give it a type
    |
 LL | fn foo(x: TypeName) {
    |        ^^^^^^^^^^^
diff --git a/src/test/ui/return-disjoint-regions.rs b/src/test/ui/return-disjoint-regions.rs
new file mode 100644
index 00000000000..d0feb3b65e1
--- /dev/null
+++ b/src/test/ui/return-disjoint-regions.rs
@@ -0,0 +1,7 @@
+// See https://github.com/rust-lang/rust/pull/67911#issuecomment-576023915
+fn f<'a, 'b>(x: i32) -> (&'a i32, &'b i32) {
+    let y = &x;
+    (y, y) //~ ERROR cannot return
+}
+
+fn main() {}
diff --git a/src/test/ui/return-disjoint-regions.stderr b/src/test/ui/return-disjoint-regions.stderr
new file mode 100644
index 00000000000..ed159298804
--- /dev/null
+++ b/src/test/ui/return-disjoint-regions.stderr
@@ -0,0 +1,11 @@
+error[E0515]: cannot return value referencing function parameter `x`
+  --> $DIR/return-disjoint-regions.rs:4:5
+   |
+LL |     let y = &x;
+   |             -- `x` is borrowed here
+LL |     (y, y)
+   |     ^^^^^^ returns a value referencing data owned by the current function
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0515`.
diff --git a/src/test/ui/rfc-2091-track-caller/call-chain.rs b/src/test/ui/rfc-2091-track-caller/call-chain.rs
index 3f1c8f7abe8..fefb84de729 100644
--- a/src/test/ui/rfc-2091-track-caller/call-chain.rs
+++ b/src/test/ui/rfc-2091-track-caller/call-chain.rs
@@ -1,7 +1,5 @@
 // run-pass
 
-#![feature(track_caller)]
-
 use std::panic::Location;
 
 struct Foo;
diff --git a/src/test/ui/rfc-2091-track-caller/caller-location-fnptr-rt-ctfe-equiv.rs b/src/test/ui/rfc-2091-track-caller/caller-location-fnptr-rt-ctfe-equiv.rs
index edf9ba2c41a..05240908917 100644
--- a/src/test/ui/rfc-2091-track-caller/caller-location-fnptr-rt-ctfe-equiv.rs
+++ b/src/test/ui/rfc-2091-track-caller/caller-location-fnptr-rt-ctfe-equiv.rs
@@ -6,7 +6,7 @@
 // run-pass
 // compile-flags: -Z unleash-the-miri-inside-of-you
 
-#![feature(core_intrinsics, const_caller_location, track_caller, const_fn)]
+#![feature(core_intrinsics, const_caller_location, const_fn)]
 
 type L = &'static std::panic::Location<'static>;
 
diff --git a/src/test/ui/rfc-2091-track-caller/caller-location-intrinsic.rs b/src/test/ui/rfc-2091-track-caller/caller-location-intrinsic.rs
index 090e912c1d0..f244b74e391 100644
--- a/src/test/ui/rfc-2091-track-caller/caller-location-intrinsic.rs
+++ b/src/test/ui/rfc-2091-track-caller/caller-location-intrinsic.rs
@@ -1,7 +1,5 @@
 // run-pass
 
-#![feature(track_caller)]
-
 #[inline(never)]
 #[track_caller]
 fn codegen_caller_loc() -> &'static core::panic::Location<'static> {
@@ -15,13 +13,13 @@ macro_rules! caller_location_from_macro {
 fn main() {
     let loc = codegen_caller_loc();
     assert_eq!(loc.file(), file!());
-    assert_eq!(loc.line(), 16);
+    assert_eq!(loc.line(), 14);
     assert_eq!(loc.column(), 15);
 
     // `Location::caller()` in a macro should behave similarly to `file!` and `line!`,
     // i.e. point to where the macro was invoked, instead of the macro itself.
     let loc2 = caller_location_from_macro!();
     assert_eq!(loc2.file(), file!());
-    assert_eq!(loc2.line(), 23);
+    assert_eq!(loc2.line(), 21);
     assert_eq!(loc2.column(), 16);
 }
diff --git a/src/test/ui/rfc-2091-track-caller/const-caller-location.rs b/src/test/ui/rfc-2091-track-caller/const-caller-location.rs
index 0614c52c660..8030a4d967a 100644
--- a/src/test/ui/rfc-2091-track-caller/const-caller-location.rs
+++ b/src/test/ui/rfc-2091-track-caller/const-caller-location.rs
@@ -1,6 +1,6 @@
 // run-pass
 
-#![feature(const_fn, track_caller)]
+#![feature(const_caller_location, const_fn)]
 
 use std::panic::Location;
 
diff --git a/src/test/ui/rfc-2091-track-caller/diverging-caller-location.rs b/src/test/ui/rfc-2091-track-caller/diverging-caller-location.rs
index 1fb75ef35ff..6681119557d 100644
--- a/src/test/ui/rfc-2091-track-caller/diverging-caller-location.rs
+++ b/src/test/ui/rfc-2091-track-caller/diverging-caller-location.rs
@@ -6,8 +6,6 @@
 //! we don't inspect the location returned -- it would be difficult to distinguish between the
 //! explicit panic and a failed assertion. That it compiles and runs is enough for this one.
 
-#![feature(track_caller)]
-
 #[track_caller]
 fn doesnt_return() -> ! {
     let _location = core::panic::Location::caller();
diff --git a/src/test/ui/rfc-2091-track-caller/error-odd-syntax.rs b/src/test/ui/rfc-2091-track-caller/error-odd-syntax.rs
index d6560231871..6f4290e2a5e 100644
--- a/src/test/ui/rfc-2091-track-caller/error-odd-syntax.rs
+++ b/src/test/ui/rfc-2091-track-caller/error-odd-syntax.rs
@@ -1,5 +1,3 @@
-#![feature(track_caller)]
-
 #[track_caller(1)]
 fn f() {}
 //~^^ ERROR malformed `track_caller` attribute input
diff --git a/src/test/ui/rfc-2091-track-caller/error-odd-syntax.stderr b/src/test/ui/rfc-2091-track-caller/error-odd-syntax.stderr
index 8906fa59506..e7ddf8df4ab 100644
--- a/src/test/ui/rfc-2091-track-caller/error-odd-syntax.stderr
+++ b/src/test/ui/rfc-2091-track-caller/error-odd-syntax.stderr
@@ -1,5 +1,5 @@
 error: malformed `track_caller` attribute input
-  --> $DIR/error-odd-syntax.rs:3:1
+  --> $DIR/error-odd-syntax.rs:1:1
    |
 LL | #[track_caller(1)]
    | ^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[track_caller]`
diff --git a/src/test/ui/rfc-2091-track-caller/error-with-invalid-abi.rs b/src/test/ui/rfc-2091-track-caller/error-with-invalid-abi.rs
index 1145f7786c7..074e1ceb791 100644
--- a/src/test/ui/rfc-2091-track-caller/error-with-invalid-abi.rs
+++ b/src/test/ui/rfc-2091-track-caller/error-with-invalid-abi.rs
@@ -1,5 +1,3 @@
-#![feature(track_caller)]
-
 #[track_caller]
 extern "C" fn f() {}
 //~^^ ERROR `#[track_caller]` requires Rust ABI
diff --git a/src/test/ui/rfc-2091-track-caller/error-with-invalid-abi.stderr b/src/test/ui/rfc-2091-track-caller/error-with-invalid-abi.stderr
index e08c52fabd6..bcc0c8170e6 100644
--- a/src/test/ui/rfc-2091-track-caller/error-with-invalid-abi.stderr
+++ b/src/test/ui/rfc-2091-track-caller/error-with-invalid-abi.stderr
@@ -1,11 +1,11 @@
 error[E0737]: `#[track_caller]` requires Rust ABI
-  --> $DIR/error-with-invalid-abi.rs:3:1
+  --> $DIR/error-with-invalid-abi.rs:1:1
    |
 LL | #[track_caller]
    | ^^^^^^^^^^^^^^^
 
 error[E0737]: `#[track_caller]` requires Rust ABI
-  --> $DIR/error-with-invalid-abi.rs:8:5
+  --> $DIR/error-with-invalid-abi.rs:6:5
    |
 LL |     #[track_caller]
    |     ^^^^^^^^^^^^^^^
diff --git a/src/test/ui/rfc-2091-track-caller/error-with-naked.rs b/src/test/ui/rfc-2091-track-caller/error-with-naked.rs
index f4573848333..2b110c9a325 100644
--- a/src/test/ui/rfc-2091-track-caller/error-with-naked.rs
+++ b/src/test/ui/rfc-2091-track-caller/error-with-naked.rs
@@ -1,4 +1,4 @@
-#![feature(naked_functions, track_caller)]
+#![feature(naked_functions)]
 
 #[track_caller] //~ ERROR cannot use `#[track_caller]` with `#[naked]`
 #[naked]
diff --git a/src/test/ui/rfc-2091-track-caller/intrinsic-wrapper.rs b/src/test/ui/rfc-2091-track-caller/intrinsic-wrapper.rs
index 76e62b89ab8..74217f47084 100644
--- a/src/test/ui/rfc-2091-track-caller/intrinsic-wrapper.rs
+++ b/src/test/ui/rfc-2091-track-caller/intrinsic-wrapper.rs
@@ -1,7 +1,5 @@
 // run-pass
 
-#![feature(track_caller)]
-
 macro_rules! caller_location_from_macro {
     () => (core::panic::Location::caller());
 }
@@ -9,13 +7,13 @@ macro_rules! caller_location_from_macro {
 fn main() {
     let loc = core::panic::Location::caller();
     assert_eq!(loc.file(), file!());
-    assert_eq!(loc.line(), 10);
+    assert_eq!(loc.line(), 8);
     assert_eq!(loc.column(), 15);
 
     // `Location::caller()` in a macro should behave similarly to `file!` and `line!`,
     // i.e. point to where the macro was invoked, instead of the macro itself.
     let loc2 = caller_location_from_macro!();
     assert_eq!(loc2.file(), file!());
-    assert_eq!(loc2.line(), 17);
+    assert_eq!(loc2.line(), 15);
     assert_eq!(loc2.column(), 16);
 }
diff --git a/src/test/ui/rfc-2091-track-caller/only-for-fns.rs b/src/test/ui/rfc-2091-track-caller/only-for-fns.rs
index 0fd59b4bf49..bc0ca955280 100644
--- a/src/test/ui/rfc-2091-track-caller/only-for-fns.rs
+++ b/src/test/ui/rfc-2091-track-caller/only-for-fns.rs
@@ -1,5 +1,3 @@
-#![feature(track_caller)]
-
 #[track_caller]
 struct S;
 //~^^ ERROR attribute should be applied to function
diff --git a/src/test/ui/rfc-2091-track-caller/only-for-fns.stderr b/src/test/ui/rfc-2091-track-caller/only-for-fns.stderr
index c2fb8fa1eb6..6666dcfa6e5 100644
--- a/src/test/ui/rfc-2091-track-caller/only-for-fns.stderr
+++ b/src/test/ui/rfc-2091-track-caller/only-for-fns.stderr
@@ -1,5 +1,5 @@
 error[E0739]: attribute should be applied to function
-  --> $DIR/only-for-fns.rs:3:1
+  --> $DIR/only-for-fns.rs:1:1
    |
 LL | #[track_caller]
    | ^^^^^^^^^^^^^^^
diff --git a/src/test/ui/rfc-2091-track-caller/pass.rs b/src/test/ui/rfc-2091-track-caller/pass.rs
index eef83b3d68f..ada150b25cf 100644
--- a/src/test/ui/rfc-2091-track-caller/pass.rs
+++ b/src/test/ui/rfc-2091-track-caller/pass.rs
@@ -1,6 +1,4 @@
 // run-pass
-#![feature(track_caller)]
-
 #[track_caller]
 fn f() {}
 
diff --git a/src/test/ui/rfc-2091-track-caller/track-caller-attribute.rs b/src/test/ui/rfc-2091-track-caller/track-caller-attribute.rs
index 76a380ed3e3..efcc1f6942d 100644
--- a/src/test/ui/rfc-2091-track-caller/track-caller-attribute.rs
+++ b/src/test/ui/rfc-2091-track-caller/track-caller-attribute.rs
@@ -1,7 +1,5 @@
 // run-pass
 
-#![feature(track_caller)]
-
 use std::panic::Location;
 
 #[track_caller]
@@ -20,21 +18,21 @@ fn nested_tracked() -> &'static Location<'static> {
 fn main() {
     let location = Location::caller();
     assert_eq!(location.file(), file!());
-    assert_eq!(location.line(), 21);
+    assert_eq!(location.line(), 19);
     assert_eq!(location.column(), 20);
 
     let tracked = tracked();
     assert_eq!(tracked.file(), file!());
-    assert_eq!(tracked.line(), 26);
+    assert_eq!(tracked.line(), 24);
     assert_eq!(tracked.column(), 19);
 
     let nested = nested_intrinsic();
     assert_eq!(nested.file(), file!());
-    assert_eq!(nested.line(), 13);
+    assert_eq!(nested.line(), 11);
     assert_eq!(nested.column(), 5);
 
     let contained = nested_tracked();
     assert_eq!(contained.file(), file!());
-    assert_eq!(contained.line(), 17);
+    assert_eq!(contained.line(), 15);
     assert_eq!(contained.column(), 5);
 }
diff --git a/src/test/ui/rfc-2091-track-caller/track-caller-ffi.rs b/src/test/ui/rfc-2091-track-caller/track-caller-ffi.rs
index 23c17d743c4..5115f687c26 100644
--- a/src/test/ui/rfc-2091-track-caller/track-caller-ffi.rs
+++ b/src/test/ui/rfc-2091-track-caller/track-caller-ffi.rs
@@ -1,7 +1,5 @@
 // run-pass
 
-#![feature(track_caller)]
-
 use std::panic::Location;
 
 extern "Rust" {
@@ -30,21 +28,21 @@ mod provides {
 fn main() {
     let location = Location::caller();
     assert_eq!(location.file(), file!());
-    assert_eq!(location.line(), 31);
+    assert_eq!(location.line(), 29);
     assert_eq!(location.column(), 20);
 
     let tracked = unsafe { rust_track_caller_ffi_test_tracked() };
     assert_eq!(tracked.file(), file!());
-    assert_eq!(tracked.line(), 36);
+    assert_eq!(tracked.line(), 34);
     assert_eq!(tracked.column(), 28);
 
     let untracked = unsafe { rust_track_caller_ffi_test_untracked() };
     assert_eq!(untracked.file(), file!());
-    assert_eq!(untracked.line(), 26);
+    assert_eq!(untracked.line(), 24);
     assert_eq!(untracked.column(), 9);
 
     let contained = rust_track_caller_ffi_test_nested_tracked();
     assert_eq!(contained.file(), file!());
-    assert_eq!(contained.line(), 14);
+    assert_eq!(contained.line(), 12);
     assert_eq!(contained.column(), 14);
 }
diff --git a/src/test/ui/rfc-2091-track-caller/tracked-fn-ptr-with-arg.rs b/src/test/ui/rfc-2091-track-caller/tracked-fn-ptr-with-arg.rs
index b17c1efb3d3..5fcfea96d54 100644
--- a/src/test/ui/rfc-2091-track-caller/tracked-fn-ptr-with-arg.rs
+++ b/src/test/ui/rfc-2091-track-caller/tracked-fn-ptr-with-arg.rs
@@ -1,7 +1,5 @@
 // run-pass
 
-#![feature(track_caller)]
-
 fn pass_to_ptr_call<T>(f: fn(T), x: T) {
     f(x);
 }
diff --git a/src/test/ui/rfc-2091-track-caller/tracked-fn-ptr.rs b/src/test/ui/rfc-2091-track-caller/tracked-fn-ptr.rs
index 8ee4d4fa168..4415d850c24 100644
--- a/src/test/ui/rfc-2091-track-caller/tracked-fn-ptr.rs
+++ b/src/test/ui/rfc-2091-track-caller/tracked-fn-ptr.rs
@@ -1,7 +1,5 @@
 // run-pass
 
-#![feature(track_caller)]
-
 fn ptr_call(f: fn()) {
     f();
 }
diff --git a/src/test/ui/rfc-2091-track-caller/tracked-trait-impls.rs b/src/test/ui/rfc-2091-track-caller/tracked-trait-impls.rs
index 0a5f92bb635..4db4c29e53d 100644
--- a/src/test/ui/rfc-2091-track-caller/tracked-trait-impls.rs
+++ b/src/test/ui/rfc-2091-track-caller/tracked-trait-impls.rs
@@ -1,7 +1,5 @@
 // run-pass
 
-#![feature(track_caller)]
-
 macro_rules! assert_expansion_site_is_tracked {
     () => {{
         let location = std::panic::Location::caller();
diff --git a/src/test/ui/rfc-2565-param-attrs/param-attrs-2018.stderr b/src/test/ui/rfc-2565-param-attrs/param-attrs-2018.stderr
index 1e51567a9b1..5516d4a4c1c 100644
--- a/src/test/ui/rfc-2565-param-attrs/param-attrs-2018.stderr
+++ b/src/test/ui/rfc-2565-param-attrs/param-attrs-2018.stderr
@@ -9,7 +9,7 @@ help: if this is a `self` type, give it a parameter name
    |
 LL | trait Trait2015 { fn foo(#[allow(C)] self: i32); }
    |                                      ^^^^^^^^^
-help: if this was a parameter name, give it a type
+help: if this is a parameter name, give it a type
    |
 LL | trait Trait2015 { fn foo(#[allow(C)] i32: TypeName); }
    |                                      ^^^^^^^^^^^^^
diff --git a/src/test/ui/span/issue-34264.stderr b/src/test/ui/span/issue-34264.stderr
index 116f5ddd5b4..40c3219bf27 100644
--- a/src/test/ui/span/issue-34264.stderr
+++ b/src/test/ui/span/issue-34264.stderr
@@ -21,7 +21,7 @@ LL | fn foo(Option<i32>, String) {}
    |                           ^ expected one of `:`, `@`, or `|`
    |
    = note: anonymous parameters are removed in the 2018 edition (see RFC 1685)
-help: if this was a parameter name, give it a type
+help: if this is a parameter name, give it a type
    |
 LL | fn foo(Option<i32>, String: TypeName) {}
    |                     ^^^^^^^^^^^^^^^^
@@ -41,7 +41,7 @@ help: if this is a `self` type, give it a parameter name
    |
 LL | fn bar(self: x, y: usize) {}
    |        ^^^^^^^
-help: if this was a parameter name, give it a type
+help: if this is a parameter name, give it a type
    |
 LL | fn bar(x: TypeName, y: usize) {}
    |        ^^^^^^^^^^^