about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2020-10-16 00:18:13 +0000
committerbors <bors@rust-lang.org>2020-10-16 00:18:13 +0000
commitb6e2dc6cdece6b498b876bc7e9377ff7d63d93e7 (patch)
treeb0cade8eff84561b5f9a195b67829b7af2c866c0
parentdd7fc54ebdca419ad9d3ab1e9f5ed14e770768ea (diff)
parente688b4d51cc9b41b18b240f5f6358daa8179e8fa (diff)
downloadrust-b6e2dc6cdece6b498b876bc7e9377ff7d63d93e7.tar.gz
rust-b6e2dc6cdece6b498b876bc7e9377ff7d63d93e7.zip
Auto merge of #78001 - Dylan-DPC:rollup-zq3kxth, r=Dylan-DPC
Rollup of 14 pull requests

Successful merges:

 - #75023 (ensure arguments are included in count mismatch span)
 - #75265 (Add `str::{Split,RSplit,SplitN,RSplitN,SplitTerminator,RSplitTerminator,SplitInclusive}::as_str` methods)
 - #75675 (mangling: mangle impl params w/ v0 scheme)
 - #76084 (Refactor io/buffered.rs into submodules)
 - #76119 (Stabilize move_ref_pattern)
 - #77493 (ICEs should always print the top of the query stack)
 - #77619 (Use futex-based thread-parker for Wasm32.)
 - #77646 (For backtrace, use StaticMutex instead of a raw sys Mutex.)
 - #77648 (Static mutex is static)
 - #77657 (Cleanup cloudabi mutexes and condvars)
 - #77672 (Simplify doc-cfg rendering based on the current context)
 - #77780 (rustc_parse: fix spans on cast and range exprs with attrs)
 - #77935 (BTreeMap: make PartialCmp/PartialEq explicit and tested)
 - #77980 (Fix intra doc link for needs_drop)

Failed merges:

r? `@ghost`
-rw-r--r--compiler/rustc_driver/src/lib.rs6
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0007.md8
-rw-r--r--compiler/rustc_feature/src/accepted.rs3
-rw-r--r--compiler/rustc_feature/src/active.rs4
-rw-r--r--compiler/rustc_hir/src/hir.rs28
-rw-r--r--compiler/rustc_middle/src/ty/instance.rs12
-rw-r--r--compiler/rustc_middle/src/ty/query/plumbing.rs13
-rw-r--r--compiler/rustc_middle/src/ty/util.rs18
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/check_match.rs70
-rw-r--r--compiler/rustc_parse/src/parser/expr.rs24
-rw-r--r--compiler/rustc_parse/src/parser/item.rs2
-rw-r--r--compiler/rustc_symbol_mangling/src/legacy.rs1
-rw-r--r--compiler/rustc_symbol_mangling/src/test.rs9
-rw-r--r--compiler/rustc_symbol_mangling/src/v0.rs65
-rw-r--r--compiler/rustc_typeck/src/check/callee.rs8
-rw-r--r--compiler/rustc_typeck/src/check/fn_ctxt/checks.rs27
-rw-r--r--library/alloc/src/collections/btree/node.rs36
-rw-r--r--library/alloc/src/collections/btree/node/tests.rs33
-rw-r--r--library/core/src/intrinsics.rs2
-rw-r--r--library/core/src/lib.rs2
-rw-r--r--library/core/src/str/iter.rs164
-rw-r--r--library/std/src/backtrace.rs6
-rw-r--r--library/std/src/io/buffered.rs1438
-rw-r--r--library/std/src/io/buffered/bufreader.rs423
-rw-r--r--library/std/src/io/buffered/bufwriter.rs387
-rw-r--r--library/std/src/io/buffered/linewriter.rs232
-rw-r--r--library/std/src/io/buffered/linewritershim.rs270
-rw-r--r--library/std/src/io/buffered/mod.rs151
-rw-r--r--library/std/src/sys/cloudabi/condvar.rs41
-rw-r--r--library/std/src/sys/cloudabi/mutex.rs54
-rw-r--r--library/std/src/sys/cloudabi/rwlock.rs47
-rw-r--r--library/std/src/sys/unix/os.rs2
-rw-r--r--library/std/src/sys/vxworks/os.rs2
-rw-r--r--library/std/src/sys/wasm/futex_atomics.rs17
-rw-r--r--library/std/src/sys/wasm/mod.rs2
-rw-r--r--library/std/src/sys_common/backtrace.rs22
-rw-r--r--library/std/src/sys_common/mutex.rs18
-rw-r--r--library/std/src/sys_common/thread_parker/mod.rs6
-rw-r--r--src/librustdoc/clean/cfg.rs31
-rw-r--r--src/librustdoc/clean/cfg/tests.rs36
-rw-r--r--src/librustdoc/html/render/mod.rs104
-rw-r--r--src/test/rustdoc/doc-cfg-simplification.rs182
-rw-r--r--src/test/rustdoc/doc-cfg.rs7
-rw-r--r--src/test/rustdoc/duplicate-cfg.rs26
-rw-r--r--src/test/ui/arg-count-mismatch.stderr9
-rw-r--r--src/test/ui/borrowck/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs2
-rw-r--r--src/test/ui/borrowck/bindings-after-at-or-patterns-slice-patterns-box-patterns.stderr34
-rw-r--r--src/test/ui/c-variadic/variadic-ffi-1.stderr18
-rw-r--r--src/test/ui/c-variadic/variadic-ffi-no-fixed-args.stderr2
-rw-r--r--src/test/ui/drop/dynamic-drop-async.rs2
-rw-r--r--src/test/ui/drop/dynamic-drop.rs1
-rw-r--r--src/test/ui/error-codes/E0007.rs11
-rw-r--r--src/test/ui/error-codes/E0007.stderr22
-rw-r--r--src/test/ui/error-codes/E0060.stderr9
-rw-r--r--src/test/ui/error-codes/E0061.stderr18
-rw-r--r--src/test/ui/hrtb/issue-58451.stderr20
-rw-r--r--src/test/ui/issues/issue-18819.stderr9
-rw-r--r--src/test/ui/issues/issue-26094.stderr9
-rw-r--r--src/test/ui/issues/issue-4935.stderr9
-rw-r--r--src/test/ui/methods/method-call-err-msg.stderr36
-rw-r--r--src/test/ui/mismatched_types/issue-38371.stderr2
-rw-r--r--src/test/ui/not-enough-arguments.rs19
-rw-r--r--src/test/ui/not-enough-arguments.stderr39
-rw-r--r--src/test/ui/parser/variadic-ffi-semantic-restrictions.stderr68
-rw-r--r--src/test/ui/pattern/bindings-after-at/bind-by-move-neither-can-live-while-the-other-survives-1.rs1
-rw-r--r--src/test/ui/pattern/bindings-after-at/bind-by-move-neither-can-live-while-the-other-survives-1.stderr12
-rw-r--r--src/test/ui/pattern/bindings-after-at/bind-by-move-no-subbindings-fun-param.rs1
-rw-r--r--src/test/ui/pattern/bindings-after-at/bind-by-move-no-subbindings-fun-param.stderr2
-rw-r--r--src/test/ui/pattern/bindings-after-at/borrowck-move-and-move.rs1
-rw-r--r--src/test/ui/pattern/bindings-after-at/borrowck-move-and-move.stderr16
-rw-r--r--src/test/ui/pattern/bindings-after-at/borrowck-pat-at-and-box-pass.rs1
-rw-r--r--src/test/ui/pattern/bindings-after-at/borrowck-pat-at-and-box.rs1
-rw-r--r--src/test/ui/pattern/bindings-after-at/borrowck-pat-at-and-box.stderr34
-rw-r--r--src/test/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse-promotion.rs1
-rw-r--r--src/test/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse-promotion.stderr2
-rw-r--r--src/test/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse.rs1
-rw-r--r--src/test/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse.stderr96
-rw-r--r--src/test/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref.rs1
-rw-r--r--src/test/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref.stderr50
-rw-r--r--src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.rs1
-rw-r--r--src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.stderr94
-rw-r--r--src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.rs1
-rw-r--r--src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.stderr68
-rw-r--r--src/test/ui/pattern/bindings-after-at/copy-and-move-mixed.rs1
-rw-r--r--src/test/ui/pattern/bindings-after-at/copy-and-move-mixed.stderr6
-rw-r--r--src/test/ui/pattern/bindings-after-at/default-binding-modes-both-sides-independent.rs1
-rw-r--r--src/test/ui/pattern/bindings-after-at/default-binding-modes-both-sides-independent.stderr12
-rw-r--r--src/test/ui/pattern/move-ref-patterns/borrowck-move-ref-pattern-pass.rs2
-rw-r--r--src/test/ui/pattern/move-ref-patterns/borrowck-move-ref-pattern.rs2
-rw-r--r--src/test/ui/pattern/move-ref-patterns/borrowck-move-ref-pattern.stderr36
-rw-r--r--src/test/ui/pattern/move-ref-patterns/by-move-sub-pat-unreachable.rs1
-rw-r--r--src/test/ui/pattern/move-ref-patterns/feature-gate-move_ref_pattern.rs23
-rw-r--r--src/test/ui/pattern/move-ref-patterns/feature-gate-move_ref_pattern.stderr66
-rw-r--r--src/test/ui/pattern/move-ref-patterns/issue-53840.rs2
-rw-r--r--src/test/ui/pattern/move-ref-patterns/move-ref-patterns-closure-captures-inside.rs2
-rw-r--r--src/test/ui/pattern/move-ref-patterns/move-ref-patterns-closure-captures-inside.stderr54
-rw-r--r--src/test/ui/pattern/move-ref-patterns/move-ref-patterns-closure-captures-pass.rs2
-rw-r--r--src/test/ui/pattern/move-ref-patterns/move-ref-patterns-closure-captures.rs2
-rw-r--r--src/test/ui/pattern/move-ref-patterns/move-ref-patterns-closure-captures.stderr6
-rw-r--r--src/test/ui/pattern/move-ref-patterns/move-ref-patterns-default-binding-modes.rs2
-rw-r--r--src/test/ui/pattern/move-ref-patterns/move-ref-patterns-default-binding-modes.stderr4
-rw-r--r--src/test/ui/pattern/move-ref-patterns/move-ref-patterns-dynamic-semantics.rs2
-rw-r--r--src/test/ui/proc-macro/invalid-punct-ident-1.rs3
-rw-r--r--src/test/ui/proc-macro/invalid-punct-ident-1.stderr2
-rw-r--r--src/test/ui/proc-macro/invalid-punct-ident-2.rs3
-rw-r--r--src/test/ui/proc-macro/invalid-punct-ident-2.stderr2
-rw-r--r--src/test/ui/proc-macro/invalid-punct-ident-3.rs3
-rw-r--r--src/test/ui/proc-macro/invalid-punct-ident-3.stderr2
-rw-r--r--src/test/ui/proc-macro/load-panic-backtrace.rs3
-rw-r--r--src/test/ui/proc-macro/load-panic-backtrace.stderr2
-rw-r--r--src/test/ui/rfc-2005-default-binding-mode/for.rs2
-rw-r--r--src/test/ui/rfc-2005-default-binding-mode/for.stderr2
-rw-r--r--src/test/ui/span/issue-34264.stderr18
-rw-r--r--src/test/ui/span/missing-unit-argument.stderr42
-rw-r--r--src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr6
-rw-r--r--src/test/ui/symbol-names/issue-75326.legacy.stderr20
-rw-r--r--src/test/ui/symbol-names/issue-75326.rs58
-rw-r--r--src/test/ui/symbol-names/issue-75326.v0.stderr20
-rw-r--r--src/test/ui/type-alias-enum-variants/enum-variant-priority-higher-than-other-inherent.stderr9
-rw-r--r--src/tools/clippy/src/driver.rs6
-rw-r--r--src/tools/clippy/tests/ui/custom_ice_message.stderr2
121 files changed, 2898 insertions, 2295 deletions
diff --git a/compiler/rustc_driver/src/lib.rs b/compiler/rustc_driver/src/lib.rs
index 136c9f6ec7d..d99e335a77a 100644
--- a/compiler/rustc_driver/src/lib.rs
+++ b/compiler/rustc_driver/src/lib.rs
@@ -1258,9 +1258,9 @@ pub fn report_ice(info: &panic::PanicInfo<'_>, bug_report_url: &str) {
     // If backtraces are enabled, also print the query stack
     let backtrace = env::var_os("RUST_BACKTRACE").map(|x| &x != "0").unwrap_or(false);
 
-    if backtrace {
-        TyCtxt::try_print_query_stack(&handler);
-    }
+    let num_frames = if backtrace { None } else { Some(2) };
+
+    TyCtxt::try_print_query_stack(&handler, num_frames);
 
     #[cfg(windows)]
     unsafe {
diff --git a/compiler/rustc_error_codes/src/error_codes/E0007.md b/compiler/rustc_error_codes/src/error_codes/E0007.md
index 2be7870d5ae..2c22b86af92 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0007.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0007.md
@@ -1,3 +1,5 @@
+#### Note: this error code is no longer emitted by the compiler.
+
 This error indicates that the bindings in a match arm would require a value to
 be moved into more than one location, thus violating unique ownership. Code
 like the following is invalid as it requires the entire `Option<String>` to be
@@ -6,11 +8,13 @@ inner `String` to be moved into a variable called `s`.
 
 Erroneous code example:
 
-```compile_fail,E0007
+```compile_fail,E0382
+#![feature(bindings_after_at)]
+
 let x = Some("s".to_string());
 
 match x {
-    op_string @ Some(s) => {}, // error: cannot bind by-move with sub-bindings
+    op_string @ Some(s) => {}, // error: use of moved value
     None => {},
 }
 ```
diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs
index e2492efb9d7..4401ec0a04e 100644
--- a/compiler/rustc_feature/src/accepted.rs
+++ b/compiler/rustc_feature/src/accepted.rs
@@ -270,6 +270,9 @@ declare_features! (
     (accepted, track_caller, "1.46.0", Some(47809), None),
     /// Allows `#[doc(alias = "...")]`.
     (accepted, doc_alias, "1.48.0", Some(50146), None),
+    /// Allows patterns with concurrent by-move and by-ref bindings.
+    /// For example, you can write `Foo(a, ref b)` where `a` is by-move and `b` is by-ref.
+    (accepted, move_ref_pattern, "1.48.0", Some(68354), None),
 
     // -------------------------------------------------------------------------
     // feature-group-end: accepted features
diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs
index 8a7f0517e73..7fbd070a609 100644
--- a/compiler/rustc_feature/src/active.rs
+++ b/compiler/rustc_feature/src/active.rs
@@ -526,10 +526,6 @@ declare_features! (
     /// For example, you can write `x @ Some(y)`.
     (active, bindings_after_at, "1.41.0", Some(65490), None),
 
-    /// Allows patterns with concurrent by-move and by-ref bindings.
-    /// For example, you can write `Foo(a, ref b)` where `a` is by-move and `b` is by-ref.
-    (active, move_ref_pattern, "1.42.0", Some(68354), None),
-
     /// Allows `impl const Trait for T` syntax.
     (active, const_trait_impl, "1.42.0", Some(67792), None),
 
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index 2141d5b1ee7..52727e3a619 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -2742,4 +2742,32 @@ impl<'hir> Node<'hir> {
             _ => None,
         }
     }
+
+    pub fn hir_id(&self) -> Option<HirId> {
+        match self {
+            Node::Item(Item { hir_id, .. })
+            | Node::ForeignItem(ForeignItem { hir_id, .. })
+            | Node::TraitItem(TraitItem { hir_id, .. })
+            | Node::ImplItem(ImplItem { hir_id, .. })
+            | Node::Field(StructField { hir_id, .. })
+            | Node::AnonConst(AnonConst { hir_id, .. })
+            | Node::Expr(Expr { hir_id, .. })
+            | Node::Stmt(Stmt { hir_id, .. })
+            | Node::Ty(Ty { hir_id, .. })
+            | Node::Binding(Pat { hir_id, .. })
+            | Node::Pat(Pat { hir_id, .. })
+            | Node::Arm(Arm { hir_id, .. })
+            | Node::Block(Block { hir_id, .. })
+            | Node::Local(Local { hir_id, .. })
+            | Node::MacroDef(MacroDef { hir_id, .. })
+            | Node::Lifetime(Lifetime { hir_id, .. })
+            | Node::Param(Param { hir_id, .. })
+            | Node::GenericParam(GenericParam { hir_id, .. }) => Some(*hir_id),
+            Node::TraitRef(TraitRef { hir_ref_id, .. }) => Some(*hir_ref_id),
+            Node::PathSegment(PathSegment { hir_id, .. }) => *hir_id,
+            Node::Variant(Variant { id, .. }) => Some(*id),
+            Node::Ctor(variant) => variant.ctor_hir_id(),
+            Node::Crate(_) | Node::Visibility(_) => None,
+        }
+    }
 }
diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs
index f8e8c209d37..4a2c97b4a40 100644
--- a/compiler/rustc_middle/src/ty/instance.rs
+++ b/compiler/rustc_middle/src/ty/instance.rs
@@ -291,7 +291,17 @@ impl<'tcx> Instance<'tcx> {
     }
 
     pub fn mono(tcx: TyCtxt<'tcx>, def_id: DefId) -> Instance<'tcx> {
-        Instance::new(def_id, tcx.empty_substs_for_def_id(def_id))
+        let substs = InternalSubsts::for_item(tcx, def_id, |param, _| match param.kind {
+            ty::GenericParamDefKind::Lifetime => tcx.lifetimes.re_erased.into(),
+            ty::GenericParamDefKind::Type { .. } => {
+                bug!("Instance::mono: {:?} has type parameters", def_id)
+            }
+            ty::GenericParamDefKind::Const { .. } => {
+                bug!("Instance::mono: {:?} has const parameters", def_id)
+            }
+        });
+
+        Instance::new(def_id, substs)
     }
 
     #[inline]
diff --git a/compiler/rustc_middle/src/ty/query/plumbing.rs b/compiler/rustc_middle/src/ty/query/plumbing.rs
index f3fa3634026..27bf22dac75 100644
--- a/compiler/rustc_middle/src/ty/query/plumbing.rs
+++ b/compiler/rustc_middle/src/ty/query/plumbing.rs
@@ -124,20 +124,23 @@ impl<'tcx> TyCtxt<'tcx> {
         })
     }
 
-    pub fn try_print_query_stack(handler: &Handler) {
+    pub fn try_print_query_stack(handler: &Handler, num_frames: Option<usize>) {
         eprintln!("query stack during panic:");
 
         // Be careful reyling on global state here: this code is called from
         // a panic hook, which means that the global `Handler` may be in a weird
         // state if it was responsible for triggering the panic.
+        let mut i = 0;
         ty::tls::with_context_opt(|icx| {
             if let Some(icx) = icx {
                 let query_map = icx.tcx.queries.try_collect_active_jobs();
 
                 let mut current_query = icx.query;
-                let mut i = 0;
 
                 while let Some(query) = current_query {
+                    if Some(i) == num_frames {
+                        break;
+                    }
                     let query_info =
                         if let Some(info) = query_map.as_ref().and_then(|map| map.get(&query)) {
                             info
@@ -163,7 +166,11 @@ impl<'tcx> TyCtxt<'tcx> {
             }
         });
 
-        eprintln!("end of query stack");
+        if num_frames == None || num_frames >= Some(i) {
+            eprintln!("end of query stack");
+        } else {
+            eprintln!("we're just showing a limited slice of the query stack");
+        }
     }
 }
 
diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs
index 8734acad9b2..b0f0f0ba57f 100644
--- a/compiler/rustc_middle/src/ty/util.rs
+++ b/compiler/rustc_middle/src/ty/util.rs
@@ -6,9 +6,9 @@ use crate::mir::interpret::{sign_extend, truncate};
 use crate::ty::fold::TypeFolder;
 use crate::ty::layout::IntegerExt;
 use crate::ty::query::TyCtxtAt;
-use crate::ty::subst::{GenericArgKind, InternalSubsts, Subst, SubstsRef};
+use crate::ty::subst::{GenericArgKind, Subst, SubstsRef};
 use crate::ty::TyKind::*;
-use crate::ty::{self, DefIdTree, GenericParamDefKind, List, Ty, TyCtxt, TypeFoldable};
+use crate::ty::{self, DefIdTree, List, Ty, TyCtxt, TypeFoldable};
 use rustc_apfloat::Float as _;
 use rustc_ast as ast;
 use rustc_attr::{self as attr, SignedInt, UnsignedInt};
@@ -509,20 +509,6 @@ impl<'tcx> TyCtxt<'tcx> {
         Some(ty::Binder::bind(env_ty))
     }
 
-    /// Given the `DefId` of some item that has no type or const parameters, make
-    /// a suitable "empty substs" for it.
-    pub fn empty_substs_for_def_id(self, item_def_id: DefId) -> SubstsRef<'tcx> {
-        InternalSubsts::for_item(self, item_def_id, |param, _| match param.kind {
-            GenericParamDefKind::Lifetime => self.lifetimes.re_erased.into(),
-            GenericParamDefKind::Type { .. } => {
-                bug!("empty_substs_for_def_id: {:?} has type parameters", item_def_id)
-            }
-            GenericParamDefKind::Const { .. } => {
-                bug!("empty_substs_for_def_id: {:?} has const parameters", item_def_id)
-            }
-        })
-    }
-
     /// Returns `true` if the node pointed to by `def_id` is a `static` item.
     pub fn is_static(self, def_id: DefId) -> bool {
         self.static_mutability(def_id).is_some()
diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
index 25a8565fb43..69de7c7e2ee 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
@@ -71,13 +71,13 @@ impl<'tcx> Visitor<'tcx> for MatchVisitor<'_, 'tcx> {
             hir::LocalSource::AwaitDesugar => ("`await` future binding", None),
         };
         self.check_irrefutable(&loc.pat, msg, sp);
-        self.check_patterns(false, &loc.pat);
+        self.check_patterns(&loc.pat);
     }
 
     fn visit_param(&mut self, param: &'tcx hir::Param<'tcx>) {
         intravisit::walk_param(self, param);
         self.check_irrefutable(&param.pat, "function argument", None);
-        self.check_patterns(false, &param.pat);
+        self.check_patterns(&param.pat);
     }
 }
 
@@ -119,10 +119,7 @@ impl PatCtxt<'_, '_> {
 }
 
 impl<'tcx> MatchVisitor<'_, 'tcx> {
-    fn check_patterns(&mut self, has_guard: bool, pat: &Pat<'_>) {
-        if !self.tcx.features().move_ref_pattern {
-            check_legality_of_move_bindings(self, has_guard, pat);
-        }
+    fn check_patterns(&mut self, pat: &Pat<'_>) {
         pat.walk_always(|pat| check_borrow_conflicts_in_at_patterns(self, pat));
         if !self.tcx.features().bindings_after_at {
             check_legality_of_bindings_in_at_patterns(self, pat);
@@ -165,7 +162,7 @@ impl<'tcx> MatchVisitor<'_, 'tcx> {
     ) {
         for arm in arms {
             // Check the arm for some things unrelated to exhaustiveness.
-            self.check_patterns(arm.guard.is_some(), &arm.pat);
+            self.check_patterns(&arm.pat);
         }
 
         let mut cx = self.new_cx(scrut.hir_id);
@@ -601,65 +598,6 @@ fn is_binding_by_move(cx: &MatchVisitor<'_, '_>, hir_id: HirId, span: Span) -> b
     !cx.typeck_results.node_type(hir_id).is_copy_modulo_regions(cx.tcx.at(span), cx.param_env)
 }
 
-/// Check the legality of legality of by-move bindings.
-fn check_legality_of_move_bindings(cx: &mut MatchVisitor<'_, '_>, has_guard: bool, pat: &Pat<'_>) {
-    let sess = cx.tcx.sess;
-    let typeck_results = cx.typeck_results;
-
-    // Find all by-ref spans.
-    let mut by_ref_spans = Vec::new();
-    pat.each_binding(|_, hir_id, span, _| {
-        if let Some(ty::BindByReference(_)) =
-            typeck_results.extract_binding_mode(sess, hir_id, span)
-        {
-            by_ref_spans.push(span);
-        }
-    });
-
-    // Find bad by-move spans:
-    let by_move_spans = &mut Vec::new();
-    let mut check_move = |p: &Pat<'_>, sub: Option<&Pat<'_>>| {
-        // Check legality of moving out of the enum.
-        //
-        // `x @ Foo(..)` is legal, but `x @ Foo(y)` isn't.
-        if sub.map_or(false, |p| p.contains_bindings()) {
-            struct_span_err!(sess, p.span, E0007, "cannot bind by-move with sub-bindings")
-                .span_label(p.span, "binds an already bound by-move value by moving it")
-                .emit();
-        } else if !has_guard && !by_ref_spans.is_empty() {
-            by_move_spans.push(p.span);
-        }
-    };
-    pat.walk_always(|p| {
-        if let hir::PatKind::Binding(.., sub) = &p.kind {
-            if let Some(ty::BindByValue(_)) =
-                typeck_results.extract_binding_mode(sess, p.hir_id, p.span)
-            {
-                if is_binding_by_move(cx, p.hir_id, p.span) {
-                    check_move(p, sub.as_deref());
-                }
-            }
-        }
-    });
-
-    // Found some bad by-move spans, error!
-    if !by_move_spans.is_empty() {
-        let mut err = feature_err(
-            &sess.parse_sess,
-            sym::move_ref_pattern,
-            by_move_spans.clone(),
-            "binding by-move and by-ref in the same pattern is unstable",
-        );
-        for span in by_ref_spans.iter() {
-            err.span_label(*span, "by-ref pattern here");
-        }
-        for span in by_move_spans.iter() {
-            err.span_label(*span, "by-move pattern here");
-        }
-        err.emit();
-    }
-}
-
 /// Check that there are no borrow or move conflicts in `binding @ subpat` patterns.
 ///
 /// For example, this would reject:
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs
index a6df41f47ce..17cbaf65420 100644
--- a/compiler/rustc_parse/src/parser/expr.rs
+++ b/compiler/rustc_parse/src/parser/expr.rs
@@ -246,11 +246,7 @@ impl<'a> Parser<'a> {
                 this.parse_assoc_expr_with(prec + prec_adjustment, LhsExpr::NotYetParsed)
             })?;
 
-            // Make sure that the span of the parent node is larger than the span of lhs and rhs,
-            // including the attributes.
-            let lhs_span =
-                lhs.attrs.iter().find(|a| a.style == AttrStyle::Outer).map_or(lhs_span, |a| a.span);
-            let span = lhs_span.to(rhs.span);
+            let span = self.mk_expr_sp(&lhs, lhs_span, rhs.span);
             lhs = match op {
                 AssocOp::Add
                 | AssocOp::Subtract
@@ -411,7 +407,7 @@ impl<'a> Parser<'a> {
             None
         };
         let rhs_span = rhs.as_ref().map_or(cur_op_span, |x| x.span);
-        let span = lhs.span.to(rhs_span);
+        let span = self.mk_expr_sp(&lhs, lhs.span, rhs_span);
         let limits =
             if op == AssocOp::DotDot { RangeLimits::HalfOpen } else { RangeLimits::Closed };
         Ok(self.mk_expr(span, self.mk_range(Some(lhs), rhs, limits)?, AttrVec::new()))
@@ -571,7 +567,11 @@ impl<'a> Parser<'a> {
         expr_kind: fn(P<Expr>, P<Ty>) -> ExprKind,
     ) -> PResult<'a, P<Expr>> {
         let mk_expr = |this: &mut Self, rhs: P<Ty>| {
-            this.mk_expr(lhs_span.to(rhs.span), expr_kind(lhs, rhs), AttrVec::new())
+            this.mk_expr(
+                this.mk_expr_sp(&lhs, lhs_span, rhs.span),
+                expr_kind(lhs, rhs),
+                AttrVec::new(),
+            )
         };
 
         // Save the state of the parser before parsing type normally, in case there is a
@@ -2324,4 +2324,14 @@ impl<'a> Parser<'a> {
     pub(super) fn mk_expr_err(&self, span: Span) -> P<Expr> {
         self.mk_expr(span, ExprKind::Err, AttrVec::new())
     }
+
+    /// Create expression span ensuring the span of the parent node
+    /// is larger than the span of lhs and rhs, including the attributes.
+    fn mk_expr_sp(&self, lhs: &P<Expr>, lhs_span: Span, rhs_span: Span) -> Span {
+        lhs.attrs
+            .iter()
+            .find(|a| a.style == AttrStyle::Outer)
+            .map_or(lhs_span, |a| a.span)
+            .to(rhs_span)
+    }
 }
diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs
index 26ca9980127..48341f71d33 100644
--- a/compiler/rustc_parse/src/parser/item.rs
+++ b/compiler/rustc_parse/src/parser/item.rs
@@ -1744,7 +1744,7 @@ impl<'a> Parser<'a> {
             }
         };
 
-        let span = lo.to(self.token.span);
+        let span = lo.until(self.token.span);
 
         Ok(Param {
             attrs: attrs.into(),
diff --git a/compiler/rustc_symbol_mangling/src/legacy.rs b/compiler/rustc_symbol_mangling/src/legacy.rs
index b96e318bd3e..2c9caf73b8e 100644
--- a/compiler/rustc_symbol_mangling/src/legacy.rs
+++ b/compiler/rustc_symbol_mangling/src/legacy.rs
@@ -115,7 +115,6 @@ fn get_symbol_hash<'tcx>(
         }
 
         // also include any type parameters (for generic items)
-        assert!(!substs.has_erasable_regions());
         substs.hash_stable(&mut hcx, &mut hasher);
 
         if let Some(instantiating_crate) = instantiating_crate {
diff --git a/compiler/rustc_symbol_mangling/src/test.rs b/compiler/rustc_symbol_mangling/src/test.rs
index d2c9b05c560..822a8352934 100644
--- a/compiler/rustc_symbol_mangling/src/test.rs
+++ b/compiler/rustc_symbol_mangling/src/test.rs
@@ -6,7 +6,7 @@
 
 use rustc_hir as hir;
 use rustc_middle::ty::print::with_no_trimmed_paths;
-use rustc_middle::ty::{Instance, TyCtxt};
+use rustc_middle::ty::{subst::InternalSubsts, Instance, TyCtxt};
 use rustc_span::symbol::{sym, Symbol};
 
 const SYMBOL_NAME: Symbol = sym::rustc_symbol_name;
@@ -36,8 +36,11 @@ impl SymbolNamesTest<'tcx> {
         let def_id = tcx.hir().local_def_id(hir_id);
         for attr in tcx.get_attrs(def_id.to_def_id()).iter() {
             if tcx.sess.check_name(attr, SYMBOL_NAME) {
-                // for now, can only use on monomorphic names
-                let instance = Instance::mono(tcx, def_id.to_def_id());
+                let def_id = def_id.to_def_id();
+                let instance = Instance::new(
+                    def_id,
+                    tcx.erase_regions(&InternalSubsts::identity_for_item(tcx, def_id)),
+                );
                 let mangled = tcx.symbol_name(instance);
                 tcx.sess.span_err(attr.span, &format!("symbol-name({})", mangled));
                 if let Ok(demangling) = rustc_demangle::try_demangle(mangled.name) {
diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs
index 183a11a5277..16d0b86903e 100644
--- a/compiler/rustc_symbol_mangling/src/v0.rs
+++ b/compiler/rustc_symbol_mangling/src/v0.rs
@@ -259,7 +259,7 @@ impl Printer<'tcx> for SymbolMangler<'tcx> {
     }
 
     fn print_impl_path(
-        self,
+        mut self,
         impl_def_id: DefId,
         substs: &'tcx [GenericArg<'tcx>],
         mut self_ty: Ty<'tcx>,
@@ -284,12 +284,37 @@ impl Printer<'tcx> for SymbolMangler<'tcx> {
             }
         }
 
-        self.path_append_impl(
-            |cx| cx.print_def_path(parent_def_id, &[]),
-            &key.disambiguated_data,
-            self_ty,
-            impl_trait_ref,
-        )
+        self.push(match impl_trait_ref {
+            Some(_) => "X",
+            None => "M",
+        });
+
+        // Encode impl generic params if the substitutions contain parameters (implying
+        // polymorphization is enabled) and this isn't an inherent impl.
+        if impl_trait_ref.is_some() && substs.iter().any(|a| a.has_param_types_or_consts()) {
+            self = self.path_generic_args(
+                |this| {
+                    this.path_append_ns(
+                        |cx| cx.print_def_path(parent_def_id, &[]),
+                        'I',
+                        key.disambiguated_data.disambiguator as u64,
+                        "",
+                    )
+                },
+                substs,
+            )?;
+        } else {
+            self.push_disambiguator(key.disambiguated_data.disambiguator as u64);
+            self = self.print_def_path(parent_def_id, &[])?;
+        }
+
+        self = self_ty.print(self)?;
+
+        if let Some(trait_ref) = impl_trait_ref {
+            self = self.print_def_path(trait_ref.def_id, trait_ref.substs)?;
+        }
+
+        Ok(self)
     }
 
     fn print_region(mut self, region: ty::Region<'_>) -> Result<Self::Region, Self::Error> {
@@ -538,6 +563,7 @@ impl Printer<'tcx> for SymbolMangler<'tcx> {
         self.push_ident(&name);
         Ok(self)
     }
+
     fn path_qualified(
         mut self,
         self_ty: Ty<'tcx>,
@@ -552,24 +578,16 @@ impl Printer<'tcx> for SymbolMangler<'tcx> {
     }
 
     fn path_append_impl(
-        mut self,
-        print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
-        disambiguated_data: &DisambiguatedDefPathData,
-        self_ty: Ty<'tcx>,
-        trait_ref: Option<ty::TraitRef<'tcx>>,
+        self,
+        _: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
+        _: &DisambiguatedDefPathData,
+        _: Ty<'tcx>,
+        _: Option<ty::TraitRef<'tcx>>,
     ) -> Result<Self::Path, Self::Error> {
-        self.push(match trait_ref {
-            Some(_) => "X",
-            None => "M",
-        });
-        self.push_disambiguator(disambiguated_data.disambiguator as u64);
-        self = print_prefix(self)?;
-        self = self_ty.print(self)?;
-        if let Some(trait_ref) = trait_ref {
-            self = self.print_def_path(trait_ref.def_id, trait_ref.substs)?;
-        }
-        Ok(self)
+        // Inlined into `print_impl_path`
+        unreachable!()
     }
+
     fn path_append(
         self,
         print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
@@ -603,6 +621,7 @@ impl Printer<'tcx> for SymbolMangler<'tcx> {
             name.as_ref().map_or("", |s| &s[..]),
         )
     }
+
     fn path_generic_args(
         mut self,
         print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
diff --git a/compiler/rustc_typeck/src/check/callee.rs b/compiler/rustc_typeck/src/check/callee.rs
index 740783aeb9d..a38fb9642b9 100644
--- a/compiler/rustc_typeck/src/check/callee.rs
+++ b/compiler/rustc_typeck/src/check/callee.rs
@@ -285,10 +285,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         arg_exprs: &'tcx [hir::Expr<'tcx>],
         expected: Expectation<'tcx>,
     ) -> Ty<'tcx> {
-        let (fn_sig, def_span) = match *callee_ty.kind() {
-            ty::FnDef(def_id, _) => {
-                (callee_ty.fn_sig(self.tcx), self.tcx.hir().span_if_local(def_id))
-            }
+        let (fn_sig, def_id) = match *callee_ty.kind() {
+            ty::FnDef(def_id, _) => (callee_ty.fn_sig(self.tcx), Some(def_id)),
             ty::FnPtr(sig) => (sig, None),
             ref t => {
                 let mut unit_variant = None;
@@ -427,7 +425,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             arg_exprs,
             fn_sig.c_variadic,
             TupleArgumentsFlag::DontTupleArguments,
-            def_span,
+            def_id,
         );
 
         fn_sig.output()
diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs
index 3224e04ee49..fd2f5eb5018 100644
--- a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs
+++ b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs
@@ -19,7 +19,7 @@ use rustc_middle::ty::fold::TypeFoldable;
 use rustc_middle::ty::{self, Ty};
 use rustc_session::Session;
 use rustc_span::symbol::{sym, Ident};
-use rustc_span::{self, Span};
+use rustc_span::{self, MultiSpan, Span};
 use rustc_trait_selection::traits::{self, ObligationCauseCode};
 
 use std::mem::replace;
@@ -83,7 +83,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             args_no_rcvr,
             method.sig.c_variadic,
             tuple_arguments,
-            self.tcx.hir().span_if_local(method.def_id),
+            Some(method.def_id),
         );
         method.sig.output()
     }
@@ -99,7 +99,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         args: &'tcx [hir::Expr<'tcx>],
         c_variadic: bool,
         tuple_arguments: TupleArgumentsFlag,
-        def_span: Option<Span>,
+        def_id: Option<DefId>,
     ) {
         let tcx = self.tcx;
         // Grab the argument types, supplying fresh type variables
@@ -172,9 +172,26 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 );
             }
 
-            if let Some(def_s) = def_span.map(|sp| tcx.sess.source_map().guess_head_span(sp)) {
-                err.span_label(def_s, "defined here");
+            if let Some(def_id) = def_id {
+                if let Some(node) = tcx.hir().get_if_local(def_id) {
+                    let mut spans: MultiSpan = node
+                        .ident()
+                        .map(|ident| ident.span)
+                        .unwrap_or_else(|| tcx.hir().span(node.hir_id().unwrap()))
+                        .into();
+
+                    if let Some(id) = node.body_id() {
+                        let body = tcx.hir().body(id);
+                        for param in body.params {
+                            spans.push_span_label(param.span, String::new());
+                        }
+                    }
+
+                    let def_kind = tcx.def_kind(def_id);
+                    err.span_note(spans, &format!("{} defined here", def_kind.descr(def_id)));
+                }
             }
+
             if sugg_unit {
                 let sugg_span = tcx.sess.source_map().end_point(expr.span);
                 // remove closing `)` from the span
diff --git a/library/alloc/src/collections/btree/node.rs b/library/alloc/src/collections/btree/node.rs
index 4fa97ff053e..903faf3fa96 100644
--- a/library/alloc/src/collections/btree/node.rs
+++ b/library/alloc/src/collections/btree/node.rs
@@ -257,8 +257,13 @@ impl<K, V> Root<K, V> {
 ///   `NodeRef` points to an internal node, and when this is `LeafOrInternal` the
 ///   `NodeRef` could be pointing to either type of node.
 pub struct NodeRef<BorrowType, K, V, Type> {
-    /// The number of levels below the node.
+    /// The number of levels below the node, a property of the node that cannot be
+    /// entirely described by `Type` and that the node does not store itself either.
+    /// Unconstrained if `Type` is `LeafOrInternal`, must be zero if `Type` is `Leaf`,
+    /// and must be non-zero if `Type` is `Internal`.
     height: usize,
+    /// The pointer to the leaf or internal node. The definition of `InternalNode`
+    /// ensures that the pointer is valid either way.
     node: NonNull<LeafNode<K, V>>,
     _marker: PhantomData<(BorrowType, Type)>,
 }
@@ -315,8 +320,8 @@ impl<BorrowType, K, V, Type> NodeRef<BorrowType, K, V, Type> {
         unsafe { usize::from((*self.as_leaf_ptr()).len) }
     }
 
-    /// Returns the height of this node in the whole tree. Zero height denotes the
-    /// leaf level.
+    /// Returns the height of this node with respect to the leaf level. Zero height means the
+    /// node is a leaf itself.
     pub fn height(&self) -> usize {
         self.height
     }
@@ -584,9 +589,11 @@ impl<'a, K, V, Type> NodeRef<marker::ValMut<'a>, K, V, Type> {
         // to avoid aliasing with outstanding references to other elements,
         // in particular, those returned to the caller in earlier iterations.
         let leaf = self.node.as_ptr();
+        let keys = unsafe { &raw const (*leaf).keys };
+        let vals = unsafe { &raw mut (*leaf).vals };
         // We must coerce to unsized array pointers because of Rust issue #74679.
-        let keys: *const [_] = unsafe { &raw const (*leaf).keys };
-        let vals: *mut [_] = unsafe { &raw mut (*leaf).vals };
+        let keys: *const [_] = keys;
+        let vals: *mut [_] = vals;
         // SAFETY: The keys and values of a node must always be initialized up to length.
         let key = unsafe { (&*keys.get_unchecked(idx)).assume_init_ref() };
         let val = unsafe { (&mut *vals.get_unchecked_mut(idx)).assume_init_mut() };
@@ -817,11 +824,25 @@ impl<BorrowType, K, V, NodeType> Handle<NodeRef<BorrowType, K, V, NodeType>, mar
     }
 }
 
+impl<BorrowType, K, V, NodeType> NodeRef<BorrowType, K, V, NodeType> {
+    /// Could be a public implementation of PartialEq, but only used in this module.
+    fn eq(&self, other: &Self) -> bool {
+        let Self { node, height, _marker: _ } = self;
+        if *node == other.node {
+            debug_assert_eq!(*height, other.height);
+            true
+        } else {
+            false
+        }
+    }
+}
+
 impl<BorrowType, K, V, NodeType, HandleType> PartialEq
     for Handle<NodeRef<BorrowType, K, V, NodeType>, HandleType>
 {
     fn eq(&self, other: &Self) -> bool {
-        self.node.node == other.node.node && self.idx == other.idx
+        let Self { node, idx, _marker: _ } = self;
+        node.eq(&other.node) && *idx == other.idx
     }
 }
 
@@ -829,7 +850,8 @@ impl<BorrowType, K, V, NodeType, HandleType> PartialOrd
     for Handle<NodeRef<BorrowType, K, V, NodeType>, HandleType>
 {
     fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
-        if self.node.node == other.node.node { Some(self.idx.cmp(&other.idx)) } else { None }
+        let Self { node, idx, _marker: _ } = self;
+        if node.eq(&other.node) { Some(idx.cmp(&other.idx)) } else { None }
     }
 }
 
diff --git a/library/alloc/src/collections/btree/node/tests.rs b/library/alloc/src/collections/btree/node/tests.rs
index 54c3709821a..2ef9aad0ccd 100644
--- a/library/alloc/src/collections/btree/node/tests.rs
+++ b/library/alloc/src/collections/btree/node/tests.rs
@@ -1,4 +1,5 @@
 use super::*;
+use core::cmp::Ordering::*;
 
 #[test]
 fn test_splitpoint() {
@@ -25,6 +26,38 @@ fn test_splitpoint() {
 }
 
 #[test]
+fn test_partial_cmp_eq() {
+    let mut root1: Root<i32, ()> = Root::new_leaf();
+    let mut leaf1 = unsafe { root1.leaf_node_as_mut() };
+    leaf1.push(1, ());
+    root1.push_internal_level();
+    let root2: Root<i32, ()> = Root::new_leaf();
+
+    let leaf_edge_1a = root1.node_as_ref().first_leaf_edge().forget_node_type();
+    let leaf_edge_1b = root1.node_as_ref().last_leaf_edge().forget_node_type();
+    let top_edge_1 = root1.node_as_ref().first_edge();
+    let top_edge_2 = root2.node_as_ref().first_edge();
+
+    assert!(leaf_edge_1a == leaf_edge_1a);
+    assert!(leaf_edge_1a != leaf_edge_1b);
+    assert!(leaf_edge_1a != top_edge_1);
+    assert!(leaf_edge_1a != top_edge_2);
+    assert!(top_edge_1 == top_edge_1);
+    assert!(top_edge_1 != top_edge_2);
+
+    assert_eq!(leaf_edge_1a.partial_cmp(&leaf_edge_1a), Some(Equal));
+    assert_eq!(leaf_edge_1a.partial_cmp(&leaf_edge_1b), Some(Less));
+    assert_eq!(leaf_edge_1a.partial_cmp(&top_edge_1), None);
+    assert_eq!(leaf_edge_1a.partial_cmp(&top_edge_2), None);
+    assert_eq!(top_edge_1.partial_cmp(&top_edge_1), Some(Equal));
+    assert_eq!(top_edge_1.partial_cmp(&top_edge_2), None);
+
+    root1.pop_internal_level();
+    unsafe { root1.into_ref().deallocate_and_ascend() };
+    unsafe { root2.into_ref().deallocate_and_ascend() };
+}
+
+#[test]
 #[cfg(target_arch = "x86_64")]
 fn test_sizes() {
     assert_eq!(core::mem::size_of::<LeafNode<(), ()>>(), 16);
diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs
index b2798ea6625..2a7c105e807 100644
--- a/library/core/src/intrinsics.rs
+++ b/library/core/src/intrinsics.rs
@@ -1082,7 +1082,7 @@ extern "rust-intrinsic" {
     /// If the actual type neither requires drop glue nor implements
     /// `Copy`, then the return value of this function is unspecified.
     ///
-    /// The stabilized version of this intrinsic is [`needs_drop`].
+    /// The stabilized version of this intrinsic is [`mem::needs_drop`](crate::mem::needs_drop).
     #[rustc_const_stable(feature = "const_needs_drop", since = "1.40.0")]
     pub fn needs_drop<T>() -> bool;
 
diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs
index c9a80b5bc77..97f27566eb0 100644
--- a/library/core/src/lib.rs
+++ b/library/core/src/lib.rs
@@ -126,6 +126,8 @@
 #![feature(staged_api)]
 #![feature(std_internals)]
 #![feature(stmt_expr_attributes)]
+#![feature(str_split_as_str)]
+#![feature(str_split_inclusive_as_str)]
 #![feature(transparent_unions)]
 #![feature(unboxed_closures)]
 #![feature(unsized_locals)]
diff --git a/library/core/src/str/iter.rs b/library/core/src/str/iter.rs
index 27a67e2b22f..bee86df520c 100644
--- a/library/core/src/str/iter.rs
+++ b/library/core/src/str/iter.rs
@@ -690,6 +690,17 @@ impl<'a, P: Pattern<'a>> SplitInternal<'a, P> {
             },
         }
     }
+
+    #[inline]
+    fn as_str(&self) -> &'a str {
+        // `Self::get_end` doesn't change `self.start`
+        if self.finished {
+            return "";
+        }
+
+        // SAFETY: `self.start` and `self.end` always lie on unicode boundaries.
+        unsafe { self.matcher.haystack().get_unchecked(self.start..self.end) }
+    }
 }
 
 generate_pattern_iterators! {
@@ -710,6 +721,48 @@ generate_pattern_iterators! {
     delegate double ended;
 }
 
+impl<'a, P: Pattern<'a>> Split<'a, P> {
+    /// Returns remainder of the splitted string
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(str_split_as_str)]
+    /// let mut split = "Mary had a little lamb".split(' ');
+    /// assert_eq!(split.as_str(), "Mary had a little lamb");
+    /// split.next();
+    /// assert_eq!(split.as_str(), "had a little lamb");
+    /// split.by_ref().for_each(drop);
+    /// assert_eq!(split.as_str(), "");
+    /// ```
+    #[inline]
+    #[unstable(feature = "str_split_as_str", issue = "77998")]
+    pub fn as_str(&self) -> &'a str {
+        self.0.as_str()
+    }
+}
+
+impl<'a, P: Pattern<'a>> RSplit<'a, P> {
+    /// Returns remainder of the splitted string
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(str_split_as_str)]
+    /// let mut split = "Mary had a little lamb".rsplit(' ');
+    /// assert_eq!(split.as_str(), "Mary had a little lamb");
+    /// split.next();
+    /// assert_eq!(split.as_str(), "Mary had a little");
+    /// split.by_ref().for_each(drop);
+    /// assert_eq!(split.as_str(), "");
+    /// ```
+    #[inline]
+    #[unstable(feature = "str_split_as_str", issue = "77998")]
+    pub fn as_str(&self) -> &'a str {
+        self.0.as_str()
+    }
+}
+
 generate_pattern_iterators! {
     forward:
         /// Created with the method [`split_terminator`].
@@ -728,6 +781,48 @@ generate_pattern_iterators! {
     delegate double ended;
 }
 
+impl<'a, P: Pattern<'a>> SplitTerminator<'a, P> {
+    /// Returns remainder of the splitted string
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(str_split_as_str)]
+    /// let mut split = "A..B..".split_terminator('.');
+    /// assert_eq!(split.as_str(), "A..B..");
+    /// split.next();
+    /// assert_eq!(split.as_str(), ".B..");
+    /// split.by_ref().for_each(drop);
+    /// assert_eq!(split.as_str(), "");
+    /// ```
+    #[inline]
+    #[unstable(feature = "str_split_as_str", issue = "77998")]
+    pub fn as_str(&self) -> &'a str {
+        self.0.as_str()
+    }
+}
+
+impl<'a, P: Pattern<'a>> RSplitTerminator<'a, P> {
+    /// Returns remainder of the splitted string
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(str_split_as_str)]
+    /// let mut split = "A..B..".rsplit_terminator('.');
+    /// assert_eq!(split.as_str(), "A..B..");
+    /// split.next();
+    /// assert_eq!(split.as_str(), "A..B");
+    /// split.by_ref().for_each(drop);
+    /// assert_eq!(split.as_str(), "");
+    /// ```
+    #[inline]
+    #[unstable(feature = "str_split_as_str", issue = "77998")]
+    pub fn as_str(&self) -> &'a str {
+        self.0.as_str()
+    }
+}
+
 derive_pattern_clone! {
     clone SplitNInternal
     with |s| SplitNInternal { iter: s.iter.clone(), ..*s }
@@ -784,6 +879,11 @@ impl<'a, P: Pattern<'a>> SplitNInternal<'a, P> {
             }
         }
     }
+
+    #[inline]
+    fn as_str(&self) -> &'a str {
+        self.iter.as_str()
+    }
 }
 
 generate_pattern_iterators! {
@@ -804,6 +904,48 @@ generate_pattern_iterators! {
     delegate single ended;
 }
 
+impl<'a, P: Pattern<'a>> SplitN<'a, P> {
+    /// Returns remainder of the splitted string
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(str_split_as_str)]
+    /// let mut split = "Mary had a little lamb".splitn(3, ' ');
+    /// assert_eq!(split.as_str(), "Mary had a little lamb");
+    /// split.next();
+    /// assert_eq!(split.as_str(), "had a little lamb");
+    /// split.by_ref().for_each(drop);
+    /// assert_eq!(split.as_str(), "");
+    /// ```
+    #[inline]
+    #[unstable(feature = "str_split_as_str", issue = "77998")]
+    pub fn as_str(&self) -> &'a str {
+        self.0.as_str()
+    }
+}
+
+impl<'a, P: Pattern<'a>> RSplitN<'a, P> {
+    /// Returns remainder of the splitted string
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(str_split_as_str)]
+    /// let mut split = "Mary had a little lamb".rsplitn(3, ' ');
+    /// assert_eq!(split.as_str(), "Mary had a little lamb");
+    /// split.next();
+    /// assert_eq!(split.as_str(), "Mary had a little");
+    /// split.by_ref().for_each(drop);
+    /// assert_eq!(split.as_str(), "");
+    /// ```
+    #[inline]
+    #[unstable(feature = "str_split_as_str", issue = "77998")]
+    pub fn as_str(&self) -> &'a str {
+        self.0.as_str()
+    }
+}
+
 derive_pattern_clone! {
     clone MatchIndicesInternal
     with |s| MatchIndicesInternal(s.0.clone())
@@ -1134,6 +1276,28 @@ impl<'a, P: Pattern<'a, Searcher: ReverseSearcher<'a>>> DoubleEndedIterator
 #[unstable(feature = "split_inclusive", issue = "72360")]
 impl<'a, P: Pattern<'a>> FusedIterator for SplitInclusive<'a, P> {}
 
+impl<'a, P: Pattern<'a>> SplitInclusive<'a, P> {
+    /// Returns remainder of the splitted string
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(str_split_inclusive_as_str)]
+    /// #![feature(split_inclusive)]
+    /// let mut split = "Mary had a little lamb".split_inclusive(' ');
+    /// assert_eq!(split.as_str(), "Mary had a little lamb");
+    /// split.next();
+    /// assert_eq!(split.as_str(), "had a little lamb");
+    /// split.by_ref().for_each(drop);
+    /// assert_eq!(split.as_str(), "");
+    /// ```
+    #[inline]
+    #[unstable(feature = "str_split_inclusive_as_str", issue = "77998")]
+    pub fn as_str(&self) -> &'a str {
+        self.0.as_str()
+    }
+}
+
 /// An iterator of [`u16`] over the string encoded as UTF-16.
 ///
 /// This struct is created by the [`encode_utf16`] method on [`str`].
diff --git a/library/std/src/backtrace.rs b/library/std/src/backtrace.rs
index cc29e1c0b05..a9d8a4e2a81 100644
--- a/library/std/src/backtrace.rs
+++ b/library/std/src/backtrace.rs
@@ -303,7 +303,8 @@ impl Backtrace {
     // Capture a backtrace which start just before the function addressed by
     // `ip`
     fn create(ip: usize) -> Backtrace {
-        let _lock = lock();
+        // SAFETY: We don't attempt to lock this reentrantly.
+        let _lock = unsafe { lock() };
         let mut frames = Vec::new();
         let mut actual_start = None;
         unsafe {
@@ -408,7 +409,8 @@ impl Capture {
         // Use the global backtrace lock to synchronize this as it's a
         // requirement of the `backtrace` crate, and then actually resolve
         // everything.
-        let _lock = lock();
+        // SAFETY: We don't attempt to lock this reentrantly.
+        let _lock = unsafe { lock() };
         for frame in self.frames.iter_mut() {
             let symbols = &mut frame.symbols;
             let frame = match &frame.frame {
diff --git a/library/std/src/io/buffered.rs b/library/std/src/io/buffered.rs
deleted file mode 100644
index 97c4b879793..00000000000
--- a/library/std/src/io/buffered.rs
+++ /dev/null
@@ -1,1438 +0,0 @@
-//! Buffering wrappers for I/O traits
-
-#[cfg(test)]
-mod tests;
-
-use crate::io::prelude::*;
-
-use crate::cmp;
-use crate::error;
-use crate::fmt;
-use crate::io::{
-    self, Error, ErrorKind, Initializer, IoSlice, IoSliceMut, SeekFrom, DEFAULT_BUF_SIZE,
-};
-use crate::memchr;
-
-/// The `BufReader<R>` struct adds buffering to any reader.
-///
-/// It can be excessively inefficient to work directly with a [`Read`] instance.
-/// For example, every call to [`read`][`TcpStream::read`] on [`TcpStream`]
-/// results in a system call. A `BufReader<R>` performs large, infrequent reads on
-/// the underlying [`Read`] and maintains an in-memory buffer of the results.
-///
-/// `BufReader<R>` can improve the speed of programs that make *small* and
-/// *repeated* read calls to the same file or network socket. It does not
-/// help when reading very large amounts at once, or reading just one or a few
-/// times. It also provides no advantage when reading from a source that is
-/// already in memory, like a [`Vec`]`<u8>`.
-///
-/// When the `BufReader<R>` is dropped, the contents of its buffer will be
-/// discarded. Creating multiple instances of a `BufReader<R>` on the same
-/// stream can cause data loss. Reading from the underlying reader after
-/// unwrapping the `BufReader<R>` with [`BufReader::into_inner`] can also cause
-/// data loss.
-///
-/// [`TcpStream::read`]: Read::read
-/// [`TcpStream`]: crate::net::TcpStream
-///
-/// # Examples
-///
-/// ```no_run
-/// use std::io::prelude::*;
-/// use std::io::BufReader;
-/// use std::fs::File;
-///
-/// fn main() -> std::io::Result<()> {
-///     let f = File::open("log.txt")?;
-///     let mut reader = BufReader::new(f);
-///
-///     let mut line = String::new();
-///     let len = reader.read_line(&mut line)?;
-///     println!("First line is {} bytes long", len);
-///     Ok(())
-/// }
-/// ```
-#[stable(feature = "rust1", since = "1.0.0")]
-pub struct BufReader<R> {
-    inner: R,
-    buf: Box<[u8]>,
-    pos: usize,
-    cap: usize,
-}
-
-impl<R: Read> BufReader<R> {
-    /// Creates a new `BufReader<R>` with a default buffer capacity. The default is currently 8 KB,
-    /// but may change in the future.
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// use std::io::BufReader;
-    /// use std::fs::File;
-    ///
-    /// fn main() -> std::io::Result<()> {
-    ///     let f = File::open("log.txt")?;
-    ///     let reader = BufReader::new(f);
-    ///     Ok(())
-    /// }
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn new(inner: R) -> BufReader<R> {
-        BufReader::with_capacity(DEFAULT_BUF_SIZE, inner)
-    }
-
-    /// Creates a new `BufReader<R>` with the specified buffer capacity.
-    ///
-    /// # Examples
-    ///
-    /// Creating a buffer with ten bytes of capacity:
-    ///
-    /// ```no_run
-    /// use std::io::BufReader;
-    /// use std::fs::File;
-    ///
-    /// fn main() -> std::io::Result<()> {
-    ///     let f = File::open("log.txt")?;
-    ///     let reader = BufReader::with_capacity(10, f);
-    ///     Ok(())
-    /// }
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn with_capacity(capacity: usize, inner: R) -> BufReader<R> {
-        unsafe {
-            let mut buffer = Vec::with_capacity(capacity);
-            buffer.set_len(capacity);
-            inner.initializer().initialize(&mut buffer);
-            BufReader { inner, buf: buffer.into_boxed_slice(), pos: 0, cap: 0 }
-        }
-    }
-}
-
-impl<R> BufReader<R> {
-    /// Gets a reference to the underlying reader.
-    ///
-    /// It is inadvisable to directly read from the underlying reader.
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// use std::io::BufReader;
-    /// use std::fs::File;
-    ///
-    /// fn main() -> std::io::Result<()> {
-    ///     let f1 = File::open("log.txt")?;
-    ///     let reader = BufReader::new(f1);
-    ///
-    ///     let f2 = reader.get_ref();
-    ///     Ok(())
-    /// }
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn get_ref(&self) -> &R {
-        &self.inner
-    }
-
-    /// Gets a mutable reference to the underlying reader.
-    ///
-    /// It is inadvisable to directly read from the underlying reader.
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// use std::io::BufReader;
-    /// use std::fs::File;
-    ///
-    /// fn main() -> std::io::Result<()> {
-    ///     let f1 = File::open("log.txt")?;
-    ///     let mut reader = BufReader::new(f1);
-    ///
-    ///     let f2 = reader.get_mut();
-    ///     Ok(())
-    /// }
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn get_mut(&mut self) -> &mut R {
-        &mut self.inner
-    }
-
-    /// Returns a reference to the internally buffered data.
-    ///
-    /// Unlike [`fill_buf`], this will not attempt to fill the buffer if it is empty.
-    ///
-    /// [`fill_buf`]: BufRead::fill_buf
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// use std::io::{BufReader, BufRead};
-    /// use std::fs::File;
-    ///
-    /// fn main() -> std::io::Result<()> {
-    ///     let f = File::open("log.txt")?;
-    ///     let mut reader = BufReader::new(f);
-    ///     assert!(reader.buffer().is_empty());
-    ///
-    ///     if reader.fill_buf()?.len() > 0 {
-    ///         assert!(!reader.buffer().is_empty());
-    ///     }
-    ///     Ok(())
-    /// }
-    /// ```
-    #[stable(feature = "bufreader_buffer", since = "1.37.0")]
-    pub fn buffer(&self) -> &[u8] {
-        &self.buf[self.pos..self.cap]
-    }
-
-    /// Returns the number of bytes the internal buffer can hold at once.
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// use std::io::{BufReader, BufRead};
-    /// use std::fs::File;
-    ///
-    /// fn main() -> std::io::Result<()> {
-    ///     let f = File::open("log.txt")?;
-    ///     let mut reader = BufReader::new(f);
-    ///
-    ///     let capacity = reader.capacity();
-    ///     let buffer = reader.fill_buf()?;
-    ///     assert!(buffer.len() <= capacity);
-    ///     Ok(())
-    /// }
-    /// ```
-    #[stable(feature = "buffered_io_capacity", since = "1.46.0")]
-    pub fn capacity(&self) -> usize {
-        self.buf.len()
-    }
-
-    /// Unwraps this `BufReader<R>`, returning the underlying reader.
-    ///
-    /// Note that any leftover data in the internal buffer is lost. Therefore,
-    /// a following read from the underlying reader may lead to data loss.
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// use std::io::BufReader;
-    /// use std::fs::File;
-    ///
-    /// fn main() -> std::io::Result<()> {
-    ///     let f1 = File::open("log.txt")?;
-    ///     let reader = BufReader::new(f1);
-    ///
-    ///     let f2 = reader.into_inner();
-    ///     Ok(())
-    /// }
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn into_inner(self) -> R {
-        self.inner
-    }
-
-    /// Invalidates all data in the internal buffer.
-    #[inline]
-    fn discard_buffer(&mut self) {
-        self.pos = 0;
-        self.cap = 0;
-    }
-}
-
-impl<R: Seek> BufReader<R> {
-    /// Seeks relative to the current position. If the new position lies within the buffer,
-    /// the buffer will not be flushed, allowing for more efficient seeks.
-    /// This method does not return the location of the underlying reader, so the caller
-    /// must track this information themselves if it is required.
-    #[unstable(feature = "bufreader_seek_relative", issue = "31100")]
-    pub fn seek_relative(&mut self, offset: i64) -> io::Result<()> {
-        let pos = self.pos as u64;
-        if offset < 0 {
-            if let Some(new_pos) = pos.checked_sub((-offset) as u64) {
-                self.pos = new_pos as usize;
-                return Ok(());
-            }
-        } else {
-            if let Some(new_pos) = pos.checked_add(offset as u64) {
-                if new_pos <= self.cap as u64 {
-                    self.pos = new_pos as usize;
-                    return Ok(());
-                }
-            }
-        }
-        self.seek(SeekFrom::Current(offset)).map(drop)
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<R: Read> Read for BufReader<R> {
-    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
-        // If we don't have any buffered data and we're doing a massive read
-        // (larger than our internal buffer), bypass our internal buffer
-        // entirely.
-        if self.pos == self.cap && buf.len() >= self.buf.len() {
-            self.discard_buffer();
-            return self.inner.read(buf);
-        }
-        let nread = {
-            let mut rem = self.fill_buf()?;
-            rem.read(buf)?
-        };
-        self.consume(nread);
-        Ok(nread)
-    }
-
-    fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
-        let total_len = bufs.iter().map(|b| b.len()).sum::<usize>();
-        if self.pos == self.cap && total_len >= self.buf.len() {
-            self.discard_buffer();
-            return self.inner.read_vectored(bufs);
-        }
-        let nread = {
-            let mut rem = self.fill_buf()?;
-            rem.read_vectored(bufs)?
-        };
-        self.consume(nread);
-        Ok(nread)
-    }
-
-    fn is_read_vectored(&self) -> bool {
-        self.inner.is_read_vectored()
-    }
-
-    // we can't skip unconditionally because of the large buffer case in read.
-    unsafe fn initializer(&self) -> Initializer {
-        self.inner.initializer()
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<R: Read> BufRead for BufReader<R> {
-    fn fill_buf(&mut self) -> io::Result<&[u8]> {
-        // If we've reached the end of our internal buffer then we need to fetch
-        // some more data from the underlying reader.
-        // Branch using `>=` instead of the more correct `==`
-        // to tell the compiler that the pos..cap slice is always valid.
-        if self.pos >= self.cap {
-            debug_assert!(self.pos == self.cap);
-            self.cap = self.inner.read(&mut self.buf)?;
-            self.pos = 0;
-        }
-        Ok(&self.buf[self.pos..self.cap])
-    }
-
-    fn consume(&mut self, amt: usize) {
-        self.pos = cmp::min(self.pos + amt, self.cap);
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<R> fmt::Debug for BufReader<R>
-where
-    R: fmt::Debug,
-{
-    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
-        fmt.debug_struct("BufReader")
-            .field("reader", &self.inner)
-            .field("buffer", &format_args!("{}/{}", self.cap - self.pos, self.buf.len()))
-            .finish()
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<R: Seek> Seek for BufReader<R> {
-    /// Seek to an offset, in bytes, in the underlying reader.
-    ///
-    /// The position used for seeking with [`SeekFrom::Current`]`(_)` is the
-    /// position the underlying reader would be at if the `BufReader<R>` had no
-    /// internal buffer.
-    ///
-    /// Seeking always discards the internal buffer, even if the seek position
-    /// would otherwise fall within it. This guarantees that calling
-    /// [`BufReader::into_inner()`] immediately after a seek yields the underlying reader
-    /// at the same position.
-    ///
-    /// To seek without discarding the internal buffer, use [`BufReader::seek_relative`].
-    ///
-    /// See [`std::io::Seek`] for more details.
-    ///
-    /// Note: In the edge case where you're seeking with [`SeekFrom::Current`]`(n)`
-    /// where `n` minus the internal buffer length overflows an `i64`, two
-    /// seeks will be performed instead of one. If the second seek returns
-    /// [`Err`], the underlying reader will be left at the same position it would
-    /// have if you called `seek` with [`SeekFrom::Current`]`(0)`.
-    ///
-    /// [`std::io::Seek`]: Seek
-    fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
-        let result: u64;
-        if let SeekFrom::Current(n) = pos {
-            let remainder = (self.cap - self.pos) as i64;
-            // it should be safe to assume that remainder fits within an i64 as the alternative
-            // means we managed to allocate 8 exbibytes and that's absurd.
-            // But it's not out of the realm of possibility for some weird underlying reader to
-            // support seeking by i64::MIN so we need to handle underflow when subtracting
-            // remainder.
-            if let Some(offset) = n.checked_sub(remainder) {
-                result = self.inner.seek(SeekFrom::Current(offset))?;
-            } else {
-                // seek backwards by our remainder, and then by the offset
-                self.inner.seek(SeekFrom::Current(-remainder))?;
-                self.discard_buffer();
-                result = self.inner.seek(SeekFrom::Current(n))?;
-            }
-        } else {
-            // Seeking with Start/End doesn't care about our buffer length.
-            result = self.inner.seek(pos)?;
-        }
-        self.discard_buffer();
-        Ok(result)
-    }
-
-    /// Returns the current seek position from the start of the stream.
-    ///
-    /// The value returned is equivalent to `self.seek(SeekFrom::Current(0))`
-    /// but does not flush the internal buffer. Due to this optimization the
-    /// function does not guarantee that calling `.into_inner()` immediately
-    /// afterwards will yield the underlying reader at the same position. Use
-    /// [`BufReader::seek`] instead if you require that guarantee.
-    ///
-    /// # Panics
-    ///
-    /// This function will panic if the position of the inner reader is smaller
-    /// than the amount of buffered data. That can happen if the inner reader
-    /// has an incorrect implementation of [`Seek::stream_position`], or if the
-    /// position has gone out of sync due to calling [`Seek::seek`] directly on
-    /// the underlying reader.
-    ///
-    /// # Example
-    ///
-    /// ```no_run
-    /// #![feature(seek_convenience)]
-    /// use std::{
-    ///     io::{self, BufRead, BufReader, Seek},
-    ///     fs::File,
-    /// };
-    ///
-    /// fn main() -> io::Result<()> {
-    ///     let mut f = BufReader::new(File::open("foo.txt")?);
-    ///
-    ///     let before = f.stream_position()?;
-    ///     f.read_line(&mut String::new())?;
-    ///     let after = f.stream_position()?;
-    ///
-    ///     println!("The first line was {} bytes long", after - before);
-    ///     Ok(())
-    /// }
-    /// ```
-    fn stream_position(&mut self) -> io::Result<u64> {
-        let remainder = (self.cap - self.pos) as u64;
-        self.inner.stream_position().map(|pos| {
-            pos.checked_sub(remainder).expect(
-                "overflow when subtracting remaining buffer size from inner stream position",
-            )
-        })
-    }
-}
-
-/// Wraps a writer and buffers its output.
-///
-/// It can be excessively inefficient to work directly with something that
-/// implements [`Write`]. For example, every call to
-/// [`write`][`TcpStream::write`] on [`TcpStream`] results in a system call. A
-/// `BufWriter<W>` keeps an in-memory buffer of data and writes it to an underlying
-/// writer in large, infrequent batches.
-///
-/// `BufWriter<W>` can improve the speed of programs that make *small* and
-/// *repeated* write calls to the same file or network socket. It does not
-/// help when writing very large amounts at once, or writing just one or a few
-/// times. It also provides no advantage when writing to a destination that is
-/// in memory, like a [`Vec`]<u8>`.
-///
-/// It is critical to call [`flush`] before `BufWriter<W>` is dropped. Though
-/// dropping will attempt to flush the contents of the buffer, any errors
-/// that happen in the process of dropping will be ignored. Calling [`flush`]
-/// ensures that the buffer is empty and thus dropping will not even attempt
-/// file operations.
-///
-/// # Examples
-///
-/// Let's write the numbers one through ten to a [`TcpStream`]:
-///
-/// ```no_run
-/// use std::io::prelude::*;
-/// use std::net::TcpStream;
-///
-/// let mut stream = TcpStream::connect("127.0.0.1:34254").unwrap();
-///
-/// for i in 0..10 {
-///     stream.write(&[i+1]).unwrap();
-/// }
-/// ```
-///
-/// Because we're not buffering, we write each one in turn, incurring the
-/// overhead of a system call per byte written. We can fix this with a
-/// `BufWriter<W>`:
-///
-/// ```no_run
-/// use std::io::prelude::*;
-/// use std::io::BufWriter;
-/// use std::net::TcpStream;
-///
-/// let mut stream = BufWriter::new(TcpStream::connect("127.0.0.1:34254").unwrap());
-///
-/// for i in 0..10 {
-///     stream.write(&[i+1]).unwrap();
-/// }
-/// stream.flush().unwrap();
-/// ```
-///
-/// By wrapping the stream with a `BufWriter<W>`, these ten writes are all grouped
-/// together by the buffer and will all be written out in one system call when
-/// the `stream` is flushed.
-///
-/// [`TcpStream::write`]: Write::write
-/// [`TcpStream`]: crate::net::TcpStream
-/// [`flush`]: Write::flush
-#[stable(feature = "rust1", since = "1.0.0")]
-pub struct BufWriter<W: Write> {
-    inner: Option<W>,
-    buf: Vec<u8>,
-    // #30888: If the inner writer panics in a call to write, we don't want to
-    // write the buffered data a second time in BufWriter's destructor. This
-    // flag tells the Drop impl if it should skip the flush.
-    panicked: bool,
-}
-
-/// An error returned by [`BufWriter::into_inner`] which combines an error that
-/// happened while writing out the buffer, and the buffered writer object
-/// which may be used to recover from the condition.
-///
-/// # Examples
-///
-/// ```no_run
-/// use std::io::BufWriter;
-/// use std::net::TcpStream;
-///
-/// let mut stream = BufWriter::new(TcpStream::connect("127.0.0.1:34254").unwrap());
-///
-/// // do stuff with the stream
-///
-/// // we want to get our `TcpStream` back, so let's try:
-///
-/// let stream = match stream.into_inner() {
-///     Ok(s) => s,
-///     Err(e) => {
-///         // Here, e is an IntoInnerError
-///         panic!("An error occurred");
-///     }
-/// };
-/// ```
-#[derive(Debug)]
-#[stable(feature = "rust1", since = "1.0.0")]
-pub struct IntoInnerError<W>(W, Error);
-
-impl<W: Write> BufWriter<W> {
-    /// Creates a new `BufWriter<W>` with a default buffer capacity. The default is currently 8 KB,
-    /// but may change in the future.
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// use std::io::BufWriter;
-    /// use std::net::TcpStream;
-    ///
-    /// let mut buffer = BufWriter::new(TcpStream::connect("127.0.0.1:34254").unwrap());
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn new(inner: W) -> BufWriter<W> {
-        BufWriter::with_capacity(DEFAULT_BUF_SIZE, inner)
-    }
-
-    /// Creates a new `BufWriter<W>` with the specified buffer capacity.
-    ///
-    /// # Examples
-    ///
-    /// Creating a buffer with a buffer of a hundred bytes.
-    ///
-    /// ```no_run
-    /// use std::io::BufWriter;
-    /// use std::net::TcpStream;
-    ///
-    /// let stream = TcpStream::connect("127.0.0.1:34254").unwrap();
-    /// let mut buffer = BufWriter::with_capacity(100, stream);
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn with_capacity(capacity: usize, inner: W) -> BufWriter<W> {
-        BufWriter { inner: Some(inner), buf: Vec::with_capacity(capacity), panicked: false }
-    }
-
-    /// Send data in our local buffer into the inner writer, looping as
-    /// necessary until either it's all been sent or an error occurs.
-    ///
-    /// Because all the data in the buffer has been reported to our owner as
-    /// "successfully written" (by returning nonzero success values from
-    /// `write`), any 0-length writes from `inner` must be reported as i/o
-    /// errors from this method.
-    fn flush_buf(&mut self) -> io::Result<()> {
-        /// Helper struct to ensure the buffer is updated after all the writes
-        /// are complete. It tracks the number of written bytes and drains them
-        /// all from the front of the buffer when dropped.
-        struct BufGuard<'a> {
-            buffer: &'a mut Vec<u8>,
-            written: usize,
-        }
-
-        impl<'a> BufGuard<'a> {
-            fn new(buffer: &'a mut Vec<u8>) -> Self {
-                Self { buffer, written: 0 }
-            }
-
-            /// The unwritten part of the buffer
-            fn remaining(&self) -> &[u8] {
-                &self.buffer[self.written..]
-            }
-
-            /// Flag some bytes as removed from the front of the buffer
-            fn consume(&mut self, amt: usize) {
-                self.written += amt;
-            }
-
-            /// true if all of the bytes have been written
-            fn done(&self) -> bool {
-                self.written >= self.buffer.len()
-            }
-        }
-
-        impl Drop for BufGuard<'_> {
-            fn drop(&mut self) {
-                if self.written > 0 {
-                    self.buffer.drain(..self.written);
-                }
-            }
-        }
-
-        let mut guard = BufGuard::new(&mut self.buf);
-        let inner = self.inner.as_mut().unwrap();
-        while !guard.done() {
-            self.panicked = true;
-            let r = inner.write(guard.remaining());
-            self.panicked = false;
-
-            match r {
-                Ok(0) => {
-                    return Err(Error::new(
-                        ErrorKind::WriteZero,
-                        "failed to write the buffered data",
-                    ));
-                }
-                Ok(n) => guard.consume(n),
-                Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {}
-                Err(e) => return Err(e),
-            }
-        }
-        Ok(())
-    }
-
-    /// Buffer some data without flushing it, regardless of the size of the
-    /// data. Writes as much as possible without exceeding capacity. Returns
-    /// the number of bytes written.
-    fn write_to_buf(&mut self, buf: &[u8]) -> usize {
-        let available = self.buf.capacity() - self.buf.len();
-        let amt_to_buffer = available.min(buf.len());
-        self.buf.extend_from_slice(&buf[..amt_to_buffer]);
-        amt_to_buffer
-    }
-
-    /// Gets a reference to the underlying writer.
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// use std::io::BufWriter;
-    /// use std::net::TcpStream;
-    ///
-    /// let mut buffer = BufWriter::new(TcpStream::connect("127.0.0.1:34254").unwrap());
-    ///
-    /// // we can use reference just like buffer
-    /// let reference = buffer.get_ref();
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn get_ref(&self) -> &W {
-        self.inner.as_ref().unwrap()
-    }
-
-    /// Gets a mutable reference to the underlying writer.
-    ///
-    /// It is inadvisable to directly write to the underlying writer.
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// use std::io::BufWriter;
-    /// use std::net::TcpStream;
-    ///
-    /// let mut buffer = BufWriter::new(TcpStream::connect("127.0.0.1:34254").unwrap());
-    ///
-    /// // we can use reference just like buffer
-    /// let reference = buffer.get_mut();
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn get_mut(&mut self) -> &mut W {
-        self.inner.as_mut().unwrap()
-    }
-
-    /// Returns a reference to the internally buffered data.
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// use std::io::BufWriter;
-    /// use std::net::TcpStream;
-    ///
-    /// let buf_writer = BufWriter::new(TcpStream::connect("127.0.0.1:34254").unwrap());
-    ///
-    /// // See how many bytes are currently buffered
-    /// let bytes_buffered = buf_writer.buffer().len();
-    /// ```
-    #[stable(feature = "bufreader_buffer", since = "1.37.0")]
-    pub fn buffer(&self) -> &[u8] {
-        &self.buf
-    }
-
-    /// Returns the number of bytes the internal buffer can hold without flushing.
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// use std::io::BufWriter;
-    /// use std::net::TcpStream;
-    ///
-    /// let buf_writer = BufWriter::new(TcpStream::connect("127.0.0.1:34254").unwrap());
-    ///
-    /// // Check the capacity of the inner buffer
-    /// let capacity = buf_writer.capacity();
-    /// // Calculate how many bytes can be written without flushing
-    /// let without_flush = capacity - buf_writer.buffer().len();
-    /// ```
-    #[stable(feature = "buffered_io_capacity", since = "1.46.0")]
-    pub fn capacity(&self) -> usize {
-        self.buf.capacity()
-    }
-
-    /// Unwraps this `BufWriter<W>`, returning the underlying writer.
-    ///
-    /// The buffer is written out before returning the writer.
-    ///
-    /// # Errors
-    ///
-    /// An [`Err`] will be returned if an error occurs while flushing the buffer.
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// use std::io::BufWriter;
-    /// use std::net::TcpStream;
-    ///
-    /// let mut buffer = BufWriter::new(TcpStream::connect("127.0.0.1:34254").unwrap());
-    ///
-    /// // unwrap the TcpStream and flush the buffer
-    /// let stream = buffer.into_inner().unwrap();
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn into_inner(mut self) -> Result<W, IntoInnerError<BufWriter<W>>> {
-        match self.flush_buf() {
-            Err(e) => Err(IntoInnerError(self, e)),
-            Ok(()) => Ok(self.inner.take().unwrap()),
-        }
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<W: Write> Write for BufWriter<W> {
-    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
-        if self.buf.len() + buf.len() > self.buf.capacity() {
-            self.flush_buf()?;
-        }
-        // FIXME: Why no len > capacity? Why not buffer len == capacity? #72919
-        if buf.len() >= self.buf.capacity() {
-            self.panicked = true;
-            let r = self.get_mut().write(buf);
-            self.panicked = false;
-            r
-        } else {
-            self.buf.extend_from_slice(buf);
-            Ok(buf.len())
-        }
-    }
-
-    fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
-        // Normally, `write_all` just calls `write` in a loop. We can do better
-        // by calling `self.get_mut().write_all()` directly, which avoids
-        // round trips through the buffer in the event of a series of partial
-        // writes in some circumstances.
-        if self.buf.len() + buf.len() > self.buf.capacity() {
-            self.flush_buf()?;
-        }
-        // FIXME: Why no len > capacity? Why not buffer len == capacity? #72919
-        if buf.len() >= self.buf.capacity() {
-            self.panicked = true;
-            let r = self.get_mut().write_all(buf);
-            self.panicked = false;
-            r
-        } else {
-            self.buf.extend_from_slice(buf);
-            Ok(())
-        }
-    }
-
-    fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
-        let total_len = bufs.iter().map(|b| b.len()).sum::<usize>();
-        if self.buf.len() + total_len > self.buf.capacity() {
-            self.flush_buf()?;
-        }
-        // FIXME: Why no len > capacity? Why not buffer len == capacity? #72919
-        if total_len >= self.buf.capacity() {
-            self.panicked = true;
-            let r = self.get_mut().write_vectored(bufs);
-            self.panicked = false;
-            r
-        } else {
-            bufs.iter().for_each(|b| self.buf.extend_from_slice(b));
-            Ok(total_len)
-        }
-    }
-
-    fn is_write_vectored(&self) -> bool {
-        self.get_ref().is_write_vectored()
-    }
-
-    fn flush(&mut self) -> io::Result<()> {
-        self.flush_buf().and_then(|()| self.get_mut().flush())
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<W: Write> fmt::Debug for BufWriter<W>
-where
-    W: fmt::Debug,
-{
-    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
-        fmt.debug_struct("BufWriter")
-            .field("writer", &self.inner.as_ref().unwrap())
-            .field("buffer", &format_args!("{}/{}", self.buf.len(), self.buf.capacity()))
-            .finish()
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<W: Write + Seek> Seek for BufWriter<W> {
-    /// Seek to the offset, in bytes, in the underlying writer.
-    ///
-    /// Seeking always writes out the internal buffer before seeking.
-    fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
-        self.flush_buf()?;
-        self.get_mut().seek(pos)
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<W: Write> Drop for BufWriter<W> {
-    fn drop(&mut self) {
-        if self.inner.is_some() && !self.panicked {
-            // dtors should not panic, so we ignore a failed flush
-            let _r = self.flush_buf();
-        }
-    }
-}
-
-impl<W> IntoInnerError<W> {
-    /// Returns the error which caused the call to [`BufWriter::into_inner()`]
-    /// to fail.
-    ///
-    /// This error was returned when attempting to write the internal buffer.
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// use std::io::BufWriter;
-    /// use std::net::TcpStream;
-    ///
-    /// let mut stream = BufWriter::new(TcpStream::connect("127.0.0.1:34254").unwrap());
-    ///
-    /// // do stuff with the stream
-    ///
-    /// // we want to get our `TcpStream` back, so let's try:
-    ///
-    /// let stream = match stream.into_inner() {
-    ///     Ok(s) => s,
-    ///     Err(e) => {
-    ///         // Here, e is an IntoInnerError, let's log the inner error.
-    ///         //
-    ///         // We'll just 'log' to stdout for this example.
-    ///         println!("{}", e.error());
-    ///
-    ///         panic!("An unexpected error occurred.");
-    ///     }
-    /// };
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn error(&self) -> &Error {
-        &self.1
-    }
-
-    /// Returns the buffered writer instance which generated the error.
-    ///
-    /// The returned object can be used for error recovery, such as
-    /// re-inspecting the buffer.
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// use std::io::BufWriter;
-    /// use std::net::TcpStream;
-    ///
-    /// let mut stream = BufWriter::new(TcpStream::connect("127.0.0.1:34254").unwrap());
-    ///
-    /// // do stuff with the stream
-    ///
-    /// // we want to get our `TcpStream` back, so let's try:
-    ///
-    /// let stream = match stream.into_inner() {
-    ///     Ok(s) => s,
-    ///     Err(e) => {
-    ///         // Here, e is an IntoInnerError, let's re-examine the buffer:
-    ///         let buffer = e.into_inner();
-    ///
-    ///         // do stuff to try to recover
-    ///
-    ///         // afterwards, let's just return the stream
-    ///         buffer.into_inner().unwrap()
-    ///     }
-    /// };
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn into_inner(self) -> W {
-        self.0
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<W> From<IntoInnerError<W>> for Error {
-    fn from(iie: IntoInnerError<W>) -> Error {
-        iie.1
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<W: Send + fmt::Debug> error::Error for IntoInnerError<W> {
-    #[allow(deprecated, deprecated_in_future)]
-    fn description(&self) -> &str {
-        error::Error::description(self.error())
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<W> fmt::Display for IntoInnerError<W> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        self.error().fmt(f)
-    }
-}
-
-/// Private helper struct for implementing the line-buffered writing logic.
-/// This shim temporarily wraps a BufWriter, and uses its internals to
-/// implement a line-buffered writer (specifically by using the internal
-/// methods like write_to_buf and flush_buf). In this way, a more
-/// efficient abstraction can be created than one that only had access to
-/// `write` and `flush`, without needlessly duplicating a lot of the
-/// implementation details of BufWriter. This also allows existing
-/// `BufWriters` to be temporarily given line-buffering logic; this is what
-/// enables Stdout to be alternately in line-buffered or block-buffered mode.
-#[derive(Debug)]
-pub(super) struct LineWriterShim<'a, W: Write> {
-    buffer: &'a mut BufWriter<W>,
-}
-
-impl<'a, W: Write> LineWriterShim<'a, W> {
-    pub fn new(buffer: &'a mut BufWriter<W>) -> Self {
-        Self { buffer }
-    }
-
-    /// Get a mutable reference to the inner writer (that is, the writer
-    /// wrapped by the BufWriter). Be careful with this writer, as writes to
-    /// it will bypass the buffer.
-    fn inner_mut(&mut self) -> &mut W {
-        self.buffer.get_mut()
-    }
-
-    /// Get the content currently buffered in self.buffer
-    fn buffered(&self) -> &[u8] {
-        self.buffer.buffer()
-    }
-
-    /// Flush the buffer iff the last byte is a newline (indicating that an
-    /// earlier write only succeeded partially, and we want to retry flushing
-    /// the buffered line before continuing with a subsequent write)
-    fn flush_if_completed_line(&mut self) -> io::Result<()> {
-        match self.buffered().last().copied() {
-            Some(b'\n') => self.buffer.flush_buf(),
-            _ => Ok(()),
-        }
-    }
-}
-
-impl<'a, W: Write> Write for LineWriterShim<'a, W> {
-    /// Write some data into this BufReader with line buffering. This means
-    /// that, if any newlines are present in the data, the data up to the last
-    /// newline is sent directly to the underlying writer, and data after it
-    /// is buffered. Returns the number of bytes written.
-    ///
-    /// This function operates on a "best effort basis"; in keeping with the
-    /// convention of `Write::write`, it makes at most one attempt to write
-    /// new data to the underlying writer. If that write only reports a partial
-    /// success, the remaining data will be buffered.
-    ///
-    /// Because this function attempts to send completed lines to the underlying
-    /// writer, it will also flush the existing buffer if it ends with a
-    /// newline, even if the incoming data does not contain any newlines.
-    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
-        let newline_idx = match memchr::memrchr(b'\n', buf) {
-            // If there are no new newlines (that is, if this write is less than
-            // one line), just do a regular buffered write (which may flush if
-            // we exceed the inner buffer's size)
-            None => {
-                self.flush_if_completed_line()?;
-                return self.buffer.write(buf);
-            }
-            // Otherwise, arrange for the lines to be written directly to the
-            // inner writer.
-            Some(newline_idx) => newline_idx + 1,
-        };
-
-        // Flush existing content to prepare for our write. We have to do this
-        // before attempting to write `buf` in order to maintain consistency;
-        // if we add `buf` to the buffer then try to flush it all at once,
-        // we're obligated to return Ok(), which would mean suppressing any
-        // errors that occur during flush.
-        self.buffer.flush_buf()?;
-
-        // This is what we're going to try to write directly to the inner
-        // writer. The rest will be buffered, if nothing goes wrong.
-        let lines = &buf[..newline_idx];
-
-        // Write `lines` directly to the inner writer. In keeping with the
-        // `write` convention, make at most one attempt to add new (unbuffered)
-        // data. Because this write doesn't touch the BufWriter state directly,
-        // and the buffer is known to be empty, we don't need to worry about
-        // self.buffer.panicked here.
-        let flushed = self.inner_mut().write(lines)?;
-
-        // If buffer returns Ok(0), propagate that to the caller without
-        // doing additional buffering; otherwise we're just guaranteeing
-        // an "ErrorKind::WriteZero" later.
-        if flushed == 0 {
-            return Ok(0);
-        }
-
-        // Now that the write has succeeded, buffer the rest (or as much of
-        // the rest as possible). If there were any unwritten newlines, we
-        // only buffer out to the last unwritten newline that fits in the
-        // buffer; this helps prevent flushing partial lines on subsequent
-        // calls to LineWriterShim::write.
-
-        // Handle the cases in order of most-common to least-common, under
-        // the presumption that most writes succeed in totality, and that most
-        // writes are smaller than the buffer.
-        // - Is this a partial line (ie, no newlines left in the unwritten tail)
-        // - If not, does the data out to the last unwritten newline fit in
-        //   the buffer?
-        // - If not, scan for the last newline that *does* fit in the buffer
-        let tail = if flushed >= newline_idx {
-            &buf[flushed..]
-        } else if newline_idx - flushed <= self.buffer.capacity() {
-            &buf[flushed..newline_idx]
-        } else {
-            let scan_area = &buf[flushed..];
-            let scan_area = &scan_area[..self.buffer.capacity()];
-            match memchr::memrchr(b'\n', scan_area) {
-                Some(newline_idx) => &scan_area[..newline_idx + 1],
-                None => scan_area,
-            }
-        };
-
-        let buffered = self.buffer.write_to_buf(tail);
-        Ok(flushed + buffered)
-    }
-
-    fn flush(&mut self) -> io::Result<()> {
-        self.buffer.flush()
-    }
-
-    /// Write some vectored data into this BufReader with line buffering. This
-    /// means that, if any newlines are present in the data, the data up to
-    /// and including the buffer containing the last newline is sent directly
-    /// to the inner writer, and the data after it is buffered. Returns the
-    /// number of bytes written.
-    ///
-    /// This function operates on a "best effort basis"; in keeping with the
-    /// convention of `Write::write`, it makes at most one attempt to write
-    /// new data to the underlying writer.
-    ///
-    /// Because this function attempts to send completed lines to the underlying
-    /// writer, it will also flush the existing buffer if it contains any
-    /// newlines.
-    ///
-    /// Because sorting through an array of `IoSlice` can be a bit convoluted,
-    /// This method differs from write in the following ways:
-    ///
-    /// - It attempts to write the full content of all the buffers up to and
-    ///   including the one containing the last newline. This means that it
-    ///   may attempt to write a partial line, that buffer has data past the
-    ///   newline.
-    /// - If the write only reports partial success, it does not attempt to
-    ///   find the precise location of the written bytes and buffer the rest.
-    ///
-    /// If the underlying vector doesn't support vectored writing, we instead
-    /// simply write the first non-empty buffer with `write`. This way, we
-    /// get the benefits of more granular partial-line handling without losing
-    /// anything in efficiency
-    fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
-        // If there's no specialized behavior for write_vectored, just use
-        // write. This has the benefit of more granular partial-line handling.
-        if !self.is_write_vectored() {
-            return match bufs.iter().find(|buf| !buf.is_empty()) {
-                Some(buf) => self.write(buf),
-                None => Ok(0),
-            };
-        }
-
-        // Find the buffer containing the last newline
-        let last_newline_buf_idx = bufs
-            .iter()
-            .enumerate()
-            .rev()
-            .find_map(|(i, buf)| memchr::memchr(b'\n', buf).map(|_| i));
-
-        // If there are no new newlines (that is, if this write is less than
-        // one line), just do a regular buffered write
-        let last_newline_buf_idx = match last_newline_buf_idx {
-            // No newlines; just do a normal buffered write
-            None => {
-                self.flush_if_completed_line()?;
-                return self.buffer.write_vectored(bufs);
-            }
-            Some(i) => i,
-        };
-
-        // Flush existing content to prepare for our write
-        self.buffer.flush_buf()?;
-
-        // This is what we're going to try to write directly to the inner
-        // writer. The rest will be buffered, if nothing goes wrong.
-        let (lines, tail) = bufs.split_at(last_newline_buf_idx + 1);
-
-        // Write `lines` directly to the inner writer. In keeping with the
-        // `write` convention, make at most one attempt to add new (unbuffered)
-        // data. Because this write doesn't touch the BufWriter state directly,
-        // and the buffer is known to be empty, we don't need to worry about
-        // self.panicked here.
-        let flushed = self.inner_mut().write_vectored(lines)?;
-
-        // If inner returns Ok(0), propagate that to the caller without
-        // doing additional buffering; otherwise we're just guaranteeing
-        // an "ErrorKind::WriteZero" later.
-        if flushed == 0 {
-            return Ok(0);
-        }
-
-        // Don't try to reconstruct the exact amount written; just bail
-        // in the event of a partial write
-        let lines_len = lines.iter().map(|buf| buf.len()).sum();
-        if flushed < lines_len {
-            return Ok(flushed);
-        }
-
-        // Now that the write has succeeded, buffer the rest (or as much of the
-        // rest as possible)
-        let buffered: usize = tail
-            .iter()
-            .filter(|buf| !buf.is_empty())
-            .map(|buf| self.buffer.write_to_buf(buf))
-            .take_while(|&n| n > 0)
-            .sum();
-
-        Ok(flushed + buffered)
-    }
-
-    fn is_write_vectored(&self) -> bool {
-        self.buffer.is_write_vectored()
-    }
-
-    /// Write some data into this BufReader with line buffering. This means
-    /// that, if any newlines are present in the data, the data up to the last
-    /// newline is sent directly to the underlying writer, and data after it
-    /// is buffered.
-    ///
-    /// Because this function attempts to send completed lines to the underlying
-    /// writer, it will also flush the existing buffer if it contains any
-    /// newlines, even if the incoming data does not contain any newlines.
-    fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
-        match memchr::memrchr(b'\n', buf) {
-            // If there are no new newlines (that is, if this write is less than
-            // one line), just do a regular buffered write (which may flush if
-            // we exceed the inner buffer's size)
-            None => {
-                self.flush_if_completed_line()?;
-                self.buffer.write_all(buf)
-            }
-            Some(newline_idx) => {
-                let (lines, tail) = buf.split_at(newline_idx + 1);
-
-                if self.buffered().is_empty() {
-                    self.inner_mut().write_all(lines)?;
-                } else {
-                    // If there is any buffered data, we add the incoming lines
-                    // to that buffer before flushing, which saves us at least
-                    // one write call. We can't really do this with `write`,
-                    // since we can't do this *and* not suppress errors *and*
-                    // report a consistent state to the caller in a return
-                    // value, but here in write_all it's fine.
-                    self.buffer.write_all(lines)?;
-                    self.buffer.flush_buf()?;
-                }
-
-                self.buffer.write_all(tail)
-            }
-        }
-    }
-}
-
-/// Wraps a writer and buffers output to it, flushing whenever a newline
-/// (`0x0a`, `'\n'`) is detected.
-///
-/// The [`BufWriter`] struct wraps a writer and buffers its output.
-/// But it only does this batched write when it goes out of scope, or when the
-/// internal buffer is full. Sometimes, you'd prefer to write each line as it's
-/// completed, rather than the entire buffer at once. Enter `LineWriter`. It
-/// does exactly that.
-///
-/// Like [`BufWriter`], a `LineWriter`’s buffer will also be flushed when the
-/// `LineWriter` goes out of scope or when its internal buffer is full.
-///
-/// If there's still a partial line in the buffer when the `LineWriter` is
-/// dropped, it will flush those contents.
-///
-/// # Examples
-///
-/// We can use `LineWriter` to write one line at a time, significantly
-/// reducing the number of actual writes to the file.
-///
-/// ```no_run
-/// use std::fs::{self, File};
-/// use std::io::prelude::*;
-/// use std::io::LineWriter;
-///
-/// fn main() -> std::io::Result<()> {
-///     let road_not_taken = b"I shall be telling this with a sigh
-/// Somewhere ages and ages hence:
-/// Two roads diverged in a wood, and I -
-/// I took the one less traveled by,
-/// And that has made all the difference.";
-///
-///     let file = File::create("poem.txt")?;
-///     let mut file = LineWriter::new(file);
-///
-///     file.write_all(b"I shall be telling this with a sigh")?;
-///
-///     // No bytes are written until a newline is encountered (or
-///     // the internal buffer is filled).
-///     assert_eq!(fs::read_to_string("poem.txt")?, "");
-///     file.write_all(b"\n")?;
-///     assert_eq!(
-///         fs::read_to_string("poem.txt")?,
-///         "I shall be telling this with a sigh\n",
-///     );
-///
-///     // Write the rest of the poem.
-///     file.write_all(b"Somewhere ages and ages hence:
-/// Two roads diverged in a wood, and I -
-/// I took the one less traveled by,
-/// And that has made all the difference.")?;
-///
-///     // The last line of the poem doesn't end in a newline, so
-///     // we have to flush or drop the `LineWriter` to finish
-///     // writing.
-///     file.flush()?;
-///
-///     // Confirm the whole poem was written.
-///     assert_eq!(fs::read("poem.txt")?, &road_not_taken[..]);
-///     Ok(())
-/// }
-/// ```
-#[stable(feature = "rust1", since = "1.0.0")]
-pub struct LineWriter<W: Write> {
-    inner: BufWriter<W>,
-}
-
-impl<W: Write> LineWriter<W> {
-    /// Creates a new `LineWriter`.
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// use std::fs::File;
-    /// use std::io::LineWriter;
-    ///
-    /// fn main() -> std::io::Result<()> {
-    ///     let file = File::create("poem.txt")?;
-    ///     let file = LineWriter::new(file);
-    ///     Ok(())
-    /// }
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn new(inner: W) -> LineWriter<W> {
-        // Lines typically aren't that long, don't use a giant buffer
-        LineWriter::with_capacity(1024, inner)
-    }
-
-    /// Creates a new `LineWriter` with a specified capacity for the internal
-    /// buffer.
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// use std::fs::File;
-    /// use std::io::LineWriter;
-    ///
-    /// fn main() -> std::io::Result<()> {
-    ///     let file = File::create("poem.txt")?;
-    ///     let file = LineWriter::with_capacity(100, file);
-    ///     Ok(())
-    /// }
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn with_capacity(capacity: usize, inner: W) -> LineWriter<W> {
-        LineWriter { inner: BufWriter::with_capacity(capacity, inner) }
-    }
-
-    /// Gets a reference to the underlying writer.
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// use std::fs::File;
-    /// use std::io::LineWriter;
-    ///
-    /// fn main() -> std::io::Result<()> {
-    ///     let file = File::create("poem.txt")?;
-    ///     let file = LineWriter::new(file);
-    ///
-    ///     let reference = file.get_ref();
-    ///     Ok(())
-    /// }
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn get_ref(&self) -> &W {
-        self.inner.get_ref()
-    }
-
-    /// Gets a mutable reference to the underlying writer.
-    ///
-    /// Caution must be taken when calling methods on the mutable reference
-    /// returned as extra writes could corrupt the output stream.
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// use std::fs::File;
-    /// use std::io::LineWriter;
-    ///
-    /// fn main() -> std::io::Result<()> {
-    ///     let file = File::create("poem.txt")?;
-    ///     let mut file = LineWriter::new(file);
-    ///
-    ///     // we can use reference just like file
-    ///     let reference = file.get_mut();
-    ///     Ok(())
-    /// }
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn get_mut(&mut self) -> &mut W {
-        self.inner.get_mut()
-    }
-
-    /// Unwraps this `LineWriter`, returning the underlying writer.
-    ///
-    /// The internal buffer is written out before returning the writer.
-    ///
-    /// # Errors
-    ///
-    /// An [`Err`] will be returned if an error occurs while flushing the buffer.
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// use std::fs::File;
-    /// use std::io::LineWriter;
-    ///
-    /// fn main() -> std::io::Result<()> {
-    ///     let file = File::create("poem.txt")?;
-    ///
-    ///     let writer: LineWriter<File> = LineWriter::new(file);
-    ///
-    ///     let file: File = writer.into_inner()?;
-    ///     Ok(())
-    /// }
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn into_inner(self) -> Result<W, IntoInnerError<LineWriter<W>>> {
-        self.inner
-            .into_inner()
-            .map_err(|IntoInnerError(buf, e)| IntoInnerError(LineWriter { inner: buf }, e))
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<W: Write> Write for LineWriter<W> {
-    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
-        LineWriterShim::new(&mut self.inner).write(buf)
-    }
-
-    fn flush(&mut self) -> io::Result<()> {
-        self.inner.flush()
-    }
-
-    fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
-        LineWriterShim::new(&mut self.inner).write_vectored(bufs)
-    }
-
-    fn is_write_vectored(&self) -> bool {
-        self.inner.is_write_vectored()
-    }
-
-    fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
-        LineWriterShim::new(&mut self.inner).write_all(buf)
-    }
-
-    fn write_all_vectored(&mut self, bufs: &mut [IoSlice<'_>]) -> io::Result<()> {
-        LineWriterShim::new(&mut self.inner).write_all_vectored(bufs)
-    }
-
-    fn write_fmt(&mut self, fmt: fmt::Arguments<'_>) -> io::Result<()> {
-        LineWriterShim::new(&mut self.inner).write_fmt(fmt)
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<W: Write> fmt::Debug for LineWriter<W>
-where
-    W: fmt::Debug,
-{
-    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
-        fmt.debug_struct("LineWriter")
-            .field("writer", &self.inner.inner)
-            .field(
-                "buffer",
-                &format_args!("{}/{}", self.inner.buf.len(), self.inner.buf.capacity()),
-            )
-            .finish()
-    }
-}
diff --git a/library/std/src/io/buffered/bufreader.rs b/library/std/src/io/buffered/bufreader.rs
new file mode 100644
index 00000000000..8fe29f08a7b
--- /dev/null
+++ b/library/std/src/io/buffered/bufreader.rs
@@ -0,0 +1,423 @@
+use crate::cmp;
+use crate::fmt;
+use crate::io::{self, BufRead, Initializer, IoSliceMut, Read, Seek, SeekFrom, DEFAULT_BUF_SIZE};
+
+/// The `BufReader<R>` struct adds buffering to any reader.
+///
+/// It can be excessively inefficient to work directly with a [`Read`] instance.
+/// For example, every call to [`read`][`TcpStream::read`] on [`TcpStream`]
+/// results in a system call. A `BufReader<R>` performs large, infrequent reads on
+/// the underlying [`Read`] and maintains an in-memory buffer of the results.
+///
+/// `BufReader<R>` can improve the speed of programs that make *small* and
+/// *repeated* read calls to the same file or network socket. It does not
+/// help when reading very large amounts at once, or reading just one or a few
+/// times. It also provides no advantage when reading from a source that is
+/// already in memory, like a [`Vec`]`<u8>`.
+///
+/// When the `BufReader<R>` is dropped, the contents of its buffer will be
+/// discarded. Creating multiple instances of a `BufReader<R>` on the same
+/// stream can cause data loss. Reading from the underlying reader after
+/// unwrapping the `BufReader<R>` with [`BufReader::into_inner`] can also cause
+/// data loss.
+///
+/// [`TcpStream::read`]: Read::read
+/// [`TcpStream`]: crate::net::TcpStream
+///
+/// # Examples
+///
+/// ```no_run
+/// use std::io::prelude::*;
+/// use std::io::BufReader;
+/// use std::fs::File;
+///
+/// fn main() -> std::io::Result<()> {
+///     let f = File::open("log.txt")?;
+///     let mut reader = BufReader::new(f);
+///
+///     let mut line = String::new();
+///     let len = reader.read_line(&mut line)?;
+///     println!("First line is {} bytes long", len);
+///     Ok(())
+/// }
+/// ```
+#[stable(feature = "rust1", since = "1.0.0")]
+pub struct BufReader<R> {
+    inner: R,
+    buf: Box<[u8]>,
+    pos: usize,
+    cap: usize,
+}
+
+impl<R: Read> BufReader<R> {
+    /// Creates a new `BufReader<R>` with a default buffer capacity. The default is currently 8 KB,
+    /// but may change in the future.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::io::BufReader;
+    /// use std::fs::File;
+    ///
+    /// fn main() -> std::io::Result<()> {
+    ///     let f = File::open("log.txt")?;
+    ///     let reader = BufReader::new(f);
+    ///     Ok(())
+    /// }
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn new(inner: R) -> BufReader<R> {
+        BufReader::with_capacity(DEFAULT_BUF_SIZE, inner)
+    }
+
+    /// Creates a new `BufReader<R>` with the specified buffer capacity.
+    ///
+    /// # Examples
+    ///
+    /// Creating a buffer with ten bytes of capacity:
+    ///
+    /// ```no_run
+    /// use std::io::BufReader;
+    /// use std::fs::File;
+    ///
+    /// fn main() -> std::io::Result<()> {
+    ///     let f = File::open("log.txt")?;
+    ///     let reader = BufReader::with_capacity(10, f);
+    ///     Ok(())
+    /// }
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn with_capacity(capacity: usize, inner: R) -> BufReader<R> {
+        unsafe {
+            let mut buffer = Vec::with_capacity(capacity);
+            buffer.set_len(capacity);
+            inner.initializer().initialize(&mut buffer);
+            BufReader { inner, buf: buffer.into_boxed_slice(), pos: 0, cap: 0 }
+        }
+    }
+}
+
+impl<R> BufReader<R> {
+    /// Gets a reference to the underlying reader.
+    ///
+    /// It is inadvisable to directly read from the underlying reader.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::io::BufReader;
+    /// use std::fs::File;
+    ///
+    /// fn main() -> std::io::Result<()> {
+    ///     let f1 = File::open("log.txt")?;
+    ///     let reader = BufReader::new(f1);
+    ///
+    ///     let f2 = reader.get_ref();
+    ///     Ok(())
+    /// }
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn get_ref(&self) -> &R {
+        &self.inner
+    }
+
+    /// Gets a mutable reference to the underlying reader.
+    ///
+    /// It is inadvisable to directly read from the underlying reader.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::io::BufReader;
+    /// use std::fs::File;
+    ///
+    /// fn main() -> std::io::Result<()> {
+    ///     let f1 = File::open("log.txt")?;
+    ///     let mut reader = BufReader::new(f1);
+    ///
+    ///     let f2 = reader.get_mut();
+    ///     Ok(())
+    /// }
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn get_mut(&mut self) -> &mut R {
+        &mut self.inner
+    }
+
+    /// Returns a reference to the internally buffered data.
+    ///
+    /// Unlike [`fill_buf`], this will not attempt to fill the buffer if it is empty.
+    ///
+    /// [`fill_buf`]: BufRead::fill_buf
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::io::{BufReader, BufRead};
+    /// use std::fs::File;
+    ///
+    /// fn main() -> std::io::Result<()> {
+    ///     let f = File::open("log.txt")?;
+    ///     let mut reader = BufReader::new(f);
+    ///     assert!(reader.buffer().is_empty());
+    ///
+    ///     if reader.fill_buf()?.len() > 0 {
+    ///         assert!(!reader.buffer().is_empty());
+    ///     }
+    ///     Ok(())
+    /// }
+    /// ```
+    #[stable(feature = "bufreader_buffer", since = "1.37.0")]
+    pub fn buffer(&self) -> &[u8] {
+        &self.buf[self.pos..self.cap]
+    }
+
+    /// Returns the number of bytes the internal buffer can hold at once.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::io::{BufReader, BufRead};
+    /// use std::fs::File;
+    ///
+    /// fn main() -> std::io::Result<()> {
+    ///     let f = File::open("log.txt")?;
+    ///     let mut reader = BufReader::new(f);
+    ///
+    ///     let capacity = reader.capacity();
+    ///     let buffer = reader.fill_buf()?;
+    ///     assert!(buffer.len() <= capacity);
+    ///     Ok(())
+    /// }
+    /// ```
+    #[stable(feature = "buffered_io_capacity", since = "1.46.0")]
+    pub fn capacity(&self) -> usize {
+        self.buf.len()
+    }
+
+    /// Unwraps this `BufReader<R>`, returning the underlying reader.
+    ///
+    /// Note that any leftover data in the internal buffer is lost. Therefore,
+    /// a following read from the underlying reader may lead to data loss.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::io::BufReader;
+    /// use std::fs::File;
+    ///
+    /// fn main() -> std::io::Result<()> {
+    ///     let f1 = File::open("log.txt")?;
+    ///     let reader = BufReader::new(f1);
+    ///
+    ///     let f2 = reader.into_inner();
+    ///     Ok(())
+    /// }
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn into_inner(self) -> R {
+        self.inner
+    }
+
+    /// Invalidates all data in the internal buffer.
+    #[inline]
+    fn discard_buffer(&mut self) {
+        self.pos = 0;
+        self.cap = 0;
+    }
+}
+
+impl<R: Seek> BufReader<R> {
+    /// Seeks relative to the current position. If the new position lies within the buffer,
+    /// the buffer will not be flushed, allowing for more efficient seeks.
+    /// This method does not return the location of the underlying reader, so the caller
+    /// must track this information themselves if it is required.
+    #[unstable(feature = "bufreader_seek_relative", issue = "31100")]
+    pub fn seek_relative(&mut self, offset: i64) -> io::Result<()> {
+        let pos = self.pos as u64;
+        if offset < 0 {
+            if let Some(new_pos) = pos.checked_sub((-offset) as u64) {
+                self.pos = new_pos as usize;
+                return Ok(());
+            }
+        } else {
+            if let Some(new_pos) = pos.checked_add(offset as u64) {
+                if new_pos <= self.cap as u64 {
+                    self.pos = new_pos as usize;
+                    return Ok(());
+                }
+            }
+        }
+        self.seek(SeekFrom::Current(offset)).map(drop)
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<R: Read> Read for BufReader<R> {
+    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
+        // If we don't have any buffered data and we're doing a massive read
+        // (larger than our internal buffer), bypass our internal buffer
+        // entirely.
+        if self.pos == self.cap && buf.len() >= self.buf.len() {
+            self.discard_buffer();
+            return self.inner.read(buf);
+        }
+        let nread = {
+            let mut rem = self.fill_buf()?;
+            rem.read(buf)?
+        };
+        self.consume(nread);
+        Ok(nread)
+    }
+
+    fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
+        let total_len = bufs.iter().map(|b| b.len()).sum::<usize>();
+        if self.pos == self.cap && total_len >= self.buf.len() {
+            self.discard_buffer();
+            return self.inner.read_vectored(bufs);
+        }
+        let nread = {
+            let mut rem = self.fill_buf()?;
+            rem.read_vectored(bufs)?
+        };
+        self.consume(nread);
+        Ok(nread)
+    }
+
+    fn is_read_vectored(&self) -> bool {
+        self.inner.is_read_vectored()
+    }
+
+    // we can't skip unconditionally because of the large buffer case in read.
+    unsafe fn initializer(&self) -> Initializer {
+        self.inner.initializer()
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<R: Read> BufRead for BufReader<R> {
+    fn fill_buf(&mut self) -> io::Result<&[u8]> {
+        // If we've reached the end of our internal buffer then we need to fetch
+        // some more data from the underlying reader.
+        // Branch using `>=` instead of the more correct `==`
+        // to tell the compiler that the pos..cap slice is always valid.
+        if self.pos >= self.cap {
+            debug_assert!(self.pos == self.cap);
+            self.cap = self.inner.read(&mut self.buf)?;
+            self.pos = 0;
+        }
+        Ok(&self.buf[self.pos..self.cap])
+    }
+
+    fn consume(&mut self, amt: usize) {
+        self.pos = cmp::min(self.pos + amt, self.cap);
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<R> fmt::Debug for BufReader<R>
+where
+    R: fmt::Debug,
+{
+    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+        fmt.debug_struct("BufReader")
+            .field("reader", &self.inner)
+            .field("buffer", &format_args!("{}/{}", self.cap - self.pos, self.buf.len()))
+            .finish()
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<R: Seek> Seek for BufReader<R> {
+    /// Seek to an offset, in bytes, in the underlying reader.
+    ///
+    /// The position used for seeking with [`SeekFrom::Current`]`(_)` is the
+    /// position the underlying reader would be at if the `BufReader<R>` had no
+    /// internal buffer.
+    ///
+    /// Seeking always discards the internal buffer, even if the seek position
+    /// would otherwise fall within it. This guarantees that calling
+    /// [`BufReader::into_inner()`] immediately after a seek yields the underlying reader
+    /// at the same position.
+    ///
+    /// To seek without discarding the internal buffer, use [`BufReader::seek_relative`].
+    ///
+    /// See [`std::io::Seek`] for more details.
+    ///
+    /// Note: In the edge case where you're seeking with [`SeekFrom::Current`]`(n)`
+    /// where `n` minus the internal buffer length overflows an `i64`, two
+    /// seeks will be performed instead of one. If the second seek returns
+    /// [`Err`], the underlying reader will be left at the same position it would
+    /// have if you called `seek` with [`SeekFrom::Current`]`(0)`.
+    ///
+    /// [`std::io::Seek`]: Seek
+    fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
+        let result: u64;
+        if let SeekFrom::Current(n) = pos {
+            let remainder = (self.cap - self.pos) as i64;
+            // it should be safe to assume that remainder fits within an i64 as the alternative
+            // means we managed to allocate 8 exbibytes and that's absurd.
+            // But it's not out of the realm of possibility for some weird underlying reader to
+            // support seeking by i64::MIN so we need to handle underflow when subtracting
+            // remainder.
+            if let Some(offset) = n.checked_sub(remainder) {
+                result = self.inner.seek(SeekFrom::Current(offset))?;
+            } else {
+                // seek backwards by our remainder, and then by the offset
+                self.inner.seek(SeekFrom::Current(-remainder))?;
+                self.discard_buffer();
+                result = self.inner.seek(SeekFrom::Current(n))?;
+            }
+        } else {
+            // Seeking with Start/End doesn't care about our buffer length.
+            result = self.inner.seek(pos)?;
+        }
+        self.discard_buffer();
+        Ok(result)
+    }
+
+    /// Returns the current seek position from the start of the stream.
+    ///
+    /// The value returned is equivalent to `self.seek(SeekFrom::Current(0))`
+    /// but does not flush the internal buffer. Due to this optimization the
+    /// function does not guarantee that calling `.into_inner()` immediately
+    /// afterwards will yield the underlying reader at the same position. Use
+    /// [`BufReader::seek`] instead if you require that guarantee.
+    ///
+    /// # Panics
+    ///
+    /// This function will panic if the position of the inner reader is smaller
+    /// than the amount of buffered data. That can happen if the inner reader
+    /// has an incorrect implementation of [`Seek::stream_position`], or if the
+    /// position has gone out of sync due to calling [`Seek::seek`] directly on
+    /// the underlying reader.
+    ///
+    /// # Example
+    ///
+    /// ```no_run
+    /// #![feature(seek_convenience)]
+    /// use std::{
+    ///     io::{self, BufRead, BufReader, Seek},
+    ///     fs::File,
+    /// };
+    ///
+    /// fn main() -> io::Result<()> {
+    ///     let mut f = BufReader::new(File::open("foo.txt")?);
+    ///
+    ///     let before = f.stream_position()?;
+    ///     f.read_line(&mut String::new())?;
+    ///     let after = f.stream_position()?;
+    ///
+    ///     println!("The first line was {} bytes long", after - before);
+    ///     Ok(())
+    /// }
+    /// ```
+    fn stream_position(&mut self) -> io::Result<u64> {
+        let remainder = (self.cap - self.pos) as u64;
+        self.inner.stream_position().map(|pos| {
+            pos.checked_sub(remainder).expect(
+                "overflow when subtracting remaining buffer size from inner stream position",
+            )
+        })
+    }
+}
diff --git a/library/std/src/io/buffered/bufwriter.rs b/library/std/src/io/buffered/bufwriter.rs
new file mode 100644
index 00000000000..8ce795a05ed
--- /dev/null
+++ b/library/std/src/io/buffered/bufwriter.rs
@@ -0,0 +1,387 @@
+use crate::fmt;
+use crate::io::{
+    self, Error, ErrorKind, IntoInnerError, IoSlice, Seek, SeekFrom, Write, DEFAULT_BUF_SIZE,
+};
+
+/// Wraps a writer and buffers its output.
+///
+/// It can be excessively inefficient to work directly with something that
+/// implements [`Write`]. For example, every call to
+/// [`write`][`TcpStream::write`] on [`TcpStream`] results in a system call. A
+/// `BufWriter<W>` keeps an in-memory buffer of data and writes it to an underlying
+/// writer in large, infrequent batches.
+///
+/// `BufWriter<W>` can improve the speed of programs that make *small* and
+/// *repeated* write calls to the same file or network socket. It does not
+/// help when writing very large amounts at once, or writing just one or a few
+/// times. It also provides no advantage when writing to a destination that is
+/// in memory, like a [`Vec`]<u8>`.
+///
+/// It is critical to call [`flush`] before `BufWriter<W>` is dropped. Though
+/// dropping will attempt to flush the contents of the buffer, any errors
+/// that happen in the process of dropping will be ignored. Calling [`flush`]
+/// ensures that the buffer is empty and thus dropping will not even attempt
+/// file operations.
+///
+/// # Examples
+///
+/// Let's write the numbers one through ten to a [`TcpStream`]:
+///
+/// ```no_run
+/// use std::io::prelude::*;
+/// use std::net::TcpStream;
+///
+/// let mut stream = TcpStream::connect("127.0.0.1:34254").unwrap();
+///
+/// for i in 0..10 {
+///     stream.write(&[i+1]).unwrap();
+/// }
+/// ```
+///
+/// Because we're not buffering, we write each one in turn, incurring the
+/// overhead of a system call per byte written. We can fix this with a
+/// `BufWriter<W>`:
+///
+/// ```no_run
+/// use std::io::prelude::*;
+/// use std::io::BufWriter;
+/// use std::net::TcpStream;
+///
+/// let mut stream = BufWriter::new(TcpStream::connect("127.0.0.1:34254").unwrap());
+///
+/// for i in 0..10 {
+///     stream.write(&[i+1]).unwrap();
+/// }
+/// stream.flush().unwrap();
+/// ```
+///
+/// By wrapping the stream with a `BufWriter<W>`, these ten writes are all grouped
+/// together by the buffer and will all be written out in one system call when
+/// the `stream` is flushed.
+///
+/// [`TcpStream::write`]: Write::write
+/// [`TcpStream`]: crate::net::TcpStream
+/// [`flush`]: Write::flush
+#[stable(feature = "rust1", since = "1.0.0")]
+pub struct BufWriter<W: Write> {
+    inner: Option<W>,
+    buf: Vec<u8>,
+    // #30888: If the inner writer panics in a call to write, we don't want to
+    // write the buffered data a second time in BufWriter's destructor. This
+    // flag tells the Drop impl if it should skip the flush.
+    panicked: bool,
+}
+
+impl<W: Write> BufWriter<W> {
+    /// Creates a new `BufWriter<W>` with a default buffer capacity. The default is currently 8 KB,
+    /// but may change in the future.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::io::BufWriter;
+    /// use std::net::TcpStream;
+    ///
+    /// let mut buffer = BufWriter::new(TcpStream::connect("127.0.0.1:34254").unwrap());
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn new(inner: W) -> BufWriter<W> {
+        BufWriter::with_capacity(DEFAULT_BUF_SIZE, inner)
+    }
+
+    /// Creates a new `BufWriter<W>` with the specified buffer capacity.
+    ///
+    /// # Examples
+    ///
+    /// Creating a buffer with a buffer of a hundred bytes.
+    ///
+    /// ```no_run
+    /// use std::io::BufWriter;
+    /// use std::net::TcpStream;
+    ///
+    /// let stream = TcpStream::connect("127.0.0.1:34254").unwrap();
+    /// let mut buffer = BufWriter::with_capacity(100, stream);
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn with_capacity(capacity: usize, inner: W) -> BufWriter<W> {
+        BufWriter { inner: Some(inner), buf: Vec::with_capacity(capacity), panicked: false }
+    }
+
+    /// Send data in our local buffer into the inner writer, looping as
+    /// necessary until either it's all been sent or an error occurs.
+    ///
+    /// Because all the data in the buffer has been reported to our owner as
+    /// "successfully written" (by returning nonzero success values from
+    /// `write`), any 0-length writes from `inner` must be reported as i/o
+    /// errors from this method.
+    pub(super) fn flush_buf(&mut self) -> io::Result<()> {
+        /// Helper struct to ensure the buffer is updated after all the writes
+        /// are complete. It tracks the number of written bytes and drains them
+        /// all from the front of the buffer when dropped.
+        struct BufGuard<'a> {
+            buffer: &'a mut Vec<u8>,
+            written: usize,
+        }
+
+        impl<'a> BufGuard<'a> {
+            fn new(buffer: &'a mut Vec<u8>) -> Self {
+                Self { buffer, written: 0 }
+            }
+
+            /// The unwritten part of the buffer
+            fn remaining(&self) -> &[u8] {
+                &self.buffer[self.written..]
+            }
+
+            /// Flag some bytes as removed from the front of the buffer
+            fn consume(&mut self, amt: usize) {
+                self.written += amt;
+            }
+
+            /// true if all of the bytes have been written
+            fn done(&self) -> bool {
+                self.written >= self.buffer.len()
+            }
+        }
+
+        impl Drop for BufGuard<'_> {
+            fn drop(&mut self) {
+                if self.written > 0 {
+                    self.buffer.drain(..self.written);
+                }
+            }
+        }
+
+        let mut guard = BufGuard::new(&mut self.buf);
+        let inner = self.inner.as_mut().unwrap();
+        while !guard.done() {
+            self.panicked = true;
+            let r = inner.write(guard.remaining());
+            self.panicked = false;
+
+            match r {
+                Ok(0) => {
+                    return Err(Error::new(
+                        ErrorKind::WriteZero,
+                        "failed to write the buffered data",
+                    ));
+                }
+                Ok(n) => guard.consume(n),
+                Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {}
+                Err(e) => return Err(e),
+            }
+        }
+        Ok(())
+    }
+
+    /// Buffer some data without flushing it, regardless of the size of the
+    /// data. Writes as much as possible without exceeding capacity. Returns
+    /// the number of bytes written.
+    pub(super) fn write_to_buf(&mut self, buf: &[u8]) -> usize {
+        let available = self.buf.capacity() - self.buf.len();
+        let amt_to_buffer = available.min(buf.len());
+        self.buf.extend_from_slice(&buf[..amt_to_buffer]);
+        amt_to_buffer
+    }
+
+    /// Gets a reference to the underlying writer.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::io::BufWriter;
+    /// use std::net::TcpStream;
+    ///
+    /// let mut buffer = BufWriter::new(TcpStream::connect("127.0.0.1:34254").unwrap());
+    ///
+    /// // we can use reference just like buffer
+    /// let reference = buffer.get_ref();
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn get_ref(&self) -> &W {
+        self.inner.as_ref().unwrap()
+    }
+
+    /// Gets a mutable reference to the underlying writer.
+    ///
+    /// It is inadvisable to directly write to the underlying writer.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::io::BufWriter;
+    /// use std::net::TcpStream;
+    ///
+    /// let mut buffer = BufWriter::new(TcpStream::connect("127.0.0.1:34254").unwrap());
+    ///
+    /// // we can use reference just like buffer
+    /// let reference = buffer.get_mut();
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn get_mut(&mut self) -> &mut W {
+        self.inner.as_mut().unwrap()
+    }
+
+    /// Returns a reference to the internally buffered data.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::io::BufWriter;
+    /// use std::net::TcpStream;
+    ///
+    /// let buf_writer = BufWriter::new(TcpStream::connect("127.0.0.1:34254").unwrap());
+    ///
+    /// // See how many bytes are currently buffered
+    /// let bytes_buffered = buf_writer.buffer().len();
+    /// ```
+    #[stable(feature = "bufreader_buffer", since = "1.37.0")]
+    pub fn buffer(&self) -> &[u8] {
+        &self.buf
+    }
+
+    /// Returns the number of bytes the internal buffer can hold without flushing.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::io::BufWriter;
+    /// use std::net::TcpStream;
+    ///
+    /// let buf_writer = BufWriter::new(TcpStream::connect("127.0.0.1:34254").unwrap());
+    ///
+    /// // Check the capacity of the inner buffer
+    /// let capacity = buf_writer.capacity();
+    /// // Calculate how many bytes can be written without flushing
+    /// let without_flush = capacity - buf_writer.buffer().len();
+    /// ```
+    #[stable(feature = "buffered_io_capacity", since = "1.46.0")]
+    pub fn capacity(&self) -> usize {
+        self.buf.capacity()
+    }
+
+    /// Unwraps this `BufWriter<W>`, returning the underlying writer.
+    ///
+    /// The buffer is written out before returning the writer.
+    ///
+    /// # Errors
+    ///
+    /// An [`Err`] will be returned if an error occurs while flushing the buffer.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::io::BufWriter;
+    /// use std::net::TcpStream;
+    ///
+    /// let mut buffer = BufWriter::new(TcpStream::connect("127.0.0.1:34254").unwrap());
+    ///
+    /// // unwrap the TcpStream and flush the buffer
+    /// let stream = buffer.into_inner().unwrap();
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn into_inner(mut self) -> Result<W, IntoInnerError<BufWriter<W>>> {
+        match self.flush_buf() {
+            Err(e) => Err(IntoInnerError::new(self, e)),
+            Ok(()) => Ok(self.inner.take().unwrap()),
+        }
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<W: Write> Write for BufWriter<W> {
+    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
+        if self.buf.len() + buf.len() > self.buf.capacity() {
+            self.flush_buf()?;
+        }
+        // FIXME: Why no len > capacity? Why not buffer len == capacity? #72919
+        if buf.len() >= self.buf.capacity() {
+            self.panicked = true;
+            let r = self.get_mut().write(buf);
+            self.panicked = false;
+            r
+        } else {
+            self.buf.extend_from_slice(buf);
+            Ok(buf.len())
+        }
+    }
+
+    fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
+        // Normally, `write_all` just calls `write` in a loop. We can do better
+        // by calling `self.get_mut().write_all()` directly, which avoids
+        // round trips through the buffer in the event of a series of partial
+        // writes in some circumstances.
+        if self.buf.len() + buf.len() > self.buf.capacity() {
+            self.flush_buf()?;
+        }
+        // FIXME: Why no len > capacity? Why not buffer len == capacity? #72919
+        if buf.len() >= self.buf.capacity() {
+            self.panicked = true;
+            let r = self.get_mut().write_all(buf);
+            self.panicked = false;
+            r
+        } else {
+            self.buf.extend_from_slice(buf);
+            Ok(())
+        }
+    }
+
+    fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
+        let total_len = bufs.iter().map(|b| b.len()).sum::<usize>();
+        if self.buf.len() + total_len > self.buf.capacity() {
+            self.flush_buf()?;
+        }
+        // FIXME: Why no len > capacity? Why not buffer len == capacity? #72919
+        if total_len >= self.buf.capacity() {
+            self.panicked = true;
+            let r = self.get_mut().write_vectored(bufs);
+            self.panicked = false;
+            r
+        } else {
+            bufs.iter().for_each(|b| self.buf.extend_from_slice(b));
+            Ok(total_len)
+        }
+    }
+
+    fn is_write_vectored(&self) -> bool {
+        self.get_ref().is_write_vectored()
+    }
+
+    fn flush(&mut self) -> io::Result<()> {
+        self.flush_buf().and_then(|()| self.get_mut().flush())
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<W: Write> fmt::Debug for BufWriter<W>
+where
+    W: fmt::Debug,
+{
+    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+        fmt.debug_struct("BufWriter")
+            .field("writer", &self.inner.as_ref().unwrap())
+            .field("buffer", &format_args!("{}/{}", self.buf.len(), self.buf.capacity()))
+            .finish()
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<W: Write + Seek> Seek for BufWriter<W> {
+    /// Seek to the offset, in bytes, in the underlying writer.
+    ///
+    /// Seeking always writes out the internal buffer before seeking.
+    fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
+        self.flush_buf()?;
+        self.get_mut().seek(pos)
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<W: Write> Drop for BufWriter<W> {
+    fn drop(&mut self) {
+        if self.inner.is_some() && !self.panicked {
+            // dtors should not panic, so we ignore a failed flush
+            let _r = self.flush_buf();
+        }
+    }
+}
diff --git a/library/std/src/io/buffered/linewriter.rs b/library/std/src/io/buffered/linewriter.rs
new file mode 100644
index 00000000000..502c6e3c6c0
--- /dev/null
+++ b/library/std/src/io/buffered/linewriter.rs
@@ -0,0 +1,232 @@
+use crate::fmt;
+use crate::io::{self, buffered::LineWriterShim, BufWriter, IntoInnerError, IoSlice, Write};
+
+/// Wraps a writer and buffers output to it, flushing whenever a newline
+/// (`0x0a`, `'\n'`) is detected.
+///
+/// The [`BufWriter`] struct wraps a writer and buffers its output.
+/// But it only does this batched write when it goes out of scope, or when the
+/// internal buffer is full. Sometimes, you'd prefer to write each line as it's
+/// completed, rather than the entire buffer at once. Enter `LineWriter`. It
+/// does exactly that.
+///
+/// Like [`BufWriter`], a `LineWriter`’s buffer will also be flushed when the
+/// `LineWriter` goes out of scope or when its internal buffer is full.
+///
+/// If there's still a partial line in the buffer when the `LineWriter` is
+/// dropped, it will flush those contents.
+///
+/// # Examples
+///
+/// We can use `LineWriter` to write one line at a time, significantly
+/// reducing the number of actual writes to the file.
+///
+/// ```no_run
+/// use std::fs::{self, File};
+/// use std::io::prelude::*;
+/// use std::io::LineWriter;
+///
+/// fn main() -> std::io::Result<()> {
+///     let road_not_taken = b"I shall be telling this with a sigh
+/// Somewhere ages and ages hence:
+/// Two roads diverged in a wood, and I -
+/// I took the one less traveled by,
+/// And that has made all the difference.";
+///
+///     let file = File::create("poem.txt")?;
+///     let mut file = LineWriter::new(file);
+///
+///     file.write_all(b"I shall be telling this with a sigh")?;
+///
+///     // No bytes are written until a newline is encountered (or
+///     // the internal buffer is filled).
+///     assert_eq!(fs::read_to_string("poem.txt")?, "");
+///     file.write_all(b"\n")?;
+///     assert_eq!(
+///         fs::read_to_string("poem.txt")?,
+///         "I shall be telling this with a sigh\n",
+///     );
+///
+///     // Write the rest of the poem.
+///     file.write_all(b"Somewhere ages and ages hence:
+/// Two roads diverged in a wood, and I -
+/// I took the one less traveled by,
+/// And that has made all the difference.")?;
+///
+///     // The last line of the poem doesn't end in a newline, so
+///     // we have to flush or drop the `LineWriter` to finish
+///     // writing.
+///     file.flush()?;
+///
+///     // Confirm the whole poem was written.
+///     assert_eq!(fs::read("poem.txt")?, &road_not_taken[..]);
+///     Ok(())
+/// }
+/// ```
+#[stable(feature = "rust1", since = "1.0.0")]
+pub struct LineWriter<W: Write> {
+    inner: BufWriter<W>,
+}
+
+impl<W: Write> LineWriter<W> {
+    /// Creates a new `LineWriter`.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs::File;
+    /// use std::io::LineWriter;
+    ///
+    /// fn main() -> std::io::Result<()> {
+    ///     let file = File::create("poem.txt")?;
+    ///     let file = LineWriter::new(file);
+    ///     Ok(())
+    /// }
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn new(inner: W) -> LineWriter<W> {
+        // Lines typically aren't that long, don't use a giant buffer
+        LineWriter::with_capacity(1024, inner)
+    }
+
+    /// Creates a new `LineWriter` with a specified capacity for the internal
+    /// buffer.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs::File;
+    /// use std::io::LineWriter;
+    ///
+    /// fn main() -> std::io::Result<()> {
+    ///     let file = File::create("poem.txt")?;
+    ///     let file = LineWriter::with_capacity(100, file);
+    ///     Ok(())
+    /// }
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn with_capacity(capacity: usize, inner: W) -> LineWriter<W> {
+        LineWriter { inner: BufWriter::with_capacity(capacity, inner) }
+    }
+
+    /// Gets a reference to the underlying writer.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs::File;
+    /// use std::io::LineWriter;
+    ///
+    /// fn main() -> std::io::Result<()> {
+    ///     let file = File::create("poem.txt")?;
+    ///     let file = LineWriter::new(file);
+    ///
+    ///     let reference = file.get_ref();
+    ///     Ok(())
+    /// }
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn get_ref(&self) -> &W {
+        self.inner.get_ref()
+    }
+
+    /// Gets a mutable reference to the underlying writer.
+    ///
+    /// Caution must be taken when calling methods on the mutable reference
+    /// returned as extra writes could corrupt the output stream.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs::File;
+    /// use std::io::LineWriter;
+    ///
+    /// fn main() -> std::io::Result<()> {
+    ///     let file = File::create("poem.txt")?;
+    ///     let mut file = LineWriter::new(file);
+    ///
+    ///     // we can use reference just like file
+    ///     let reference = file.get_mut();
+    ///     Ok(())
+    /// }
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn get_mut(&mut self) -> &mut W {
+        self.inner.get_mut()
+    }
+
+    /// Unwraps this `LineWriter`, returning the underlying writer.
+    ///
+    /// The internal buffer is written out before returning the writer.
+    ///
+    /// # Errors
+    ///
+    /// An [`Err`] will be returned if an error occurs while flushing the buffer.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs::File;
+    /// use std::io::LineWriter;
+    ///
+    /// fn main() -> std::io::Result<()> {
+    ///     let file = File::create("poem.txt")?;
+    ///
+    ///     let writer: LineWriter<File> = LineWriter::new(file);
+    ///
+    ///     let file: File = writer.into_inner()?;
+    ///     Ok(())
+    /// }
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn into_inner(self) -> Result<W, IntoInnerError<LineWriter<W>>> {
+        self.inner.into_inner().map_err(|err| err.new_wrapped(|inner| LineWriter { inner }))
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<W: Write> Write for LineWriter<W> {
+    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
+        LineWriterShim::new(&mut self.inner).write(buf)
+    }
+
+    fn flush(&mut self) -> io::Result<()> {
+        self.inner.flush()
+    }
+
+    fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
+        LineWriterShim::new(&mut self.inner).write_vectored(bufs)
+    }
+
+    fn is_write_vectored(&self) -> bool {
+        self.inner.is_write_vectored()
+    }
+
+    fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
+        LineWriterShim::new(&mut self.inner).write_all(buf)
+    }
+
+    fn write_all_vectored(&mut self, bufs: &mut [IoSlice<'_>]) -> io::Result<()> {
+        LineWriterShim::new(&mut self.inner).write_all_vectored(bufs)
+    }
+
+    fn write_fmt(&mut self, fmt: fmt::Arguments<'_>) -> io::Result<()> {
+        LineWriterShim::new(&mut self.inner).write_fmt(fmt)
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<W: Write> fmt::Debug for LineWriter<W>
+where
+    W: fmt::Debug,
+{
+    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+        fmt.debug_struct("LineWriter")
+            .field("writer", &self.get_ref())
+            .field(
+                "buffer",
+                &format_args!("{}/{}", self.inner.buffer().len(), self.inner.capacity()),
+            )
+            .finish()
+    }
+}
diff --git a/library/std/src/io/buffered/linewritershim.rs b/library/std/src/io/buffered/linewritershim.rs
new file mode 100644
index 00000000000..a80d08db869
--- /dev/null
+++ b/library/std/src/io/buffered/linewritershim.rs
@@ -0,0 +1,270 @@
+use crate::io::{self, BufWriter, IoSlice, Write};
+use crate::memchr;
+
+/// Private helper struct for implementing the line-buffered writing logic.
+/// This shim temporarily wraps a BufWriter, and uses its internals to
+/// implement a line-buffered writer (specifically by using the internal
+/// methods like write_to_buf and flush_buf). In this way, a more
+/// efficient abstraction can be created than one that only had access to
+/// `write` and `flush`, without needlessly duplicating a lot of the
+/// implementation details of BufWriter. This also allows existing
+/// `BufWriters` to be temporarily given line-buffering logic; this is what
+/// enables Stdout to be alternately in line-buffered or block-buffered mode.
+#[derive(Debug)]
+pub struct LineWriterShim<'a, W: Write> {
+    buffer: &'a mut BufWriter<W>,
+}
+
+impl<'a, W: Write> LineWriterShim<'a, W> {
+    pub fn new(buffer: &'a mut BufWriter<W>) -> Self {
+        Self { buffer }
+    }
+
+    /// Get a mutable reference to the inner writer (that is, the writer
+    /// wrapped by the BufWriter). Be careful with this writer, as writes to
+    /// it will bypass the buffer.
+    fn inner_mut(&mut self) -> &mut W {
+        self.buffer.get_mut()
+    }
+
+    /// Get the content currently buffered in self.buffer
+    fn buffered(&self) -> &[u8] {
+        self.buffer.buffer()
+    }
+
+    /// Flush the buffer iff the last byte is a newline (indicating that an
+    /// earlier write only succeeded partially, and we want to retry flushing
+    /// the buffered line before continuing with a subsequent write)
+    fn flush_if_completed_line(&mut self) -> io::Result<()> {
+        match self.buffered().last().copied() {
+            Some(b'\n') => self.buffer.flush_buf(),
+            _ => Ok(()),
+        }
+    }
+}
+
+impl<'a, W: Write> Write for LineWriterShim<'a, W> {
+    /// Write some data into this BufReader with line buffering. This means
+    /// that, if any newlines are present in the data, the data up to the last
+    /// newline is sent directly to the underlying writer, and data after it
+    /// is buffered. Returns the number of bytes written.
+    ///
+    /// This function operates on a "best effort basis"; in keeping with the
+    /// convention of `Write::write`, it makes at most one attempt to write
+    /// new data to the underlying writer. If that write only reports a partial
+    /// success, the remaining data will be buffered.
+    ///
+    /// Because this function attempts to send completed lines to the underlying
+    /// writer, it will also flush the existing buffer if it ends with a
+    /// newline, even if the incoming data does not contain any newlines.
+    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
+        let newline_idx = match memchr::memrchr(b'\n', buf) {
+            // If there are no new newlines (that is, if this write is less than
+            // one line), just do a regular buffered write (which may flush if
+            // we exceed the inner buffer's size)
+            None => {
+                self.flush_if_completed_line()?;
+                return self.buffer.write(buf);
+            }
+            // Otherwise, arrange for the lines to be written directly to the
+            // inner writer.
+            Some(newline_idx) => newline_idx + 1,
+        };
+
+        // Flush existing content to prepare for our write. We have to do this
+        // before attempting to write `buf` in order to maintain consistency;
+        // if we add `buf` to the buffer then try to flush it all at once,
+        // we're obligated to return Ok(), which would mean suppressing any
+        // errors that occur during flush.
+        self.buffer.flush_buf()?;
+
+        // This is what we're going to try to write directly to the inner
+        // writer. The rest will be buffered, if nothing goes wrong.
+        let lines = &buf[..newline_idx];
+
+        // Write `lines` directly to the inner writer. In keeping with the
+        // `write` convention, make at most one attempt to add new (unbuffered)
+        // data. Because this write doesn't touch the BufWriter state directly,
+        // and the buffer is known to be empty, we don't need to worry about
+        // self.buffer.panicked here.
+        let flushed = self.inner_mut().write(lines)?;
+
+        // If buffer returns Ok(0), propagate that to the caller without
+        // doing additional buffering; otherwise we're just guaranteeing
+        // an "ErrorKind::WriteZero" later.
+        if flushed == 0 {
+            return Ok(0);
+        }
+
+        // Now that the write has succeeded, buffer the rest (or as much of
+        // the rest as possible). If there were any unwritten newlines, we
+        // only buffer out to the last unwritten newline that fits in the
+        // buffer; this helps prevent flushing partial lines on subsequent
+        // calls to LineWriterShim::write.
+
+        // Handle the cases in order of most-common to least-common, under
+        // the presumption that most writes succeed in totality, and that most
+        // writes are smaller than the buffer.
+        // - Is this a partial line (ie, no newlines left in the unwritten tail)
+        // - If not, does the data out to the last unwritten newline fit in
+        //   the buffer?
+        // - If not, scan for the last newline that *does* fit in the buffer
+        let tail = if flushed >= newline_idx {
+            &buf[flushed..]
+        } else if newline_idx - flushed <= self.buffer.capacity() {
+            &buf[flushed..newline_idx]
+        } else {
+            let scan_area = &buf[flushed..];
+            let scan_area = &scan_area[..self.buffer.capacity()];
+            match memchr::memrchr(b'\n', scan_area) {
+                Some(newline_idx) => &scan_area[..newline_idx + 1],
+                None => scan_area,
+            }
+        };
+
+        let buffered = self.buffer.write_to_buf(tail);
+        Ok(flushed + buffered)
+    }
+
+    fn flush(&mut self) -> io::Result<()> {
+        self.buffer.flush()
+    }
+
+    /// Write some vectored data into this BufReader with line buffering. This
+    /// means that, if any newlines are present in the data, the data up to
+    /// and including the buffer containing the last newline is sent directly
+    /// to the inner writer, and the data after it is buffered. Returns the
+    /// number of bytes written.
+    ///
+    /// This function operates on a "best effort basis"; in keeping with the
+    /// convention of `Write::write`, it makes at most one attempt to write
+    /// new data to the underlying writer.
+    ///
+    /// Because this function attempts to send completed lines to the underlying
+    /// writer, it will also flush the existing buffer if it contains any
+    /// newlines.
+    ///
+    /// Because sorting through an array of `IoSlice` can be a bit convoluted,
+    /// This method differs from write in the following ways:
+    ///
+    /// - It attempts to write the full content of all the buffers up to and
+    ///   including the one containing the last newline. This means that it
+    ///   may attempt to write a partial line, that buffer has data past the
+    ///   newline.
+    /// - If the write only reports partial success, it does not attempt to
+    ///   find the precise location of the written bytes and buffer the rest.
+    ///
+    /// If the underlying vector doesn't support vectored writing, we instead
+    /// simply write the first non-empty buffer with `write`. This way, we
+    /// get the benefits of more granular partial-line handling without losing
+    /// anything in efficiency
+    fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
+        // If there's no specialized behavior for write_vectored, just use
+        // write. This has the benefit of more granular partial-line handling.
+        if !self.is_write_vectored() {
+            return match bufs.iter().find(|buf| !buf.is_empty()) {
+                Some(buf) => self.write(buf),
+                None => Ok(0),
+            };
+        }
+
+        // Find the buffer containing the last newline
+        let last_newline_buf_idx = bufs
+            .iter()
+            .enumerate()
+            .rev()
+            .find_map(|(i, buf)| memchr::memchr(b'\n', buf).map(|_| i));
+
+        // If there are no new newlines (that is, if this write is less than
+        // one line), just do a regular buffered write
+        let last_newline_buf_idx = match last_newline_buf_idx {
+            // No newlines; just do a normal buffered write
+            None => {
+                self.flush_if_completed_line()?;
+                return self.buffer.write_vectored(bufs);
+            }
+            Some(i) => i,
+        };
+
+        // Flush existing content to prepare for our write
+        self.buffer.flush_buf()?;
+
+        // This is what we're going to try to write directly to the inner
+        // writer. The rest will be buffered, if nothing goes wrong.
+        let (lines, tail) = bufs.split_at(last_newline_buf_idx + 1);
+
+        // Write `lines` directly to the inner writer. In keeping with the
+        // `write` convention, make at most one attempt to add new (unbuffered)
+        // data. Because this write doesn't touch the BufWriter state directly,
+        // and the buffer is known to be empty, we don't need to worry about
+        // self.panicked here.
+        let flushed = self.inner_mut().write_vectored(lines)?;
+
+        // If inner returns Ok(0), propagate that to the caller without
+        // doing additional buffering; otherwise we're just guaranteeing
+        // an "ErrorKind::WriteZero" later.
+        if flushed == 0 {
+            return Ok(0);
+        }
+
+        // Don't try to reconstruct the exact amount written; just bail
+        // in the event of a partial write
+        let lines_len = lines.iter().map(|buf| buf.len()).sum();
+        if flushed < lines_len {
+            return Ok(flushed);
+        }
+
+        // Now that the write has succeeded, buffer the rest (or as much of the
+        // rest as possible)
+        let buffered: usize = tail
+            .iter()
+            .filter(|buf| !buf.is_empty())
+            .map(|buf| self.buffer.write_to_buf(buf))
+            .take_while(|&n| n > 0)
+            .sum();
+
+        Ok(flushed + buffered)
+    }
+
+    fn is_write_vectored(&self) -> bool {
+        self.buffer.is_write_vectored()
+    }
+
+    /// Write some data into this BufReader with line buffering. This means
+    /// that, if any newlines are present in the data, the data up to the last
+    /// newline is sent directly to the underlying writer, and data after it
+    /// is buffered.
+    ///
+    /// Because this function attempts to send completed lines to the underlying
+    /// writer, it will also flush the existing buffer if it contains any
+    /// newlines, even if the incoming data does not contain any newlines.
+    fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
+        match memchr::memrchr(b'\n', buf) {
+            // If there are no new newlines (that is, if this write is less than
+            // one line), just do a regular buffered write (which may flush if
+            // we exceed the inner buffer's size)
+            None => {
+                self.flush_if_completed_line()?;
+                self.buffer.write_all(buf)
+            }
+            Some(newline_idx) => {
+                let (lines, tail) = buf.split_at(newline_idx + 1);
+
+                if self.buffered().is_empty() {
+                    self.inner_mut().write_all(lines)?;
+                } else {
+                    // If there is any buffered data, we add the incoming lines
+                    // to that buffer before flushing, which saves us at least
+                    // one write call. We can't really do this with `write`,
+                    // since we can't do this *and* not suppress errors *and*
+                    // report a consistent state to the caller in a return
+                    // value, but here in write_all it's fine.
+                    self.buffer.write_all(lines)?;
+                    self.buffer.flush_buf()?;
+                }
+
+                self.buffer.write_all(tail)
+            }
+        }
+    }
+}
diff --git a/library/std/src/io/buffered/mod.rs b/library/std/src/io/buffered/mod.rs
new file mode 100644
index 00000000000..f9caeaf98e2
--- /dev/null
+++ b/library/std/src/io/buffered/mod.rs
@@ -0,0 +1,151 @@
+//! Buffering wrappers for I/O traits
+
+mod bufreader;
+mod bufwriter;
+mod linewriter;
+mod linewritershim;
+
+#[cfg(test)]
+mod tests;
+
+use crate::error;
+use crate::fmt;
+use crate::io::Error;
+
+pub use bufreader::BufReader;
+pub use bufwriter::BufWriter;
+pub use linewriter::LineWriter;
+use linewritershim::LineWriterShim;
+
+/// An error returned by [`BufWriter::into_inner`] which combines an error that
+/// happened while writing out the buffer, and the buffered writer object
+/// which may be used to recover from the condition.
+///
+/// # Examples
+///
+/// ```no_run
+/// use std::io::BufWriter;
+/// use std::net::TcpStream;
+///
+/// let mut stream = BufWriter::new(TcpStream::connect("127.0.0.1:34254").unwrap());
+///
+/// // do stuff with the stream
+///
+/// // we want to get our `TcpStream` back, so let's try:
+///
+/// let stream = match stream.into_inner() {
+///     Ok(s) => s,
+///     Err(e) => {
+///         // Here, e is an IntoInnerError
+///         panic!("An error occurred");
+///     }
+/// };
+/// ```
+#[derive(Debug)]
+#[stable(feature = "rust1", since = "1.0.0")]
+pub struct IntoInnerError<W>(W, Error);
+
+impl<W> IntoInnerError<W> {
+    /// Construct a new IntoInnerError
+    fn new(writer: W, error: Error) -> Self {
+        Self(writer, error)
+    }
+
+    /// Helper to construct a new IntoInnerError; intended to help with
+    /// adapters that wrap other adapters
+    fn new_wrapped<W2>(self, f: impl FnOnce(W) -> W2) -> IntoInnerError<W2> {
+        let Self(writer, error) = self;
+        IntoInnerError::new(f(writer), error)
+    }
+
+    /// Returns the error which caused the call to [`BufWriter::into_inner()`]
+    /// to fail.
+    ///
+    /// This error was returned when attempting to write the internal buffer.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::io::BufWriter;
+    /// use std::net::TcpStream;
+    ///
+    /// let mut stream = BufWriter::new(TcpStream::connect("127.0.0.1:34254").unwrap());
+    ///
+    /// // do stuff with the stream
+    ///
+    /// // we want to get our `TcpStream` back, so let's try:
+    ///
+    /// let stream = match stream.into_inner() {
+    ///     Ok(s) => s,
+    ///     Err(e) => {
+    ///         // Here, e is an IntoInnerError, let's log the inner error.
+    ///         //
+    ///         // We'll just 'log' to stdout for this example.
+    ///         println!("{}", e.error());
+    ///
+    ///         panic!("An unexpected error occurred.");
+    ///     }
+    /// };
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn error(&self) -> &Error {
+        &self.1
+    }
+
+    /// Returns the buffered writer instance which generated the error.
+    ///
+    /// The returned object can be used for error recovery, such as
+    /// re-inspecting the buffer.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::io::BufWriter;
+    /// use std::net::TcpStream;
+    ///
+    /// let mut stream = BufWriter::new(TcpStream::connect("127.0.0.1:34254").unwrap());
+    ///
+    /// // do stuff with the stream
+    ///
+    /// // we want to get our `TcpStream` back, so let's try:
+    ///
+    /// let stream = match stream.into_inner() {
+    ///     Ok(s) => s,
+    ///     Err(e) => {
+    ///         // Here, e is an IntoInnerError, let's re-examine the buffer:
+    ///         let buffer = e.into_inner();
+    ///
+    ///         // do stuff to try to recover
+    ///
+    ///         // afterwards, let's just return the stream
+    ///         buffer.into_inner().unwrap()
+    ///     }
+    /// };
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn into_inner(self) -> W {
+        self.0
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<W> From<IntoInnerError<W>> for Error {
+    fn from(iie: IntoInnerError<W>) -> Error {
+        iie.1
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<W: Send + fmt::Debug> error::Error for IntoInnerError<W> {
+    #[allow(deprecated, deprecated_in_future)]
+    fn description(&self) -> &str {
+        error::Error::description(self.error())
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<W> fmt::Display for IntoInnerError<W> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        self.error().fmt(f)
+    }
+}
diff --git a/library/std/src/sys/cloudabi/condvar.rs b/library/std/src/sys/cloudabi/condvar.rs
index 82d89b260fa..f09bc01701b 100644
--- a/library/std/src/sys/cloudabi/condvar.rs
+++ b/library/std/src/sys/cloudabi/condvar.rs
@@ -1,4 +1,3 @@
-use crate::cell::UnsafeCell;
 use crate::mem;
 use crate::sync::atomic::{AtomicU32, Ordering};
 use crate::sys::cloudabi::abi;
@@ -12,7 +11,7 @@ extern "C" {
 }
 
 pub struct Condvar {
-    condvar: UnsafeCell<AtomicU32>,
+    condvar: AtomicU32,
 }
 
 pub type MovableCondvar = Condvar;
@@ -20,29 +19,28 @@ pub type MovableCondvar = Condvar;
 unsafe impl Send for Condvar {}
 unsafe impl Sync for Condvar {}
 
-const NEW: Condvar =
-    Condvar { condvar: UnsafeCell::new(AtomicU32::new(abi::CONDVAR_HAS_NO_WAITERS.0)) };
-
 impl Condvar {
     pub const fn new() -> Condvar {
-        NEW
+        Condvar { condvar: AtomicU32::new(abi::CONDVAR_HAS_NO_WAITERS.0) }
     }
 
     pub unsafe fn init(&mut self) {}
 
     pub unsafe fn notify_one(&self) {
-        let condvar = self.condvar.get();
-        if (*condvar).load(Ordering::Relaxed) != abi::CONDVAR_HAS_NO_WAITERS.0 {
-            let ret = abi::condvar_signal(condvar as *mut abi::condvar, abi::scope::PRIVATE, 1);
+        if self.condvar.load(Ordering::Relaxed) != abi::CONDVAR_HAS_NO_WAITERS.0 {
+            let ret = abi::condvar_signal(
+                &self.condvar as *const AtomicU32 as *mut abi::condvar,
+                abi::scope::PRIVATE,
+                1,
+            );
             assert_eq!(ret, abi::errno::SUCCESS, "Failed to signal on condition variable");
         }
     }
 
     pub unsafe fn notify_all(&self) {
-        let condvar = self.condvar.get();
-        if (*condvar).load(Ordering::Relaxed) != abi::CONDVAR_HAS_NO_WAITERS.0 {
+        if self.condvar.load(Ordering::Relaxed) != abi::CONDVAR_HAS_NO_WAITERS.0 {
             let ret = abi::condvar_signal(
-                condvar as *mut abi::condvar,
+                &self.condvar as *const AtomicU32 as *mut abi::condvar,
                 abi::scope::PRIVATE,
                 abi::nthreads::MAX,
             );
@@ -53,20 +51,19 @@ impl Condvar {
     pub unsafe fn wait(&self, mutex: &Mutex) {
         let mutex = mutex::raw(mutex);
         assert_eq!(
-            (*mutex).load(Ordering::Relaxed) & !abi::LOCK_KERNEL_MANAGED.0,
+            mutex.load(Ordering::Relaxed) & !abi::LOCK_KERNEL_MANAGED.0,
             __pthread_thread_id.0 | abi::LOCK_WRLOCKED.0,
             "This lock is not write-locked by this thread"
         );
 
         // Call into the kernel to wait on the condition variable.
-        let condvar = self.condvar.get();
         let subscription = abi::subscription {
             type_: abi::eventtype::CONDVAR,
             union: abi::subscription_union {
                 condvar: abi::subscription_condvar {
-                    condvar: condvar as *mut abi::condvar,
+                    condvar: &self.condvar as *const AtomicU32 as *mut abi::condvar,
                     condvar_scope: abi::scope::PRIVATE,
-                    lock: mutex as *mut abi::lock,
+                    lock: mutex as *const AtomicU32 as *mut abi::lock,
                     lock_scope: abi::scope::PRIVATE,
                 },
             },
@@ -86,13 +83,12 @@ impl Condvar {
     pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool {
         let mutex = mutex::raw(mutex);
         assert_eq!(
-            (*mutex).load(Ordering::Relaxed) & !abi::LOCK_KERNEL_MANAGED.0,
+            mutex.load(Ordering::Relaxed) & !abi::LOCK_KERNEL_MANAGED.0,
             __pthread_thread_id.0 | abi::LOCK_WRLOCKED.0,
             "This lock is not write-locked by this thread"
         );
 
         // Call into the kernel to wait on the condition variable.
-        let condvar = self.condvar.get();
         let timeout =
             checked_dur2intervals(&dur).expect("overflow converting duration to nanoseconds");
         let subscriptions = [
@@ -100,9 +96,9 @@ impl Condvar {
                 type_: abi::eventtype::CONDVAR,
                 union: abi::subscription_union {
                     condvar: abi::subscription_condvar {
-                        condvar: condvar as *mut abi::condvar,
+                        condvar: &self.condvar as *const AtomicU32 as *mut abi::condvar,
                         condvar_scope: abi::scope::PRIVATE,
-                        lock: mutex as *mut abi::lock,
+                        lock: mutex as *const AtomicU32 as *mut abi::lock,
                         lock_scope: abi::scope::PRIVATE,
                     },
                 },
@@ -124,7 +120,7 @@ impl Condvar {
         let mut nevents: mem::MaybeUninit<usize> = mem::MaybeUninit::uninit();
         let ret = abi::poll(
             subscriptions.as_ptr(),
-            mem::MaybeUninit::first_ptr_mut(&mut events),
+            mem::MaybeUninit::slice_as_mut_ptr(&mut events),
             2,
             nevents.as_mut_ptr(),
         );
@@ -144,9 +140,8 @@ impl Condvar {
     }
 
     pub unsafe fn destroy(&self) {
-        let condvar = self.condvar.get();
         assert_eq!(
-            (*condvar).load(Ordering::Relaxed),
+            self.condvar.load(Ordering::Relaxed),
             abi::CONDVAR_HAS_NO_WAITERS.0,
             "Attempted to destroy a condition variable with blocked threads"
         );
diff --git a/library/std/src/sys/cloudabi/mutex.rs b/library/std/src/sys/cloudabi/mutex.rs
index 66839e05bf0..1203d8de0c5 100644
--- a/library/std/src/sys/cloudabi/mutex.rs
+++ b/library/std/src/sys/cloudabi/mutex.rs
@@ -1,4 +1,4 @@
-use crate::cell::UnsafeCell;
+use crate::cell::Cell;
 use crate::mem;
 use crate::mem::MaybeUninit;
 use crate::sync::atomic::{AtomicU32, Ordering};
@@ -17,7 +17,7 @@ pub struct Mutex(RWLock);
 
 pub type MovableMutex = Mutex;
 
-pub unsafe fn raw(m: &Mutex) -> *mut AtomicU32 {
+pub unsafe fn raw(m: &Mutex) -> &AtomicU32 {
     rwlock::raw(&m.0)
 }
 
@@ -50,28 +50,23 @@ impl Mutex {
 }
 
 pub struct ReentrantMutex {
-    lock: UnsafeCell<MaybeUninit<AtomicU32>>,
-    recursion: UnsafeCell<MaybeUninit<u32>>,
+    lock: AtomicU32,
+    recursion: Cell<u32>,
 }
 
+unsafe impl Send for ReentrantMutex {}
+unsafe impl Sync for ReentrantMutex {}
+
 impl ReentrantMutex {
     pub const unsafe fn uninitialized() -> ReentrantMutex {
-        ReentrantMutex {
-            lock: UnsafeCell::new(MaybeUninit::uninit()),
-            recursion: UnsafeCell::new(MaybeUninit::uninit()),
-        }
+        ReentrantMutex { lock: AtomicU32::new(abi::LOCK_UNLOCKED.0), recursion: Cell::new(0) }
     }
 
-    pub unsafe fn init(&self) {
-        *self.lock.get() = MaybeUninit::new(AtomicU32::new(abi::LOCK_UNLOCKED.0));
-        *self.recursion.get() = MaybeUninit::new(0);
-    }
+    pub unsafe fn init(&self) {}
 
     pub unsafe fn try_lock(&self) -> bool {
         // Attempt to acquire the lock.
-        let lock = (*self.lock.get()).as_mut_ptr();
-        let recursion = (*self.recursion.get()).as_mut_ptr();
-        if let Err(old) = (*lock).compare_exchange(
+        if let Err(old) = self.lock.compare_exchange(
             abi::LOCK_UNLOCKED.0,
             __pthread_thread_id.0 | abi::LOCK_WRLOCKED.0,
             Ordering::Acquire,
@@ -80,14 +75,14 @@ impl ReentrantMutex {
             // If we fail to acquire the lock, it may be the case
             // that we've already acquired it and may need to recurse.
             if old & !abi::LOCK_KERNEL_MANAGED.0 == __pthread_thread_id.0 | abi::LOCK_WRLOCKED.0 {
-                *recursion += 1;
+                self.recursion.set(self.recursion.get() + 1);
                 true
             } else {
                 false
             }
         } else {
             // Success.
-            assert_eq!(*recursion, 0, "Mutex has invalid recursion count");
+            assert_eq!(self.recursion.get(), 0, "Mutex has invalid recursion count");
             true
         }
     }
@@ -95,7 +90,7 @@ impl ReentrantMutex {
     pub unsafe fn lock(&self) {
         if !self.try_lock() {
             // Call into the kernel to acquire a write lock.
-            let lock = self.lock.get();
+            let lock = &self.lock as *const AtomicU32;
             let subscription = abi::subscription {
                 type_: abi::eventtype::LOCK_WRLOCK,
                 union: abi::subscription_union {
@@ -116,17 +111,17 @@ impl ReentrantMutex {
     }
 
     pub unsafe fn unlock(&self) {
-        let lock = (*self.lock.get()).as_mut_ptr();
-        let recursion = (*self.recursion.get()).as_mut_ptr();
         assert_eq!(
-            (*lock).load(Ordering::Relaxed) & !abi::LOCK_KERNEL_MANAGED.0,
+            self.lock.load(Ordering::Relaxed) & !abi::LOCK_KERNEL_MANAGED.0,
             __pthread_thread_id.0 | abi::LOCK_WRLOCKED.0,
             "This mutex is locked by a different thread"
         );
 
-        if *recursion > 0 {
-            *recursion -= 1;
-        } else if !(*lock)
+        let r = self.recursion.get();
+        if r > 0 {
+            self.recursion.set(r - 1);
+        } else if !self
+            .lock
             .compare_exchange(
                 __pthread_thread_id.0 | abi::LOCK_WRLOCKED.0,
                 abi::LOCK_UNLOCKED.0,
@@ -137,19 +132,20 @@ impl ReentrantMutex {
         {
             // Lock is managed by kernelspace. Call into the kernel
             // to unblock waiting threads.
-            let ret = abi::lock_unlock(lock as *mut abi::lock, abi::scope::PRIVATE);
+            let ret = abi::lock_unlock(
+                &self.lock as *const AtomicU32 as *mut abi::lock,
+                abi::scope::PRIVATE,
+            );
             assert_eq!(ret, abi::errno::SUCCESS, "Failed to unlock a mutex");
         }
     }
 
     pub unsafe fn destroy(&self) {
-        let lock = (*self.lock.get()).as_mut_ptr();
-        let recursion = (*self.recursion.get()).as_mut_ptr();
         assert_eq!(
-            (*lock).load(Ordering::Relaxed),
+            self.lock.load(Ordering::Relaxed),
             abi::LOCK_UNLOCKED.0,
             "Attempted to destroy locked mutex"
         );
-        assert_eq!(*recursion, 0, "Recursion counter invalid");
+        assert_eq!(self.recursion.get(), 0, "Recursion counter invalid");
     }
 }
diff --git a/library/std/src/sys/cloudabi/rwlock.rs b/library/std/src/sys/cloudabi/rwlock.rs
index b8af5af1d70..508de8ba47c 100644
--- a/library/std/src/sys/cloudabi/rwlock.rs
+++ b/library/std/src/sys/cloudabi/rwlock.rs
@@ -1,4 +1,3 @@
-use crate::cell::UnsafeCell;
 use crate::mem;
 use crate::mem::MaybeUninit;
 use crate::sync::atomic::{AtomicU32, Ordering};
@@ -13,28 +12,25 @@ extern "C" {
 static mut RDLOCKS_ACQUIRED: u32 = 0;
 
 pub struct RWLock {
-    lock: UnsafeCell<AtomicU32>,
+    lock: AtomicU32,
 }
 
-pub unsafe fn raw(r: &RWLock) -> *mut AtomicU32 {
-    r.lock.get()
+pub unsafe fn raw(r: &RWLock) -> &AtomicU32 {
+    &r.lock
 }
 
 unsafe impl Send for RWLock {}
 unsafe impl Sync for RWLock {}
 
-const NEW: RWLock = RWLock { lock: UnsafeCell::new(AtomicU32::new(abi::LOCK_UNLOCKED.0)) };
-
 impl RWLock {
     pub const fn new() -> RWLock {
-        NEW
+        RWLock { lock: AtomicU32::new(abi::LOCK_UNLOCKED.0) }
     }
 
     pub unsafe fn try_read(&self) -> bool {
-        let lock = self.lock.get();
         let mut old = abi::LOCK_UNLOCKED.0;
         while let Err(cur) =
-            (*lock).compare_exchange_weak(old, old + 1, Ordering::Acquire, Ordering::Relaxed)
+            self.lock.compare_exchange_weak(old, old + 1, Ordering::Acquire, Ordering::Relaxed)
         {
             if (cur & abi::LOCK_WRLOCKED.0) != 0 {
                 // Another thread already has a write lock.
@@ -61,12 +57,11 @@ impl RWLock {
     pub unsafe fn read(&self) {
         if !self.try_read() {
             // Call into the kernel to acquire a read lock.
-            let lock = self.lock.get();
             let subscription = abi::subscription {
                 type_: abi::eventtype::LOCK_RDLOCK,
                 union: abi::subscription_union {
                     lock: abi::subscription_lock {
-                        lock: lock as *mut abi::lock,
+                        lock: &self.lock as *const AtomicU32 as *mut abi::lock,
                         lock_scope: abi::scope::PRIVATE,
                     },
                 },
@@ -96,11 +91,10 @@ impl RWLock {
         assert!(RDLOCKS_ACQUIRED > 0, "Bad lock count");
         let mut old = 1;
         loop {
-            let lock = self.lock.get();
             if old == 1 | abi::LOCK_KERNEL_MANAGED.0 {
                 // Last read lock while threads are waiting. Attempt to upgrade
                 // to a write lock before calling into the kernel to unlock.
-                if let Err(cur) = (*lock).compare_exchange_weak(
+                if let Err(cur) = self.lock.compare_exchange_weak(
                     old,
                     __pthread_thread_id.0 | abi::LOCK_WRLOCKED.0 | abi::LOCK_KERNEL_MANAGED.0,
                     Ordering::Acquire,
@@ -109,7 +103,10 @@ impl RWLock {
                     old = cur;
                 } else {
                     // Call into the kernel to unlock.
-                    let ret = abi::lock_unlock(lock as *mut abi::lock, abi::scope::PRIVATE);
+                    let ret = abi::lock_unlock(
+                        &self.lock as *const AtomicU32 as *mut abi::lock,
+                        abi::scope::PRIVATE,
+                    );
                     assert_eq!(ret, abi::errno::SUCCESS, "Failed to write unlock a rwlock");
                     break;
                 }
@@ -122,7 +119,7 @@ impl RWLock {
                     0,
                     "Attempted to read-unlock a write-locked rwlock"
                 );
-                if let Err(cur) = (*lock).compare_exchange_weak(
+                if let Err(cur) = self.lock.compare_exchange_weak(
                     old,
                     old - 1,
                     Ordering::Acquire,
@@ -140,8 +137,7 @@ impl RWLock {
 
     pub unsafe fn try_write(&self) -> bool {
         // Attempt to acquire the lock.
-        let lock = self.lock.get();
-        if let Err(old) = (*lock).compare_exchange(
+        if let Err(old) = self.lock.compare_exchange(
             abi::LOCK_UNLOCKED.0,
             __pthread_thread_id.0 | abi::LOCK_WRLOCKED.0,
             Ordering::Acquire,
@@ -163,12 +159,11 @@ impl RWLock {
     pub unsafe fn write(&self) {
         if !self.try_write() {
             // Call into the kernel to acquire a write lock.
-            let lock = self.lock.get();
             let subscription = abi::subscription {
                 type_: abi::eventtype::LOCK_WRLOCK,
                 union: abi::subscription_union {
                     lock: abi::subscription_lock {
-                        lock: lock as *mut abi::lock,
+                        lock: &self.lock as *const AtomicU32 as *mut abi::lock,
                         lock_scope: abi::scope::PRIVATE,
                     },
                 },
@@ -184,14 +179,14 @@ impl RWLock {
     }
 
     pub unsafe fn write_unlock(&self) {
-        let lock = self.lock.get();
         assert_eq!(
-            (*lock).load(Ordering::Relaxed) & !abi::LOCK_KERNEL_MANAGED.0,
+            self.lock.load(Ordering::Relaxed) & !abi::LOCK_KERNEL_MANAGED.0,
             __pthread_thread_id.0 | abi::LOCK_WRLOCKED.0,
             "This rwlock is not write-locked by this thread"
         );
 
-        if !(*lock)
+        if !self
+            .lock
             .compare_exchange(
                 __pthread_thread_id.0 | abi::LOCK_WRLOCKED.0,
                 abi::LOCK_UNLOCKED.0,
@@ -202,15 +197,17 @@ impl RWLock {
         {
             // Lock is managed by kernelspace. Call into the kernel
             // to unblock waiting threads.
-            let ret = abi::lock_unlock(lock as *mut abi::lock, abi::scope::PRIVATE);
+            let ret = abi::lock_unlock(
+                &self.lock as *const AtomicU32 as *mut abi::lock,
+                abi::scope::PRIVATE,
+            );
             assert_eq!(ret, abi::errno::SUCCESS, "Failed to write unlock a rwlock");
         }
     }
 
     pub unsafe fn destroy(&self) {
-        let lock = self.lock.get();
         assert_eq!(
-            (*lock).load(Ordering::Relaxed),
+            self.lock.load(Ordering::Relaxed),
             abi::LOCK_UNLOCKED.0,
             "Attempted to destroy locked rwlock"
         );
diff --git a/library/std/src/sys/unix/os.rs b/library/std/src/sys/unix/os.rs
index c9f9ed01e12..2392238d0a1 100644
--- a/library/std/src/sys/unix/os.rs
+++ b/library/std/src/sys/unix/os.rs
@@ -470,7 +470,7 @@ pub unsafe fn environ() -> *mut *const *const c_char {
     &mut environ
 }
 
-pub unsafe fn env_lock() -> StaticMutexGuard<'static> {
+pub unsafe fn env_lock() -> StaticMutexGuard {
     // It is UB to attempt to acquire this mutex reentrantly!
     static ENV_LOCK: StaticMutex = StaticMutex::new();
     ENV_LOCK.lock()
diff --git a/library/std/src/sys/vxworks/os.rs b/library/std/src/sys/vxworks/os.rs
index 08394a8d29d..6eaec6f1e50 100644
--- a/library/std/src/sys/vxworks/os.rs
+++ b/library/std/src/sys/vxworks/os.rs
@@ -212,7 +212,7 @@ pub unsafe fn environ() -> *mut *const *const c_char {
     &mut environ
 }
 
-pub unsafe fn env_lock() -> StaticMutexGuard<'static> {
+pub unsafe fn env_lock() -> StaticMutexGuard {
     // It is UB to attempt to acquire this mutex reentrantly!
     static ENV_LOCK: StaticMutex = StaticMutex::new();
     ENV_LOCK.lock()
diff --git a/library/std/src/sys/wasm/futex_atomics.rs b/library/std/src/sys/wasm/futex_atomics.rs
new file mode 100644
index 00000000000..3d8bf42f725
--- /dev/null
+++ b/library/std/src/sys/wasm/futex_atomics.rs
@@ -0,0 +1,17 @@
+use crate::arch::wasm32;
+use crate::convert::TryInto;
+use crate::sync::atomic::AtomicI32;
+use crate::time::Duration;
+
+pub fn futex_wait(futex: &AtomicI32, expected: i32, timeout: Option<Duration>) {
+    let timeout = timeout.and_then(|t| t.as_nanos().try_into().ok()).unwrap_or(-1);
+    unsafe {
+        wasm32::memory_atomic_wait32(futex as *const AtomicI32 as *mut i32, expected, timeout);
+    }
+}
+
+pub fn futex_wake(futex: &AtomicI32) {
+    unsafe {
+        wasm32::memory_atomic_notify(futex as *const AtomicI32 as *mut i32, 1);
+    }
+}
diff --git a/library/std/src/sys/wasm/mod.rs b/library/std/src/sys/wasm/mod.rs
index 18295e1129a..11c6896f050 100644
--- a/library/std/src/sys/wasm/mod.rs
+++ b/library/std/src/sys/wasm/mod.rs
@@ -55,6 +55,8 @@ cfg_if::cfg_if! {
         pub mod mutex;
         #[path = "rwlock_atomics.rs"]
         pub mod rwlock;
+        #[path = "futex_atomics.rs"]
+        pub mod futex;
     } else {
         #[path = "../unsupported/condvar.rs"]
         pub mod condvar;
diff --git a/library/std/src/sys_common/backtrace.rs b/library/std/src/sys_common/backtrace.rs
index 1c5fbf7d701..a549770d8b3 100644
--- a/library/std/src/sys_common/backtrace.rs
+++ b/library/std/src/sys_common/backtrace.rs
@@ -8,27 +8,15 @@ use crate::io;
 use crate::io::prelude::*;
 use crate::path::{self, Path, PathBuf};
 use crate::sync::atomic::{self, Ordering};
-use crate::sys::mutex::Mutex;
+use crate::sys_common::mutex::StaticMutex;
 
 /// Max number of frames to print.
 const MAX_NB_FRAMES: usize = 100;
 
-pub fn lock() -> impl Drop {
-    struct Guard;
-    static LOCK: Mutex = Mutex::new();
-
-    impl Drop for Guard {
-        fn drop(&mut self) {
-            unsafe {
-                LOCK.unlock();
-            }
-        }
-    }
-
-    unsafe {
-        LOCK.lock();
-        Guard
-    }
+// SAFETY: Don't attempt to lock this reentrantly.
+pub unsafe fn lock() -> impl Drop {
+    static LOCK: StaticMutex = StaticMutex::new();
+    LOCK.lock()
 }
 
 /// Prints the current backtrace.
diff --git a/library/std/src/sys_common/mutex.rs b/library/std/src/sys_common/mutex.rs
index 91d919a3f9b..f3e7efb955a 100644
--- a/library/std/src/sys_common/mutex.rs
+++ b/library/std/src/sys_common/mutex.rs
@@ -3,8 +3,7 @@ use crate::sys::mutex as imp;
 /// An OS-based mutual exclusion lock, meant for use in static variables.
 ///
 /// This mutex has a const constructor ([`StaticMutex::new`]), does not
-/// implement `Drop` to cleanup resources, and causes UB when moved or used
-/// reentrantly.
+/// implement `Drop` to cleanup resources, and causes UB when used reentrantly.
 ///
 /// This mutex does not implement poisoning.
 ///
@@ -16,11 +15,6 @@ unsafe impl Sync for StaticMutex {}
 
 impl StaticMutex {
     /// Creates a new mutex for use.
-    ///
-    /// Behavior is undefined if the mutex is moved after it is
-    /// first used with any of the functions below.
-    /// Also, the behavior is undefined if this mutex is ever used reentrantly,
-    /// i.e., `lock` is called by the thread currently holding the lock.
     pub const fn new() -> Self {
         Self(imp::Mutex::new())
     }
@@ -28,19 +22,19 @@ impl StaticMutex {
     /// Calls raw_lock() and then returns an RAII guard to guarantee the mutex
     /// will be unlocked.
     ///
-    /// It is undefined behaviour to call this function while locked, or if the
-    /// mutex has been moved since the last time this was called.
+    /// It is undefined behaviour to call this function while locked by the
+    /// same thread.
     #[inline]
-    pub unsafe fn lock(&self) -> StaticMutexGuard<'_> {
+    pub unsafe fn lock(&'static self) -> StaticMutexGuard {
         self.0.lock();
         StaticMutexGuard(&self.0)
     }
 }
 
 #[must_use]
-pub struct StaticMutexGuard<'a>(&'a imp::Mutex);
+pub struct StaticMutexGuard(&'static imp::Mutex);
 
-impl Drop for StaticMutexGuard<'_> {
+impl Drop for StaticMutexGuard {
     #[inline]
     fn drop(&mut self) {
         unsafe {
diff --git a/library/std/src/sys_common/thread_parker/mod.rs b/library/std/src/sys_common/thread_parker/mod.rs
index 23c17c8e2cf..5e75ac65de4 100644
--- a/library/std/src/sys_common/thread_parker/mod.rs
+++ b/library/std/src/sys_common/thread_parker/mod.rs
@@ -1,5 +1,9 @@
 cfg_if::cfg_if! {
-    if #[cfg(any(target_os = "linux", target_os = "android"))] {
+    if #[cfg(any(
+        target_os = "linux",
+        target_os = "android",
+        all(target_arch = "wasm32", target_feature = "atomics"),
+    ))] {
         mod futex;
         pub use futex::Parker;
     } else {
diff --git a/src/librustdoc/clean/cfg.rs b/src/librustdoc/clean/cfg.rs
index c039b181178..b659f3eab43 100644
--- a/src/librustdoc/clean/cfg.rs
+++ b/src/librustdoc/clean/cfg.rs
@@ -201,6 +201,37 @@ impl Cfg {
             _ => false,
         }
     }
+
+    /// Attempt to simplify this cfg by assuming that `assume` is already known to be true, will
+    /// return `None` if simplification managed to completely eliminate any requirements from this
+    /// `Cfg`.
+    ///
+    /// See `tests::test_simplify_with` for examples.
+    pub(crate) fn simplify_with(&self, assume: &Cfg) -> Option<Cfg> {
+        if self == assume {
+            return None;
+        }
+
+        if let Cfg::All(a) = self {
+            let mut sub_cfgs: Vec<Cfg> = if let Cfg::All(b) = assume {
+                a.iter().filter(|a| !b.contains(a)).cloned().collect()
+            } else {
+                a.iter().filter(|&a| a != assume).cloned().collect()
+            };
+            let len = sub_cfgs.len();
+            return match len {
+                0 => None,
+                1 => sub_cfgs.pop(),
+                _ => Some(Cfg::All(sub_cfgs)),
+            };
+        } else if let Cfg::All(b) = assume {
+            if b.contains(self) {
+                return None;
+            }
+        }
+
+        Some(self.clone())
+    }
 }
 
 impl ops::Not for Cfg {
diff --git a/src/librustdoc/clean/cfg/tests.rs b/src/librustdoc/clean/cfg/tests.rs
index 794a7bcaf1c..3a78269f19a 100644
--- a/src/librustdoc/clean/cfg/tests.rs
+++ b/src/librustdoc/clean/cfg/tests.rs
@@ -433,3 +433,39 @@ fn test_render_long_html() {
         );
     })
 }
+
+#[test]
+fn test_simplify_with() {
+    // This is a tiny subset of things that could be simplified, but it likely covers 90% of
+    // real world usecases well.
+    with_default_session_globals(|| {
+        let foo = word_cfg("foo");
+        let bar = word_cfg("bar");
+        let baz = word_cfg("baz");
+        let quux = word_cfg("quux");
+
+        let foobar = Cfg::All(vec![foo.clone(), bar.clone()]);
+        let barbaz = Cfg::All(vec![bar.clone(), baz.clone()]);
+        let foobarbaz = Cfg::All(vec![foo.clone(), bar.clone(), baz.clone()]);
+        let bazquux = Cfg::All(vec![baz.clone(), quux.clone()]);
+
+        // Unrelated cfgs don't affect each other
+        assert_eq!(foo.simplify_with(&bar).as_ref(), Some(&foo));
+        assert_eq!(foobar.simplify_with(&bazquux).as_ref(), Some(&foobar));
+
+        // Identical cfgs are eliminated
+        assert_eq!(foo.simplify_with(&foo), None);
+        assert_eq!(foobar.simplify_with(&foobar), None);
+
+        // Multiple cfgs eliminate a single assumed cfg
+        assert_eq!(foobar.simplify_with(&foo).as_ref(), Some(&bar));
+        assert_eq!(foobar.simplify_with(&bar).as_ref(), Some(&foo));
+
+        // A single cfg is eliminated by multiple assumed cfg containing it
+        assert_eq!(foo.simplify_with(&foobar), None);
+
+        // Multiple cfgs eliminate the matching subset of multiple assumed cfg
+        assert_eq!(foobar.simplify_with(&barbaz).as_ref(), Some(&foo));
+        assert_eq!(foobar.simplify_with(&foobarbaz), None);
+    });
+}
diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs
index f81ea0f6d46..22ae7af617f 100644
--- a/src/librustdoc/html/render/mod.rs
+++ b/src/librustdoc/html/render/mod.rs
@@ -1763,11 +1763,11 @@ crate fn shorten(s: String) -> String {
     }
 }
 
-fn document(w: &mut Buffer, cx: &Context, item: &clean::Item) {
+fn document(w: &mut Buffer, cx: &Context, item: &clean::Item, parent: Option<&clean::Item>) {
     if let Some(ref name) = item.name {
         info!("Documenting {}", name);
     }
-    document_stability(w, cx, item, false);
+    document_stability(w, cx, item, false, parent);
     document_full(w, item, cx, "", false);
 }
 
@@ -1851,8 +1851,14 @@ fn document_full(w: &mut Buffer, item: &clean::Item, cx: &Context, prefix: &str,
     }
 }
 
-fn document_stability(w: &mut Buffer, cx: &Context, item: &clean::Item, is_hidden: bool) {
-    let stabilities = short_stability(item, cx);
+fn document_stability(
+    w: &mut Buffer,
+    cx: &Context,
+    item: &clean::Item,
+    is_hidden: bool,
+    parent: Option<&clean::Item>,
+) {
+    let stabilities = short_stability(item, cx, parent);
     if !stabilities.is_empty() {
         write!(w, "<div class='stability{}'>", if is_hidden { " hidden" } else { "" });
         for stability in stabilities {
@@ -1952,7 +1958,7 @@ pub fn compare_names(mut lhs: &str, mut rhs: &str) -> Ordering {
 }
 
 fn item_module(w: &mut Buffer, cx: &Context, item: &clean::Item, items: &[clean::Item]) {
-    document(w, cx, item);
+    document(w, cx, item, None);
 
     let mut indices = (0..items.len()).filter(|i| !items[*i].is_stripped()).collect::<Vec<usize>>();
 
@@ -2111,7 +2117,7 @@ fn item_module(w: &mut Buffer, cx: &Context, item: &clean::Item, items: &[clean:
                          <td class='docblock-short'>{stab_tags}{docs}</td>\
                      </tr>",
                     name = *myitem.name.as_ref().unwrap(),
-                    stab_tags = stability_tags(myitem),
+                    stab_tags = stability_tags(myitem, item),
                     docs = MarkdownSummaryLine(doc_value, &myitem.links()).into_string(),
                     class = myitem.type_(),
                     add = add,
@@ -2135,7 +2141,7 @@ fn item_module(w: &mut Buffer, cx: &Context, item: &clean::Item, items: &[clean:
 
 /// Render the stability and deprecation tags that are displayed in the item's summary at the
 /// module level.
-fn stability_tags(item: &clean::Item) -> String {
+fn stability_tags(item: &clean::Item, parent: &clean::Item) -> String {
     let mut tags = String::new();
 
     fn tag_html(class: &str, title: &str, contents: &str) -> String {
@@ -2159,7 +2165,13 @@ fn stability_tags(item: &clean::Item) -> String {
         tags += &tag_html("unstable", "", "Experimental");
     }
 
-    if let Some(ref cfg) = item.attrs.cfg {
+    let cfg = match (&item.attrs.cfg, parent.attrs.cfg.as_ref()) {
+        (Some(cfg), Some(parent_cfg)) => cfg.simplify_with(parent_cfg),
+        (cfg, _) => cfg.as_deref().cloned(),
+    };
+
+    debug!("Portability {:?} - {:?} = {:?}", item.attrs.cfg, parent.attrs.cfg, cfg);
+    if let Some(ref cfg) = cfg {
         tags += &tag_html("portability", &cfg.render_long_plain(), &cfg.render_short_html());
     }
 
@@ -2168,7 +2180,7 @@ fn stability_tags(item: &clean::Item) -> String {
 
 /// Render the stability and/or deprecation warning that is displayed at the top of the item's
 /// documentation.
-fn short_stability(item: &clean::Item, cx: &Context) -> Vec<String> {
+fn short_stability(item: &clean::Item, cx: &Context, parent: Option<&clean::Item>) -> Vec<String> {
     let mut stability = vec![];
     let error_codes = cx.shared.codes;
 
@@ -2243,7 +2255,18 @@ fn short_stability(item: &clean::Item, cx: &Context) -> Vec<String> {
         stability.push(format!("<div class='stab unstable'>{}</div>", message));
     }
 
-    if let Some(ref cfg) = item.attrs.cfg {
+    let cfg = match (&item.attrs.cfg, parent.and_then(|p| p.attrs.cfg.as_ref())) {
+        (Some(cfg), Some(parent_cfg)) => cfg.simplify_with(parent_cfg),
+        (cfg, _) => cfg.as_deref().cloned(),
+    };
+
+    debug!(
+        "Portability {:?} - {:?} = {:?}",
+        item.attrs.cfg,
+        parent.and_then(|p| p.attrs.cfg.as_ref()),
+        cfg
+    );
+    if let Some(cfg) = cfg {
         stability.push(format!("<div class='stab portability'>{}</div>", cfg.render_long_html()));
     }
 
@@ -2282,7 +2305,7 @@ fn item_constant(w: &mut Buffer, cx: &Context, it: &clean::Item, c: &clean::Cons
     }
 
     write!(w, "</pre>");
-    document(w, cx, it)
+    document(w, cx, it, None)
 }
 
 fn item_static(w: &mut Buffer, cx: &Context, it: &clean::Item, s: &clean::Static) {
@@ -2296,7 +2319,7 @@ fn item_static(w: &mut Buffer, cx: &Context, it: &clean::Item, s: &clean::Static
         name = it.name.as_ref().unwrap(),
         typ = s.type_.print()
     );
-    document(w, cx, it)
+    document(w, cx, it, None)
 }
 
 fn item_function(w: &mut Buffer, cx: &Context, it: &clean::Item, f: &clean::Function) {
@@ -2329,7 +2352,7 @@ fn item_function(w: &mut Buffer, cx: &Context, it: &clean::Item, f: &clean::Func
             .print(),
         spotlight = spotlight_decl(&f.decl),
     );
-    document(w, cx, it)
+    document(w, cx, it, None)
 }
 
 fn render_implementor(
@@ -2354,6 +2377,7 @@ fn render_implementor(
         w,
         cx,
         implementor,
+        None,
         AssocItemLink::Anchor(None),
         RenderMode::Normal,
         implementor.impl_item.stable_since().as_deref(),
@@ -2383,6 +2407,7 @@ fn render_impls(
                 &mut buffer,
                 cx,
                 i,
+                Some(containing_item),
                 assoc_link,
                 RenderMode::Normal,
                 containing_item.stable_since().as_deref(),
@@ -2502,7 +2527,7 @@ fn item_trait(w: &mut Buffer, cx: &Context, it: &clean::Item, t: &clean::Trait,
     });
 
     // Trait documentation
-    document(w, cx, it);
+    document(w, cx, it, None);
 
     fn write_small_section_header(w: &mut Buffer, id: &str, title: &str, extra_content: &str) {
         write!(
@@ -2520,6 +2545,7 @@ fn item_trait(w: &mut Buffer, cx: &Context, it: &clean::Item, t: &clean::Trait,
 
     fn trait_item(w: &mut Buffer, cx: &Context, m: &clean::Item, t: &clean::Item) {
         let name = m.name.as_ref().unwrap();
+        info!("Documenting {} on {}", name, t.name.as_deref().unwrap_or_default());
         let item_type = m.type_();
         let id = cx.derive_id(format!("{}.{}", item_type, name));
         write!(w, "<h3 id='{id}' class='method'><code>", id = id,);
@@ -2527,7 +2553,7 @@ fn item_trait(w: &mut Buffer, cx: &Context, it: &clean::Item, t: &clean::Trait,
         write!(w, "</code>");
         render_stability_since(w, m, t);
         write!(w, "</h3>");
-        document(w, cx, m);
+        document(w, cx, m, Some(t));
     }
 
     if !types.is_empty() {
@@ -2628,6 +2654,7 @@ fn item_trait(w: &mut Buffer, cx: &Context, it: &clean::Item, t: &clean::Trait,
                     w,
                     cx,
                     &implementor,
+                    None,
                     assoc_link,
                     RenderMode::Normal,
                     implementor.impl_item.stable_since().as_deref(),
@@ -2890,7 +2917,7 @@ fn item_struct(w: &mut Buffer, cx: &Context, it: &clean::Item, s: &clean::Struct
         write!(w, "</pre>")
     });
 
-    document(w, cx, it);
+    document(w, cx, it, None);
     let mut fields = s
         .fields
         .iter()
@@ -2925,7 +2952,7 @@ fn item_struct(w: &mut Buffer, cx: &Context, it: &clean::Item, s: &clean::Struct
                     name = field.name.as_ref().unwrap(),
                     ty = ty.print()
                 );
-                document(w, cx, field);
+                document(w, cx, field, Some(it));
             }
         }
     }
@@ -2940,7 +2967,7 @@ fn item_union(w: &mut Buffer, cx: &Context, it: &clean::Item, s: &clean::Union,
         write!(w, "</pre>")
     });
 
-    document(w, cx, it);
+    document(w, cx, it, None);
     let mut fields = s
         .fields
         .iter()
@@ -2972,7 +2999,7 @@ fn item_union(w: &mut Buffer, cx: &Context, it: &clean::Item, s: &clean::Union,
             if let Some(stability_class) = field.stability_class() {
                 write!(w, "<span class='stab {stab}'></span>", stab = stability_class);
             }
-            document(w, cx, field);
+            document(w, cx, field, Some(it));
         }
     }
     render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All, cache)
@@ -3027,7 +3054,7 @@ fn item_enum(w: &mut Buffer, cx: &Context, it: &clean::Item, e: &clean::Enum, ca
         write!(w, "</pre>")
     });
 
-    document(w, cx, it);
+    document(w, cx, it, None);
     if !e.variants.is_empty() {
         write!(
             w,
@@ -3060,7 +3087,7 @@ fn item_enum(w: &mut Buffer, cx: &Context, it: &clean::Item, e: &clean::Enum, ca
                 }
             }
             write!(w, "</code></div>");
-            document(w, cx, variant);
+            document(w, cx, variant, Some(it));
             document_non_exhaustive(w, variant);
 
             use crate::clean::{Variant, VariantKind};
@@ -3095,7 +3122,7 @@ fn item_enum(w: &mut Buffer, cx: &Context, it: &clean::Item, e: &clean::Enum, ca
                             f = field.name.as_ref().unwrap(),
                             t = ty.print()
                         );
-                        document(w, cx, field);
+                        document(w, cx, field, Some(variant));
                     }
                 }
                 write!(w, "</div></div>");
@@ -3293,6 +3320,10 @@ fn render_assoc_items(
     what: AssocItemRender<'_>,
     cache: &Cache,
 ) {
+    info!(
+        "Documenting associated items of {}",
+        containing_item.name.as_deref().unwrap_or_default()
+    );
     let v = match cache.impls.get(&it) {
         Some(v) => v,
         None => return,
@@ -3327,6 +3358,7 @@ fn render_assoc_items(
                 w,
                 cx,
                 i,
+                Some(containing_item),
                 AssocItemLink::Anchor(None),
                 render_mode,
                 containing_item.stable_since().as_deref(),
@@ -3518,6 +3550,7 @@ fn render_impl(
     w: &mut Buffer,
     cx: &Context,
     i: &Impl,
+    parent: Option<&clean::Item>,
     link: AssocItemLink<'_>,
     render_mode: RenderMode,
     outer_version: Option<&str>,
@@ -3600,6 +3633,7 @@ fn render_impl(
         w: &mut Buffer,
         cx: &Context,
         item: &clean::Item,
+        parent: Option<&clean::Item>,
         link: AssocItemLink<'_>,
         render_mode: RenderMode,
         is_default_item: bool,
@@ -3684,7 +3718,7 @@ fn render_impl(
                     if let Some(it) = t.items.iter().find(|i| i.name == item.name) {
                         // We need the stability of the item from the trait
                         // because impls can't have a stability.
-                        document_stability(w, cx, it, is_hidden);
+                        document_stability(w, cx, it, is_hidden, parent);
                         if item.doc_value().is_some() {
                             document_full(w, item, cx, "", is_hidden);
                         } else if show_def_docs {
@@ -3694,13 +3728,13 @@ fn render_impl(
                         }
                     }
                 } else {
-                    document_stability(w, cx, item, is_hidden);
+                    document_stability(w, cx, item, is_hidden, parent);
                     if show_def_docs {
                         document_full(w, item, cx, "", is_hidden);
                     }
                 }
             } else {
-                document_stability(w, cx, item, is_hidden);
+                document_stability(w, cx, item, is_hidden, parent);
                 if show_def_docs {
                     document_short(w, item, link, "", is_hidden);
                 }
@@ -3717,6 +3751,7 @@ fn render_impl(
             w,
             cx,
             trait_item,
+            parent,
             link,
             render_mode,
             false,
@@ -3732,6 +3767,7 @@ fn render_impl(
         cx: &Context,
         t: &clean::Trait,
         i: &clean::Impl,
+        parent: Option<&clean::Item>,
         render_mode: RenderMode,
         outer_version: Option<&str>,
         show_def_docs: bool,
@@ -3749,6 +3785,7 @@ fn render_impl(
                 w,
                 cx,
                 trait_item,
+                parent,
                 assoc_link,
                 render_mode,
                 true,
@@ -3771,6 +3808,7 @@ fn render_impl(
                 cx,
                 t,
                 &i.inner_impl(),
+                parent,
                 render_mode,
                 outer_version,
                 show_def_docs,
@@ -3799,7 +3837,7 @@ fn item_opaque_ty(
         bounds = bounds(&t.bounds, false)
     );
 
-    document(w, cx, it);
+    document(w, cx, it, None);
 
     // Render any items associated directly to this alias, as otherwise they
     // won't be visible anywhere in the docs. It would be nice to also show
@@ -3826,7 +3864,7 @@ fn item_trait_alias(
         bounds(&t.bounds, true)
     );
 
-    document(w, cx, it);
+    document(w, cx, it, None);
 
     // Render any items associated directly to this alias, as otherwise they
     // won't be visible anywhere in the docs. It would be nice to also show
@@ -3847,7 +3885,7 @@ fn item_typedef(w: &mut Buffer, cx: &Context, it: &clean::Item, t: &clean::Typed
         type_ = t.type_.print()
     );
 
-    document(w, cx, it);
+    document(w, cx, it, None);
 
     // Render any items associated directly to this alias, as otherwise they
     // won't be visible anywhere in the docs. It would be nice to also show
@@ -3866,7 +3904,7 @@ fn item_foreign_type(w: &mut Buffer, cx: &Context, it: &clean::Item, cache: &Cac
         it.name.as_ref().unwrap(),
     );
 
-    document(w, cx, it);
+    document(w, cx, it, None);
 
     render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All, cache)
 }
@@ -4511,7 +4549,7 @@ fn item_macro(w: &mut Buffer, cx: &Context, it: &clean::Item, t: &clean::Macro)
             None,
         ))
     });
-    document(w, cx, it)
+    document(w, cx, it, None)
 }
 
 fn item_proc_macro(w: &mut Buffer, cx: &Context, it: &clean::Item, m: &clean::ProcMacro) {
@@ -4541,16 +4579,16 @@ fn item_proc_macro(w: &mut Buffer, cx: &Context, it: &clean::Item, m: &clean::Pr
             write!(w, "</pre>");
         }
     }
-    document(w, cx, it)
+    document(w, cx, it, None)
 }
 
 fn item_primitive(w: &mut Buffer, cx: &Context, it: &clean::Item, cache: &Cache) {
-    document(w, cx, it);
+    document(w, cx, it, None);
     render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All, cache)
 }
 
 fn item_keyword(w: &mut Buffer, cx: &Context, it: &clean::Item) {
-    document(w, cx, it)
+    document(w, cx, it, None)
 }
 
 crate const BASIC_KEYWORDS: &str = "rust, rustlang, rust-lang";
diff --git a/src/test/rustdoc/doc-cfg-simplification.rs b/src/test/rustdoc/doc-cfg-simplification.rs
new file mode 100644
index 00000000000..633df661be0
--- /dev/null
+++ b/src/test/rustdoc/doc-cfg-simplification.rs
@@ -0,0 +1,182 @@
+#![crate_name = "globuliferous"]
+#![feature(doc_cfg)]
+
+// @has 'globuliferous/index.html'
+// @count   - '//*[@class="stab portability"]' 1
+// @matches - '//*[@class="stab portability"]' '^ratel$'
+
+// @has 'globuliferous/ratel/index.html'
+// @count   - '//*[@class="stab portability"]' 8
+// @matches - '//*[@class="stab portability"]' 'crate feature ratel'
+// @matches - '//*[@class="stab portability"]' '^zoonosology$'
+// @matches - '//*[@class="stab portability"]' '^yusho$'
+// @matches - '//*[@class="stab portability"]' '^nunciative$'
+// @matches - '//*[@class="stab portability"]' '^thionic$'
+// @matches - '//*[@class="stab portability"]' '^zincic$'
+// @matches - '//*[@class="stab portability"]' '^cosmotellurian$'
+// @matches - '//*[@class="stab portability"]' '^aposiopesis$'
+#[doc(cfg(feature = "ratel"))]
+pub mod ratel {
+    // @has 'globuliferous/ratel/fn.ovicide.html'
+    // @count   - '//*[@class="stab portability"]' 1
+    // @matches - '//*[@class="stab portability"]' 'crate feature ratel'
+    pub fn ovicide() {}
+
+    // @has 'globuliferous/ratel/fn.zoonosology.html'
+    // @count   - '//*[@class="stab portability"]' 1
+    // @matches - '//*[@class="stab portability"]' 'crate features ratel and zoonosology'
+    #[doc(cfg(feature = "zoonosology"))]
+    pub fn zoonosology() {}
+
+    // @has 'globuliferous/ratel/constant.DIAGRAPHICS.html'
+    // @count   - '//*[@class="stab portability"]' 1
+    // @matches - '//*[@class="stab portability"]' 'crate feature ratel'
+    pub const DIAGRAPHICS: () = ();
+
+    // @has 'globuliferous/ratel/constant.YUSHO.html'
+    // @count   - '//*[@class="stab portability"]' 1
+    // @matches - '//*[@class="stab portability"]' 'crate features ratel and yusho'
+    #[doc(cfg(feature = "yusho"))]
+    pub const YUSHO: () = ();
+
+    // @has 'globuliferous/ratel/static.KEYBUGLE.html'
+    // @count   - '//*[@class="stab portability"]' 1
+    // @matches - '//*[@class="stab portability"]' 'crate feature ratel'
+    pub static KEYBUGLE: () = ();
+
+    // @has 'globuliferous/ratel/static.NUNCIATIVE.html'
+    // @count   - '//*[@class="stab portability"]' 1
+    // @matches - '//*[@class="stab portability"]' 'crate features ratel and nunciative'
+    #[doc(cfg(feature = "nunciative"))]
+    pub static NUNCIATIVE: () = ();
+
+    // @has 'globuliferous/ratel/type.Wrick.html'
+    // @count   - '//*[@class="stab portability"]' 1
+    // @matches - '//*[@class="stab portability"]' 'crate feature ratel'
+    pub type Wrick = ();
+
+    // @has 'globuliferous/ratel/type.Thionic.html'
+    // @count   - '//*[@class="stab portability"]' 1
+    // @matches - '//*[@class="stab portability"]' 'crate features ratel and thionic'
+    #[doc(cfg(feature = "thionic"))]
+    pub type Thionic = ();
+
+    // @has 'globuliferous/ratel/struct.Eventration.html'
+    // @count   - '//*[@class="stab portability"]' 1
+    // @matches - '//*[@class="stab portability"]' 'crate feature ratel'
+    pub struct Eventration;
+
+    // @has 'globuliferous/ratel/struct.Zincic.html'
+    // @count   - '//*[@class="stab portability"]' 2
+    // @matches - '//*[@class="stab portability"]' 'crate features ratel and zincic'
+    // @matches - '//*[@class="stab portability"]' 'crate feature rutherford'
+    #[doc(cfg(feature = "zincic"))]
+    pub struct Zincic {
+        pub rectigrade: (),
+
+        #[doc(cfg(feature = "rutherford"))]
+        pub rutherford: (),
+    }
+
+    // @has 'globuliferous/ratel/enum.Cosmotellurian.html'
+    // @count   - '//*[@class="stab portability"]' 10
+    // @matches - '//*[@class="stab portability"]' 'crate features ratel and cosmotellurian'
+    // @matches - '//*[@class="stab portability"]' 'crate feature biotaxy'
+    // @matches - '//*[@class="stab portability"]' 'crate feature xiphopagus'
+    // @matches - '//*[@class="stab portability"]' 'crate feature juxtapositive'
+    // @matches - '//*[@class="stab portability"]' 'crate feature fuero'
+    // @matches - '//*[@class="stab portability"]' 'crate feature palaeophile'
+    // @matches - '//*[@class="stab portability"]' 'crate feature broadcloth'
+    // @matches - '//*[@class="stab portability"]' 'crate features broadcloth and xanthocomic'
+    // @matches - '//*[@class="stab portability"]' 'crate feature broadcloth'
+    // @matches - '//*[@class="stab portability"]' 'crate features broadcloth and whosoever'
+    #[doc(cfg(feature = "cosmotellurian"))]
+    pub enum Cosmotellurian {
+        Groundsel {
+            jagger: (),
+
+            #[doc(cfg(feature = "xiphopagus"))]
+            xiphopagus: (),
+        },
+
+        #[doc(cfg(feature = "biotaxy"))]
+        Biotaxy {
+            glossography: (),
+
+            #[doc(cfg(feature = "juxtapositive"))]
+            juxtapositive: (),
+        },
+    }
+
+    impl Cosmotellurian {
+        pub fn uxoricide() {}
+
+        #[doc(cfg(feature = "fuero"))]
+        pub fn fuero() {}
+
+        pub const MAMELLE: () = ();
+
+        #[doc(cfg(feature = "palaeophile"))]
+        pub const PALAEOPHILE: () = ();
+    }
+
+    #[doc(cfg(feature = "broadcloth"))]
+    impl Cosmotellurian {
+        pub fn trabeculated() {}
+
+        #[doc(cfg(feature = "xanthocomic"))]
+        pub fn xanthocomic() {}
+
+        pub const BRACHIFEROUS: () = ();
+
+        #[doc(cfg(feature = "whosoever"))]
+        pub const WHOSOEVER: () = ();
+    }
+
+    // @has 'globuliferous/ratel/trait.Gnotobiology.html'
+    // @count   - '//*[@class="stab portability"]' 4
+    // @matches - '//*[@class="stab portability"]' 'crate feature ratel'
+    // @matches - '//*[@class="stab portability"]' 'crate feature unzymotic'
+    // @matches - '//*[@class="stab portability"]' 'crate feature summate'
+    // @matches - '//*[@class="stab portability"]' 'crate feature unctuous'
+    pub trait Gnotobiology {
+        const XYLOTHERAPY: ();
+
+        #[doc(cfg(feature = "unzymotic"))]
+        const UNZYMOTIC: ();
+
+        type Lepadoid;
+
+        #[doc(cfg(feature = "summate"))]
+        type Summate;
+
+        fn decalcomania();
+
+        #[doc(cfg(feature = "unctuous"))]
+        fn unctuous();
+    }
+
+    // @has 'globuliferous/ratel/trait.Aposiopesis.html'
+    // @count   - '//*[@class="stab portability"]' 4
+    // @matches - '//*[@class="stab portability"]' 'crate features ratel and aposiopesis'
+    // @matches - '//*[@class="stab portability"]' 'crate feature umbracious'
+    // @matches - '//*[@class="stab portability"]' 'crate feature uakari'
+    // @matches - '//*[@class="stab portability"]' 'crate feature rotograph'
+    #[doc(cfg(feature = "aposiopesis"))]
+    pub trait Aposiopesis {
+        const REDHIBITION: ();
+
+        #[doc(cfg(feature = "umbracious"))]
+        const UMBRACIOUS: ();
+
+        type Ophthalmoscope;
+
+        #[doc(cfg(feature = "uakari"))]
+        type Uakari;
+
+        fn meseems();
+
+        #[doc(cfg(feature = "rotograph"))]
+        fn rotograph();
+    }
+}
diff --git a/src/test/rustdoc/doc-cfg.rs b/src/test/rustdoc/doc-cfg.rs
index aa407b7e926..d7041ee2f1a 100644
--- a/src/test/rustdoc/doc-cfg.rs
+++ b/src/test/rustdoc/doc-cfg.rs
@@ -10,9 +10,8 @@ pub struct Portable;
 // @has doc_cfg/unix_only/index.html \
 //  '//*[@id="main"]/*[@class="stability"]/*[@class="stab portability"]' \
 //  'This is supported on Unix only.'
-// @matches - '//*[@class="module-item"]//*[@class="stab portability"]' '\AUnix\Z'
-// @matches - '//*[@class="module-item"]//*[@class="stab portability"]' '\AUnix and ARM\Z'
-// @count - '//*[@class="stab portability"]' 3
+// @matches - '//*[@class="module-item"]//*[@class="stab portability"]' '\AARM\Z'
+// @count - '//*[@class="stab portability"]' 2
 #[doc(cfg(unix))]
 pub mod unix_only {
     // @has doc_cfg/unix_only/fn.unix_only_function.html \
@@ -26,7 +25,7 @@ pub mod unix_only {
     // @has doc_cfg/unix_only/trait.ArmOnly.html \
     //  '//*[@id="main"]/*[@class="stability"]/*[@class="stab portability"]' \
     //  'This is supported on Unix and ARM only.'
-    // @count - '//*[@class="stab portability"]' 3
+    // @count - '//*[@class="stab portability"]' 2
     #[doc(cfg(target_arch = "arm"))]
     pub trait ArmOnly {
         fn unix_and_arm_only_function();
diff --git a/src/test/rustdoc/duplicate-cfg.rs b/src/test/rustdoc/duplicate-cfg.rs
index 47ba362c977..7b938af3c7d 100644
--- a/src/test/rustdoc/duplicate-cfg.rs
+++ b/src/test/rustdoc/duplicate-cfg.rs
@@ -14,45 +14,41 @@
 pub struct Foo;
 
 // @has 'foo/bar/index.html'
-// @matches '-' '//*[@class="module-item"]//*[@class="stab portability"]' '^sync$'
-// @has '-' '//*[@class="module-item"]//*[@class="stab portability"]/@title' 'This is supported on crate feature `sync` only'
-
-// @has 'foo/bar/struct.Bar.html'
 // @has '-' '//*[@class="stab portability"]' 'This is supported on crate feature sync only.'
 #[doc(cfg(feature = "sync"))]
 pub mod bar {
+    // @has 'foo/bar/struct.Bar.html'
+    // @has '-' '//*[@class="stab portability"]' 'This is supported on crate feature sync only.'
     #[doc(cfg(feature = "sync"))]
     pub struct Bar;
 }
 
 // @has 'foo/baz/index.html'
-// @matches '-' '//*[@class="module-item"]//*[@class="stab portability"]' '^sync and send$'
-// @has '-' '//*[@class="module-item"]//*[@class="stab portability"]/@title' 'This is supported on crate features `sync` and `send` only'
-
-// @has 'foo/baz/struct.Baz.html'
 // @has '-' '//*[@class="stab portability"]' 'This is supported on crate features sync and send only.'
 #[doc(cfg(all(feature = "sync", feature = "send")))]
 pub mod baz {
+    // @has 'foo/baz/struct.Baz.html'
+    // @has '-' '//*[@class="stab portability"]' 'This is supported on crate features sync and send only.'
     #[doc(cfg(feature = "sync"))]
     pub struct Baz;
 }
 
-// @has 'foo/qux/struct.Qux.html'
-// @has '-' '//*[@class="stab portability"]' 'This is supported on crate features sync and send only.'
+// @has 'foo/qux/index.html'
+// @has '-' '//*[@class="stab portability"]' 'This is supported on crate feature sync only.'
 #[doc(cfg(feature = "sync"))]
 pub mod qux {
+    // @has 'foo/qux/struct.Qux.html'
+    // @has '-' '//*[@class="stab portability"]' 'This is supported on crate features sync and send only.'
     #[doc(cfg(all(feature = "sync", feature = "send")))]
     pub struct Qux;
 }
 
 // @has 'foo/quux/index.html'
-// @matches '-' '//*[@class="module-item"]//*[@class="stab portability"]' '^sync and send and foo and bar$'
-// @has '-' '//*[@class="module-item"]//*[@class="stab portability"]/@title' 'This is supported on crate feature `sync` and crate feature `send` and `foo` and `bar` only'
-
-// @has 'foo/quux/struct.Quux.html'
-// @has '-' '//*[@class="stab portability"]' 'This is supported on crate feature sync and crate feature send and foo and bar only.'
+// @has '-' '//*[@class="stab portability"]' 'This is supported on crate feature sync and crate feature send and foo only.'
 #[doc(cfg(all(feature = "sync", feature = "send", foo)))]
 pub mod quux {
+    // @has 'foo/quux/struct.Quux.html'
+    // @has '-' '//*[@class="stab portability"]' 'This is supported on crate feature sync and crate feature send and foo and bar only.'
     #[doc(cfg(all(feature = "send", feature = "sync", bar)))]
     pub struct Quux;
 }
diff --git a/src/test/ui/arg-count-mismatch.stderr b/src/test/ui/arg-count-mismatch.stderr
index 7bc06134a69..d0577e4864a 100644
--- a/src/test/ui/arg-count-mismatch.stderr
+++ b/src/test/ui/arg-count-mismatch.stderr
@@ -1,13 +1,16 @@
 error[E0061]: this function takes 1 argument but 0 arguments were supplied
   --> $DIR/arg-count-mismatch.rs:5:28
    |
-LL | fn f(x: isize) { }
-   | -------------- defined here
-LL | 
 LL | fn main() { let i: (); i = f(); }
    |                            ^-- supplied 0 arguments
    |                            |
    |                            expected 1 argument
+   |
+note: function defined here
+  --> $DIR/arg-count-mismatch.rs:3:4
+   |
+LL | fn f(x: isize) { }
+   |    ^ --------
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/borrowck/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs b/src/test/ui/borrowck/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs
index b67d494866b..97f96ab6929 100644
--- a/src/test/ui/borrowck/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs
+++ b/src/test/ui/borrowck/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs
@@ -3,8 +3,6 @@
 #![feature(or_patterns)]
 #![feature(box_patterns)]
 
-#![feature(move_ref_pattern)]
-
 enum Test {
     Foo,
     Bar,
diff --git a/src/test/ui/borrowck/bindings-after-at-or-patterns-slice-patterns-box-patterns.stderr b/src/test/ui/borrowck/bindings-after-at-or-patterns-slice-patterns-box-patterns.stderr
index 1bf81589275..96e313b39ed 100644
--- a/src/test/ui/borrowck/bindings-after-at-or-patterns-slice-patterns-box-patterns.stderr
+++ b/src/test/ui/borrowck/bindings-after-at-or-patterns-slice-patterns-box-patterns.stderr
@@ -1,5 +1,5 @@
 error: cannot borrow value as mutable because it is also borrowed as immutable
-  --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:40:9
+  --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:38:9
    |
 LL |         ref foo @ [.., ref mut bar] => (),
    |         -------^^^^^^^^-----------^
@@ -8,7 +8,7 @@ LL |         ref foo @ [.., ref mut bar] => (),
    |         immutable borrow, by `foo`, occurs here
 
 error: cannot borrow value as mutable because it is also borrowed as immutable
-  --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:124:9
+  --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:122:9
    |
 LL |         ref foo @ Some(box ref mut s) => (),
    |         -------^^^^^^^^^^^^---------^
@@ -17,7 +17,7 @@ LL |         ref foo @ Some(box ref mut s) => (),
    |         immutable borrow, by `foo`, occurs here
 
 error[E0382]: borrow of moved value: `x`
-  --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:22:5
+  --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:20:5
    |
 LL | fn bindings_after_at_slice_patterns_move_binding(x: [String; 4]) {
    |                                                  - move occurs because `x` has type `[String; 4]`, which does not implement the `Copy` trait
@@ -29,7 +29,7 @@ LL |     &x;
    |     ^^ value borrowed here after move
 
 error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable
-  --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:32:5
+  --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:30:5
    |
 LL |         ref mut foo @ [.., _] => Some(foo),
    |         --------------------- mutable borrow occurs here
@@ -41,7 +41,7 @@ LL |     drop(r);
    |          - mutable borrow later used here
 
 error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable
-  --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:54:5
+  --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:52:5
    |
 LL |         [ref foo @ .., ref bar] => Some(foo),
    |          ------------ immutable borrow occurs here
@@ -53,7 +53,7 @@ LL |     drop(r);
    |          - immutable borrow later used here
 
 error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable
-  --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:66:5
+  --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:64:5
    |
 LL |         ref foo @ [.., ref bar] => Some(foo),
    |         ----------------------- immutable borrow occurs here
@@ -65,7 +65,7 @@ LL |     drop(r);
    |          - immutable borrow later used here
 
 error[E0382]: borrow of moved value: `x`
-  --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:80:5
+  --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:78:5
    |
 LL | fn bindings_after_at_or_patterns_move(x: Option<Test>) {
    |                                       - move occurs because `x` has type `Option<Test>`, which does not implement the `Copy` trait
@@ -80,7 +80,7 @@ LL |     &x;
    |     ^^ value borrowed here after move
 
 error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable
-  --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:90:5
+  --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:88:5
    |
 LL |         ref foo @ Some(Test::Foo | Test::Bar) => Some(foo),
    |         ------------------------------------- immutable borrow occurs here
@@ -92,7 +92,7 @@ LL |     drop(r);
    |          - immutable borrow later used here
 
 error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable
-  --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:102:5
+  --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:100:5
    |
 LL |         ref mut foo @ Some(Test::Foo | Test::Bar) => Some(foo),
    |         ----------------------------------------- mutable borrow occurs here
@@ -104,7 +104,7 @@ LL |     drop(r);
    |          - mutable borrow later used here
 
 error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable
-  --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:116:5
+  --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:114:5
    |
 LL |         ref foo @ Some(box ref s) => Some(foo),
    |         ------------------------- immutable borrow occurs here
@@ -116,7 +116,7 @@ LL |     drop(r);
    |          - immutable borrow later used here
 
 error[E0382]: borrow of moved value: `x`
-  --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:138:5
+  --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:136:5
    |
 LL | fn bindings_after_at_slice_patterns_or_patterns_moves(x: [Option<Test>; 4]) {
    |                                                       - move occurs because `x` has type `[Option<Test>; 4]`, which does not implement the `Copy` trait
@@ -131,7 +131,7 @@ LL |     &x;
    |     ^^ value borrowed here after move
 
 error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable
-  --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:148:5
+  --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:146:5
    |
 LL |         ref a @ [ref b @ .., Some(Test::Foo | Test::Bar)] => Some(a),
    |         ------------------------------------------------- immutable borrow occurs here
@@ -143,7 +143,7 @@ LL |     drop(r);
    |          - immutable borrow later used here
 
 error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable
-  --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:160:5
+  --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:158:5
    |
 LL |         ref a @ [ref b @ .., Some(Test::Foo | Test::Bar)] => Some(b),
    |                  ---------- immutable borrow occurs here
@@ -155,7 +155,7 @@ LL |     drop(r);
    |          - immutable borrow later used here
 
 error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable
-  --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:174:5
+  --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:172:5
    |
 LL |         [_, ref a @ Some(box ref b), ..] => Some(a),
    |             ----------------------- immutable borrow occurs here
@@ -167,7 +167,7 @@ LL |     drop(r);
    |          - immutable borrow later used here
 
 error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable
-  --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:190:5
+  --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:188:5
    |
 LL |         [_, ref a @ Some(box Test::Foo | box Test::Bar), ..] => Some(a),
    |             ------------------------------------------- immutable borrow occurs here
@@ -179,7 +179,7 @@ LL |     drop(r);
    |          - immutable borrow later used here
 
 error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable
-  --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:204:5
+  --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:202:5
    |
 LL |         [_, ref mut a @ Some(box Test::Foo | box Test::Bar), ..] => Some(a),
    |             ----------------------------------------------- mutable borrow occurs here
@@ -191,7 +191,7 @@ LL |     drop(r);
    |          - mutable borrow later used here
 
 error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable
-  --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:218:5
+  --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:216:5
    |
 LL |         ref a @ [_, ref b @ Some(box Test::Foo | box Test::Bar), ..] => Some(a),
    |         ------------------------------------------------------------ immutable borrow occurs here
diff --git a/src/test/ui/c-variadic/variadic-ffi-1.stderr b/src/test/ui/c-variadic/variadic-ffi-1.stderr
index 89ea65fd43f..6f2a6c359b5 100644
--- a/src/test/ui/c-variadic/variadic-ffi-1.stderr
+++ b/src/test/ui/c-variadic/variadic-ffi-1.stderr
@@ -7,24 +7,30 @@ LL |     fn printf(_: *const u8, ...);
 error[E0060]: this function takes at least 2 arguments but 0 arguments were supplied
   --> $DIR/variadic-ffi-1.rs:17:9
    |
-LL |     fn foo(f: isize, x: u8, ...);
-   |     ----------------------------- defined here
-...
 LL |         foo();
    |         ^^^-- supplied 0 arguments
    |         |
    |         expected at least 2 arguments
+   |
+note: function defined here
+  --> $DIR/variadic-ffi-1.rs:10:8
+   |
+LL |     fn foo(f: isize, x: u8, ...);
+   |        ^^^
 
 error[E0060]: this function takes at least 2 arguments but 1 argument was supplied
   --> $DIR/variadic-ffi-1.rs:18:9
    |
-LL |     fn foo(f: isize, x: u8, ...);
-   |     ----------------------------- defined here
-...
 LL |         foo(1);
    |         ^^^ - supplied 1 argument
    |         |
    |         expected at least 2 arguments
+   |
+note: function defined here
+  --> $DIR/variadic-ffi-1.rs:10:8
+   |
+LL |     fn foo(f: isize, x: u8, ...);
+   |        ^^^
 
 error[E0308]: mismatched types
   --> $DIR/variadic-ffi-1.rs:20:56
diff --git a/src/test/ui/c-variadic/variadic-ffi-no-fixed-args.stderr b/src/test/ui/c-variadic/variadic-ffi-no-fixed-args.stderr
index 7af38c88f43..e11ba43ca2a 100644
--- a/src/test/ui/c-variadic/variadic-ffi-no-fixed-args.stderr
+++ b/src/test/ui/c-variadic/variadic-ffi-no-fixed-args.stderr
@@ -2,7 +2,7 @@ error: C-variadic function must be declared with at least one named argument
   --> $DIR/variadic-ffi-no-fixed-args.rs:2:12
    |
 LL |     fn foo(...);
-   |            ^^^^
+   |            ^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/drop/dynamic-drop-async.rs b/src/test/ui/drop/dynamic-drop-async.rs
index 88d36ab6aa6..b027faa9d7c 100644
--- a/src/test/ui/drop/dynamic-drop-async.rs
+++ b/src/test/ui/drop/dynamic-drop-async.rs
@@ -7,8 +7,6 @@
 // edition:2018
 // ignore-wasm32-bare compiled with panic=abort by default
 
-#![feature(move_ref_pattern)]
-
 #![allow(unused)]
 
 use std::{
diff --git a/src/test/ui/drop/dynamic-drop.rs b/src/test/ui/drop/dynamic-drop.rs
index d31736f142c..ada61bf0df0 100644
--- a/src/test/ui/drop/dynamic-drop.rs
+++ b/src/test/ui/drop/dynamic-drop.rs
@@ -2,7 +2,6 @@
 // ignore-wasm32-bare compiled with panic=abort by default
 
 #![feature(generators, generator_trait, untagged_unions)]
-#![feature(move_ref_pattern)]
 #![feature(bindings_after_at)]
 
 #![allow(unused_assignments)]
diff --git a/src/test/ui/error-codes/E0007.rs b/src/test/ui/error-codes/E0007.rs
deleted file mode 100644
index 022ac5fc113..00000000000
--- a/src/test/ui/error-codes/E0007.rs
+++ /dev/null
@@ -1,11 +0,0 @@
-#![feature(bindings_after_at)]
-
-fn main() {
-    let x = Some("s".to_string());
-    match x {
-        op_string @ Some(s) => {},
-        //~^ ERROR E0007
-        //~| ERROR E0382
-        None => {},
-    }
-}
diff --git a/src/test/ui/error-codes/E0007.stderr b/src/test/ui/error-codes/E0007.stderr
deleted file mode 100644
index 89c10516194..00000000000
--- a/src/test/ui/error-codes/E0007.stderr
+++ /dev/null
@@ -1,22 +0,0 @@
-error[E0007]: cannot bind by-move with sub-bindings
-  --> $DIR/E0007.rs:6:9
-   |
-LL |         op_string @ Some(s) => {},
-   |         ^^^^^^^^^^^^^^^^^^^ binds an already bound by-move value by moving it
-
-error[E0382]: use of moved value
-  --> $DIR/E0007.rs:6:26
-   |
-LL |     let x = Some("s".to_string());
-   |         - move occurs because `x` has type `Option<String>`, which does not implement the `Copy` trait
-LL |     match x {
-LL |         op_string @ Some(s) => {},
-   |         -----------------^-
-   |         |                |
-   |         |                value used here after move
-   |         value moved here
-
-error: aborting due to 2 previous errors
-
-Some errors have detailed explanations: E0007, E0382.
-For more information about an error, try `rustc --explain E0007`.
diff --git a/src/test/ui/error-codes/E0060.stderr b/src/test/ui/error-codes/E0060.stderr
index a600592c6c2..c80014d1476 100644
--- a/src/test/ui/error-codes/E0060.stderr
+++ b/src/test/ui/error-codes/E0060.stderr
@@ -1,13 +1,16 @@
 error[E0060]: this function takes at least 1 argument but 0 arguments were supplied
   --> $DIR/E0060.rs:6:14
    |
-LL |     fn printf(_: *const u8, ...) -> u32;
-   |     ------------------------------------ defined here
-...
 LL |     unsafe { printf(); }
    |              ^^^^^^-- supplied 0 arguments
    |              |
    |              expected at least 1 argument
+   |
+note: function defined here
+  --> $DIR/E0060.rs:2:8
+   |
+LL |     fn printf(_: *const u8, ...) -> u32;
+   |        ^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/error-codes/E0061.stderr b/src/test/ui/error-codes/E0061.stderr
index dfefa0df313..98488a2d298 100644
--- a/src/test/ui/error-codes/E0061.stderr
+++ b/src/test/ui/error-codes/E0061.stderr
@@ -1,24 +1,30 @@
 error[E0061]: this function takes 2 arguments but 1 argument was supplied
   --> $DIR/E0061.rs:6:5
    |
-LL | fn f(a: u16, b: &str) {}
-   | --------------------- defined here
-...
 LL |     f(0);
    |     ^ - supplied 1 argument
    |     |
    |     expected 2 arguments
+   |
+note: function defined here
+  --> $DIR/E0061.rs:1:4
+   |
+LL | fn f(a: u16, b: &str) {}
+   |    ^ ------  -------
 
 error[E0061]: this function takes 1 argument but 0 arguments were supplied
   --> $DIR/E0061.rs:10:5
    |
-LL | fn f2(a: u16) {}
-   | ------------- defined here
-...
 LL |     f2();
    |     ^^-- supplied 0 arguments
    |     |
    |     expected 1 argument
+   |
+note: function defined here
+  --> $DIR/E0061.rs:3:4
+   |
+LL | fn f2(a: u16) {}
+   |    ^^ ------
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/hrtb/issue-58451.stderr b/src/test/ui/hrtb/issue-58451.stderr
index bd08fc1bfae..2cc1c7a2e72 100644
--- a/src/test/ui/hrtb/issue-58451.stderr
+++ b/src/test/ui/hrtb/issue-58451.stderr
@@ -1,16 +1,16 @@
 error[E0061]: this function takes 1 argument but 0 arguments were supplied
   --> $DIR/issue-58451.rs:12:9
    |
-LL | / fn f<I>(i: I)
-LL | | where
-LL | |     I: IntoIterator,
-LL | |     I::Item: for<'a> Into<&'a ()>,
-   | |__________________________________- defined here
-...
-LL |       f(&[f()]);
-   |           ^-- supplied 0 arguments
-   |           |
-   |           expected 1 argument
+LL |     f(&[f()]);
+   |         ^-- supplied 0 arguments
+   |         |
+   |         expected 1 argument
+   |
+note: function defined here
+  --> $DIR/issue-58451.rs:5:4
+   |
+LL | fn f<I>(i: I)
+   |    ^    ----
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-18819.stderr b/src/test/ui/issues/issue-18819.stderr
index a952c9b46c9..b10d26abe34 100644
--- a/src/test/ui/issues/issue-18819.stderr
+++ b/src/test/ui/issues/issue-18819.stderr
@@ -1,13 +1,16 @@
 error[E0061]: this function takes 2 arguments but 1 argument was supplied
   --> $DIR/issue-18819.rs:16:5
    |
-LL | fn print_x(_: &dyn Foo<Item=bool>, extra: &str) {
-   | ----------------------------------------------- defined here
-...
 LL |     print_x(X);
    |     ^^^^^^^ - supplied 1 argument
    |     |
    |     expected 2 arguments
+   |
+note: function defined here
+  --> $DIR/issue-18819.rs:11:4
+   |
+LL | fn print_x(_: &dyn Foo<Item=bool>, extra: &str) {
+   |    ^^^^^^^ ----------------------  -----------
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-26094.stderr b/src/test/ui/issues/issue-26094.stderr
index 2038d88bf46..a6f1ac9286c 100644
--- a/src/test/ui/issues/issue-26094.stderr
+++ b/src/test/ui/issues/issue-26094.stderr
@@ -4,11 +4,14 @@ error[E0061]: this function takes 0 arguments but 1 argument was supplied
 LL |         $other(None)
    |                ---- supplied 1 argument
 ...
-LL | fn some_function() {}
-   | ------------------ defined here
-...
 LL |     some_macro!(some_function);
    |                 ^^^^^^^^^^^^^ expected 0 arguments
+   |
+note: function defined here
+  --> $DIR/issue-26094.rs:7:4
+   |
+LL | fn some_function() {}
+   |    ^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-4935.stderr b/src/test/ui/issues/issue-4935.stderr
index 0cc686e1cf8..03b9b91edef 100644
--- a/src/test/ui/issues/issue-4935.stderr
+++ b/src/test/ui/issues/issue-4935.stderr
@@ -1,13 +1,16 @@
 error[E0061]: this function takes 1 argument but 2 arguments were supplied
   --> $DIR/issue-4935.rs:5:13
    |
-LL | fn foo(a: usize) {}
-   | ---------------- defined here
-LL |
 LL | fn main() { foo(5, 6) }
    |             ^^^ -  - supplied 2 arguments
    |             |
    |             expected 1 argument
+   |
+note: function defined here
+  --> $DIR/issue-4935.rs:3:4
+   |
+LL | fn foo(a: usize) {}
+   |    ^^^ --------
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/methods/method-call-err-msg.stderr b/src/test/ui/methods/method-call-err-msg.stderr
index b0d1bb9823b..60f9eeeca27 100644
--- a/src/test/ui/methods/method-call-err-msg.stderr
+++ b/src/test/ui/methods/method-call-err-msg.stderr
@@ -1,35 +1,44 @@
 error[E0061]: this function takes 0 arguments but 1 argument was supplied
   --> $DIR/method-call-err-msg.rs:13:7
    |
-LL |     fn zero(self) -> Foo { self }
-   |     -------------------- defined here
-...
 LL |     x.zero(0)
    |       ^^^^ - supplied 1 argument
    |       |
    |       expected 0 arguments
+   |
+note: associated function defined here
+  --> $DIR/method-call-err-msg.rs:5:8
+   |
+LL |     fn zero(self) -> Foo { self }
+   |        ^^^^ ----
 
 error[E0061]: this function takes 1 argument but 0 arguments were supplied
   --> $DIR/method-call-err-msg.rs:14:7
    |
-LL |     fn one(self, _: isize) -> Foo { self }
-   |     ----------------------------- defined here
-...
 LL |      .one()
    |       ^^^- supplied 0 arguments
    |       |
    |       expected 1 argument
+   |
+note: associated function defined here
+  --> $DIR/method-call-err-msg.rs:6:8
+   |
+LL |     fn one(self, _: isize) -> Foo { self }
+   |        ^^^ ----  --------
 
 error[E0061]: this function takes 2 arguments but 1 argument was supplied
   --> $DIR/method-call-err-msg.rs:15:7
    |
-LL |     fn two(self, _: isize, _: isize) -> Foo { self }
-   |     --------------------------------------- defined here
-...
 LL |      .two(0);
    |       ^^^ - supplied 1 argument
    |       |
    |       expected 2 arguments
+   |
+note: associated function defined here
+  --> $DIR/method-call-err-msg.rs:7:8
+   |
+LL |     fn two(self, _: isize, _: isize) -> Foo { self }
+   |        ^^^ ----  --------  --------
 
 error[E0599]: no method named `take` found for struct `Foo` in the current scope
   --> $DIR/method-call-err-msg.rs:19:7
@@ -53,13 +62,16 @@ LL |      .take()
 error[E0061]: this function takes 3 arguments but 0 arguments were supplied
   --> $DIR/method-call-err-msg.rs:21:7
    |
-LL |     fn three<T>(self, _: T, _: T, _: T) -> Foo { self }
-   |     ------------------------------------------ defined here
-...
 LL |     y.three::<usize>();
    |       ^^^^^--------- supplied 0 arguments
    |       |
    |       expected 3 arguments
+   |
+note: associated function defined here
+  --> $DIR/method-call-err-msg.rs:8:8
+   |
+LL |     fn three<T>(self, _: T, _: T, _: T) -> Foo { self }
+   |        ^^^^^    ----  ----  ----  ----
 
 error: aborting due to 5 previous errors
 
diff --git a/src/test/ui/mismatched_types/issue-38371.stderr b/src/test/ui/mismatched_types/issue-38371.stderr
index c2bce305877..5d2ce9302ec 100644
--- a/src/test/ui/mismatched_types/issue-38371.stderr
+++ b/src/test/ui/mismatched_types/issue-38371.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
   --> $DIR/issue-38371.rs:4:8
    |
 LL | fn foo(&foo: Foo) {
-   |        ^^^^------
+   |        ^^^^-----
    |        |     |
    |        |     expected due to this
    |        expected struct `Foo`, found reference
diff --git a/src/test/ui/not-enough-arguments.rs b/src/test/ui/not-enough-arguments.rs
index 631bb1dd274..42476255188 100644
--- a/src/test/ui/not-enough-arguments.rs
+++ b/src/test/ui/not-enough-arguments.rs
@@ -6,7 +6,26 @@ fn foo(a: isize, b: isize, c: isize, d:isize) {
   panic!();
 }
 
+// Check that all arguments are shown in the error message, even if they're across multiple lines.
+fn bar(
+    a: i32,
+    b: i32,
+    c: i32,
+    d: i32,
+    e: i32,
+    f: i32,
+) {
+    println!("{}", a);
+    println!("{}", b);
+    println!("{}", c);
+    println!("{}", d);
+    println!("{}", e);
+    println!("{}", f);
+}
+
 fn main() {
   foo(1, 2, 3);
   //~^ ERROR this function takes 4 arguments but 3
+  bar(1, 2, 3);
+  //~^ ERROR this function takes 6 arguments but 3
 }
diff --git a/src/test/ui/not-enough-arguments.stderr b/src/test/ui/not-enough-arguments.stderr
index f2b57f71400..df957837241 100644
--- a/src/test/ui/not-enough-arguments.stderr
+++ b/src/test/ui/not-enough-arguments.stderr
@@ -1,14 +1,43 @@
 error[E0061]: this function takes 4 arguments but 3 arguments were supplied
-  --> $DIR/not-enough-arguments.rs:10:3
+  --> $DIR/not-enough-arguments.rs:27:3
    |
-LL | fn foo(a: isize, b: isize, c: isize, d:isize) {
-   | --------------------------------------------- defined here
-...
 LL |   foo(1, 2, 3);
    |   ^^^ -  -  - supplied 3 arguments
    |   |
    |   expected 4 arguments
+   |
+note: function defined here
+  --> $DIR/not-enough-arguments.rs:5:4
+   |
+LL | fn foo(a: isize, b: isize, c: isize, d:isize) {
+   |    ^^^ --------  --------  --------  -------
+
+error[E0061]: this function takes 6 arguments but 3 arguments were supplied
+  --> $DIR/not-enough-arguments.rs:29:3
+   |
+LL |   bar(1, 2, 3);
+   |   ^^^ -  -  - supplied 3 arguments
+   |   |
+   |   expected 6 arguments
+   |
+note: function defined here
+  --> $DIR/not-enough-arguments.rs:10:4
+   |
+LL | fn bar(
+   |    ^^^
+LL |     a: i32,
+   |     ------
+LL |     b: i32,
+   |     ------
+LL |     c: i32,
+   |     ------
+LL |     d: i32,
+   |     ------
+LL |     e: i32,
+   |     ------
+LL |     f: i32,
+   |     ------
 
-error: aborting due to previous error
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0061`.
diff --git a/src/test/ui/parser/variadic-ffi-semantic-restrictions.stderr b/src/test/ui/parser/variadic-ffi-semantic-restrictions.stderr
index 21992a29670..3f3ddfed14a 100644
--- a/src/test/ui/parser/variadic-ffi-semantic-restrictions.stderr
+++ b/src/test/ui/parser/variadic-ffi-semantic-restrictions.stderr
@@ -2,205 +2,205 @@ error: only foreign or `unsafe extern "C" functions may be C-variadic
   --> $DIR/variadic-ffi-semantic-restrictions.rs:5:19
    |
 LL | fn f1_1(x: isize, ...) {}
-   |                   ^^^^
+   |                   ^^^
 
 error: C-variadic function must be declared with at least one named argument
   --> $DIR/variadic-ffi-semantic-restrictions.rs:8:9
    |
 LL | fn f1_2(...) {}
-   |         ^^^^
+   |         ^^^
 
 error: only foreign or `unsafe extern "C" functions may be C-variadic
   --> $DIR/variadic-ffi-semantic-restrictions.rs:8:9
    |
 LL | fn f1_2(...) {}
-   |         ^^^^
+   |         ^^^
 
 error: only foreign or `unsafe extern "C" functions may be C-variadic
   --> $DIR/variadic-ffi-semantic-restrictions.rs:12:30
    |
 LL | extern "C" fn f2_1(x: isize, ...) {}
-   |                              ^^^^
+   |                              ^^^
 
 error: C-variadic function must be declared with at least one named argument
   --> $DIR/variadic-ffi-semantic-restrictions.rs:15:20
    |
 LL | extern "C" fn f2_2(...) {}
-   |                    ^^^^
+   |                    ^^^
 
 error: only foreign or `unsafe extern "C" functions may be C-variadic
   --> $DIR/variadic-ffi-semantic-restrictions.rs:15:20
    |
 LL | extern "C" fn f2_2(...) {}
-   |                    ^^^^
+   |                    ^^^
 
 error: `...` must be the last argument of a C-variadic function
   --> $DIR/variadic-ffi-semantic-restrictions.rs:19:20
    |
 LL | extern "C" fn f2_3(..., x: isize) {}
-   |                    ^^^^
+   |                    ^^^
 
 error: only foreign or `unsafe extern "C" functions may be C-variadic
   --> $DIR/variadic-ffi-semantic-restrictions.rs:19:20
    |
 LL | extern "C" fn f2_3(..., x: isize) {}
-   |                    ^^^^
+   |                    ^^^
 
 error: only foreign or `unsafe extern "C" functions may be C-variadic
   --> $DIR/variadic-ffi-semantic-restrictions.rs:23:26
    |
 LL | extern fn f3_1(x: isize, ...) {}
-   |                          ^^^^
+   |                          ^^^
 
 error: C-variadic function must be declared with at least one named argument
   --> $DIR/variadic-ffi-semantic-restrictions.rs:26:16
    |
 LL | extern fn f3_2(...) {}
-   |                ^^^^
+   |                ^^^
 
 error: only foreign or `unsafe extern "C" functions may be C-variadic
   --> $DIR/variadic-ffi-semantic-restrictions.rs:26:16
    |
 LL | extern fn f3_2(...) {}
-   |                ^^^^
+   |                ^^^
 
 error: `...` must be the last argument of a C-variadic function
   --> $DIR/variadic-ffi-semantic-restrictions.rs:30:16
    |
 LL | extern fn f3_3(..., x: isize) {}
-   |                ^^^^
+   |                ^^^
 
 error: only foreign or `unsafe extern "C" functions may be C-variadic
   --> $DIR/variadic-ffi-semantic-restrictions.rs:30:16
    |
 LL | extern fn f3_3(..., x: isize) {}
-   |                ^^^^
+   |                ^^^
 
 error: C-variadic function must be declared with at least one named argument
   --> $DIR/variadic-ffi-semantic-restrictions.rs:35:13
    |
 LL |     fn e_f1(...);
-   |             ^^^^
+   |             ^^^
 
 error: `...` must be the last argument of a C-variadic function
   --> $DIR/variadic-ffi-semantic-restrictions.rs:37:13
    |
 LL |     fn e_f2(..., x: isize);
-   |             ^^^^
+   |             ^^^
 
 error: only foreign or `unsafe extern "C" functions may be C-variadic
   --> $DIR/variadic-ffi-semantic-restrictions.rs:44:23
    |
 LL |     fn i_f1(x: isize, ...) {}
-   |                       ^^^^
+   |                       ^^^
 
 error: C-variadic function must be declared with at least one named argument
   --> $DIR/variadic-ffi-semantic-restrictions.rs:46:13
    |
 LL |     fn i_f2(...) {}
-   |             ^^^^
+   |             ^^^
 
 error: only foreign or `unsafe extern "C" functions may be C-variadic
   --> $DIR/variadic-ffi-semantic-restrictions.rs:46:13
    |
 LL |     fn i_f2(...) {}
-   |             ^^^^
+   |             ^^^
 
 error: `...` must be the last argument of a C-variadic function
   --> $DIR/variadic-ffi-semantic-restrictions.rs:49:13
    |
 LL |     fn i_f3(..., x: isize, ...) {}
-   |             ^^^^
+   |             ^^^
 
 error: only foreign or `unsafe extern "C" functions may be C-variadic
   --> $DIR/variadic-ffi-semantic-restrictions.rs:49:13
    |
 LL |     fn i_f3(..., x: isize, ...) {}
-   |             ^^^^
+   |             ^^^
 
 error: only foreign or `unsafe extern "C" functions may be C-variadic
   --> $DIR/variadic-ffi-semantic-restrictions.rs:49:28
    |
 LL |     fn i_f3(..., x: isize, ...) {}
-   |                            ^^^^
+   |                            ^^^
 
 error: `...` must be the last argument of a C-variadic function
   --> $DIR/variadic-ffi-semantic-restrictions.rs:53:13
    |
 LL |     fn i_f4(..., x: isize, ...) {}
-   |             ^^^^
+   |             ^^^
 
 error: only foreign or `unsafe extern "C" functions may be C-variadic
   --> $DIR/variadic-ffi-semantic-restrictions.rs:53:13
    |
 LL |     fn i_f4(..., x: isize, ...) {}
-   |             ^^^^
+   |             ^^^
 
 error: only foreign or `unsafe extern "C" functions may be C-variadic
   --> $DIR/variadic-ffi-semantic-restrictions.rs:53:28
    |
 LL |     fn i_f4(..., x: isize, ...) {}
-   |                            ^^^^
+   |                            ^^^
 
 error: only foreign or `unsafe extern "C" functions may be C-variadic
   --> $DIR/variadic-ffi-semantic-restrictions.rs:60:23
    |
 LL |     fn t_f1(x: isize, ...) {}
-   |                       ^^^^
+   |                       ^^^
 
 error: only foreign or `unsafe extern "C" functions may be C-variadic
   --> $DIR/variadic-ffi-semantic-restrictions.rs:62:23
    |
 LL |     fn t_f2(x: isize, ...);
-   |                       ^^^^
+   |                       ^^^
 
 error: C-variadic function must be declared with at least one named argument
   --> $DIR/variadic-ffi-semantic-restrictions.rs:64:13
    |
 LL |     fn t_f3(...) {}
-   |             ^^^^
+   |             ^^^
 
 error: only foreign or `unsafe extern "C" functions may be C-variadic
   --> $DIR/variadic-ffi-semantic-restrictions.rs:64:13
    |
 LL |     fn t_f3(...) {}
-   |             ^^^^
+   |             ^^^
 
 error: C-variadic function must be declared with at least one named argument
   --> $DIR/variadic-ffi-semantic-restrictions.rs:67:13
    |
 LL |     fn t_f4(...);
-   |             ^^^^
+   |             ^^^
 
 error: only foreign or `unsafe extern "C" functions may be C-variadic
   --> $DIR/variadic-ffi-semantic-restrictions.rs:67:13
    |
 LL |     fn t_f4(...);
-   |             ^^^^
+   |             ^^^
 
 error: `...` must be the last argument of a C-variadic function
   --> $DIR/variadic-ffi-semantic-restrictions.rs:70:13
    |
 LL |     fn t_f5(..., x: isize) {}
-   |             ^^^^
+   |             ^^^
 
 error: only foreign or `unsafe extern "C" functions may be C-variadic
   --> $DIR/variadic-ffi-semantic-restrictions.rs:70:13
    |
 LL |     fn t_f5(..., x: isize) {}
-   |             ^^^^
+   |             ^^^
 
 error: `...` must be the last argument of a C-variadic function
   --> $DIR/variadic-ffi-semantic-restrictions.rs:73:13
    |
 LL |     fn t_f6(..., x: isize);
-   |             ^^^^
+   |             ^^^
 
 error: only foreign or `unsafe extern "C" functions may be C-variadic
   --> $DIR/variadic-ffi-semantic-restrictions.rs:73:13
    |
 LL |     fn t_f6(..., x: isize);
-   |             ^^^^
+   |             ^^^
 
 error: aborting due to 34 previous errors
 
diff --git a/src/test/ui/pattern/bindings-after-at/bind-by-move-neither-can-live-while-the-other-survives-1.rs b/src/test/ui/pattern/bindings-after-at/bind-by-move-neither-can-live-while-the-other-survives-1.rs
index c00296c34c4..ba9543bf738 100644
--- a/src/test/ui/pattern/bindings-after-at/bind-by-move-neither-can-live-while-the-other-survives-1.rs
+++ b/src/test/ui/pattern/bindings-after-at/bind-by-move-neither-can-live-while-the-other-survives-1.rs
@@ -3,7 +3,6 @@
 // where one side is by-ref and the other is by-move.
 
 #![feature(bindings_after_at)]
-#![feature(move_ref_pattern)]
 
 struct X {
     x: (),
diff --git a/src/test/ui/pattern/bindings-after-at/bind-by-move-neither-can-live-while-the-other-survives-1.stderr b/src/test/ui/pattern/bindings-after-at/bind-by-move-neither-can-live-while-the-other-survives-1.stderr
index 8a6ea8e91a2..44dbcb9a754 100644
--- a/src/test/ui/pattern/bindings-after-at/bind-by-move-neither-can-live-while-the-other-survives-1.stderr
+++ b/src/test/ui/pattern/bindings-after-at/bind-by-move-neither-can-live-while-the-other-survives-1.stderr
@@ -1,5 +1,5 @@
 error: cannot move out of value because it is borrowed
-  --> $DIR/bind-by-move-neither-can-live-while-the-other-survives-1.rs:15:14
+  --> $DIR/bind-by-move-neither-can-live-while-the-other-survives-1.rs:14:14
    |
 LL |         Some(ref _y @ _z) => {}
    |              ------^^^--
@@ -8,7 +8,7 @@ LL |         Some(ref _y @ _z) => {}
    |              value borrowed, by `_y`, here
 
 error: borrow of moved value
-  --> $DIR/bind-by-move-neither-can-live-while-the-other-survives-1.rs:21:14
+  --> $DIR/bind-by-move-neither-can-live-while-the-other-survives-1.rs:20:14
    |
 LL |         Some(_z @ ref _y) => {}
    |              --^^^------
@@ -18,7 +18,7 @@ LL |         Some(_z @ ref _y) => {}
    |              move occurs because `_z` has type `X` which does not implement the `Copy` trait
 
 error: cannot move out of value because it is borrowed
-  --> $DIR/bind-by-move-neither-can-live-while-the-other-survives-1.rs:29:14
+  --> $DIR/bind-by-move-neither-can-live-while-the-other-survives-1.rs:28:14
    |
 LL |         Some(ref mut _y @ _z) => {}
    |              ----------^^^--
@@ -27,7 +27,7 @@ LL |         Some(ref mut _y @ _z) => {}
    |              value borrowed, by `_y`, here
 
 error: borrow of moved value
-  --> $DIR/bind-by-move-neither-can-live-while-the-other-survives-1.rs:35:14
+  --> $DIR/bind-by-move-neither-can-live-while-the-other-survives-1.rs:34:14
    |
 LL |         Some(_z @ ref mut _y) => {}
    |              --^^^----------
@@ -37,7 +37,7 @@ LL |         Some(_z @ ref mut _y) => {}
    |              move occurs because `_z` has type `X` which does not implement the `Copy` trait
 
 error[E0382]: borrow of moved value
-  --> $DIR/bind-by-move-neither-can-live-while-the-other-survives-1.rs:21:19
+  --> $DIR/bind-by-move-neither-can-live-while-the-other-survives-1.rs:20:19
    |
 LL |         Some(_z @ ref _y) => {}
    |              -----^^^^^^
@@ -52,7 +52,7 @@ LL |         Some(ref _z @ ref _y) => {}
    |              ^^^
 
 error[E0382]: borrow of moved value
-  --> $DIR/bind-by-move-neither-can-live-while-the-other-survives-1.rs:35:19
+  --> $DIR/bind-by-move-neither-can-live-while-the-other-survives-1.rs:34:19
    |
 LL |         Some(_z @ ref mut _y) => {}
    |              -----^^^^^^^^^^
diff --git a/src/test/ui/pattern/bindings-after-at/bind-by-move-no-subbindings-fun-param.rs b/src/test/ui/pattern/bindings-after-at/bind-by-move-no-subbindings-fun-param.rs
index 7a2e5128b85..3ab6f40725c 100644
--- a/src/test/ui/pattern/bindings-after-at/bind-by-move-no-subbindings-fun-param.rs
+++ b/src/test/ui/pattern/bindings-after-at/bind-by-move-no-subbindings-fun-param.rs
@@ -1,7 +1,6 @@
 // See issue #12534.
 
 #![feature(bindings_after_at)]
-#![feature(move_ref_pattern)]
 
 fn main() {}
 
diff --git a/src/test/ui/pattern/bindings-after-at/bind-by-move-no-subbindings-fun-param.stderr b/src/test/ui/pattern/bindings-after-at/bind-by-move-no-subbindings-fun-param.stderr
index cfd978e1327..f25d5a2d9b8 100644
--- a/src/test/ui/pattern/bindings-after-at/bind-by-move-no-subbindings-fun-param.stderr
+++ b/src/test/ui/pattern/bindings-after-at/bind-by-move-no-subbindings-fun-param.stderr
@@ -1,5 +1,5 @@
 error[E0382]: use of moved value
-  --> $DIR/bind-by-move-no-subbindings-fun-param.rs:10:12
+  --> $DIR/bind-by-move-no-subbindings-fun-param.rs:9:12
    |
 LL | fn f(a @ A(u): A) -> Box<u8> {
    |      ------^-
diff --git a/src/test/ui/pattern/bindings-after-at/borrowck-move-and-move.rs b/src/test/ui/pattern/bindings-after-at/borrowck-move-and-move.rs
index 10865b92393..d014c9828da 100644
--- a/src/test/ui/pattern/bindings-after-at/borrowck-move-and-move.rs
+++ b/src/test/ui/pattern/bindings-after-at/borrowck-move-and-move.rs
@@ -1,7 +1,6 @@
 // Test that moving on both sides of an `@` pattern is not allowed.
 
 #![feature(bindings_after_at)]
-#![feature(move_ref_pattern)]
 
 fn main() {
     struct U; // Not copy!
diff --git a/src/test/ui/pattern/bindings-after-at/borrowck-move-and-move.stderr b/src/test/ui/pattern/bindings-after-at/borrowck-move-and-move.stderr
index d28edd11e12..5039f580ff6 100644
--- a/src/test/ui/pattern/bindings-after-at/borrowck-move-and-move.stderr
+++ b/src/test/ui/pattern/bindings-after-at/borrowck-move-and-move.stderr
@@ -1,5 +1,5 @@
 error[E0382]: use of moved value
-  --> $DIR/borrowck-move-and-move.rs:14:13
+  --> $DIR/borrowck-move-and-move.rs:13:13
    |
 LL |     let a @ b = U;
    |         ----^   - move occurs because value has type `U`, which does not implement the `Copy` trait
@@ -8,7 +8,7 @@ LL |     let a @ b = U;
    |         value moved here
 
 error[E0382]: use of moved value
-  --> $DIR/borrowck-move-and-move.rs:16:17
+  --> $DIR/borrowck-move-and-move.rs:15:17
    |
 LL |     let a @ (b, c) = (U, U);
    |         --------^-   ------ move occurs because value has type `(U, U)`, which does not implement the `Copy` trait
@@ -17,7 +17,7 @@ LL |     let a @ (b, c) = (U, U);
    |         value moved here
 
 error[E0382]: use of moved value
-  --> $DIR/borrowck-move-and-move.rs:18:17
+  --> $DIR/borrowck-move-and-move.rs:17:17
    |
 LL |     let a @ (b, c) = (u(), u());
    |         --------^-   ---------- move occurs because value has type `(U, U)`, which does not implement the `Copy` trait
@@ -26,7 +26,7 @@ LL |     let a @ (b, c) = (u(), u());
    |         value moved here
 
 error[E0382]: use of moved value
-  --> $DIR/borrowck-move-and-move.rs:21:16
+  --> $DIR/borrowck-move-and-move.rs:20:16
    |
 LL |     match Ok(U) {
    |           ----- move occurs because value has type `std::result::Result<U, U>`, which does not implement the `Copy` trait
@@ -37,7 +37,7 @@ LL |         a @ Ok(b) | a @ Err(b) => {}
    |         value moved here
 
 error[E0382]: use of moved value
-  --> $DIR/borrowck-move-and-move.rs:21:29
+  --> $DIR/borrowck-move-and-move.rs:20:29
    |
 LL |     match Ok(U) {
    |           ----- move occurs because value has type `std::result::Result<U, U>`, which does not implement the `Copy` trait
@@ -48,7 +48,7 @@ LL |         a @ Ok(b) | a @ Err(b) => {}
    |                     value moved here
 
 error[E0382]: use of moved value
-  --> $DIR/borrowck-move-and-move.rs:28:22
+  --> $DIR/borrowck-move-and-move.rs:27:22
    |
 LL |     match [u(), u(), u(), u()] {
    |           -------------------- move occurs because value has type `[U; 4]`, which does not implement the `Copy` trait
@@ -59,7 +59,7 @@ LL |         xs @ [a, .., b] => {}
    |         value moved here
 
 error[E0382]: use of moved value
-  --> $DIR/borrowck-move-and-move.rs:32:18
+  --> $DIR/borrowck-move-and-move.rs:31:18
    |
 LL |     match [u(), u(), u(), u()] {
    |           -------------------- move occurs because value has type `[U; 4]`, which does not implement the `Copy` trait
@@ -70,7 +70,7 @@ LL |         xs @ [_, ys @ .., _] => {}
    |         value moved here
 
 error[E0382]: use of moved value
-  --> $DIR/borrowck-move-and-move.rs:25:16
+  --> $DIR/borrowck-move-and-move.rs:24:16
    |
 LL |     fn fun(a @ b: U) {}
    |            ----^
diff --git a/src/test/ui/pattern/bindings-after-at/borrowck-pat-at-and-box-pass.rs b/src/test/ui/pattern/bindings-after-at/borrowck-pat-at-and-box-pass.rs
index 271f4bca0fc..f1ee87bc9c6 100644
--- a/src/test/ui/pattern/bindings-after-at/borrowck-pat-at-and-box-pass.rs
+++ b/src/test/ui/pattern/bindings-after-at/borrowck-pat-at-and-box-pass.rs
@@ -3,7 +3,6 @@
 // Test `@` patterns combined with `box` patterns.
 
 #![feature(bindings_after_at)]
-#![feature(move_ref_pattern)]
 #![feature(box_patterns)]
 
 #[derive(Copy, Clone)]
diff --git a/src/test/ui/pattern/bindings-after-at/borrowck-pat-at-and-box.rs b/src/test/ui/pattern/bindings-after-at/borrowck-pat-at-and-box.rs
index f1680e9e888..236710ed854 100644
--- a/src/test/ui/pattern/bindings-after-at/borrowck-pat-at-and-box.rs
+++ b/src/test/ui/pattern/bindings-after-at/borrowck-pat-at-and-box.rs
@@ -1,7 +1,6 @@
 // Test `@` patterns combined with `box` patterns.
 
 #![feature(bindings_after_at)]
-#![feature(move_ref_pattern)]
 #![feature(box_patterns)]
 
 #[derive(Copy, Clone)]
diff --git a/src/test/ui/pattern/bindings-after-at/borrowck-pat-at-and-box.stderr b/src/test/ui/pattern/bindings-after-at/borrowck-pat-at-and-box.stderr
index 44888369ab2..d9a8bbfb6b1 100644
--- a/src/test/ui/pattern/bindings-after-at/borrowck-pat-at-and-box.stderr
+++ b/src/test/ui/pattern/bindings-after-at/borrowck-pat-at-and-box.stderr
@@ -1,5 +1,5 @@
 error: cannot move out of value because it is borrowed
-  --> $DIR/borrowck-pat-at-and-box.rs:37:9
+  --> $DIR/borrowck-pat-at-and-box.rs:36:9
    |
 LL |     let ref a @ box b = Box::new(NC);
    |         -----^^^^^^^-
@@ -8,7 +8,7 @@ LL |     let ref a @ box b = Box::new(NC);
    |         value borrowed, by `a`, here
 
 error: cannot borrow value as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-at-and-box.rs:39:9
+  --> $DIR/borrowck-pat-at-and-box.rs:38:9
    |
 LL |     let ref a @ box ref mut b = Box::new(nc());
    |         -----^^^^^^^---------
@@ -17,7 +17,7 @@ LL |     let ref a @ box ref mut b = Box::new(nc());
    |         immutable borrow, by `a`, occurs here
 
 error: cannot borrow value as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-at-and-box.rs:41:9
+  --> $DIR/borrowck-pat-at-and-box.rs:40:9
    |
 LL |     let ref a @ box ref mut b = Box::new(NC);
    |         -----^^^^^^^---------
@@ -26,7 +26,7 @@ LL |     let ref a @ box ref mut b = Box::new(NC);
    |         immutable borrow, by `a`, occurs here
 
 error: cannot borrow value as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-at-and-box.rs:43:9
+  --> $DIR/borrowck-pat-at-and-box.rs:42:9
    |
 LL |     let ref a @ box ref mut b = Box::new(NC);
    |         -----^^^^^^^---------
@@ -35,7 +35,7 @@ LL |     let ref a @ box ref mut b = Box::new(NC);
    |         immutable borrow, by `a`, occurs here
 
 error: cannot borrow value as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-at-and-box.rs:46:9
+  --> $DIR/borrowck-pat-at-and-box.rs:45:9
    |
 LL |     let ref a @ box ref mut b = Box::new(NC);
    |         -----^^^^^^^---------
@@ -44,7 +44,7 @@ LL |     let ref a @ box ref mut b = Box::new(NC);
    |         immutable borrow, by `a`, occurs here
 
 error: cannot borrow value as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-pat-at-and-box.rs:52:9
+  --> $DIR/borrowck-pat-at-and-box.rs:51:9
    |
 LL |     let ref mut a @ box ref b = Box::new(NC);
    |         ---------^^^^^^^-----
@@ -53,7 +53,7 @@ LL |     let ref mut a @ box ref b = Box::new(NC);
    |         mutable borrow, by `a`, occurs here
 
 error: cannot borrow value as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-pat-at-and-box.rs:66:9
+  --> $DIR/borrowck-pat-at-and-box.rs:65:9
    |
 LL |         ref mut a @ box ref b => {
    |         ---------^^^^^^^-----
@@ -62,7 +62,7 @@ LL |         ref mut a @ box ref b => {
    |         mutable borrow, by `a`, occurs here
 
 error: cannot borrow value as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-pat-at-and-box.rs:58:11
+  --> $DIR/borrowck-pat-at-and-box.rs:57:11
    |
 LL |     fn f5(ref mut a @ box ref b: Box<NC>) {
    |           ---------^^^^^^^-----
@@ -71,7 +71,7 @@ LL |     fn f5(ref mut a @ box ref b: Box<NC>) {
    |           mutable borrow, by `a`, occurs here
 
 error[E0382]: use of moved value
-  --> $DIR/borrowck-pat-at-and-box.rs:21:18
+  --> $DIR/borrowck-pat-at-and-box.rs:20:18
    |
 LL |     let a @ box &b = Box::new(&C);
    |         ---------^   ------------ move occurs because value has type `Box<&C>`, which does not implement the `Copy` trait
@@ -80,7 +80,7 @@ LL |     let a @ box &b = Box::new(&C);
    |         value moved here
 
 error[E0382]: use of moved value
-  --> $DIR/borrowck-pat-at-and-box.rs:24:17
+  --> $DIR/borrowck-pat-at-and-box.rs:23:17
    |
 LL |     let a @ box b = Box::new(C);
    |         --------^   ----------- move occurs because value has type `Box<C>`, which does not implement the `Copy` trait
@@ -89,7 +89,7 @@ LL |     let a @ box b = Box::new(C);
    |         value moved here
 
 error[E0382]: use of moved value
-  --> $DIR/borrowck-pat-at-and-box.rs:34:17
+  --> $DIR/borrowck-pat-at-and-box.rs:33:17
    |
 LL |     match Box::new(C) {
    |           ----------- move occurs because value has type `Box<C>`, which does not implement the `Copy` trait
@@ -100,7 +100,7 @@ LL |         a @ box b => {}
    |         value moved here
 
 error[E0502]: cannot borrow value as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-at-and-box.rs:46:21
+  --> $DIR/borrowck-pat-at-and-box.rs:45:21
    |
 LL |     let ref a @ box ref mut b = Box::new(NC);
    |         ------------^^^^^^^^^
@@ -112,7 +112,7 @@ LL |     drop(a);
    |          - immutable borrow later used here
 
 error[E0502]: cannot borrow value as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-pat-at-and-box.rs:52:25
+  --> $DIR/borrowck-pat-at-and-box.rs:51:25
    |
 LL |     let ref mut a @ box ref b = Box::new(NC);
    |         ----------------^^^^^
@@ -124,7 +124,7 @@ LL |     *a = Box::new(NC);
    |     -- mutable borrow later used here
 
 error[E0502]: cannot borrow value as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-pat-at-and-box.rs:66:25
+  --> $DIR/borrowck-pat-at-and-box.rs:65:25
    |
 LL |         ref mut a @ box ref b => {
    |         ----------------^^^^^
@@ -136,7 +136,7 @@ LL |             *a = Box::new(NC);
    |             -- mutable borrow later used here
 
 error[E0382]: use of moved value
-  --> $DIR/borrowck-pat-at-and-box.rs:27:20
+  --> $DIR/borrowck-pat-at-and-box.rs:26:20
    |
 LL |     fn f1(a @ box &b: Box<&C>) {}
    |           ---------^
@@ -146,7 +146,7 @@ LL |     fn f1(a @ box &b: Box<&C>) {}
    |           move occurs because value has type `Box<&C>`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value
-  --> $DIR/borrowck-pat-at-and-box.rs:30:19
+  --> $DIR/borrowck-pat-at-and-box.rs:29:19
    |
 LL |     fn f2(a @ box b: Box<C>) {}
    |           --------^
@@ -156,7 +156,7 @@ LL |     fn f2(a @ box b: Box<C>) {}
    |           move occurs because value has type `Box<C>`, which does not implement the `Copy` trait
 
 error[E0502]: cannot borrow value as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-pat-at-and-box.rs:58:27
+  --> $DIR/borrowck-pat-at-and-box.rs:57:27
    |
 LL |     fn f5(ref mut a @ box ref b: Box<NC>) {
    |           ----------------^^^^^
diff --git a/src/test/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse-promotion.rs b/src/test/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse-promotion.rs
index 993954b450e..a22d27763d2 100644
--- a/src/test/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse-promotion.rs
+++ b/src/test/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse-promotion.rs
@@ -2,7 +2,6 @@
 // Currently this logic exists in THIR match checking as opposed to borrowck.
 
 #![feature(bindings_after_at)]
-#![feature(move_ref_pattern)]
 
 fn main() {
     struct U;
diff --git a/src/test/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse-promotion.stderr b/src/test/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse-promotion.stderr
index dacf23f9ded..0e09d478e3a 100644
--- a/src/test/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse-promotion.stderr
+++ b/src/test/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse-promotion.stderr
@@ -1,5 +1,5 @@
 error: borrow of moved value
-  --> $DIR/borrowck-pat-by-move-and-ref-inverse-promotion.rs:9:9
+  --> $DIR/borrowck-pat-by-move-and-ref-inverse-promotion.rs:8:9
    |
 LL |     let a @ ref b = U;
    |         -^^^-----
diff --git a/src/test/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse.rs b/src/test/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse.rs
index 7d9618c8df7..3e5a543c4c3 100644
--- a/src/test/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse.rs
+++ b/src/test/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse.rs
@@ -1,7 +1,6 @@
 // Test that `by_move_binding @ pat_with_by_ref_bindings` is prevented.
 
 #![feature(bindings_after_at)]
-#![feature(move_ref_pattern)]
 
 fn main() {
     struct U;
diff --git a/src/test/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse.stderr b/src/test/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse.stderr
index 86e09e55585..282031aeb07 100644
--- a/src/test/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse.stderr
+++ b/src/test/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse.stderr
@@ -1,5 +1,5 @@
 error: borrow of moved value
-  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:29:9
+  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:28:9
    |
 LL |     let a @ ref b = U;
    |         -^^^-----
@@ -9,7 +9,7 @@ LL |     let a @ ref b = U;
    |         move occurs because `a` has type `U` which does not implement the `Copy` trait
 
 error: borrow of moved value
-  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:31:9
+  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:30:9
    |
 LL |     let a @ (mut b @ ref mut c, d @ ref e) = (U, U);
    |         -^^^^^^^^^^^^---------^^^^^^-----^
@@ -20,7 +20,7 @@ LL |     let a @ (mut b @ ref mut c, d @ ref e) = (U, U);
    |         move occurs because `a` has type `(U, U)` which does not implement the `Copy` trait
 
 error: borrow of moved value
-  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:31:14
+  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:30:14
    |
 LL |     let a @ (mut b @ ref mut c, d @ ref e) = (U, U);
    |              -----^^^---------
@@ -30,7 +30,7 @@ LL |     let a @ (mut b @ ref mut c, d @ ref e) = (U, U);
    |              move occurs because `b` has type `U` which does not implement the `Copy` trait
 
 error: borrow of moved value
-  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:31:33
+  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:30:33
    |
 LL |     let a @ (mut b @ ref mut c, d @ ref e) = (U, U);
    |                                 -^^^-----
@@ -40,7 +40,7 @@ LL |     let a @ (mut b @ ref mut c, d @ ref e) = (U, U);
    |                                 move occurs because `d` has type `U` which does not implement the `Copy` trait
 
 error: borrow of moved value
-  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:38:9
+  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:37:9
    |
 LL |     let a @ [ref mut b, ref c] = [U, U];
    |         -^^^^---------^^-----^
@@ -51,7 +51,7 @@ LL |     let a @ [ref mut b, ref c] = [U, U];
    |         move occurs because `a` has type `[U; 2]` which does not implement the `Copy` trait
 
 error: borrow of moved value
-  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:41:9
+  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:40:9
    |
 LL |     let a @ ref b = u();
    |         -^^^-----
@@ -61,7 +61,7 @@ LL |     let a @ ref b = u();
    |         move occurs because `a` has type `U` which does not implement the `Copy` trait
 
 error: borrow of moved value
-  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:44:9
+  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:43:9
    |
 LL |     let a @ (mut b @ ref mut c, d @ ref e) = (u(), u());
    |         -^^^^^^^^^^^^---------^^^^^^-----^
@@ -72,7 +72,7 @@ LL |     let a @ (mut b @ ref mut c, d @ ref e) = (u(), u());
    |         move occurs because `a` has type `(U, U)` which does not implement the `Copy` trait
 
 error: borrow of moved value
-  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:44:14
+  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:43:14
    |
 LL |     let a @ (mut b @ ref mut c, d @ ref e) = (u(), u());
    |              -----^^^---------
@@ -82,7 +82,7 @@ LL |     let a @ (mut b @ ref mut c, d @ ref e) = (u(), u());
    |              move occurs because `b` has type `U` which does not implement the `Copy` trait
 
 error: borrow of moved value
-  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:44:33
+  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:43:33
    |
 LL |     let a @ (mut b @ ref mut c, d @ ref e) = (u(), u());
    |                                 -^^^-----
@@ -92,7 +92,7 @@ LL |     let a @ (mut b @ ref mut c, d @ ref e) = (u(), u());
    |                                 move occurs because `d` has type `U` which does not implement the `Copy` trait
 
 error: borrow of moved value
-  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:51:9
+  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:50:9
    |
 LL |     let a @ [ref mut b, ref c] = [u(), u()];
    |         -^^^^---------^^-----^
@@ -103,7 +103,7 @@ LL |     let a @ [ref mut b, ref c] = [u(), u()];
    |         move occurs because `a` has type `[U; 2]` which does not implement the `Copy` trait
 
 error: borrow of moved value
-  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:56:9
+  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:55:9
    |
 LL |         a @ Some(ref b) => {}
    |         -^^^^^^^^-----^
@@ -113,7 +113,7 @@ LL |         a @ Some(ref b) => {}
    |         move occurs because `a` has type `Option<U>` which does not implement the `Copy` trait
 
 error: borrow of moved value
-  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:61:9
+  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:60:9
    |
 LL |         a @ Some((mut b @ ref mut c, d @ ref e)) => {}
    |         -^^^^^^^^^^^^^^^^^---------^^^^^^-----^^
@@ -124,7 +124,7 @@ LL |         a @ Some((mut b @ ref mut c, d @ ref e)) => {}
    |         move occurs because `a` has type `Option<(U, U)>` which does not implement the `Copy` trait
 
 error: borrow of moved value
-  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:61:19
+  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:60:19
    |
 LL |         a @ Some((mut b @ ref mut c, d @ ref e)) => {}
    |                   -----^^^---------
@@ -134,7 +134,7 @@ LL |         a @ Some((mut b @ ref mut c, d @ ref e)) => {}
    |                   move occurs because `b` has type `U` which does not implement the `Copy` trait
 
 error: borrow of moved value
-  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:61:38
+  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:60:38
    |
 LL |         a @ Some((mut b @ ref mut c, d @ ref e)) => {}
    |                                      -^^^-----
@@ -144,7 +144,7 @@ LL |         a @ Some((mut b @ ref mut c, d @ ref e)) => {}
    |                                      move occurs because `d` has type `U` which does not implement the `Copy` trait
 
 error: borrow of moved value
-  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:71:9
+  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:70:9
    |
 LL |         mut a @ Some([ref b, ref mut c]) => {}
    |         -----^^^^^^^^^-----^^---------^^
@@ -155,7 +155,7 @@ LL |         mut a @ Some([ref b, ref mut c]) => {}
    |         move occurs because `a` has type `Option<[U; 2]>` which does not implement the `Copy` trait
 
 error: borrow of moved value
-  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:77:9
+  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:76:9
    |
 LL |         a @ Some(ref b) => {}
    |         -^^^^^^^^-----^
@@ -165,7 +165,7 @@ LL |         a @ Some(ref b) => {}
    |         move occurs because `a` has type `Option<U>` which does not implement the `Copy` trait
 
 error: borrow of moved value
-  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:83:9
+  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:82:9
    |
 LL |         a @ Some((mut b @ ref mut c, d @ ref e)) => {}
    |         -^^^^^^^^^^^^^^^^^---------^^^^^^-----^^
@@ -176,7 +176,7 @@ LL |         a @ Some((mut b @ ref mut c, d @ ref e)) => {}
    |         move occurs because `a` has type `Option<(U, U)>` which does not implement the `Copy` trait
 
 error: borrow of moved value
-  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:83:19
+  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:82:19
    |
 LL |         a @ Some((mut b @ ref mut c, d @ ref e)) => {}
    |                   -----^^^---------
@@ -186,7 +186,7 @@ LL |         a @ Some((mut b @ ref mut c, d @ ref e)) => {}
    |                   move occurs because `b` has type `U` which does not implement the `Copy` trait
 
 error: borrow of moved value
-  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:83:38
+  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:82:38
    |
 LL |         a @ Some((mut b @ ref mut c, d @ ref e)) => {}
    |                                      -^^^-----
@@ -196,7 +196,7 @@ LL |         a @ Some((mut b @ ref mut c, d @ ref e)) => {}
    |                                      move occurs because `d` has type `U` which does not implement the `Copy` trait
 
 error: borrow of moved value
-  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:93:9
+  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:92:9
    |
 LL |         mut a @ Some([ref b, ref mut c]) => {}
    |         -----^^^^^^^^^-----^^---------^^
@@ -207,7 +207,7 @@ LL |         mut a @ Some([ref b, ref mut c]) => {}
    |         move occurs because `a` has type `Option<[U; 2]>` which does not implement the `Copy` trait
 
 error: borrow of moved value
-  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:14:11
+  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:13:11
    |
 LL |     fn f1(a @ ref b: U) {}
    |           -^^^-----
@@ -217,7 +217,7 @@ LL |     fn f1(a @ ref b: U) {}
    |           move occurs because `a` has type `U` which does not implement the `Copy` trait
 
 error: borrow of moved value
-  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:18:11
+  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:17:11
    |
 LL |     fn f2(mut a @ (b @ ref c, mut d @ ref e): (U, U)) {}
    |           -----^^^^^^^^-----^^^^^^^^^^-----^
@@ -228,7 +228,7 @@ LL |     fn f2(mut a @ (b @ ref c, mut d @ ref e): (U, U)) {}
    |           move occurs because `a` has type `(U, U)` which does not implement the `Copy` trait
 
 error: borrow of moved value
-  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:18:20
+  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:17:20
    |
 LL |     fn f2(mut a @ (b @ ref c, mut d @ ref e): (U, U)) {}
    |                    -^^^-----
@@ -238,7 +238,7 @@ LL |     fn f2(mut a @ (b @ ref c, mut d @ ref e): (U, U)) {}
    |                    move occurs because `b` has type `U` which does not implement the `Copy` trait
 
 error: borrow of moved value
-  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:18:31
+  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:17:31
    |
 LL |     fn f2(mut a @ (b @ ref c, mut d @ ref e): (U, U)) {}
    |                               -----^^^-----
@@ -248,7 +248,7 @@ LL |     fn f2(mut a @ (b @ ref c, mut d @ ref e): (U, U)) {}
    |                               move occurs because `d` has type `U` which does not implement the `Copy` trait
 
 error: borrow of moved value
-  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:25:11
+  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:24:11
    |
 LL |     fn f3(a @ [ref mut b, ref c]: [U; 2]) {}
    |           -^^^^---------^^-----^
@@ -259,7 +259,7 @@ LL |     fn f3(a @ [ref mut b, ref c]: [U; 2]) {}
    |           move occurs because `a` has type `[U; 2]` which does not implement the `Copy` trait
 
 error[E0382]: borrow of moved value
-  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:31:22
+  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:30:22
    |
 LL |     let a @ (mut b @ ref mut c, d @ ref e) = (U, U);
    |              --------^^^^^^^^^
@@ -270,7 +270,7 @@ LL |     let a @ (mut b @ ref mut c, d @ ref e) = (U, U);
    = note: move occurs because value has type `U`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value
-  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:31:33
+  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:30:33
    |
 LL |     let a @ (mut b @ ref mut c, d @ ref e) = (U, U);
    |         ------------------------^^^^^^^^^-   ------ move occurs because value has type `(U, U)`, which does not implement the `Copy` trait
@@ -279,7 +279,7 @@ LL |     let a @ (mut b @ ref mut c, d @ ref e) = (U, U);
    |         value moved here
 
 error[E0382]: borrow of moved value
-  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:31:37
+  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:30:37
    |
 LL |     let a @ (mut b @ ref mut c, d @ ref e) = (U, U);
    |                                 ----^^^^^
@@ -290,7 +290,7 @@ LL |     let a @ (mut b @ ref mut c, d @ ref e) = (U, U);
    = note: move occurs because value has type `U`, which does not implement the `Copy` trait
 
 error[E0382]: borrow of moved value
-  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:38:25
+  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:37:25
    |
 LL |     let a @ [ref mut b, ref c] = [U, U];
    |         ----------------^^^^^-   ------ move occurs because value has type `[U; 2]`, which does not implement the `Copy` trait
@@ -299,7 +299,7 @@ LL |     let a @ [ref mut b, ref c] = [U, U];
    |         value moved here
 
 error[E0382]: borrow of moved value
-  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:41:13
+  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:40:13
    |
 LL |     let a @ ref b = u();
    |         ----^^^^^   --- move occurs because value has type `U`, which does not implement the `Copy` trait
@@ -308,7 +308,7 @@ LL |     let a @ ref b = u();
    |         value moved here
 
 error[E0382]: borrow of moved value
-  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:44:22
+  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:43:22
    |
 LL |     let a @ (mut b @ ref mut c, d @ ref e) = (u(), u());
    |              --------^^^^^^^^^
@@ -319,7 +319,7 @@ LL |     let a @ (mut b @ ref mut c, d @ ref e) = (u(), u());
    = note: move occurs because value has type `U`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value
-  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:44:33
+  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:43:33
    |
 LL |     let a @ (mut b @ ref mut c, d @ ref e) = (u(), u());
    |         ------------------------^^^^^^^^^-   ---------- move occurs because value has type `(U, U)`, which does not implement the `Copy` trait
@@ -328,7 +328,7 @@ LL |     let a @ (mut b @ ref mut c, d @ ref e) = (u(), u());
    |         value moved here
 
 error[E0382]: borrow of moved value
-  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:44:37
+  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:43:37
    |
 LL |     let a @ (mut b @ ref mut c, d @ ref e) = (u(), u());
    |                                 ----^^^^^
@@ -339,7 +339,7 @@ LL |     let a @ (mut b @ ref mut c, d @ ref e) = (u(), u());
    = note: move occurs because value has type `U`, which does not implement the `Copy` trait
 
 error[E0382]: borrow of moved value
-  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:51:25
+  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:50:25
    |
 LL |     let a @ [ref mut b, ref c] = [u(), u()];
    |         ----------------^^^^^-   ---------- move occurs because value has type `[U; 2]`, which does not implement the `Copy` trait
@@ -348,7 +348,7 @@ LL |     let a @ [ref mut b, ref c] = [u(), u()];
    |         value moved here
 
 error[E0382]: borrow of moved value
-  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:61:27
+  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:60:27
    |
 LL |         a @ Some((mut b @ ref mut c, d @ ref e)) => {}
    |                   --------^^^^^^^^^
@@ -363,7 +363,7 @@ LL |         a @ Some((ref mut b @ ref mut c, d @ ref e)) => {}
    |                   ^^^
 
 error[E0382]: use of moved value
-  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:61:38
+  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:60:38
    |
 LL |     match Some((U, U)) {
    |           ------------ move occurs because value has type `Option<(U, U)>`, which does not implement the `Copy` trait
@@ -374,7 +374,7 @@ LL |         a @ Some((mut b @ ref mut c, d @ ref e)) => {}
    |         value moved here
 
 error[E0382]: borrow of moved value
-  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:61:42
+  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:60:42
    |
 LL |         a @ Some((mut b @ ref mut c, d @ ref e)) => {}
    |                                      ----^^^^^
@@ -389,7 +389,7 @@ LL |         a @ Some((mut b @ ref mut c, ref d @ ref e)) => {}
    |                                      ^^^
 
 error[E0382]: borrow of moved value
-  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:71:30
+  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:70:30
    |
 LL |     match Some([U, U]) {
    |           ------------ move occurs because value has type `Option<[U; 2]>`, which does not implement the `Copy` trait
@@ -400,7 +400,7 @@ LL |         mut a @ Some([ref b, ref mut c]) => {}
    |         value moved here
 
 error[E0382]: borrow of moved value
-  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:77:18
+  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:76:18
    |
 LL |     match Some(u()) {
    |           --------- move occurs because value has type `Option<U>`, which does not implement the `Copy` trait
@@ -411,7 +411,7 @@ LL |         a @ Some(ref b) => {}
    |         value moved here
 
 error[E0382]: borrow of moved value
-  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:83:27
+  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:82:27
    |
 LL |         a @ Some((mut b @ ref mut c, d @ ref e)) => {}
    |                   --------^^^^^^^^^
@@ -426,7 +426,7 @@ LL |         a @ Some((ref mut b @ ref mut c, d @ ref e)) => {}
    |                   ^^^
 
 error[E0382]: use of moved value
-  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:83:38
+  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:82:38
    |
 LL |     match Some((u(), u())) {
    |           ---------------- move occurs because value has type `Option<(U, U)>`, which does not implement the `Copy` trait
@@ -437,7 +437,7 @@ LL |         a @ Some((mut b @ ref mut c, d @ ref e)) => {}
    |         value moved here
 
 error[E0382]: borrow of moved value
-  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:83:42
+  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:82:42
    |
 LL |         a @ Some((mut b @ ref mut c, d @ ref e)) => {}
    |                                      ----^^^^^
@@ -452,7 +452,7 @@ LL |         a @ Some((mut b @ ref mut c, ref d @ ref e)) => {}
    |                                      ^^^
 
 error[E0382]: borrow of moved value
-  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:93:30
+  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:92:30
    |
 LL |     match Some([u(), u()]) {
    |           ---------------- move occurs because value has type `Option<[U; 2]>`, which does not implement the `Copy` trait
@@ -463,7 +463,7 @@ LL |         mut a @ Some([ref b, ref mut c]) => {}
    |         value moved here
 
 error[E0382]: borrow of moved value
-  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:14:15
+  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:13:15
    |
 LL |     fn f1(a @ ref b: U) {}
    |           ----^^^^^
@@ -473,7 +473,7 @@ LL |     fn f1(a @ ref b: U) {}
    |           move occurs because value has type `U`, which does not implement the `Copy` trait
 
 error[E0382]: borrow of moved value
-  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:18:24
+  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:17:24
    |
 LL |     fn f2(mut a @ (b @ ref c, mut d @ ref e): (U, U)) {}
    |                    ----^^^^^
@@ -484,7 +484,7 @@ LL |     fn f2(mut a @ (b @ ref c, mut d @ ref e): (U, U)) {}
    = note: move occurs because value has type `U`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value
-  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:18:31
+  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:17:31
    |
 LL |     fn f2(mut a @ (b @ ref c, mut d @ ref e): (U, U)) {}
    |           --------------------^^^^^^^^^^^^^-
@@ -494,7 +494,7 @@ LL |     fn f2(mut a @ (b @ ref c, mut d @ ref e): (U, U)) {}
    |           move occurs because value has type `(U, U)`, which does not implement the `Copy` trait
 
 error[E0382]: borrow of moved value
-  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:18:39
+  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:17:39
    |
 LL |     fn f2(mut a @ (b @ ref c, mut d @ ref e): (U, U)) {}
    |                               --------^^^^^
@@ -505,7 +505,7 @@ LL |     fn f2(mut a @ (b @ ref c, mut d @ ref e): (U, U)) {}
    = note: move occurs because value has type `U`, which does not implement the `Copy` trait
 
 error[E0382]: borrow of moved value
-  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:25:27
+  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:24:27
    |
 LL |     fn f3(a @ [ref mut b, ref c]: [U; 2]) {}
    |           ----------------^^^^^-
diff --git a/src/test/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref.rs b/src/test/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref.rs
index b7c8c8766c0..42c3290ddfb 100644
--- a/src/test/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref.rs
+++ b/src/test/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref.rs
@@ -1,7 +1,6 @@
 // Test that `ref mut? @ pat_with_by_move_bindings` is prevented.
 
 #![feature(bindings_after_at)]
-#![feature(move_ref_pattern)]
 
 fn main() {
     struct U;
diff --git a/src/test/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref.stderr b/src/test/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref.stderr
index e5419efa00b..a275705b193 100644
--- a/src/test/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref.stderr
+++ b/src/test/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref.stderr
@@ -1,5 +1,5 @@
 error: cannot move out of value because it is borrowed
-  --> $DIR/borrowck-pat-by-move-and-ref.rs:23:9
+  --> $DIR/borrowck-pat-by-move-and-ref.rs:22:9
    |
 LL |     let ref a @ b = U;
    |         -----^^^-
@@ -8,7 +8,7 @@ LL |     let ref a @ b = U;
    |         value borrowed, by `a`, here
 
 error: cannot move out of value because it is borrowed
-  --> $DIR/borrowck-pat-by-move-and-ref.rs:25:9
+  --> $DIR/borrowck-pat-by-move-and-ref.rs:24:9
    |
 LL |     let ref a @ (ref b @ mut c, ref d @ e) = (U, U);
    |         -----^^^^^^^^^^^^-----^^^^^^^^^^-^
@@ -18,7 +18,7 @@ LL |     let ref a @ (ref b @ mut c, ref d @ e) = (U, U);
    |         value borrowed, by `a`, here
 
 error: cannot move out of value because it is borrowed
-  --> $DIR/borrowck-pat-by-move-and-ref.rs:25:18
+  --> $DIR/borrowck-pat-by-move-and-ref.rs:24:18
    |
 LL |     let ref a @ (ref b @ mut c, ref d @ e) = (U, U);
    |                  -----^^^-----
@@ -27,7 +27,7 @@ LL |     let ref a @ (ref b @ mut c, ref d @ e) = (U, U);
    |                  value borrowed, by `b`, here
 
 error: cannot move out of value because it is borrowed
-  --> $DIR/borrowck-pat-by-move-and-ref.rs:25:33
+  --> $DIR/borrowck-pat-by-move-and-ref.rs:24:33
    |
 LL |     let ref a @ (ref b @ mut c, ref d @ e) = (U, U);
    |                                 -----^^^-
@@ -36,7 +36,7 @@ LL |     let ref a @ (ref b @ mut c, ref d @ e) = (U, U);
    |                                 value borrowed, by `d`, here
 
 error: cannot move out of value because it is borrowed
-  --> $DIR/borrowck-pat-by-move-and-ref.rs:29:9
+  --> $DIR/borrowck-pat-by-move-and-ref.rs:28:9
    |
 LL |     let ref mut a @ [b, mut c] = [U, U];
    |         ---------^^^^-^^-----^
@@ -46,7 +46,7 @@ LL |     let ref mut a @ [b, mut c] = [U, U];
    |         value borrowed, by `a`, here
 
 error: cannot move out of value because it is borrowed
-  --> $DIR/borrowck-pat-by-move-and-ref.rs:31:9
+  --> $DIR/borrowck-pat-by-move-and-ref.rs:30:9
    |
 LL |     let ref a @ b = u();
    |         -----^^^-
@@ -55,7 +55,7 @@ LL |     let ref a @ b = u();
    |         value borrowed, by `a`, here
 
 error: cannot move out of value because it is borrowed
-  --> $DIR/borrowck-pat-by-move-and-ref.rs:33:9
+  --> $DIR/borrowck-pat-by-move-and-ref.rs:32:9
    |
 LL |     let ref a @ (ref b @ mut c, ref d @ e) = (u(), u());
    |         -----^^^^^^^^^^^^-----^^^^^^^^^^-^
@@ -65,7 +65,7 @@ LL |     let ref a @ (ref b @ mut c, ref d @ e) = (u(), u());
    |         value borrowed, by `a`, here
 
 error: cannot move out of value because it is borrowed
-  --> $DIR/borrowck-pat-by-move-and-ref.rs:33:18
+  --> $DIR/borrowck-pat-by-move-and-ref.rs:32:18
    |
 LL |     let ref a @ (ref b @ mut c, ref d @ e) = (u(), u());
    |                  -----^^^-----
@@ -74,7 +74,7 @@ LL |     let ref a @ (ref b @ mut c, ref d @ e) = (u(), u());
    |                  value borrowed, by `b`, here
 
 error: cannot move out of value because it is borrowed
-  --> $DIR/borrowck-pat-by-move-and-ref.rs:33:33
+  --> $DIR/borrowck-pat-by-move-and-ref.rs:32:33
    |
 LL |     let ref a @ (ref b @ mut c, ref d @ e) = (u(), u());
    |                                 -----^^^-
@@ -83,7 +83,7 @@ LL |     let ref a @ (ref b @ mut c, ref d @ e) = (u(), u());
    |                                 value borrowed, by `d`, here
 
 error: cannot move out of value because it is borrowed
-  --> $DIR/borrowck-pat-by-move-and-ref.rs:37:9
+  --> $DIR/borrowck-pat-by-move-and-ref.rs:36:9
    |
 LL |     let ref mut a @ [b, mut c] = [u(), u()];
    |         ---------^^^^-^^-----^
@@ -93,7 +93,7 @@ LL |     let ref mut a @ [b, mut c] = [u(), u()];
    |         value borrowed, by `a`, here
 
 error: cannot move out of value because it is borrowed
-  --> $DIR/borrowck-pat-by-move-and-ref.rs:41:9
+  --> $DIR/borrowck-pat-by-move-and-ref.rs:40:9
    |
 LL |         ref a @ Some(b) => {}
    |         -----^^^^^^^^-^
@@ -102,7 +102,7 @@ LL |         ref a @ Some(b) => {}
    |         value borrowed, by `a`, here
 
 error: cannot move out of value because it is borrowed
-  --> $DIR/borrowck-pat-by-move-and-ref.rs:46:9
+  --> $DIR/borrowck-pat-by-move-and-ref.rs:45:9
    |
 LL |         ref a @ Some((ref b @ mut c, ref d @ e)) => {}
    |         -----^^^^^^^^^^^^^^^^^-----^^^^^^^^^^-^^
@@ -112,7 +112,7 @@ LL |         ref a @ Some((ref b @ mut c, ref d @ e)) => {}
    |         value borrowed, by `a`, here
 
 error: cannot move out of value because it is borrowed
-  --> $DIR/borrowck-pat-by-move-and-ref.rs:46:23
+  --> $DIR/borrowck-pat-by-move-and-ref.rs:45:23
    |
 LL |         ref a @ Some((ref b @ mut c, ref d @ e)) => {}
    |                       -----^^^-----
@@ -121,7 +121,7 @@ LL |         ref a @ Some((ref b @ mut c, ref d @ e)) => {}
    |                       value borrowed, by `b`, here
 
 error: cannot move out of value because it is borrowed
-  --> $DIR/borrowck-pat-by-move-and-ref.rs:46:38
+  --> $DIR/borrowck-pat-by-move-and-ref.rs:45:38
    |
 LL |         ref a @ Some((ref b @ mut c, ref d @ e)) => {}
    |                                      -----^^^-
@@ -130,7 +130,7 @@ LL |         ref a @ Some((ref b @ mut c, ref d @ e)) => {}
    |                                      value borrowed, by `d`, here
 
 error: cannot move out of value because it is borrowed
-  --> $DIR/borrowck-pat-by-move-and-ref.rs:53:9
+  --> $DIR/borrowck-pat-by-move-and-ref.rs:52:9
    |
 LL |         ref mut a @ Some([b, mut c]) => {}
    |         ---------^^^^^^^^^-^^-----^^
@@ -140,7 +140,7 @@ LL |         ref mut a @ Some([b, mut c]) => {}
    |         value borrowed, by `a`, here
 
 error: cannot move out of value because it is borrowed
-  --> $DIR/borrowck-pat-by-move-and-ref.rs:58:9
+  --> $DIR/borrowck-pat-by-move-and-ref.rs:57:9
    |
 LL |         ref a @ Some(b) => {}
    |         -----^^^^^^^^-^
@@ -149,7 +149,7 @@ LL |         ref a @ Some(b) => {}
    |         value borrowed, by `a`, here
 
 error: cannot move out of value because it is borrowed
-  --> $DIR/borrowck-pat-by-move-and-ref.rs:63:9
+  --> $DIR/borrowck-pat-by-move-and-ref.rs:62:9
    |
 LL |         ref a @ Some((ref b @ mut c, ref d @ e)) => {}
    |         -----^^^^^^^^^^^^^^^^^-----^^^^^^^^^^-^^
@@ -159,7 +159,7 @@ LL |         ref a @ Some((ref b @ mut c, ref d @ e)) => {}
    |         value borrowed, by `a`, here
 
 error: cannot move out of value because it is borrowed
-  --> $DIR/borrowck-pat-by-move-and-ref.rs:63:23
+  --> $DIR/borrowck-pat-by-move-and-ref.rs:62:23
    |
 LL |         ref a @ Some((ref b @ mut c, ref d @ e)) => {}
    |                       -----^^^-----
@@ -168,7 +168,7 @@ LL |         ref a @ Some((ref b @ mut c, ref d @ e)) => {}
    |                       value borrowed, by `b`, here
 
 error: cannot move out of value because it is borrowed
-  --> $DIR/borrowck-pat-by-move-and-ref.rs:63:38
+  --> $DIR/borrowck-pat-by-move-and-ref.rs:62:38
    |
 LL |         ref a @ Some((ref b @ mut c, ref d @ e)) => {}
    |                                      -----^^^-
@@ -177,7 +177,7 @@ LL |         ref a @ Some((ref b @ mut c, ref d @ e)) => {}
    |                                      value borrowed, by `d`, here
 
 error: cannot move out of value because it is borrowed
-  --> $DIR/borrowck-pat-by-move-and-ref.rs:70:9
+  --> $DIR/borrowck-pat-by-move-and-ref.rs:69:9
    |
 LL |         ref mut a @ Some([b, mut c]) => {}
    |         ---------^^^^^^^^^-^^-----^^
@@ -187,7 +187,7 @@ LL |         ref mut a @ Some([b, mut c]) => {}
    |         value borrowed, by `a`, here
 
 error: cannot move out of value because it is borrowed
-  --> $DIR/borrowck-pat-by-move-and-ref.rs:14:11
+  --> $DIR/borrowck-pat-by-move-and-ref.rs:13:11
    |
 LL |     fn f1(ref a @ b: U) {}
    |           -----^^^-
@@ -196,7 +196,7 @@ LL |     fn f1(ref a @ b: U) {}
    |           value borrowed, by `a`, here
 
 error: cannot move out of value because it is borrowed
-  --> $DIR/borrowck-pat-by-move-and-ref.rs:16:11
+  --> $DIR/borrowck-pat-by-move-and-ref.rs:15:11
    |
 LL |     fn f2(ref a @ (ref b @ mut c, ref d @ e): (U, U)) {}
    |           -----^^^^^^^^^^^^-----^^^^^^^^^^-^
@@ -206,7 +206,7 @@ LL |     fn f2(ref a @ (ref b @ mut c, ref d @ e): (U, U)) {}
    |           value borrowed, by `a`, here
 
 error: cannot move out of value because it is borrowed
-  --> $DIR/borrowck-pat-by-move-and-ref.rs:16:20
+  --> $DIR/borrowck-pat-by-move-and-ref.rs:15:20
    |
 LL |     fn f2(ref a @ (ref b @ mut c, ref d @ e): (U, U)) {}
    |                    -----^^^-----
@@ -215,7 +215,7 @@ LL |     fn f2(ref a @ (ref b @ mut c, ref d @ e): (U, U)) {}
    |                    value borrowed, by `b`, here
 
 error: cannot move out of value because it is borrowed
-  --> $DIR/borrowck-pat-by-move-and-ref.rs:16:35
+  --> $DIR/borrowck-pat-by-move-and-ref.rs:15:35
    |
 LL |     fn f2(ref a @ (ref b @ mut c, ref d @ e): (U, U)) {}
    |                                   -----^^^-
@@ -224,7 +224,7 @@ LL |     fn f2(ref a @ (ref b @ mut c, ref d @ e): (U, U)) {}
    |                                   value borrowed, by `d`, here
 
 error: cannot move out of value because it is borrowed
-  --> $DIR/borrowck-pat-by-move-and-ref.rs:20:11
+  --> $DIR/borrowck-pat-by-move-and-ref.rs:19:11
    |
 LL |     fn f3(ref mut a @ [b, mut c]: [U; 2]) {}
    |           ---------^^^^-^^-----^
diff --git a/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.rs b/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.rs
index 2b5e339c639..f67cd45ca95 100644
--- a/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.rs
+++ b/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.rs
@@ -1,5 +1,4 @@
 #![feature(bindings_after_at)]
-#![feature(move_ref_pattern)]
 
 enum Option<T> {
     None,
diff --git a/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.stderr b/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.stderr
index 695da9639af..e6231dd49ba 100644
--- a/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.stderr
+++ b/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.stderr
@@ -1,5 +1,5 @@
 error: cannot borrow value as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:11:9
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:10:9
    |
 LL |         ref mut z @ &mut Some(ref a) => {
    |         ---------^^^^^^^^^^^^^-----^
@@ -8,7 +8,7 @@ LL |         ref mut z @ &mut Some(ref a) => {
    |         mutable borrow, by `z`, occurs here
 
 error: cannot borrow value as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:35:9
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:34:9
    |
 LL |     let ref mut a @ (ref b @ ref mut c) = u(); // sub-in-sub
    |         ---------^^^^-----------------^
@@ -18,7 +18,7 @@ LL |     let ref mut a @ (ref b @ ref mut c) = u(); // sub-in-sub
    |         first mutable borrow, by `a`, occurs here
 
 error: cannot borrow value as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:35:22
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:34:22
    |
 LL |     let ref mut a @ (ref b @ ref mut c) = u(); // sub-in-sub
    |                      -----^^^---------
@@ -27,7 +27,7 @@ LL |     let ref mut a @ (ref b @ ref mut c) = u(); // sub-in-sub
    |                      immutable borrow, by `b`, occurs here
 
 error: cannot borrow value as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:39:9
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:38:9
    |
 LL |     let ref a @ ref mut b = U;
    |         -----^^^---------
@@ -36,7 +36,7 @@ LL |     let ref a @ ref mut b = U;
    |         immutable borrow, by `a`, occurs here
 
 error: cannot borrow value as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:41:9
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:40:9
    |
 LL |     let ref mut a @ ref b = U;
    |         ---------^^^-----
@@ -45,7 +45,7 @@ LL |     let ref mut a @ ref b = U;
    |         mutable borrow, by `a`, occurs here
 
 error: cannot borrow value as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:43:9
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:42:9
    |
 LL |     let ref a @ (ref mut b, ref mut c) = (U, U);
    |         -----^^^^---------^^---------^
@@ -55,7 +55,7 @@ LL |     let ref a @ (ref mut b, ref mut c) = (U, U);
    |         immutable borrow, by `a`, occurs here
 
 error: cannot borrow value as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:45:9
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:44:9
    |
 LL |     let ref mut a @ (ref b, ref c) = (U, U);
    |         ---------^^^^-----^^-----^
@@ -65,7 +65,7 @@ LL |     let ref mut a @ (ref b, ref c) = (U, U);
    |         mutable borrow, by `a`, occurs here
 
 error: cannot borrow value as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:48:9
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:47:9
    |
 LL |     let ref mut a @ ref b = u();
    |         ---------^^^-----
@@ -74,7 +74,7 @@ LL |     let ref mut a @ ref b = u();
    |         mutable borrow, by `a`, occurs here
 
 error: cannot borrow value as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:53:9
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:52:9
    |
 LL |     let ref a @ ref mut b = u();
    |         -----^^^---------
@@ -83,7 +83,7 @@ LL |     let ref a @ ref mut b = u();
    |         immutable borrow, by `a`, occurs here
 
 error: cannot borrow value as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:59:9
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:58:9
    |
 LL |     let ref mut a @ ref b = U;
    |         ---------^^^-----
@@ -92,7 +92,7 @@ LL |     let ref mut a @ ref b = U;
    |         mutable borrow, by `a`, occurs here
 
 error: cannot borrow value as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:63:9
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:62:9
    |
 LL |     let ref a @ ref mut b = U;
    |         -----^^^---------
@@ -101,7 +101,7 @@ LL |     let ref a @ ref mut b = U;
    |         immutable borrow, by `a`, occurs here
 
 error: cannot borrow value as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:69:9
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:68:9
    |
 LL |         ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) => {
    |         ---------^^^^^^-----^
@@ -110,7 +110,7 @@ LL |         ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) => {
    |         mutable borrow, by `a`, occurs here
 
 error: cannot borrow value as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:69:33
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:68:33
    |
 LL |         ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) => {
    |                                 ---------^^^^^^^-----^
@@ -119,7 +119,7 @@ LL |         ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) => {
    |                                 mutable borrow, by `a`, occurs here
 
 error: cannot borrow value as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:78:9
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:77:9
    |
 LL |         ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) => {
    |         -----^^^^^^---------^
@@ -128,7 +128,7 @@ LL |         ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) => {
    |         immutable borrow, by `a`, occurs here
 
 error: cannot borrow value as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:78:33
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:77:33
    |
 LL |         ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) => {
    |                                 -----^^^^^^^---------^
@@ -137,7 +137,7 @@ LL |         ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) => {
    |                                 immutable borrow, by `a`, occurs here
 
 error: cannot borrow value as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:89:9
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:88:9
    |
 LL |         ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { *b = U; false } => {}
    |         -----^^^^^^---------^
@@ -146,7 +146,7 @@ LL |         ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { *b = U; false }
    |         immutable borrow, by `a`, occurs here
 
 error: cannot borrow value as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:89:33
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:88:33
    |
 LL |         ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { *b = U; false } => {}
    |                                 -----^^^^^^^---------^
@@ -155,7 +155,7 @@ LL |         ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { *b = U; false }
    |                                 immutable borrow, by `a`, occurs here
 
 error: cannot borrow value as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:96:9
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:95:9
    |
 LL |         ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { *a = Err(U); false } => {}
    |         ---------^^^^^^-----^
@@ -164,7 +164,7 @@ LL |         ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { *a = Err(U); fa
    |         mutable borrow, by `a`, occurs here
 
 error: cannot borrow value as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:96:33
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:95:33
    |
 LL |         ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { *a = Err(U); false } => {}
    |                                 ---------^^^^^^^-----^
@@ -173,7 +173,7 @@ LL |         ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { *a = Err(U); fa
    |                                 mutable borrow, by `a`, occurs here
 
 error: cannot borrow value as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:103:9
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:102:9
    |
 LL |         ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false } => {}
    |         -----^^^^^^---------^
@@ -182,7 +182,7 @@ LL |         ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false
    |         immutable borrow, by `a`, occurs here
 
 error: cannot borrow value as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:103:33
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:102:33
    |
 LL |         ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false } => {}
    |                                 -----^^^^^^^---------^
@@ -191,7 +191,7 @@ LL |         ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false
    |                                 immutable borrow, by `a`, occurs here
 
 error: cannot borrow value as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:111:9
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:110:9
    |
 LL |         ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false } => {}
    |         ---------^^^^^^-----^
@@ -200,7 +200,7 @@ LL |         ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false
    |         mutable borrow, by `a`, occurs here
 
 error: cannot borrow value as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:111:33
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:110:33
    |
 LL |         ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false } => {}
    |                                 ---------^^^^^^^-----^
@@ -209,7 +209,7 @@ LL |         ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false
    |                                 mutable borrow, by `a`, occurs here
 
 error: cannot borrow value as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:119:9
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:118:9
    |
 LL |     let ref a @ (ref mut b, ref mut c) = (U, U);
    |         -----^^^^---------^^---------^
@@ -219,7 +219,7 @@ LL |     let ref a @ (ref mut b, ref mut c) = (U, U);
    |         immutable borrow, by `a`, occurs here
 
 error: cannot borrow value as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:124:9
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:123:9
    |
 LL |     let ref a @ (ref mut b, ref mut c) = (U, U);
    |         -----^^^^---------^^---------^
@@ -229,7 +229,7 @@ LL |     let ref a @ (ref mut b, ref mut c) = (U, U);
    |         immutable borrow, by `a`, occurs here
 
 error: cannot borrow value as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:131:9
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:130:9
    |
 LL |     let ref a @ (ref mut b, ref mut c) = (U, U);
    |         -----^^^^---------^^---------^
@@ -239,7 +239,7 @@ LL |     let ref a @ (ref mut b, ref mut c) = (U, U);
    |         immutable borrow, by `a`, occurs here
 
 error: cannot borrow value as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:136:9
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:135:9
    |
 LL |     let ref mut a @ (ref b, ref c) = (U, U);
    |         ---------^^^^-----^^-----^
@@ -249,7 +249,7 @@ LL |     let ref mut a @ (ref b, ref c) = (U, U);
    |         mutable borrow, by `a`, occurs here
 
 error: cannot borrow value as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:25:11
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:24:11
    |
 LL |     fn f1(ref a @ ref mut b: U) {}
    |           -----^^^---------
@@ -258,7 +258,7 @@ LL |     fn f1(ref a @ ref mut b: U) {}
    |           immutable borrow, by `a`, occurs here
 
 error: cannot borrow value as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:27:11
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:26:11
    |
 LL |     fn f2(ref mut a @ ref b: U) {}
    |           ---------^^^-----
@@ -267,7 +267,7 @@ LL |     fn f2(ref mut a @ ref b: U) {}
    |           mutable borrow, by `a`, occurs here
 
 error: cannot borrow value as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:29:11
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:28:11
    |
 LL |     fn f3(ref a @ [ref b, ref mut mid @ .., ref c]: [U; 4]) {}
    |           -----^^^^^^^^^^^----------------^^^^^^^^
@@ -276,7 +276,7 @@ LL |     fn f3(ref a @ [ref b, ref mut mid @ .., ref c]: [U; 4]) {}
    |           immutable borrow, by `a`, occurs here
 
 error: cannot borrow value as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:31:22
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:30:22
    |
 LL |     fn f4_also_moved(ref a @ ref mut b @ c: U) {}
    |                      -----^^^-------------
@@ -286,7 +286,7 @@ LL |     fn f4_also_moved(ref a @ ref mut b @ c: U) {}
    |                      immutable borrow, by `a`, occurs here
 
 error: cannot move out of value because it is borrowed
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:31:30
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:30:30
    |
 LL |     fn f4_also_moved(ref a @ ref mut b @ c: U) {}
    |                              ---------^^^-
@@ -295,7 +295,7 @@ LL |     fn f4_also_moved(ref a @ ref mut b @ c: U) {}
    |                              value borrowed, by `b`, here
 
 error[E0502]: cannot borrow value as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:11:31
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:10:31
    |
 LL |         ref mut z @ &mut Some(ref a) => {
    |         ----------------------^^^^^-
@@ -307,7 +307,7 @@ LL |             **z = None;
    |             ---------- mutable borrow later used here
 
 error[E0502]: cannot borrow value as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:48:21
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:47:21
    |
 LL |     let ref mut a @ ref b = u();
    |         ------------^^^^^
@@ -319,7 +319,7 @@ LL |     *a = u();
    |     -------- mutable borrow later used here
 
 error[E0502]: cannot borrow value as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:53:17
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:52:17
    |
 LL |     let ref a @ ref mut b = u();
    |         --------^^^^^^^^^
@@ -331,7 +331,7 @@ LL |     drop(a);
    |          - immutable borrow later used here
 
 error[E0502]: cannot borrow value as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:78:20
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:77:20
    |
 LL |         ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) => {
    |         -----------^^^^^^^^^-
@@ -343,7 +343,7 @@ LL |             drop(a);
    |                  - immutable borrow later used here
 
 error[E0502]: cannot borrow value as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:78:45
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:77:45
    |
 LL |         ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) => {
    |                                 ------------^^^^^^^^^-
@@ -355,7 +355,7 @@ LL |             drop(a);
    |                  - immutable borrow later used here
 
 error[E0594]: cannot assign to `*b`, as it is immutable for the pattern guard
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:89:61
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:88:61
    |
 LL |         ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { *b = U; false } => {}
    |                                                             ^^^^^^ cannot assign
@@ -363,7 +363,7 @@ LL |         ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { *b = U; false }
    = note: variables bound in patterns are immutable until the end of the pattern guard
 
 error[E0594]: cannot assign to `*a`, as it is immutable for the pattern guard
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:96:61
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:95:61
    |
 LL |         ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { *a = Err(U); false } => {}
    |                                                             ^^^^^^^^^^^ cannot assign
@@ -371,7 +371,7 @@ LL |         ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { *a = Err(U); fa
    = note: variables bound in patterns are immutable until the end of the pattern guard
 
 error[E0507]: cannot move out of `b` in pattern guard
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:103:66
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:102:66
    |
 LL |         ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false } => {}
    |                                                                  ^ move occurs because `b` has type `&mut U`, which does not implement the `Copy` trait
@@ -379,7 +379,7 @@ LL |         ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false
    = note: variables bound in patterns cannot be moved from until after the end of the pattern guard
 
 error[E0507]: cannot move out of `b` in pattern guard
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:103:66
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:102:66
    |
 LL |         ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false } => {}
    |                                                                  ^ move occurs because `b` has type `&mut U`, which does not implement the `Copy` trait
@@ -387,7 +387,7 @@ LL |         ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false
    = note: variables bound in patterns cannot be moved from until after the end of the pattern guard
 
 error[E0507]: cannot move out of `a` in pattern guard
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:111:66
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:110:66
    |
 LL |         ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false } => {}
    |                                                                  ^ move occurs because `a` has type `&mut std::result::Result<U, U>`, which does not implement the `Copy` trait
@@ -395,7 +395,7 @@ LL |         ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false
    = note: variables bound in patterns cannot be moved from until after the end of the pattern guard
 
 error[E0507]: cannot move out of `a` in pattern guard
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:111:66
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:110:66
    |
 LL |         ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false } => {}
    |                                                                  ^ move occurs because `a` has type `&mut std::result::Result<U, U>`, which does not implement the `Copy` trait
@@ -403,7 +403,7 @@ LL |         ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false
    = note: variables bound in patterns cannot be moved from until after the end of the pattern guard
 
 error[E0502]: cannot borrow value as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:124:18
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:123:18
    |
 LL |     let ref a @ (ref mut b, ref mut c) = (U, U);
    |         ---------^^^^^^^^^------------
@@ -415,7 +415,7 @@ LL |     drop(a);
    |          - immutable borrow later used here
 
 error[E0502]: cannot borrow value as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:124:29
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:123:29
    |
 LL |     let ref a @ (ref mut b, ref mut c) = (U, U);
    |         --------------------^^^^^^^^^-
@@ -427,7 +427,7 @@ LL |     drop(a);
    |          - immutable borrow later used here
 
 error[E0502]: cannot borrow value as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:131:18
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:130:18
    |
 LL |     let ref a @ (ref mut b, ref mut c) = (U, U);
    |         ---------^^^^^^^^^------------
@@ -439,7 +439,7 @@ LL |     drop(a);
    |          - immutable borrow later used here
 
 error[E0502]: cannot borrow value as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:131:29
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:130:29
    |
 LL |     let ref a @ (ref mut b, ref mut c) = (U, U);
    |         --------------------^^^^^^^^^-
diff --git a/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.rs b/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.rs
index a208d0087ff..8faaa1c881f 100644
--- a/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.rs
+++ b/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.rs
@@ -1,7 +1,6 @@
 // Test that `ref mut x @ ref mut y` and varieties of that are not allowed.
 
 #![feature(bindings_after_at)]
-#![feature(move_ref_pattern)]
 
 fn main() {
     struct U;
diff --git a/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.stderr b/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.stderr
index 1cd3e267b99..2e0f5fcabdd 100644
--- a/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.stderr
+++ b/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.stderr
@@ -1,5 +1,5 @@
 error: cannot borrow value as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:28:9
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:27:9
    |
 LL |     let ref mut a @ ref mut b = U;
    |         ---------^^^---------
@@ -8,7 +8,7 @@ LL |     let ref mut a @ ref mut b = U;
    |         first mutable borrow, by `a`, occurs here
 
 error: cannot borrow value as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:32:9
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:31:9
    |
 LL |     let ref mut a @ ref mut b = U;
    |         ---------^^^---------
@@ -17,7 +17,7 @@ LL |     let ref mut a @ ref mut b = U;
    |         first mutable borrow, by `a`, occurs here
 
 error: cannot borrow value as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:35:9
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:34:9
    |
 LL |     let ref mut a @ ref mut b = U;
    |         ---------^^^---------
@@ -26,7 +26,7 @@ LL |     let ref mut a @ ref mut b = U;
    |         first mutable borrow, by `a`, occurs here
 
 error: cannot borrow value as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:38:9
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:37:9
    |
 LL |     let ref mut a @ ref mut b = U;
    |         ---------^^^---------
@@ -35,7 +35,7 @@ LL |     let ref mut a @ ref mut b = U;
    |         first mutable borrow, by `a`, occurs here
 
 error: cannot borrow value as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:42:9
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:41:9
    |
 LL |     let ref mut a @ ref mut b = U;
    |         ---------^^^---------
@@ -44,7 +44,7 @@ LL |     let ref mut a @ ref mut b = U;
    |         first mutable borrow, by `a`, occurs here
 
 error: cannot borrow value as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:46:9
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:45:9
    |
 LL |       let ref mut a @ (
    |           ^--------
@@ -66,7 +66,7 @@ LL | |     ) = (U, [U, U, U]);
    | |_____^
 
 error: cannot borrow value as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:56:9
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:55:9
    |
 LL |       let ref mut a @ (
    |           ^--------
@@ -88,7 +88,7 @@ LL | |         ) = (u(), [u(), u(), u()]);
    | |_________^
 
 error: borrow of moved value
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:66:9
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:65:9
    |
 LL |     let a @ (ref mut b, ref mut c) = (U, U);
    |         -^^^^---------^^---------^
@@ -99,7 +99,7 @@ LL |     let a @ (ref mut b, ref mut c) = (U, U);
    |         move occurs because `a` has type `(U, U)` which does not implement the `Copy` trait
 
 error: borrow of moved value
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:70:9
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:69:9
    |
 LL |     let a @ (b, [c, d]) = &mut val; // Same as ^--
    |         -^^^^-^^^-^^-^^
@@ -111,7 +111,7 @@ LL |     let a @ (b, [c, d]) = &mut val; // Same as ^--
    |         move occurs because `a` has type `&mut (U, [U; 2])` which does not implement the `Copy` trait
 
 error: borrow of moved value
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:74:9
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:73:9
    |
 LL |     let a @ &mut ref mut b = &mut U;
    |         -^^^^^^^^---------
@@ -121,7 +121,7 @@ LL |     let a @ &mut ref mut b = &mut U;
    |         move occurs because `a` has type `&mut U` which does not implement the `Copy` trait
 
 error: borrow of moved value
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:77:9
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:76:9
    |
 LL |     let a @ &mut (ref mut b, ref mut c) = &mut (U, U);
    |         -^^^^^^^^^---------^^---------^
@@ -132,7 +132,7 @@ LL |     let a @ &mut (ref mut b, ref mut c) = &mut (U, U);
    |         move occurs because `a` has type `&mut (U, U)` which does not implement the `Copy` trait
 
 error: cannot borrow value as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:82:9
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:81:9
    |
 LL |         ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
    |         ---------^^^^^^---------^
@@ -141,7 +141,7 @@ LL |         ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
    |         first mutable borrow, by `a`, occurs here
 
 error: cannot borrow value as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:82:37
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:81:37
    |
 LL |         ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
    |                                     ---------^^^^^^^---------^
@@ -150,7 +150,7 @@ LL |         ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
    |                                     first mutable borrow, by `a`, occurs here
 
 error: cannot borrow value as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:88:9
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:87:9
    |
 LL |         ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
    |         ---------^^^^^^---------^
@@ -159,7 +159,7 @@ LL |         ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
    |         first mutable borrow, by `a`, occurs here
 
 error: cannot borrow value as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:88:37
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:87:37
    |
 LL |         ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
    |                                     ---------^^^^^^^---------^
@@ -168,7 +168,7 @@ LL |         ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
    |                                     first mutable borrow, by `a`, occurs here
 
 error: cannot borrow value as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:95:9
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:94:9
    |
 LL |         ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
    |         ---------^^^^^^---------^
@@ -177,7 +177,7 @@ LL |         ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
    |         first mutable borrow, by `a`, occurs here
 
 error: cannot borrow value as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:95:37
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:94:37
    |
 LL |         ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
    |                                     ---------^^^^^^^---------^
@@ -186,7 +186,7 @@ LL |         ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
    |                                     first mutable borrow, by `a`, occurs here
 
 error: cannot borrow value as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:107:9
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:106:9
    |
 LL |         ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
    |         ---------^^^^^^---------^
@@ -195,7 +195,7 @@ LL |         ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
    |         first mutable borrow, by `a`, occurs here
 
 error: cannot borrow value as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:107:37
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:106:37
    |
 LL |         ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
    |                                     ---------^^^^^^^---------^
@@ -204,7 +204,7 @@ LL |         ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
    |                                     first mutable borrow, by `a`, occurs here
 
 error: cannot borrow value as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:11:11
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:10:11
    |
 LL |     fn f1(ref mut a @ ref mut b: U) {}
    |           ---------^^^---------
@@ -213,7 +213,7 @@ LL |     fn f1(ref mut a @ ref mut b: U) {}
    |           first mutable borrow, by `a`, occurs here
 
 error: cannot borrow value as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:13:11
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:12:11
    |
 LL |     fn f2(ref mut a @ ref mut b: U) {}
    |           ---------^^^---------
@@ -222,7 +222,7 @@ LL |     fn f2(ref mut a @ ref mut b: U) {}
    |           first mutable borrow, by `a`, occurs here
 
 error: cannot borrow value as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:16:9
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:15:9
    |
 LL |           ref mut a @ [
    |           ^--------
@@ -240,7 +240,7 @@ LL | |         ] : [[U; 4]; 5]
    | |_________^
 
 error: cannot borrow value as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:24:22
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:23:22
    |
 LL |     fn f4_also_moved(ref mut a @ ref mut b @ c: U) {}
    |                      ---------^^^-------------
@@ -250,7 +250,7 @@ LL |     fn f4_also_moved(ref mut a @ ref mut b @ c: U) {}
    |                      first mutable borrow, by `a`, occurs here
 
 error: cannot move out of value because it is borrowed
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:24:34
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:23:34
    |
 LL |     fn f4_also_moved(ref mut a @ ref mut b @ c: U) {}
    |                                  ---------^^^-
@@ -259,7 +259,7 @@ LL |     fn f4_also_moved(ref mut a @ ref mut b @ c: U) {}
    |                                  value borrowed, by `b`, here
 
 error[E0499]: cannot borrow value as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:28:21
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:27:21
    |
 LL |     let ref mut a @ ref mut b = U;
    |         ------------^^^^^^^^^
@@ -271,7 +271,7 @@ LL |     drop(a);
    |          - first borrow later used here
 
 error[E0499]: cannot borrow value as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:38:21
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:37:21
    |
 LL |     let ref mut a @ ref mut b = U;
    |         ------------^^^^^^^^^
@@ -283,7 +283,7 @@ LL |     *a = U;
    |     ------ first borrow later used here
 
 error[E0382]: borrow of moved value
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:66:25
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:65:25
    |
 LL |     let a @ (ref mut b, ref mut c) = (U, U);
    |         ----------------^^^^^^^^^-   ------ move occurs because value has type `(U, U)`, which does not implement the `Copy` trait
@@ -292,7 +292,7 @@ LL |     let a @ (ref mut b, ref mut c) = (U, U);
    |         value moved here
 
 error[E0382]: borrow of moved value
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:70:21
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:69:21
    |
 LL |     let a @ (b, [c, d]) = &mut val; // Same as ^--
    |         ------------^--   -------- move occurs because value has type `&mut (U, [U; 2])`, which does not implement the `Copy` trait
@@ -301,7 +301,7 @@ LL |     let a @ (b, [c, d]) = &mut val; // Same as ^--
    |         value moved here
 
 error[E0382]: borrow of moved value
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:74:18
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:73:18
    |
 LL |     let a @ &mut ref mut b = &mut U;
    |         ---------^^^^^^^^^   ------ move occurs because value has type `&mut U`, which does not implement the `Copy` trait
@@ -310,7 +310,7 @@ LL |     let a @ &mut ref mut b = &mut U;
    |         value moved here
 
 error[E0382]: borrow of moved value
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:77:30
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:76:30
    |
 LL |     let a @ &mut (ref mut b, ref mut c) = &mut (U, U);
    |         ---------------------^^^^^^^^^-   ----------- move occurs because value has type `&mut (U, U)`, which does not implement the `Copy` trait
@@ -319,7 +319,7 @@ LL |     let a @ &mut (ref mut b, ref mut c) = &mut (U, U);
    |         value moved here
 
 error[E0499]: cannot borrow value as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:95:24
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:94:24
    |
 LL |         ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
    |         ---------------^^^^^^^^^-
@@ -331,7 +331,7 @@ LL |             *a = Err(U);
    |             ----------- first borrow later used here
 
 error[E0499]: cannot borrow value as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:95:53
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:94:53
    |
 LL |         ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
    |                                     ----------------^^^^^^^^^-
@@ -343,7 +343,7 @@ LL |             *a = Err(U);
    |             ----------- first borrow later used here
 
 error[E0499]: cannot borrow value as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:107:24
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:106:24
    |
 LL |         ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
    |         ---------------^^^^^^^^^-
@@ -355,7 +355,7 @@ LL |             drop(a);
    |                  - first borrow later used here
 
 error[E0499]: cannot borrow value as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:107:53
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:106:53
    |
 LL |         ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
    |                                     ----------------^^^^^^^^^-
diff --git a/src/test/ui/pattern/bindings-after-at/copy-and-move-mixed.rs b/src/test/ui/pattern/bindings-after-at/copy-and-move-mixed.rs
index 821d4b42962..3954d17e1c2 100644
--- a/src/test/ui/pattern/bindings-after-at/copy-and-move-mixed.rs
+++ b/src/test/ui/pattern/bindings-after-at/copy-and-move-mixed.rs
@@ -1,7 +1,6 @@
 // Test that mixing `Copy` and non-`Copy` types in `@` patterns is forbidden.
 
 #![feature(bindings_after_at)]
-#![feature(move_ref_pattern)]
 
 #[derive(Copy, Clone)]
 struct C;
diff --git a/src/test/ui/pattern/bindings-after-at/copy-and-move-mixed.stderr b/src/test/ui/pattern/bindings-after-at/copy-and-move-mixed.stderr
index 7e89008a604..cc2786a13f4 100644
--- a/src/test/ui/pattern/bindings-after-at/copy-and-move-mixed.stderr
+++ b/src/test/ui/pattern/bindings-after-at/copy-and-move-mixed.stderr
@@ -1,5 +1,5 @@
 error[E0382]: use of moved value
-  --> $DIR/copy-and-move-mixed.rs:12:19
+  --> $DIR/copy-and-move-mixed.rs:11:19
    |
 LL |     let a @ NC(b, c) = NC(C, C);
    |         ----------^-   -------- move occurs because value has type `NC<C, C>`, which does not implement the `Copy` trait
@@ -8,7 +8,7 @@ LL |     let a @ NC(b, c) = NC(C, C);
    |         value moved here
 
 error[E0382]: use of moved value
-  --> $DIR/copy-and-move-mixed.rs:15:19
+  --> $DIR/copy-and-move-mixed.rs:14:19
    |
 LL |     let a @ NC(b, c @ NC(d, e)) = NC(C, NC(C, C));
    |         ----------^^^^^^^^^^^^-   --------------- move occurs because value has type `NC<C, NC<C, C>>`, which does not implement the `Copy` trait
@@ -17,7 +17,7 @@ LL |     let a @ NC(b, c @ NC(d, e)) = NC(C, NC(C, C));
    |         value moved here
 
 error[E0382]: use of moved value
-  --> $DIR/copy-and-move-mixed.rs:15:29
+  --> $DIR/copy-and-move-mixed.rs:14:29
    |
 LL |     let a @ NC(b, c @ NC(d, e)) = NC(C, NC(C, C));
    |                   ----------^-
diff --git a/src/test/ui/pattern/bindings-after-at/default-binding-modes-both-sides-independent.rs b/src/test/ui/pattern/bindings-after-at/default-binding-modes-both-sides-independent.rs
index a45497229ac..276088b9a9e 100644
--- a/src/test/ui/pattern/bindings-after-at/default-binding-modes-both-sides-independent.rs
+++ b/src/test/ui/pattern/bindings-after-at/default-binding-modes-both-sides-independent.rs
@@ -8,7 +8,6 @@
 // this would create problems for the generalization aforementioned.
 
 #![feature(bindings_after_at)]
-#![feature(move_ref_pattern)]
 
 fn main() {
     struct NotCopy;
diff --git a/src/test/ui/pattern/bindings-after-at/default-binding-modes-both-sides-independent.stderr b/src/test/ui/pattern/bindings-after-at/default-binding-modes-both-sides-independent.stderr
index a63a5a1e6c7..11d5e24f34e 100644
--- a/src/test/ui/pattern/bindings-after-at/default-binding-modes-both-sides-independent.stderr
+++ b/src/test/ui/pattern/bindings-after-at/default-binding-modes-both-sides-independent.stderr
@@ -1,5 +1,5 @@
 error: cannot move out of value because it is borrowed
-  --> $DIR/default-binding-modes-both-sides-independent.rs:28:9
+  --> $DIR/default-binding-modes-both-sides-independent.rs:27:9
    |
 LL |     let ref a @ b = NotCopy;
    |         -----^^^-
@@ -8,7 +8,7 @@ LL |     let ref a @ b = NotCopy;
    |         value borrowed, by `a`, here
 
 error: cannot move out of value because it is borrowed
-  --> $DIR/default-binding-modes-both-sides-independent.rs:31:9
+  --> $DIR/default-binding-modes-both-sides-independent.rs:30:9
    |
 LL |     let ref mut a @ b = NotCopy;
    |         ---------^^^-
@@ -17,7 +17,7 @@ LL |     let ref mut a @ b = NotCopy;
    |         value borrowed, by `a`, here
 
 error: cannot move out of value because it is borrowed
-  --> $DIR/default-binding-modes-both-sides-independent.rs:36:12
+  --> $DIR/default-binding-modes-both-sides-independent.rs:35:12
    |
 LL |         Ok(ref a @ b) | Err(b @ ref a) => {
    |            -----^^^-
@@ -26,7 +26,7 @@ LL |         Ok(ref a @ b) | Err(b @ ref a) => {
    |            value borrowed, by `a`, here
 
 error: borrow of moved value
-  --> $DIR/default-binding-modes-both-sides-independent.rs:36:29
+  --> $DIR/default-binding-modes-both-sides-independent.rs:35:29
    |
 LL |         Ok(ref a @ b) | Err(b @ ref a) => {
    |                             -^^^-----
@@ -36,7 +36,7 @@ LL |         Ok(ref a @ b) | Err(b @ ref a) => {
    |                             move occurs because `b` has type `NotCopy` which does not implement the `Copy` trait
 
 error: cannot move out of value because it is borrowed
-  --> $DIR/default-binding-modes-both-sides-independent.rs:44:9
+  --> $DIR/default-binding-modes-both-sides-independent.rs:43:9
    |
 LL |         ref a @ b => {
    |         -----^^^-
@@ -45,7 +45,7 @@ LL |         ref a @ b => {
    |         value borrowed, by `a`, here
 
 error[E0505]: cannot move out of value because it is borrowed
-  --> $DIR/default-binding-modes-both-sides-independent.rs:31:21
+  --> $DIR/default-binding-modes-both-sides-independent.rs:30:21
    |
 LL |     let ref mut a @ b = NotCopy;
    |         ------------^
diff --git a/src/test/ui/pattern/move-ref-patterns/borrowck-move-ref-pattern-pass.rs b/src/test/ui/pattern/move-ref-patterns/borrowck-move-ref-pattern-pass.rs
index d2d4e61e049..5445696fdff 100644
--- a/src/test/ui/pattern/move-ref-patterns/borrowck-move-ref-pattern-pass.rs
+++ b/src/test/ui/pattern/move-ref-patterns/borrowck-move-ref-pattern-pass.rs
@@ -1,7 +1,5 @@
 // check-pass
 
-#![feature(move_ref_pattern)]
-
 fn main() {}
 
 struct U;
diff --git a/src/test/ui/pattern/move-ref-patterns/borrowck-move-ref-pattern.rs b/src/test/ui/pattern/move-ref-patterns/borrowck-move-ref-pattern.rs
index 3ee008fd84f..9c320edc4dc 100644
--- a/src/test/ui/pattern/move-ref-patterns/borrowck-move-ref-pattern.rs
+++ b/src/test/ui/pattern/move-ref-patterns/borrowck-move-ref-pattern.rs
@@ -1,5 +1,3 @@
-#![feature(move_ref_pattern)]
-
 fn main() {}
 
 struct U;
diff --git a/src/test/ui/pattern/move-ref-patterns/borrowck-move-ref-pattern.stderr b/src/test/ui/pattern/move-ref-patterns/borrowck-move-ref-pattern.stderr
index d718ee29cf9..285c203f382 100644
--- a/src/test/ui/pattern/move-ref-patterns/borrowck-move-ref-pattern.stderr
+++ b/src/test/ui/pattern/move-ref-patterns/borrowck-move-ref-pattern.stderr
@@ -1,5 +1,5 @@
 error[E0505]: cannot move out of `arr[..]` because it is borrowed
-  --> $DIR/borrowck-move-ref-pattern.rs:10:24
+  --> $DIR/borrowck-move-ref-pattern.rs:8:24
    |
 LL |     let hold_all = &arr;
    |                    ---- borrow of `arr` occurs here
@@ -10,7 +10,7 @@ LL |     drop(hold_all);
    |          -------- borrow later used here
 
 error[E0384]: cannot assign twice to immutable variable `_x1`
-  --> $DIR/borrowck-move-ref-pattern.rs:11:5
+  --> $DIR/borrowck-move-ref-pattern.rs:9:5
    |
 LL |     let [ref _x0_hold, _x1, ref xs_hold @ ..] = arr;
    |                        ---
@@ -21,7 +21,7 @@ LL |     _x1 = U;
    |     ^^^^^^^ cannot assign twice to immutable variable
 
 error[E0505]: cannot move out of `arr[..]` because it is borrowed
-  --> $DIR/borrowck-move-ref-pattern.rs:13:10
+  --> $DIR/borrowck-move-ref-pattern.rs:11:10
    |
 LL |     let [ref _x0_hold, _x1, ref xs_hold @ ..] = arr;
    |          ------------ borrow of `arr[..]` occurs here
@@ -32,7 +32,7 @@ LL |     drop(_x0_hold);
    |          -------- borrow later used here
 
 error[E0502]: cannot borrow `arr[..]` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-move-ref-pattern.rs:15:16
+  --> $DIR/borrowck-move-ref-pattern.rs:13:16
    |
 LL |     let [ref _x0_hold, _x1, ref xs_hold @ ..] = arr;
    |                             ---------------- immutable borrow occurs here
@@ -44,7 +44,7 @@ LL |     drop(xs_hold);
    |          ------- immutable borrow later used here
 
 error[E0505]: cannot move out of `arr[..]` because it is borrowed
-  --> $DIR/borrowck-move-ref-pattern.rs:15:29
+  --> $DIR/borrowck-move-ref-pattern.rs:13:29
    |
 LL |     let [ref _x0_hold, _x1, ref xs_hold @ ..] = arr;
    |                             ---------------- borrow of `arr[..]` occurs here
@@ -56,7 +56,7 @@ LL |     drop(xs_hold);
    |          ------- borrow later used here
 
 error[E0505]: cannot move out of `arr[..]` because it is borrowed
-  --> $DIR/borrowck-move-ref-pattern.rs:15:34
+  --> $DIR/borrowck-move-ref-pattern.rs:13:34
    |
 LL |     let [ref _x0_hold, _x1, ref xs_hold @ ..] = arr;
    |                             ---------------- borrow of `arr[..]` occurs here
@@ -68,7 +68,7 @@ LL |     drop(xs_hold);
    |          ------- borrow later used here
 
 error[E0384]: cannot assign twice to immutable variable `_x1`
-  --> $DIR/borrowck-move-ref-pattern.rs:25:5
+  --> $DIR/borrowck-move-ref-pattern.rs:23:5
    |
 LL |     let (ref _x0, _x1, ref _x2, ..) = tup;
    |                   ---
@@ -79,7 +79,7 @@ LL |     _x1 = U;
    |     ^^^^^^^ cannot assign twice to immutable variable
 
 error[E0502]: cannot borrow `tup.0` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-move-ref-pattern.rs:26:20
+  --> $DIR/borrowck-move-ref-pattern.rs:24:20
    |
 LL |     let (ref _x0, _x1, ref _x2, ..) = tup;
    |          ------- immutable borrow occurs here
@@ -91,7 +91,7 @@ LL |     *_x0 = U;
    |     -------- immutable borrow later used here
 
 error[E0502]: cannot borrow `tup.0` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-move-ref-pattern.rs:27:10
+  --> $DIR/borrowck-move-ref-pattern.rs:25:10
    |
 LL |     let (ref _x0, _x1, ref _x2, ..) = tup;
    |          ------- immutable borrow occurs here
@@ -102,7 +102,7 @@ LL |     *_x0 = U;
    |     -------- immutable borrow later used here
 
 error[E0594]: cannot assign to `*_x0` which is behind a `&` reference
-  --> $DIR/borrowck-move-ref-pattern.rs:28:5
+  --> $DIR/borrowck-move-ref-pattern.rs:26:5
    |
 LL |     let (ref _x0, _x1, ref _x2, ..) = tup;
    |          ------- help: consider changing this to be a mutable reference: `ref mut _x0`
@@ -111,7 +111,7 @@ LL |     *_x0 = U;
    |     ^^^^^^^^ `_x0` is a `&` reference, so the data it refers to cannot be written
 
 error[E0594]: cannot assign to `*_x2` which is behind a `&` reference
-  --> $DIR/borrowck-move-ref-pattern.rs:29:5
+  --> $DIR/borrowck-move-ref-pattern.rs:27:5
    |
 LL |     let (ref _x0, _x1, ref _x2, ..) = tup;
    |                        ------- help: consider changing this to be a mutable reference: `ref mut _x2`
@@ -120,7 +120,7 @@ LL |     *_x2 = U;
    |     ^^^^^^^^ `_x2` is a `&` reference, so the data it refers to cannot be written
 
 error[E0382]: use of moved value: `tup.1`
-  --> $DIR/borrowck-move-ref-pattern.rs:30:10
+  --> $DIR/borrowck-move-ref-pattern.rs:28:10
    |
 LL |     let (ref _x0, _x1, ref _x2, ..) = tup;
    |                   --- value moved here
@@ -131,7 +131,7 @@ LL |     drop(tup.1);
    = note: move occurs because `tup.1` has type `U`, which does not implement the `Copy` trait
 
 error[E0382]: borrow of moved value: `tup.1`
-  --> $DIR/borrowck-move-ref-pattern.rs:31:20
+  --> $DIR/borrowck-move-ref-pattern.rs:29:20
    |
 LL |     drop(tup.1);
    |          ----- value moved here
@@ -141,7 +141,7 @@ LL |     let _x1_hold = &tup.1;
    = note: move occurs because `tup.1` has type `U`, which does not implement the `Copy` trait
 
 error[E0502]: cannot borrow `tup.3` as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-move-ref-pattern.rs:33:20
+  --> $DIR/borrowck-move-ref-pattern.rs:31:20
    |
 LL |     let (.., ref mut _x3) = tup;
    |              ----------- mutable borrow occurs here
@@ -152,7 +152,7 @@ LL |     drop(_x3);
    |          --- mutable borrow later used here
 
 error[E0499]: cannot borrow `tup.3` as mutable more than once at a time
-  --> $DIR/borrowck-move-ref-pattern.rs:34:20
+  --> $DIR/borrowck-move-ref-pattern.rs:32:20
    |
 LL |     let (.., ref mut _x3) = tup;
    |              ----------- first mutable borrow occurs here
@@ -164,7 +164,7 @@ LL |     drop(_x3);
    |          --- first borrow later used here
 
 error[E0499]: cannot borrow `tup.3` as mutable more than once at a time
-  --> $DIR/borrowck-move-ref-pattern.rs:35:14
+  --> $DIR/borrowck-move-ref-pattern.rs:33:14
    |
 LL |     let (.., ref mut _x3) = tup;
    |              ----------- first mutable borrow occurs here
@@ -176,7 +176,7 @@ LL |     drop(_x3);
    |          --- first borrow later used here
 
 error[E0502]: cannot borrow `tup.3` as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-move-ref-pattern.rs:36:14
+  --> $DIR/borrowck-move-ref-pattern.rs:34:14
    |
 LL |     let (.., ref mut _x3) = tup;
    |              ----------- mutable borrow occurs here
@@ -187,7 +187,7 @@ LL |     drop(_x3);
    |          --- mutable borrow later used here
 
 error[E0382]: use of moved value: `tup`
-  --> $DIR/borrowck-move-ref-pattern.rs:45:14
+  --> $DIR/borrowck-move-ref-pattern.rs:43:14
    |
 LL |     let mut tup = (U, U, U);
    |         ------- move occurs because `tup` has type `(U, U, U)`, which does not implement the `Copy` trait
diff --git a/src/test/ui/pattern/move-ref-patterns/by-move-sub-pat-unreachable.rs b/src/test/ui/pattern/move-ref-patterns/by-move-sub-pat-unreachable.rs
index 08fb5cd2e16..18663c3fe3f 100644
--- a/src/test/ui/pattern/move-ref-patterns/by-move-sub-pat-unreachable.rs
+++ b/src/test/ui/pattern/move-ref-patterns/by-move-sub-pat-unreachable.rs
@@ -4,7 +4,6 @@
 
 // check-pass
 
-#![feature(move_ref_pattern)]
 #![feature(bindings_after_at)]
 
 fn main() {
diff --git a/src/test/ui/pattern/move-ref-patterns/feature-gate-move_ref_pattern.rs b/src/test/ui/pattern/move-ref-patterns/feature-gate-move_ref_pattern.rs
deleted file mode 100644
index fb92eb1ba32..00000000000
--- a/src/test/ui/pattern/move-ref-patterns/feature-gate-move_ref_pattern.rs
+++ /dev/null
@@ -1,23 +0,0 @@
-fn main() {
-    #[derive(Clone)]
-    struct X {
-        x: (),
-    }
-    let mut tup = (X { x: () }, X { x: () });
-    match Some(tup.clone()) {
-        Some((y, ref z)) => {}
-        //~^ ERROR binding by-move and by-ref in the same pattern is unstable
-        None => panic!(),
-    }
-
-    let (ref a, b) = tup.clone();
-    //~^ ERROR binding by-move and by-ref in the same pattern is unstable
-
-    let (a, mut b) = &tup;
-    //~^ ERROR binding by-move and by-ref in the same pattern is unstable
-    //~| ERROR cannot move out of a shared reference
-
-    let (mut a, b) = &mut tup;
-    //~^ ERROR binding by-move and by-ref in the same pattern is unstable
-    //~| ERROR cannot move out of a mutable reference
-}
diff --git a/src/test/ui/pattern/move-ref-patterns/feature-gate-move_ref_pattern.stderr b/src/test/ui/pattern/move-ref-patterns/feature-gate-move_ref_pattern.stderr
deleted file mode 100644
index 5335569a972..00000000000
--- a/src/test/ui/pattern/move-ref-patterns/feature-gate-move_ref_pattern.stderr
+++ /dev/null
@@ -1,66 +0,0 @@
-error[E0658]: binding by-move and by-ref in the same pattern is unstable
-  --> $DIR/feature-gate-move_ref_pattern.rs:8:15
-   |
-LL |         Some((y, ref z)) => {}
-   |               ^  ----- by-ref pattern here
-   |               |
-   |               by-move pattern here
-   |
-   = note: see issue #68354 <https://github.com/rust-lang/rust/issues/68354> for more information
-   = help: add `#![feature(move_ref_pattern)]` to the crate attributes to enable
-
-error[E0658]: binding by-move and by-ref in the same pattern is unstable
-  --> $DIR/feature-gate-move_ref_pattern.rs:13:17
-   |
-LL |     let (ref a, b) = tup.clone();
-   |          -----  ^ by-move pattern here
-   |          |
-   |          by-ref pattern here
-   |
-   = note: see issue #68354 <https://github.com/rust-lang/rust/issues/68354> for more information
-   = help: add `#![feature(move_ref_pattern)]` to the crate attributes to enable
-
-error[E0658]: binding by-move and by-ref in the same pattern is unstable
-  --> $DIR/feature-gate-move_ref_pattern.rs:16:13
-   |
-LL |     let (a, mut b) = &tup;
-   |          -  ^^^^^ by-move pattern here
-   |          |
-   |          by-ref pattern here
-   |
-   = note: see issue #68354 <https://github.com/rust-lang/rust/issues/68354> for more information
-   = help: add `#![feature(move_ref_pattern)]` to the crate attributes to enable
-
-error[E0658]: binding by-move and by-ref in the same pattern is unstable
-  --> $DIR/feature-gate-move_ref_pattern.rs:20:10
-   |
-LL |     let (mut a, b) = &mut tup;
-   |          ^^^^^  - by-ref pattern here
-   |          |
-   |          by-move pattern here
-   |
-   = note: see issue #68354 <https://github.com/rust-lang/rust/issues/68354> for more information
-   = help: add `#![feature(move_ref_pattern)]` to the crate attributes to enable
-
-error[E0507]: cannot move out of a shared reference
-  --> $DIR/feature-gate-move_ref_pattern.rs:16:22
-   |
-LL |     let (a, mut b) = &tup;
-   |             -----    ^^^^
-   |             |
-   |             data moved here
-   |             move occurs because `b` has type `X`, which does not implement the `Copy` trait
-
-error[E0507]: cannot move out of a mutable reference
-  --> $DIR/feature-gate-move_ref_pattern.rs:20:22
-   |
-LL |     let (mut a, b) = &mut tup;
-   |          -----       ^^^^^^^^
-   |          |
-   |          data moved here
-   |          move occurs because `a` has type `X`, which does not implement the `Copy` trait
-
-error: aborting due to 6 previous errors
-
-Some errors have detailed explanations: E0507, E0658.
-For more information about an error, try `rustc --explain E0507`.
diff --git a/src/test/ui/pattern/move-ref-patterns/issue-53840.rs b/src/test/ui/pattern/move-ref-patterns/issue-53840.rs
index ab7d10d9f83..80effc497ed 100644
--- a/src/test/ui/pattern/move-ref-patterns/issue-53840.rs
+++ b/src/test/ui/pattern/move-ref-patterns/issue-53840.rs
@@ -1,7 +1,5 @@
 // check-pass
 
-#![feature(move_ref_pattern)]
-
 enum E {
     Foo(String, String, String),
 }
diff --git a/src/test/ui/pattern/move-ref-patterns/move-ref-patterns-closure-captures-inside.rs b/src/test/ui/pattern/move-ref-patterns/move-ref-patterns-closure-captures-inside.rs
index 4c3ca62e165..ebb1683af7d 100644
--- a/src/test/ui/pattern/move-ref-patterns/move-ref-patterns-closure-captures-inside.rs
+++ b/src/test/ui/pattern/move-ref-patterns/move-ref-patterns-closure-captures-inside.rs
@@ -1,5 +1,3 @@
-#![feature(move_ref_pattern)]
-
 fn main() {
     struct S; // Not `Copy`.
 
diff --git a/src/test/ui/pattern/move-ref-patterns/move-ref-patterns-closure-captures-inside.stderr b/src/test/ui/pattern/move-ref-patterns/move-ref-patterns-closure-captures-inside.stderr
index 9ad84879595..f19fed08917 100644
--- a/src/test/ui/pattern/move-ref-patterns/move-ref-patterns-closure-captures-inside.stderr
+++ b/src/test/ui/pattern/move-ref-patterns/move-ref-patterns-closure-captures-inside.stderr
@@ -1,5 +1,5 @@
 error[E0382]: borrow of moved value: `tup0`
-  --> $DIR/move-ref-patterns-closure-captures-inside.rs:33:10
+  --> $DIR/move-ref-patterns-closure-captures-inside.rs:31:10
    |
 LL |     let mut tup0 = (S, S);
    |         -------- move occurs because `tup0` has type `(S, S)`, which does not implement the `Copy` trait
@@ -14,7 +14,7 @@ LL |     drop(&tup0);
    |          ^^^^^ value borrowed here after move
 
 error[E0382]: borrow of moved value: `tup1`
-  --> $DIR/move-ref-patterns-closure-captures-inside.rs:34:10
+  --> $DIR/move-ref-patterns-closure-captures-inside.rs:32:10
    |
 LL |     let mut tup1 = (S, S, S);
    |         -------- move occurs because `tup1` has type `(S, S, S)`, which does not implement the `Copy` trait
@@ -29,7 +29,7 @@ LL |     drop(&tup1);
    |          ^^^^^ value borrowed here after move
 
 error[E0382]: borrow of moved value: `tup2`
-  --> $DIR/move-ref-patterns-closure-captures-inside.rs:35:10
+  --> $DIR/move-ref-patterns-closure-captures-inside.rs:33:10
    |
 LL |     let tup2 = (S, S);
    |         ---- move occurs because `tup2` has type `(S, S)`, which does not implement the `Copy` trait
@@ -44,7 +44,7 @@ LL |     drop(&tup2);
    |          ^^^^^ value borrowed here after move
 
 error[E0382]: borrow of moved value: `tup3`
-  --> $DIR/move-ref-patterns-closure-captures-inside.rs:36:10
+  --> $DIR/move-ref-patterns-closure-captures-inside.rs:34:10
    |
 LL |     let tup3 = (S, S, S);
    |         ---- move occurs because `tup3` has type `(S, S, S)`, which does not implement the `Copy` trait
@@ -59,7 +59,7 @@ LL |     drop(&tup3);
    |          ^^^^^ value borrowed here after move
 
 error[E0382]: borrow of moved value: `tup4`
-  --> $DIR/move-ref-patterns-closure-captures-inside.rs:41:10
+  --> $DIR/move-ref-patterns-closure-captures-inside.rs:39:10
    |
 LL |     let tup4 = (S, S);
    |         ---- move occurs because `tup4` has type `(S, S)`, which does not implement the `Copy` trait
@@ -74,7 +74,7 @@ LL |     drop(&tup4.0);
    |          ^^^^^^^ value borrowed here after move
 
 error[E0382]: borrow of moved value: `arr0`
-  --> $DIR/move-ref-patterns-closure-captures-inside.rs:43:10
+  --> $DIR/move-ref-patterns-closure-captures-inside.rs:41:10
    |
 LL |     let mut arr0 = [S, S, S];
    |         -------- move occurs because `arr0` has type `[S; 3]`, which does not implement the `Copy` trait
@@ -89,7 +89,7 @@ LL |     drop(&arr0);
    |          ^^^^^ value borrowed here after move
 
 error[E0382]: borrow of moved value: `arr1`
-  --> $DIR/move-ref-patterns-closure-captures-inside.rs:44:36
+  --> $DIR/move-ref-patterns-closure-captures-inside.rs:42:36
    |
 LL |     let mut arr1 = [S, S, S, S, S];
    |         -------- move occurs because `arr1` has type `[S; 5]`, which does not implement the `Copy` trait
@@ -104,7 +104,7 @@ LL |     let [_, mov1, mov2, mov3, _] = &arr1;
    |                                    ^^^^^ value borrowed here after move
 
 error[E0382]: borrow of moved value: `arr2`
-  --> $DIR/move-ref-patterns-closure-captures-inside.rs:45:10
+  --> $DIR/move-ref-patterns-closure-captures-inside.rs:43:10
    |
 LL |     let arr2 = [S, S, S];
    |         ---- move occurs because `arr2` has type `[S; 3]`, which does not implement the `Copy` trait
@@ -119,7 +119,7 @@ LL |     drop(&arr2);
    |          ^^^^^ value borrowed here after move
 
 error[E0382]: borrow of moved value: `arr3`
-  --> $DIR/move-ref-patterns-closure-captures-inside.rs:46:36
+  --> $DIR/move-ref-patterns-closure-captures-inside.rs:44:36
    |
 LL |     let arr3 = [S, S, S, S, S];
    |         ---- move occurs because `arr3` has type `[S; 5]`, which does not implement the `Copy` trait
@@ -134,7 +134,7 @@ LL |     let [_, mov1, mov2, mov3, _] = &arr3;
    |                                    ^^^^^ value borrowed here after move
 
 error[E0382]: borrow of moved value: `tup0`
-  --> $DIR/move-ref-patterns-closure-captures-inside.rs:77:10
+  --> $DIR/move-ref-patterns-closure-captures-inside.rs:75:10
    |
 LL |     let mut tup0: Option<(S, S)> = None;
    |         -------- move occurs because `tup0` has type `Option<(S, S)>`, which does not implement the `Copy` trait
@@ -148,7 +148,7 @@ LL |     drop(&tup0);
    |          ^^^^^ value borrowed here after move
 
 error[E0382]: borrow of moved value: `tup1`
-  --> $DIR/move-ref-patterns-closure-captures-inside.rs:78:10
+  --> $DIR/move-ref-patterns-closure-captures-inside.rs:76:10
    |
 LL |     let mut tup1: Option<(S, S, S)> = None;
    |         -------- move occurs because `tup1` has type `Option<(S, S, S)>`, which does not implement the `Copy` trait
@@ -163,7 +163,7 @@ LL |     drop(&tup1);
    |          ^^^^^ value borrowed here after move
 
 error[E0382]: borrow of moved value: `tup2`
-  --> $DIR/move-ref-patterns-closure-captures-inside.rs:79:10
+  --> $DIR/move-ref-patterns-closure-captures-inside.rs:77:10
    |
 LL |     let tup2: Option<(S, S)> = None;
    |         ---- move occurs because `tup2` has type `Option<(S, S)>`, which does not implement the `Copy` trait
@@ -178,7 +178,7 @@ LL |     drop(&tup2);
    |          ^^^^^ value borrowed here after move
 
 error[E0382]: borrow of moved value: `tup3`
-  --> $DIR/move-ref-patterns-closure-captures-inside.rs:80:10
+  --> $DIR/move-ref-patterns-closure-captures-inside.rs:78:10
    |
 LL |     let tup3: Option<(S, S, S)> = None;
    |         ---- move occurs because `tup3` has type `Option<(S, S, S)>`, which does not implement the `Copy` trait
@@ -193,7 +193,7 @@ LL |     drop(&tup3);
    |          ^^^^^ value borrowed here after move
 
 error[E0382]: borrow of moved value: `tup4`
-  --> $DIR/move-ref-patterns-closure-captures-inside.rs:81:21
+  --> $DIR/move-ref-patterns-closure-captures-inside.rs:79:21
    |
 LL |     let tup4: Option<(S, S)> = None;
    |         ---- move occurs because `tup4` has type `Option<(S, S)>`, which does not implement the `Copy` trait
@@ -208,7 +208,7 @@ LL |     m!((ref x, _) = &tup4);
    |                     ^^^^^ value borrowed here after move
 
 error[E0382]: borrow of moved value: `arr0`
-  --> $DIR/move-ref-patterns-closure-captures-inside.rs:82:10
+  --> $DIR/move-ref-patterns-closure-captures-inside.rs:80:10
    |
 LL |     let mut arr0: Option<[S; 3]> = None;
    |         -------- move occurs because `arr0` has type `Option<[S; 3]>`, which does not implement the `Copy` trait
@@ -223,7 +223,7 @@ LL |     drop(&arr0);
    |          ^^^^^ value borrowed here after move
 
 error[E0382]: borrow of moved value: `arr1`
-  --> $DIR/move-ref-patterns-closure-captures-inside.rs:83:35
+  --> $DIR/move-ref-patterns-closure-captures-inside.rs:81:35
    |
 LL |     let mut arr1: Option<[S; 5]> = None;
    |         -------- move occurs because `arr1` has type `Option<[S; 5]>`, which does not implement the `Copy` trait
@@ -238,7 +238,7 @@ LL |     m!([_, mov1, mov2, mov3, _] = &arr1);
    |                                   ^^^^^ value borrowed here after move
 
 error[E0382]: borrow of moved value: `arr2`
-  --> $DIR/move-ref-patterns-closure-captures-inside.rs:84:10
+  --> $DIR/move-ref-patterns-closure-captures-inside.rs:82:10
    |
 LL |     let arr2: Option<[S; 3]> = None;
    |         ---- move occurs because `arr2` has type `Option<[S; 3]>`, which does not implement the `Copy` trait
@@ -253,7 +253,7 @@ LL |     drop(&arr2);
    |          ^^^^^ value borrowed here after move
 
 error[E0382]: borrow of moved value: `arr3`
-  --> $DIR/move-ref-patterns-closure-captures-inside.rs:85:35
+  --> $DIR/move-ref-patterns-closure-captures-inside.rs:83:35
    |
 LL |     let arr3: Option<[S; 5]> = None;
    |         ---- move occurs because `arr3` has type `Option<[S; 5]>`, which does not implement the `Copy` trait
@@ -267,7 +267,7 @@ LL |     m!([_, mov1, mov2, mov3, _] = &arr3);
    |                                   ^^^^^ value borrowed here after move
 
 error[E0382]: borrow of moved value: `tup0`
-  --> $DIR/move-ref-patterns-closure-captures-inside.rs:113:10
+  --> $DIR/move-ref-patterns-closure-captures-inside.rs:111:10
    |
 LL |     let mut tup0: Option<(S, S)> = None;
    |         -------- move occurs because `tup0` has type `Option<(S, S)>`, which does not implement the `Copy` trait
@@ -281,7 +281,7 @@ LL |     drop(&tup0);
    |          ^^^^^ value borrowed here after move
 
 error[E0382]: borrow of moved value: `tup1`
-  --> $DIR/move-ref-patterns-closure-captures-inside.rs:114:10
+  --> $DIR/move-ref-patterns-closure-captures-inside.rs:112:10
    |
 LL |     let mut tup1: Option<(S, S, S)> = None;
    |         -------- move occurs because `tup1` has type `Option<(S, S, S)>`, which does not implement the `Copy` trait
@@ -296,7 +296,7 @@ LL |     drop(&tup1);
    |          ^^^^^ value borrowed here after move
 
 error[E0382]: borrow of moved value: `tup2`
-  --> $DIR/move-ref-patterns-closure-captures-inside.rs:115:10
+  --> $DIR/move-ref-patterns-closure-captures-inside.rs:113:10
    |
 LL |     let tup2: Option<(S, S)> = None;
    |         ---- move occurs because `tup2` has type `Option<(S, S)>`, which does not implement the `Copy` trait
@@ -311,7 +311,7 @@ LL |     drop(&tup2);
    |          ^^^^^ value borrowed here after move
 
 error[E0382]: borrow of moved value: `tup3`
-  --> $DIR/move-ref-patterns-closure-captures-inside.rs:116:10
+  --> $DIR/move-ref-patterns-closure-captures-inside.rs:114:10
    |
 LL |     let tup3: Option<(S, S, S)> = None;
    |         ---- move occurs because `tup3` has type `Option<(S, S, S)>`, which does not implement the `Copy` trait
@@ -326,7 +326,7 @@ LL |     drop(&tup3);
    |          ^^^^^ value borrowed here after move
 
 error[E0382]: borrow of moved value: `tup4`
-  --> $DIR/move-ref-patterns-closure-captures-inside.rs:117:21
+  --> $DIR/move-ref-patterns-closure-captures-inside.rs:115:21
    |
 LL |     let tup4: Option<(S, S)> = None;
    |         ---- move occurs because `tup4` has type `Option<(S, S)>`, which does not implement the `Copy` trait
@@ -341,7 +341,7 @@ LL |     m!((ref x, _) = &tup4);
    |                     ^^^^^ value borrowed here after move
 
 error[E0382]: borrow of moved value: `arr0`
-  --> $DIR/move-ref-patterns-closure-captures-inside.rs:118:10
+  --> $DIR/move-ref-patterns-closure-captures-inside.rs:116:10
    |
 LL |     let mut arr0: Option<[S; 3]> = None;
    |         -------- move occurs because `arr0` has type `Option<[S; 3]>`, which does not implement the `Copy` trait
@@ -356,7 +356,7 @@ LL |     drop(&arr0);
    |          ^^^^^ value borrowed here after move
 
 error[E0382]: borrow of moved value: `arr1`
-  --> $DIR/move-ref-patterns-closure-captures-inside.rs:119:35
+  --> $DIR/move-ref-patterns-closure-captures-inside.rs:117:35
    |
 LL |     let mut arr1: Option<[S; 5]> = None;
    |         -------- move occurs because `arr1` has type `Option<[S; 5]>`, which does not implement the `Copy` trait
@@ -371,7 +371,7 @@ LL |     m!([_, mov1, mov2, mov3, _] = &arr1);
    |                                   ^^^^^ value borrowed here after move
 
 error[E0382]: borrow of moved value: `arr2`
-  --> $DIR/move-ref-patterns-closure-captures-inside.rs:120:10
+  --> $DIR/move-ref-patterns-closure-captures-inside.rs:118:10
    |
 LL |     let arr2: Option<[S; 3]> = None;
    |         ---- move occurs because `arr2` has type `Option<[S; 3]>`, which does not implement the `Copy` trait
@@ -386,7 +386,7 @@ LL |     drop(&arr2);
    |          ^^^^^ value borrowed here after move
 
 error[E0382]: borrow of moved value: `arr3`
-  --> $DIR/move-ref-patterns-closure-captures-inside.rs:121:35
+  --> $DIR/move-ref-patterns-closure-captures-inside.rs:119:35
    |
 LL |     let arr3: Option<[S; 5]> = None;
    |         ---- move occurs because `arr3` has type `Option<[S; 5]>`, which does not implement the `Copy` trait
diff --git a/src/test/ui/pattern/move-ref-patterns/move-ref-patterns-closure-captures-pass.rs b/src/test/ui/pattern/move-ref-patterns/move-ref-patterns-closure-captures-pass.rs
index e1844d36e4a..583f70f41aa 100644
--- a/src/test/ui/pattern/move-ref-patterns/move-ref-patterns-closure-captures-pass.rs
+++ b/src/test/ui/pattern/move-ref-patterns/move-ref-patterns-closure-captures-pass.rs
@@ -1,7 +1,5 @@
 // check-pass
 
-#![feature(move_ref_pattern)]
-
 fn main() {
     struct U;
     fn accept_fn_once(_: impl FnOnce()) {}
diff --git a/src/test/ui/pattern/move-ref-patterns/move-ref-patterns-closure-captures.rs b/src/test/ui/pattern/move-ref-patterns/move-ref-patterns-closure-captures.rs
index 7f1c02c05cb..cd619cc41eb 100644
--- a/src/test/ui/pattern/move-ref-patterns/move-ref-patterns-closure-captures.rs
+++ b/src/test/ui/pattern/move-ref-patterns/move-ref-patterns-closure-captures.rs
@@ -1,5 +1,3 @@
-#![feature(move_ref_pattern)]
-
 fn main() {
     struct U;
     fn accept_fn_once(_: &impl FnOnce()) {}
diff --git a/src/test/ui/pattern/move-ref-patterns/move-ref-patterns-closure-captures.stderr b/src/test/ui/pattern/move-ref-patterns/move-ref-patterns-closure-captures.stderr
index ca82353c1c9..d96e863939c 100644
--- a/src/test/ui/pattern/move-ref-patterns/move-ref-patterns-closure-captures.stderr
+++ b/src/test/ui/pattern/move-ref-patterns/move-ref-patterns-closure-captures.stderr
@@ -1,5 +1,5 @@
 error[E0525]: expected a closure that implements the `FnMut` trait, but this closure only implements `FnOnce`
-  --> $DIR/move-ref-patterns-closure-captures.rs:11:14
+  --> $DIR/move-ref-patterns-closure-captures.rs:9:14
    |
 LL |     let c1 = || {
    |              ^^ this closure implements `FnOnce`, not `FnMut`
@@ -11,7 +11,7 @@ LL |     accept_fn_mut(&c1);
    |     ------------- the requirement to implement `FnMut` derives from here
 
 error[E0525]: expected a closure that implements the `Fn` trait, but this closure only implements `FnOnce`
-  --> $DIR/move-ref-patterns-closure-captures.rs:11:14
+  --> $DIR/move-ref-patterns-closure-captures.rs:9:14
    |
 LL |     let c1 = || {
    |              ^^ this closure implements `FnOnce`, not `Fn`
@@ -23,7 +23,7 @@ LL |     accept_fn(&c1);
    |     --------- the requirement to implement `Fn` derives from here
 
 error[E0525]: expected a closure that implements the `Fn` trait, but this closure only implements `FnMut`
-  --> $DIR/move-ref-patterns-closure-captures.rs:22:14
+  --> $DIR/move-ref-patterns-closure-captures.rs:20:14
    |
 LL |     let c2 = || {
    |              ^^ this closure implements `FnMut`, not `Fn`
diff --git a/src/test/ui/pattern/move-ref-patterns/move-ref-patterns-default-binding-modes.rs b/src/test/ui/pattern/move-ref-patterns/move-ref-patterns-default-binding-modes.rs
index 5c51c47d979..1dd66aad57a 100644
--- a/src/test/ui/pattern/move-ref-patterns/move-ref-patterns-default-binding-modes.rs
+++ b/src/test/ui/pattern/move-ref-patterns/move-ref-patterns-default-binding-modes.rs
@@ -1,5 +1,3 @@
-#![feature(move_ref_pattern)]
-
 fn main() {
     struct U;
 
diff --git a/src/test/ui/pattern/move-ref-patterns/move-ref-patterns-default-binding-modes.stderr b/src/test/ui/pattern/move-ref-patterns/move-ref-patterns-default-binding-modes.stderr
index f92699f5c3c..6952c743a30 100644
--- a/src/test/ui/pattern/move-ref-patterns/move-ref-patterns-default-binding-modes.stderr
+++ b/src/test/ui/pattern/move-ref-patterns/move-ref-patterns-default-binding-modes.stderr
@@ -1,5 +1,5 @@
 error[E0507]: cannot move out of a shared reference
-  --> $DIR/move-ref-patterns-default-binding-modes.rs:10:22
+  --> $DIR/move-ref-patterns-default-binding-modes.rs:8:22
    |
 LL |     let (a, mut b) = &p;
    |             -----    ^^
@@ -8,7 +8,7 @@ LL |     let (a, mut b) = &p;
    |             move occurs because `b` has type `U`, which does not implement the `Copy` trait
 
 error[E0507]: cannot move out of a mutable reference
-  --> $DIR/move-ref-patterns-default-binding-modes.rs:14:22
+  --> $DIR/move-ref-patterns-default-binding-modes.rs:12:22
    |
 LL |     let (a, mut b) = &mut p;
    |             -----    ^^^^^^
diff --git a/src/test/ui/pattern/move-ref-patterns/move-ref-patterns-dynamic-semantics.rs b/src/test/ui/pattern/move-ref-patterns/move-ref-patterns-dynamic-semantics.rs
index c78695390b5..1d6d9acead1 100644
--- a/src/test/ui/pattern/move-ref-patterns/move-ref-patterns-dynamic-semantics.rs
+++ b/src/test/ui/pattern/move-ref-patterns/move-ref-patterns-dynamic-semantics.rs
@@ -3,8 +3,6 @@
 // This test checks the dynamic semantics and drop order of pattern matching
 // where a product pattern has both a by-move and by-ref binding.
 
-#![feature(move_ref_pattern)]
-
 use std::cell::RefCell;
 use std::rc::Rc;
 
diff --git a/src/test/ui/proc-macro/invalid-punct-ident-1.rs b/src/test/ui/proc-macro/invalid-punct-ident-1.rs
index 3f78dea917b..a3133a1a790 100644
--- a/src/test/ui/proc-macro/invalid-punct-ident-1.rs
+++ b/src/test/ui/proc-macro/invalid-punct-ident-1.rs
@@ -9,6 +9,9 @@
 // normalize-stderr-test "note: we would appreciate a bug report.*\n\n" -> ""
 // normalize-stderr-test "note: compiler flags.*\n\n" -> ""
 // normalize-stderr-test "note: rustc.*running on.*\n\n" -> ""
+// normalize-stderr-test "query stack during panic:\n" -> ""
+// normalize-stderr-test "we're just showing a limited slice of the query stack\n" -> ""
+// normalize-stderr-test "end of query stack\n" -> ""
 
 #[macro_use]
 extern crate invalid_punct_ident;
diff --git a/src/test/ui/proc-macro/invalid-punct-ident-1.stderr b/src/test/ui/proc-macro/invalid-punct-ident-1.stderr
index fc821d29d5a..5ef22709cb3 100644
--- a/src/test/ui/proc-macro/invalid-punct-ident-1.stderr
+++ b/src/test/ui/proc-macro/invalid-punct-ident-1.stderr
@@ -1,5 +1,5 @@
 error: proc macro panicked
-  --> $DIR/invalid-punct-ident-1.rs:16:1
+  --> $DIR/invalid-punct-ident-1.rs:19:1
    |
 LL | invalid_punct!();
    | ^^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/proc-macro/invalid-punct-ident-2.rs b/src/test/ui/proc-macro/invalid-punct-ident-2.rs
index 4e89e80ae7c..04a0a873311 100644
--- a/src/test/ui/proc-macro/invalid-punct-ident-2.rs
+++ b/src/test/ui/proc-macro/invalid-punct-ident-2.rs
@@ -9,6 +9,9 @@
 // normalize-stderr-test "note: we would appreciate a bug report.*\n\n" -> ""
 // normalize-stderr-test "note: compiler flags.*\n\n" -> ""
 // normalize-stderr-test "note: rustc.*running on.*\n\n" -> ""
+// normalize-stderr-test "query stack during panic:\n" -> ""
+// normalize-stderr-test "we're just showing a limited slice of the query stack\n" -> ""
+// normalize-stderr-test "end of query stack\n" -> ""
 
 #[macro_use]
 extern crate invalid_punct_ident;
diff --git a/src/test/ui/proc-macro/invalid-punct-ident-2.stderr b/src/test/ui/proc-macro/invalid-punct-ident-2.stderr
index 8b30edaf85c..4bd7a5351d3 100644
--- a/src/test/ui/proc-macro/invalid-punct-ident-2.stderr
+++ b/src/test/ui/proc-macro/invalid-punct-ident-2.stderr
@@ -1,5 +1,5 @@
 error: proc macro panicked
-  --> $DIR/invalid-punct-ident-2.rs:16:1
+  --> $DIR/invalid-punct-ident-2.rs:19:1
    |
 LL | invalid_ident!();
    | ^^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/proc-macro/invalid-punct-ident-3.rs b/src/test/ui/proc-macro/invalid-punct-ident-3.rs
index 8d8ce8f932e..aebba341625 100644
--- a/src/test/ui/proc-macro/invalid-punct-ident-3.rs
+++ b/src/test/ui/proc-macro/invalid-punct-ident-3.rs
@@ -9,6 +9,9 @@
 // normalize-stderr-test "note: we would appreciate a bug report.*\n\n" -> ""
 // normalize-stderr-test "note: compiler flags.*\n\n" -> ""
 // normalize-stderr-test "note: rustc.*running on.*\n\n" -> ""
+// normalize-stderr-test "query stack during panic:\n" -> ""
+// normalize-stderr-test "we're just showing a limited slice of the query stack\n" -> ""
+// normalize-stderr-test "end of query stack\n" -> ""
 
 #[macro_use]
 extern crate invalid_punct_ident;
diff --git a/src/test/ui/proc-macro/invalid-punct-ident-3.stderr b/src/test/ui/proc-macro/invalid-punct-ident-3.stderr
index d46fab08e14..072d13956ac 100644
--- a/src/test/ui/proc-macro/invalid-punct-ident-3.stderr
+++ b/src/test/ui/proc-macro/invalid-punct-ident-3.stderr
@@ -1,5 +1,5 @@
 error: proc macro panicked
-  --> $DIR/invalid-punct-ident-3.rs:16:1
+  --> $DIR/invalid-punct-ident-3.rs:19:1
    |
 LL | invalid_raw_ident!();
    | ^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/proc-macro/load-panic-backtrace.rs b/src/test/ui/proc-macro/load-panic-backtrace.rs
index 90fe109abb8..4a3ba9aee74 100644
--- a/src/test/ui/proc-macro/load-panic-backtrace.rs
+++ b/src/test/ui/proc-macro/load-panic-backtrace.rs
@@ -10,6 +10,9 @@
 // normalize-stderr-test "note: we would appreciate a bug report.*\n\n" -> ""
 // normalize-stderr-test "note: compiler flags.*\n\n" -> ""
 // normalize-stderr-test "note: rustc.*running on.*\n\n" -> ""
+// normalize-stderr-test "query stack during panic:\n" -> ""
+// normalize-stderr-test "we're just showing a limited slice of the query stack\n" -> ""
+// normalize-stderr-test "end of query stack\n" -> ""
 
 #[macro_use]
 extern crate test_macros;
diff --git a/src/test/ui/proc-macro/load-panic-backtrace.stderr b/src/test/ui/proc-macro/load-panic-backtrace.stderr
index 63378b5735a..f825047e331 100644
--- a/src/test/ui/proc-macro/load-panic-backtrace.stderr
+++ b/src/test/ui/proc-macro/load-panic-backtrace.stderr
@@ -1,6 +1,6 @@
 at 'panic-derive', $DIR/auxiliary/test-macros.rs:43:5
 error: proc-macro derive panicked
-  --> $DIR/load-panic-backtrace.rs:17:10
+  --> $DIR/load-panic-backtrace.rs:20:10
    |
 LL | #[derive(Panic)]
    |          ^^^^^
diff --git a/src/test/ui/rfc-2005-default-binding-mode/for.rs b/src/test/ui/rfc-2005-default-binding-mode/for.rs
index aa42c7bb9c2..d6c5a13b1bd 100644
--- a/src/test/ui/rfc-2005-default-binding-mode/for.rs
+++ b/src/test/ui/rfc-2005-default-binding-mode/for.rs
@@ -1,5 +1,3 @@
-#![feature(move_ref_pattern)]
-
 struct Foo {}
 
 pub fn main() {
diff --git a/src/test/ui/rfc-2005-default-binding-mode/for.stderr b/src/test/ui/rfc-2005-default-binding-mode/for.stderr
index ef624313880..9cc20a7bf31 100644
--- a/src/test/ui/rfc-2005-default-binding-mode/for.stderr
+++ b/src/test/ui/rfc-2005-default-binding-mode/for.stderr
@@ -1,5 +1,5 @@
 error[E0507]: cannot move out of a shared reference
-  --> $DIR/for.rs:8:23
+  --> $DIR/for.rs:6:23
    |
 LL |     for (n, mut m) in &tups {
    |             -----     ^^^^^
diff --git a/src/test/ui/span/issue-34264.stderr b/src/test/ui/span/issue-34264.stderr
index 40c3219bf27..5cda17fd6a1 100644
--- a/src/test/ui/span/issue-34264.stderr
+++ b/src/test/ui/span/issue-34264.stderr
@@ -53,13 +53,16 @@ LL | fn bar(_: x, y: usize) {}
 error[E0061]: this function takes 2 arguments but 3 arguments were supplied
   --> $DIR/issue-34264.rs:7:5
    |
-LL | fn foo(Option<i32>, String) {}
-   | --------------------------- defined here
-...
 LL |     foo(Some(42), 2, "");
    |     ^^^ --------  -  -- supplied 3 arguments
    |     |
    |     expected 2 arguments
+   |
+note: function defined here
+  --> $DIR/issue-34264.rs:1:4
+   |
+LL | fn foo(Option<i32>, String) {}
+   |    ^^^ -----------  ------
 
 error[E0308]: mismatched types
   --> $DIR/issue-34264.rs:8:13
@@ -70,13 +73,16 @@ LL |     bar("", "");
 error[E0061]: this function takes 2 arguments but 3 arguments were supplied
   --> $DIR/issue-34264.rs:10:5
    |
-LL | fn bar(x, y: usize) {}
-   | ------------------- defined here
-...
 LL |     bar(1, 2, 3);
    |     ^^^ -  -  - supplied 3 arguments
    |     |
    |     expected 2 arguments
+   |
+note: function defined here
+  --> $DIR/issue-34264.rs:3:4
+   |
+LL | fn bar(x, y: usize) {}
+   |    ^^^ -  --------
 
 error: aborting due to 6 previous errors
 
diff --git a/src/test/ui/span/missing-unit-argument.stderr b/src/test/ui/span/missing-unit-argument.stderr
index f6344fba3d3..b15da2cb479 100644
--- a/src/test/ui/span/missing-unit-argument.stderr
+++ b/src/test/ui/span/missing-unit-argument.stderr
@@ -12,34 +12,42 @@ LL |     let _: Result<(), String> = Ok(());
 error[E0061]: this function takes 2 arguments but 0 arguments were supplied
   --> $DIR/missing-unit-argument.rs:12:5
    |
-LL | fn foo(():(), ():()) {}
-   | -------------------- defined here
-...
 LL |     foo();
    |     ^^^-- supplied 0 arguments
    |     |
    |     expected 2 arguments
+   |
+note: function defined here
+  --> $DIR/missing-unit-argument.rs:1:4
+   |
+LL | fn foo(():(), ():()) {}
+   |    ^^^ -----  -----
 
 error[E0061]: this function takes 2 arguments but 1 argument was supplied
   --> $DIR/missing-unit-argument.rs:13:5
    |
-LL | fn foo(():(), ():()) {}
-   | -------------------- defined here
-...
 LL |     foo(());
    |     ^^^ -- supplied 1 argument
    |     |
    |     expected 2 arguments
+   |
+note: function defined here
+  --> $DIR/missing-unit-argument.rs:1:4
+   |
+LL | fn foo(():(), ():()) {}
+   |    ^^^ -----  -----
 
 error[E0061]: this function takes 1 argument but 0 arguments were supplied
   --> $DIR/missing-unit-argument.rs:14:5
    |
-LL | fn bar(():()) {}
-   | ------------- defined here
-...
 LL |     bar();
    |     ^^^-- supplied 0 arguments
    |
+note: function defined here
+  --> $DIR/missing-unit-argument.rs:2:4
+   |
+LL | fn bar(():()) {}
+   |    ^^^ -----
 help: expected the unit value `()`; create it with empty parentheses
    |
 LL |     bar(());
@@ -48,12 +56,14 @@ LL |     bar(());
 error[E0061]: this function takes 1 argument but 0 arguments were supplied
   --> $DIR/missing-unit-argument.rs:15:7
    |
-LL |     fn baz(self, (): ()) { }
-   |     -------------------- defined here
-...
 LL |     S.baz();
    |       ^^^- supplied 0 arguments
    |
+note: associated function defined here
+  --> $DIR/missing-unit-argument.rs:6:8
+   |
+LL |     fn baz(self, (): ()) { }
+   |        ^^^ ----  ------
 help: expected the unit value `()`; create it with empty parentheses
    |
 LL |     S.baz(());
@@ -62,12 +72,14 @@ LL |     S.baz(());
 error[E0061]: this function takes 1 argument but 0 arguments were supplied
   --> $DIR/missing-unit-argument.rs:16:7
    |
-LL |     fn generic<T>(self, _: T) { }
-   |     ------------------------- defined here
-...
 LL |     S.generic::<()>();
    |       ^^^^^^^------ supplied 0 arguments
    |
+note: associated function defined here
+  --> $DIR/missing-unit-argument.rs:7:8
+   |
+LL |     fn generic<T>(self, _: T) { }
+   |        ^^^^^^^    ----  ----
 help: expected the unit value `()`; create it with empty parentheses
    |
 LL |     S.generic::<()>(());
diff --git a/src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr b/src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr
index c1eea56f70d..8a9a1e57935 100644
--- a/src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr
+++ b/src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr
@@ -13,7 +13,7 @@ error[E0277]: the trait bound `&dyn std::io::Write: std::io::Write` is not satis
 LL |     let fp = BufWriter::new(fp);
    |              ^^^^^^^^^^^^^^ the trait `std::io::Write` is not implemented for `&dyn std::io::Write`
    | 
-  ::: $SRC_DIR/std/src/io/buffered.rs:LL:COL
+  ::: $SRC_DIR/std/src/io/buffered/bufwriter.rs:LL:COL
    |
 LL | pub struct BufWriter<W: Write> {
    |                         ----- required by this bound in `BufWriter`
@@ -26,7 +26,7 @@ error[E0277]: the trait bound `&dyn std::io::Write: std::io::Write` is not satis
 LL |     let fp = BufWriter::new(fp);
    |              ^^^^^^^^^^^^^^^^^^ the trait `std::io::Write` is not implemented for `&dyn std::io::Write`
    | 
-  ::: $SRC_DIR/std/src/io/buffered.rs:LL:COL
+  ::: $SRC_DIR/std/src/io/buffered/bufwriter.rs:LL:COL
    |
 LL | pub struct BufWriter<W: Write> {
    |                         ----- required by this bound in `BufWriter`
@@ -39,7 +39,7 @@ error[E0599]: no method named `write_fmt` found for struct `BufWriter<&dyn std::
 LL |     writeln!(fp, "hello world").unwrap();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ method not found in `BufWriter<&dyn std::io::Write>`
    | 
-  ::: $SRC_DIR/std/src/io/buffered.rs:LL:COL
+  ::: $SRC_DIR/std/src/io/buffered/bufwriter.rs:LL:COL
    |
 LL | pub struct BufWriter<W: Write> {
    | ------------------------------ doesn't satisfy `BufWriter<&dyn std::io::Write>: std::io::Write`
diff --git a/src/test/ui/symbol-names/issue-75326.legacy.stderr b/src/test/ui/symbol-names/issue-75326.legacy.stderr
new file mode 100644
index 00000000000..5f822f6660c
--- /dev/null
+++ b/src/test/ui/symbol-names/issue-75326.legacy.stderr
@@ -0,0 +1,20 @@
+error: symbol-name(_ZN72_$LT$issue_75326..Foo$LT$I$C$E$GT$$u20$as$u20$issue_75326..Iterator2$GT$4next17SYMBOL_HASH)
+  --> $DIR/issue-75326.rs:43:5
+   |
+LL |     #[rustc_symbol_name]
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: demangling(<issue_75326::Foo<I,E> as issue_75326::Iterator2>::next::SYMBOL_HASH)
+  --> $DIR/issue-75326.rs:43:5
+   |
+LL |     #[rustc_symbol_name]
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: demangling-alt(<issue_75326::Foo<I,E> as issue_75326::Iterator2>::next)
+  --> $DIR/issue-75326.rs:43:5
+   |
+LL |     #[rustc_symbol_name]
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/symbol-names/issue-75326.rs b/src/test/ui/symbol-names/issue-75326.rs
new file mode 100644
index 00000000000..ce315164cef
--- /dev/null
+++ b/src/test/ui/symbol-names/issue-75326.rs
@@ -0,0 +1,58 @@
+// build-fail
+// ignore-tidy-linelength
+// revisions: legacy v0
+//[legacy]compile-flags: -Z symbol-mangling-version=legacy
+//[v0]compile-flags: -Z symbol-mangling-version=v0
+//[legacy]normalize-stderr-32bit: "h[\d\w]+" -> "SYMBOL_HASH"
+//[legacy]normalize-stderr-64bit: "h[\d\w]+" -> "SYMBOL_HASH"
+
+#![feature(rustc_attrs)]
+
+pub(crate) struct Foo<I, E>(I, E);
+
+pub trait Iterator2 {
+    type Item;
+
+    fn next(&mut self) -> Option<Self::Item>;
+
+    fn find<P>(&mut self, predicate: P) -> Option<Self::Item>
+    where
+        Self: Sized,
+        P: FnMut(&Self::Item) -> bool,
+    {
+        unimplemented!()
+    }
+}
+
+struct Bar;
+
+impl Iterator2 for Bar {
+    type Item = (u32, u16);
+
+    fn next(&mut self) -> Option<Self::Item> {
+        unimplemented!()
+    }
+}
+
+impl<I, T, E> Iterator2 for Foo<I, E>
+where
+    I: Iterator2<Item = (T, E)>,
+{
+    type Item = T;
+
+    #[rustc_symbol_name]
+    //[legacy]~^ ERROR symbol-name(_ZN72_$LT$issue_75326..Foo$LT$I$C$E$GT$$u20$as$u20$issue_75326..Iterator2$GT$4next
+    //[legacy]~| ERROR demangling(<issue_75326::Foo<I,E> as issue_75326::Iterator2>::next
+    //[legacy]~| ERROR demangling-alt(<issue_75326::Foo<I,E> as issue_75326::Iterator2>::next)
+    //[v0]~^^^^  ERROR symbol-name(_RNvXINICs4fqI2P2rA04_11issue_75326s_0pppEINtB5_3FooppENtB5_9Iterator24nextB5_)
+    //[v0]~|     ERROR demangling(<issue_75326[317d481089b8c8fe]::Foo<_, _> as issue_75326[317d481089b8c8fe]::Iterator2>::next)
+    //[v0]~|     ERROR demangling-alt(<issue_75326::Foo<_, _> as issue_75326::Iterator2>::next)
+    fn next(&mut self) -> Option<Self::Item> {
+        self.find(|_| true)
+    }
+}
+
+fn main() {
+    let mut a = Foo(Bar, 1u16);
+    let _ = a.next();
+}
diff --git a/src/test/ui/symbol-names/issue-75326.v0.stderr b/src/test/ui/symbol-names/issue-75326.v0.stderr
new file mode 100644
index 00000000000..59bdfa8ca36
--- /dev/null
+++ b/src/test/ui/symbol-names/issue-75326.v0.stderr
@@ -0,0 +1,20 @@
+error: symbol-name(_RNvXINICs4fqI2P2rA04_11issue_75326s_0pppEINtB5_3FooppENtB5_9Iterator24nextB5_)
+  --> $DIR/issue-75326.rs:43:5
+   |
+LL |     #[rustc_symbol_name]
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: demangling(<issue_75326[317d481089b8c8fe]::Foo<_, _> as issue_75326[317d481089b8c8fe]::Iterator2>::next)
+  --> $DIR/issue-75326.rs:43:5
+   |
+LL |     #[rustc_symbol_name]
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: demangling-alt(<issue_75326::Foo<_, _> as issue_75326::Iterator2>::next)
+  --> $DIR/issue-75326.rs:43:5
+   |
+LL |     #[rustc_symbol_name]
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/type-alias-enum-variants/enum-variant-priority-higher-than-other-inherent.stderr b/src/test/ui/type-alias-enum-variants/enum-variant-priority-higher-than-other-inherent.stderr
index 46e7dd0c517..20e26058451 100644
--- a/src/test/ui/type-alias-enum-variants/enum-variant-priority-higher-than-other-inherent.stderr
+++ b/src/test/ui/type-alias-enum-variants/enum-variant-priority-higher-than-other-inherent.stderr
@@ -1,13 +1,16 @@
 error[E0061]: this function takes 1 argument but 0 arguments were supplied
   --> $DIR/enum-variant-priority-higher-than-other-inherent.rs:21:5
    |
-LL |     V(u8)
-   |     ----- defined here
-...
 LL |     <E>::V();
    |     ^^^^^^-- supplied 0 arguments
    |     |
    |     expected 1 argument
+   |
+note: tuple variant defined here
+  --> $DIR/enum-variant-priority-higher-than-other-inherent.rs:5:5
+   |
+LL |     V(u8)
+   |     ^^^^^
 
 error[E0308]: mismatched types
   --> $DIR/enum-variant-priority-higher-than-other-inherent.rs:22:17
diff --git a/src/tools/clippy/src/driver.rs b/src/tools/clippy/src/driver.rs
index 377f6d22446..805828eece1 100644
--- a/src/tools/clippy/src/driver.rs
+++ b/src/tools/clippy/src/driver.rs
@@ -277,9 +277,9 @@ fn report_clippy_ice(info: &panic::PanicInfo<'_>, bug_report_url: &str) {
     // If backtraces are enabled, also print the query stack
     let backtrace = env::var_os("RUST_BACKTRACE").map_or(false, |x| &x != "0");
 
-    if backtrace {
-        TyCtxt::try_print_query_stack(&handler);
-    }
+    let num_frames = if backtrace { None } else { Some(2) };
+
+    TyCtxt::try_print_query_stack(&handler, num_frames);
 }
 
 fn toolchain_path(home: Option<String>, toolchain: Option<String>) -> Option<PathBuf> {
diff --git a/src/tools/clippy/tests/ui/custom_ice_message.stderr b/src/tools/clippy/tests/ui/custom_ice_message.stderr
index a9a65a38c10..a1b8e2ee162 100644
--- a/src/tools/clippy/tests/ui/custom_ice_message.stderr
+++ b/src/tools/clippy/tests/ui/custom_ice_message.stderr
@@ -9,3 +9,5 @@ note: we would appreciate a bug report: https://github.com/rust-lang/rust-clippy
 
 note: Clippy version: foo
 
+query stack during panic:
+end of query stack