about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2021-01-24 23:04:15 +0000
committerbors <bors@rust-lang.org>2021-01-24 23:04:15 +0000
commitd3163e96553ae8cb1fca0e62084b124e8b98310b (patch)
tree8f0e190a1dd178971317e5cab80cc9ea453d6dd9
parent1d0d76f8dd4f5f6ecbeab575b87edaf1c9f56bb8 (diff)
parent529f15f9b9c5bcd1d2a02e2fa74027a5c5a458de (diff)
Auto merge of #81355 - jonas-schievink:rollup-vpaadij, r=jonas-schievink
Rollup of 14 pull requests

Successful merges:

 - #75180 (Implement Error for &(impl Error))
 - #78578 (Permit mutable references in all const contexts)
 - #79174 (Make std::future a re-export of core::future)
 - #79884 (Replace magic numbers with existing constants)
 - #80855 (Expand assert!(expr, args..) to include $crate for hygiene on 2021.)
 - #80933 (Fix sysroot option not being honored across rustc)
 - #81259 (Replace version_check dependency with own version parsing code)
 - #81264 (Add unstable option to control doctest run directory)
 - #81279 (Small refactor in typeck)
 - #81297 (Don't provide backend_optimization_level query for extern crates)
 - #81302 (Fix rendering of stabilization version for trait implementors)
 - #81310 (Do not mark unit variants as used when in path pattern)
 - #81320 (Make bad shlex parsing a pretty error)
 - #81338 (Clean up `dominators_given_rpo`)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
-rw-r--r--Cargo.lock1
-rw-r--r--compiler/rustc_attr/Cargo.toml1
-rw-r--r--compiler/rustc_attr/src/builtin.rs32
-rw-r--r--compiler/rustc_builtin_macros/src/assert.rs26
-rw-r--r--compiler/rustc_codegen_ssa/src/back/link.rs28
-rw-r--r--compiler/rustc_codegen_ssa/src/base.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/lib.rs3
-rw-r--r--compiler/rustc_data_structures/src/graph/dominators/mod.rs16
-rw-r--r--compiler/rustc_mir/src/transform/check_consts/ops.rs71
-rw-r--r--compiler/rustc_mir/src/transform/check_consts/validation.rs29
-rw-r--r--compiler/rustc_passes/src/dead.rs2
-rw-r--r--compiler/rustc_typeck/src/check/check.rs242
-rw-r--r--library/core/src/time.rs20
-rw-r--r--library/std/src/error.rs21
-rw-r--r--library/std/src/future.rs17
-rw-r--r--library/std/src/lib.rs5
-rw-r--r--src/librustdoc/config.rs5
-rw-r--r--src/librustdoc/doctest.rs3
-rw-r--r--src/librustdoc/html/render/mod.rs51
-rw-r--r--src/librustdoc/lib.rs8
-rw-r--r--src/test/rustdoc-ui/run-directory.correct.stdout6
-rw-r--r--src/test/rustdoc-ui/run-directory.incorrect.stdout6
-rw-r--r--src/test/rustdoc-ui/run-directory.rs23
-rw-r--r--src/test/rustdoc/implementor-stable-version.rs19
-rw-r--r--src/test/ui/check-static-immutable-mut-slices.rs2
-rw-r--r--src/test/ui/check-static-immutable-mut-slices.stderr4
-rw-r--r--src/test/ui/consts/const-address-of-mut.stderr24
-rw-r--r--src/test/ui/consts/const-eval/issue-65394.stderr9
-rw-r--r--src/test/ui/consts/const-multi-ref.stderr10
-rw-r--r--src/test/ui/consts/const-mut-refs/const_mut_address_of.rs3
-rw-r--r--src/test/ui/consts/const-mut-refs/const_mut_address_of.stderr15
-rw-r--r--src/test/ui/consts/const-mut-refs/const_mut_refs.rs4
-rw-r--r--src/test/ui/consts/const-mut-refs/const_mut_refs.stderr21
-rw-r--r--src/test/ui/consts/const-mut-refs/mut_ref_in_final.rs57
-rw-r--r--src/test/ui/consts/const-mut-refs/mut_ref_in_final.stderr60
-rw-r--r--src/test/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.rs28
-rw-r--r--src/test/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.stderr23
-rw-r--r--src/test/ui/consts/const_let_assign3.stderr17
-rw-r--r--src/test/ui/consts/issue-17718-const-bad-values.rs3
-rw-r--r--src/test/ui/consts/issue-17718-const-bad-values.stderr12
-rw-r--r--src/test/ui/consts/projection_qualif.mut_refs.stderr19
-rw-r--r--src/test/ui/consts/projection_qualif.stock.stderr19
-rw-r--r--src/test/ui/consts/read_from_static_mut_ref.rs9
-rw-r--r--src/test/ui/consts/read_from_static_mut_ref.stderr9
-rw-r--r--src/test/ui/consts/static_mut_containing_mut_ref2.mut_refs.stderr8
-rw-r--r--src/test/ui/consts/static_mut_containing_mut_ref2.rs3
-rw-r--r--src/test/ui/consts/static_mut_containing_mut_ref2.stock.stderr9
-rw-r--r--src/test/ui/consts/write_to_mut_ref_dest.mut_refs.stderr12
-rw-r--r--src/test/ui/consts/write_to_mut_ref_dest.rs (renamed from src/test/ui/consts/projection_qualif.rs)2
-rw-r--r--src/test/ui/consts/write_to_mut_ref_dest.stock.stderr21
-rw-r--r--src/test/ui/consts/write_to_static_via_mut_ref.rs8
-rw-r--r--src/test/ui/consts/write_to_static_via_mut_ref.stderr16
-rw-r--r--src/test/ui/error-codes/E0017.rs9
-rw-r--r--src/test/ui/error-codes/E0017.stderr35
-rw-r--r--src/test/ui/error-codes/E0388.rs7
-rw-r--r--src/test/ui/error-codes/E0388.stderr29
-rw-r--r--src/test/ui/feature-gates/feature-gate-cfg-version.rs30
-rw-r--r--src/test/ui/feature-gates/feature-gate-cfg-version.stderr110
-rw-r--r--src/test/ui/hygiene/no_implicit_prelude-2021.rs9
-rw-r--r--src/test/ui/issues/issue-46604.rs2
-rw-r--r--src/test/ui/issues/issue-46604.stderr4
-rw-r--r--src/test/ui/lint/dead-code/const-and-self.rs21
-rw-r--r--src/test/ui/lint/dead-code/const-and-self.stderr20
-rw-r--r--src/test/ui/never_type/issue-52443.stderr9
-rw-r--r--src/test/ui/unsafe/ranged_ints2_const.rs6
-rw-r--r--src/test/ui/unsafe/ranged_ints2_const.stderr11
-rw-r--r--src/tools/jsondocck/src/main.rs17
67 files changed, 942 insertions, 441 deletions
diff --git a/Cargo.lock b/Cargo.lock
index de5158ab073..9d726b240da 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -3568,7 +3568,6 @@ dependencies = [
  "rustc_serialize",
  "rustc_session",
  "rustc_span",
- "version_check",
 ]
 
 [[package]]
diff --git a/compiler/rustc_attr/Cargo.toml b/compiler/rustc_attr/Cargo.toml
index 5f941a0a650..dc0711a5b0f 100644
--- a/compiler/rustc_attr/Cargo.toml
+++ b/compiler/rustc_attr/Cargo.toml
@@ -18,4 +18,3 @@ rustc_lexer = { path = "../rustc_lexer" }
 rustc_macros = { path = "../rustc_macros" }
 rustc_session = { path = "../rustc_session" }
 rustc_ast = { path = "../rustc_ast" }
-version_check = "0.9"
diff --git a/compiler/rustc_attr/src/builtin.rs b/compiler/rustc_attr/src/builtin.rs
index ead90f23ce7..26baaf07880 100644
--- a/compiler/rustc_attr/src/builtin.rs
+++ b/compiler/rustc_attr/src/builtin.rs
@@ -10,7 +10,6 @@ use rustc_session::Session;
 use rustc_span::hygiene::Transparency;
 use rustc_span::{symbol::sym, symbol::Symbol, Span};
 use std::num::NonZeroU32;
-use version_check::Version;
 
 pub fn is_builtin_attr(attr: &Attribute) -> bool {
     attr.is_doc_comment() || attr.ident().filter(|ident| is_builtin_attr_name(ident.name)).is_some()
@@ -526,6 +525,26 @@ fn gate_cfg(gated_cfg: &GatedCfg, cfg_span: Span, sess: &ParseSess, features: &F
     }
 }
 
+#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
+struct Version {
+    major: u16,
+    minor: u16,
+    patch: u16,
+}
+
+fn parse_version(s: &str, allow_appendix: bool) -> Option<Version> {
+    let mut components = s.split('-');
+    let d = components.next()?;
+    if !allow_appendix && components.next().is_some() {
+        return None;
+    }
+    let mut digits = d.splitn(3, '.');
+    let major = digits.next()?.parse().ok()?;
+    let minor = digits.next()?.parse().ok()?;
+    let patch = digits.next().unwrap_or("0").parse().ok()?;
+    Some(Version { major, minor, patch })
+}
+
 /// Evaluate a cfg-like condition (with `any` and `all`), using `eval` to
 /// evaluate individual items.
 pub fn eval_condition(
@@ -555,16 +574,21 @@ pub fn eval_condition(
                     return false;
                 }
             };
-            let min_version = match Version::parse(&min_version.as_str()) {
+            let min_version = match parse_version(&min_version.as_str(), false) {
                 Some(ver) => ver,
                 None => {
-                    sess.span_diagnostic.struct_span_err(*span, "invalid version literal").emit();
+                    sess.span_diagnostic
+                        .struct_span_warn(
+                            *span,
+                            "unknown version literal format, assuming it refers to a future version",
+                        )
+                        .emit();
                     return false;
                 }
             };
             let channel = env!("CFG_RELEASE_CHANNEL");
             let nightly = channel == "nightly" || channel == "dev";
-            let rustc_version = Version::parse(env!("CFG_RELEASE")).unwrap();
+            let rustc_version = parse_version(env!("CFG_RELEASE"), true).unwrap();
 
             // See https://github.com/rust-lang/rust/issues/64796#issuecomment-625474439 for details
             if nightly { rustc_version > min_version } else { rustc_version >= min_version }
diff --git a/compiler/rustc_builtin_macros/src/assert.rs b/compiler/rustc_builtin_macros/src/assert.rs
index bb6d3f6a007..f82269c4eee 100644
--- a/compiler/rustc_builtin_macros/src/assert.rs
+++ b/compiler/rustc_builtin_macros/src/assert.rs
@@ -12,27 +12,43 @@ use rustc_span::{Span, DUMMY_SP};
 
 pub fn expand_assert<'cx>(
     cx: &'cx mut ExtCtxt<'_>,
-    sp: Span,
+    span: Span,
     tts: TokenStream,
 ) -> Box<dyn MacResult + 'cx> {
-    let Assert { cond_expr, custom_message } = match parse_assert(cx, sp, tts) {
+    let Assert { cond_expr, custom_message } = match parse_assert(cx, span, tts) {
         Ok(assert) => assert,
         Err(mut err) => {
             err.emit();
-            return DummyResult::any(sp);
+            return DummyResult::any(span);
         }
     };
 
     // `core::panic` and `std::panic` are different macros, so we use call-site
     // context to pick up whichever is currently in scope.
-    let sp = cx.with_call_site_ctxt(sp);
+    let sp = cx.with_call_site_ctxt(span);
 
     let panic_call = if let Some(tokens) = custom_message {
+        let path = if span.rust_2021() {
+            // On edition 2021, we always call `$crate::panic!()`.
+            Path {
+                span: sp,
+                segments: cx
+                    .std_path(&[sym::panic])
+                    .into_iter()
+                    .map(|ident| PathSegment::from_ident(ident))
+                    .collect(),
+                tokens: None,
+            }
+        } else {
+            // Before edition 2021, we call `panic!()` unqualified,
+            // such that it calls either `std::panic!()` or `core::panic!()`.
+            Path::from_ident(Ident::new(sym::panic, sp))
+        };
         // Pass the custom message to panic!().
         cx.expr(
             sp,
             ExprKind::MacCall(MacCall {
-                path: Path::from_ident(Ident::new(sym::panic, sp)),
+                path,
                 args: P(MacArgs::Delimited(
                     DelimSpan::from_single(sp),
                     MacDelimiter::Parenthesis,
diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs
index e51904f308d..72e049b6d74 100644
--- a/compiler/rustc_codegen_ssa/src/back/link.rs
+++ b/compiler/rustc_codegen_ssa/src/back/link.rs
@@ -885,9 +885,22 @@ fn link_sanitizers(sess: &Session, crate_type: CrateType, linker: &mut dyn Linke
 }
 
 fn link_sanitizer_runtime(sess: &Session, linker: &mut dyn Linker, name: &str) {
-    let default_sysroot = filesearch::get_or_default_sysroot();
-    let default_tlib =
-        filesearch::make_target_lib_path(&default_sysroot, sess.opts.target_triple.triple());
+    fn find_sanitizer_runtime(sess: &Session, filename: &String) -> PathBuf {
+        let session_tlib =
+            filesearch::make_target_lib_path(&sess.sysroot, sess.opts.target_triple.triple());
+        let path = session_tlib.join(&filename);
+        if path.exists() {
+            return session_tlib;
+        } else {
+            let default_sysroot = filesearch::get_or_default_sysroot();
+            let default_tlib = filesearch::make_target_lib_path(
+                &default_sysroot,
+                sess.opts.target_triple.triple(),
+            );
+            return default_tlib;
+        }
+    }
+
     let channel = option_env!("CFG_RELEASE_CHANNEL")
         .map(|channel| format!("-{}", channel))
         .unwrap_or_default();
@@ -898,10 +911,11 @@ fn link_sanitizer_runtime(sess: &Session, linker: &mut dyn Linker, name: &str) {
             // LLVM will link to `@rpath/*.dylib`, so we need to specify an
             // rpath to the library as well (the rpath should be absolute, see
             // PR #41352 for details).
-            let libname = format!("rustc{}_rt.{}", channel, name);
-            let rpath = default_tlib.to_str().expect("non-utf8 component in path");
+            let filename = format!("rustc{}_rt.{}", channel, name);
+            let path = find_sanitizer_runtime(&sess, &filename);
+            let rpath = path.to_str().expect("non-utf8 component in path");
             linker.args(&["-Wl,-rpath", "-Xlinker", rpath]);
-            linker.link_dylib(Symbol::intern(&libname));
+            linker.link_dylib(Symbol::intern(&filename));
         }
         "aarch64-fuchsia"
         | "aarch64-unknown-linux-gnu"
@@ -909,7 +923,7 @@ fn link_sanitizer_runtime(sess: &Session, linker: &mut dyn Linker, name: &str) {
         | "x86_64-unknown-freebsd"
         | "x86_64-unknown-linux-gnu" => {
             let filename = format!("librustc{}_rt.{}.a", channel, name);
-            let path = default_tlib.join(&filename);
+            let path = find_sanitizer_runtime(&sess, &filename).join(&filename);
             linker.link_whole_rlib(&path);
         }
         _ => {}
diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs
index 2ce5fe5ad50..b205ea9cf6c 100644
--- a/compiler/rustc_codegen_ssa/src/base.rs
+++ b/compiler/rustc_codegen_ssa/src/base.rs
@@ -783,7 +783,7 @@ impl CrateInfo {
     }
 }
 
-pub fn provide_both(providers: &mut Providers) {
+pub fn provide(providers: &mut Providers) {
     providers.backend_optimization_level = |tcx, cratenum| {
         let for_speed = match tcx.sess.opts.optimize {
             // If globally no optimisation is done, #[optimize] has no effect.
diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs
index e27eac3f69b..0307117e1c8 100644
--- a/compiler/rustc_codegen_ssa/src/lib.rs
+++ b/compiler/rustc_codegen_ssa/src/lib.rs
@@ -160,13 +160,12 @@ pub struct CodegenResults {
 
 pub fn provide(providers: &mut Providers) {
     crate::back::symbol_export::provide(providers);
-    crate::base::provide_both(providers);
+    crate::base::provide(providers);
     crate::target_features::provide(providers);
 }
 
 pub fn provide_extern(providers: &mut Providers) {
     crate::back::symbol_export::provide_extern(providers);
-    crate::base::provide_both(providers);
 }
 
 /// Checks if the given filename ends with the `.rcgu.o` extension that `rustc`
diff --git a/compiler/rustc_data_structures/src/graph/dominators/mod.rs b/compiler/rustc_data_structures/src/graph/dominators/mod.rs
index 1cfbce2355e..ad62e3c9fc8 100644
--- a/compiler/rustc_data_structures/src/graph/dominators/mod.rs
+++ b/compiler/rustc_data_structures/src/graph/dominators/mod.rs
@@ -8,7 +8,6 @@
 use super::iterate::reverse_post_order;
 use super::ControlFlowGraph;
 use rustc_index::vec::{Idx, IndexVec};
-use std::borrow::BorrowMut;
 use std::cmp::Ordering;
 
 #[cfg(test)]
@@ -20,22 +19,17 @@ pub fn dominators<G: ControlFlowGraph>(graph: G) -> Dominators<G::Node> {
     dominators_given_rpo(graph, &rpo)
 }
 
-fn dominators_given_rpo<G: ControlFlowGraph + BorrowMut<G>>(
-    mut graph: G,
-    rpo: &[G::Node],
-) -> Dominators<G::Node> {
-    let start_node = graph.borrow().start_node();
+fn dominators_given_rpo<G: ControlFlowGraph>(graph: G, rpo: &[G::Node]) -> Dominators<G::Node> {
+    let start_node = graph.start_node();
     assert_eq!(rpo[0], start_node);
 
     // compute the post order index (rank) for each node
-    let mut post_order_rank: IndexVec<G::Node, usize> =
-        (0..graph.borrow().num_nodes()).map(|_| 0).collect();
+    let mut post_order_rank = IndexVec::from_elem_n(0, graph.num_nodes());
     for (index, node) in rpo.iter().rev().cloned().enumerate() {
         post_order_rank[node] = index;
     }
 
-    let mut immediate_dominators: IndexVec<G::Node, Option<G::Node>> =
-        (0..graph.borrow().num_nodes()).map(|_| None).collect();
+    let mut immediate_dominators = IndexVec::from_elem_n(None, graph.num_nodes());
     immediate_dominators[start_node] = Some(start_node);
 
     let mut changed = true;
@@ -44,7 +38,7 @@ fn dominators_given_rpo<G: ControlFlowGraph + BorrowMut<G>>(
 
         for &node in &rpo[1..] {
             let mut new_idom = None;
-            for pred in graph.borrow_mut().predecessors(node) {
+            for pred in graph.predecessors(node) {
                 if immediate_dominators[pred].is_some() {
                     // (*) dominators for `pred` have been calculated
                     new_idom = Some(if let Some(new_idom) = new_idom {
diff --git a/compiler/rustc_mir/src/transform/check_consts/ops.rs b/compiler/rustc_mir/src/transform/check_consts/ops.rs
index 99ffb0edce9..6f98760a7b0 100644
--- a/compiler/rustc_mir/src/transform/check_consts/ops.rs
+++ b/compiler/rustc_mir/src/transform/check_consts/ops.rs
@@ -268,16 +268,20 @@ impl NonConstOp for CellBorrow {
 }
 
 #[derive(Debug)]
+/// This op is for `&mut` borrows in the trailing expression of a constant
+/// which uses the "enclosing scopes rule" to leak its locals into anonymous
+/// static or const items.
 pub struct MutBorrow(pub hir::BorrowKind);
 
 impl NonConstOp for MutBorrow {
-    fn status_in_item(&self, ccx: &ConstCx<'_, '_>) -> Status {
-        // Forbid everywhere except in const fn with a feature gate
-        if ccx.const_kind() == hir::ConstContext::ConstFn {
-            Status::Unstable(sym::const_mut_refs)
-        } else {
-            Status::Forbidden
-        }
+    fn status_in_item(&self, _ccx: &ConstCx<'_, '_>) -> Status {
+        Status::Forbidden
+    }
+
+    fn importance(&self) -> DiagnosticImportance {
+        // If there were primary errors (like non-const function calls), do not emit further
+        // errors about mutable references.
+        DiagnosticImportance::Secondary
     }
 
     fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
@@ -286,25 +290,15 @@ impl NonConstOp for MutBorrow {
             hir::BorrowKind::Ref => "",
         };
 
-        let mut err = if ccx.const_kind() == hir::ConstContext::ConstFn {
-            feature_err(
-                &ccx.tcx.sess.parse_sess,
-                sym::const_mut_refs,
-                span,
-                &format!("{}mutable references are not allowed in {}s", raw, ccx.const_kind()),
-            )
-        } else {
-            let mut err = struct_span_err!(
-                ccx.tcx.sess,
-                span,
-                E0764,
-                "{}mutable references are not allowed in {}s",
-                raw,
-                ccx.const_kind(),
-            );
-            err.span_label(span, format!("`&{}mut` is only allowed in `const fn`", raw));
-            err
-        };
+        let mut err = struct_span_err!(
+            ccx.tcx.sess,
+            span,
+            E0764,
+            "{}mutable references are not allowed in the final value of {}s",
+            raw,
+            ccx.const_kind(),
+        );
+
         if ccx.tcx.sess.teach(&err.get_code().unwrap()) {
             err.note(
                 "References in statics and constants may only refer \
@@ -322,6 +316,29 @@ impl NonConstOp for MutBorrow {
 }
 
 #[derive(Debug)]
+pub struct TransientMutBorrow(pub hir::BorrowKind);
+
+impl NonConstOp for TransientMutBorrow {
+    fn status_in_item(&self, _: &ConstCx<'_, '_>) -> Status {
+        Status::Unstable(sym::const_mut_refs)
+    }
+
+    fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
+        let raw = match self.0 {
+            hir::BorrowKind::Raw => "raw ",
+            hir::BorrowKind::Ref => "",
+        };
+
+        feature_err(
+            &ccx.tcx.sess.parse_sess,
+            sym::const_mut_refs,
+            span,
+            &format!("{}mutable references are not allowed in {}s", raw, ccx.const_kind()),
+        )
+    }
+}
+
+#[derive(Debug)]
 pub struct MutDeref;
 impl NonConstOp for MutDeref {
     fn status_in_item(&self, _: &ConstCx<'_, '_>) -> Status {
@@ -329,7 +346,7 @@ impl NonConstOp for MutDeref {
     }
 
     fn importance(&self) -> DiagnosticImportance {
-        // Usually a side-effect of a `MutBorrow` somewhere.
+        // Usually a side-effect of a `TransientMutBorrow` somewhere.
         DiagnosticImportance::Secondary
     }
 
diff --git a/compiler/rustc_mir/src/transform/check_consts/validation.rs b/compiler/rustc_mir/src/transform/check_consts/validation.rs
index 08d969b27be..a92997dddac 100644
--- a/compiler/rustc_mir/src/transform/check_consts/validation.rs
+++ b/compiler/rustc_mir/src/transform/check_consts/validation.rs
@@ -466,6 +466,29 @@ impl Validator<'mir, 'tcx> {
             }
         }
     }
+
+    fn check_mut_borrow(&mut self, local: Local, kind: hir::BorrowKind) {
+        match self.const_kind() {
+            // In a const fn all borrows are transient or point to the places given via
+            // references in the arguments (so we already checked them with
+            // TransientMutBorrow/MutBorrow as appropriate).
+            // The borrow checker guarantees that no new non-transient borrows are created.
+            // NOTE: Once we have heap allocations during CTFE we need to figure out
+            // how to prevent `const fn` to create long-lived allocations that point
+            // to mutable memory.
+            hir::ConstContext::ConstFn => self.check_op(ops::TransientMutBorrow(kind)),
+            _ => {
+                // Locals with StorageDead do not live beyond the evaluation and can
+                // thus safely be borrowed without being able to be leaked to the final
+                // value of the constant.
+                if self.local_has_storage_dead(local) {
+                    self.check_op(ops::TransientMutBorrow(kind));
+                } else {
+                    self.check_op(ops::MutBorrow(kind));
+                }
+            }
+        }
+    }
 }
 
 impl Visitor<'tcx> for Validator<'mir, 'tcx> {
@@ -562,15 +585,15 @@ impl Visitor<'tcx> for Validator<'mir, 'tcx> {
 
                 if !is_allowed {
                     if let BorrowKind::Mut { .. } = kind {
-                        self.check_op(ops::MutBorrow(hir::BorrowKind::Ref));
+                        self.check_mut_borrow(place.local, hir::BorrowKind::Ref)
                     } else {
                         self.check_op(ops::CellBorrow);
                     }
                 }
             }
 
-            Rvalue::AddressOf(Mutability::Mut, _) => {
-                self.check_op(ops::MutBorrow(hir::BorrowKind::Raw))
+            Rvalue::AddressOf(Mutability::Mut, ref place) => {
+                self.check_mut_borrow(place.local, hir::BorrowKind::Raw)
             }
 
             Rvalue::Ref(_, BorrowKind::Shared | BorrowKind::Shallow, ref place)
diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs
index 80a24c90421..3b1b53553d5 100644
--- a/compiler/rustc_passes/src/dead.rs
+++ b/compiler/rustc_passes/src/dead.rs
@@ -290,6 +290,7 @@ impl<'tcx> Visitor<'tcx> for MarkSymbolVisitor<'tcx> {
     }
 
     fn visit_pat(&mut self, pat: &'tcx hir::Pat<'tcx>) {
+        self.in_pat = true;
         match pat.kind {
             PatKind::Struct(ref path, ref fields, _) => {
                 let res = self.typeck_results().qpath_res(path, pat.hir_id);
@@ -302,7 +303,6 @@ impl<'tcx> Visitor<'tcx> for MarkSymbolVisitor<'tcx> {
             _ => (),
         }
 
-        self.in_pat = true;
         intravisit::walk_pat(self, pat);
         self.in_pat = false;
     }
diff --git a/compiler/rustc_typeck/src/check/check.rs b/compiler/rustc_typeck/src/check/check.rs
index ab3c26fac83..47361092a5c 100644
--- a/compiler/rustc_typeck/src/check/check.rs
+++ b/compiler/rustc_typeck/src/check/check.rs
@@ -846,21 +846,13 @@ pub(super) fn check_specialization_validity<'tcx>(
         Ok(ancestors) => ancestors,
         Err(_) => return,
     };
-    let mut ancestor_impls = ancestors
-        .skip(1)
-        .filter_map(|parent| {
-            if parent.is_from_trait() {
-                None
-            } else {
-                Some((parent, parent.item(tcx, trait_item.ident, kind, trait_def.def_id)))
-            }
-        })
-        .peekable();
-
-    if ancestor_impls.peek().is_none() {
-        // No parent, nothing to specialize.
-        return;
-    }
+    let mut ancestor_impls = ancestors.skip(1).filter_map(|parent| {
+        if parent.is_from_trait() {
+            None
+        } else {
+            Some((parent, parent.item(tcx, trait_item.ident, kind, trait_def.def_id)))
+        }
+    });
 
     let opt_result = ancestor_impls.find_map(|(parent_impl, parent_item)| {
         match parent_item {
@@ -902,8 +894,6 @@ pub(super) fn check_impl_items_against_trait<'tcx>(
     impl_trait_ref: ty::TraitRef<'tcx>,
     impl_item_refs: &[hir::ImplItemRef<'_>],
 ) {
-    let impl_span = tcx.sess.source_map().guess_head_span(full_impl_span);
-
     // If the trait reference itself is erroneous (so the compilation is going
     // to fail), skip checking the items here -- the `impl_item` table in `tcx`
     // isn't populated for such impls.
@@ -931,111 +921,75 @@ pub(super) fn check_impl_items_against_trait<'tcx>(
 
     // Locate trait definition and items
     let trait_def = tcx.trait_def(impl_trait_ref.def_id);
-
-    let impl_items = || impl_item_refs.iter().map(|iiref| tcx.hir().impl_item(iiref.id));
+    let impl_items = impl_item_refs.iter().map(|iiref| tcx.hir().impl_item(iiref.id));
+    let associated_items = tcx.associated_items(impl_trait_ref.def_id);
 
     // Check existing impl methods to see if they are both present in trait
     // and compatible with trait signature
-    for impl_item in impl_items() {
-        let namespace = impl_item.kind.namespace();
+    for impl_item in impl_items {
         let ty_impl_item = tcx.associated_item(tcx.hir().local_def_id(impl_item.hir_id));
-        let ty_trait_item = tcx
-            .associated_items(impl_trait_ref.def_id)
-            .find_by_name_and_namespace(tcx, ty_impl_item.ident, namespace, impl_trait_ref.def_id)
-            .or_else(|| {
-                // Not compatible, but needed for the error message
-                tcx.associated_items(impl_trait_ref.def_id)
-                    .filter_by_name(tcx, ty_impl_item.ident, impl_trait_ref.def_id)
-                    .next()
-            });
-
-        // Check that impl definition matches trait definition
-        if let Some(ty_trait_item) = ty_trait_item {
+
+        let mut items =
+            associated_items.filter_by_name(tcx, ty_impl_item.ident, impl_trait_ref.def_id);
+
+        let (compatible_kind, ty_trait_item) = if let Some(ty_trait_item) = items.next() {
+            let is_compatible = |ty: &&ty::AssocItem| match (ty.kind, &impl_item.kind) {
+                (ty::AssocKind::Const, hir::ImplItemKind::Const(..)) => true,
+                (ty::AssocKind::Fn, hir::ImplItemKind::Fn(..)) => true,
+                (ty::AssocKind::Type, hir::ImplItemKind::TyAlias(..)) => true,
+                _ => false,
+            };
+
+            // If we don't have a compatible item, we'll use the first one whose name matches
+            // to report an error.
+            let mut compatible_kind = is_compatible(&ty_trait_item);
+            let mut trait_item = ty_trait_item;
+
+            if !compatible_kind {
+                if let Some(ty_trait_item) = items.find(is_compatible) {
+                    compatible_kind = true;
+                    trait_item = ty_trait_item;
+                }
+            }
+
+            (compatible_kind, trait_item)
+        } else {
+            continue;
+        };
+
+        if compatible_kind {
             match impl_item.kind {
                 hir::ImplItemKind::Const(..) => {
                     // Find associated const definition.
-                    if ty_trait_item.kind == ty::AssocKind::Const {
-                        compare_const_impl(
-                            tcx,
-                            &ty_impl_item,
-                            impl_item.span,
-                            &ty_trait_item,
-                            impl_trait_ref,
-                        );
-                    } else {
-                        let mut err = struct_span_err!(
-                            tcx.sess,
-                            impl_item.span,
-                            E0323,
-                            "item `{}` is an associated const, \
-                             which doesn't match its trait `{}`",
-                            ty_impl_item.ident,
-                            impl_trait_ref.print_only_trait_path()
-                        );
-                        err.span_label(impl_item.span, "does not match trait");
-                        // We can only get the spans from local trait definition
-                        // Same for E0324 and E0325
-                        if let Some(trait_span) = tcx.hir().span_if_local(ty_trait_item.def_id) {
-                            err.span_label(trait_span, "item in trait");
-                        }
-                        err.emit()
-                    }
+                    compare_const_impl(
+                        tcx,
+                        &ty_impl_item,
+                        impl_item.span,
+                        &ty_trait_item,
+                        impl_trait_ref,
+                    );
                 }
                 hir::ImplItemKind::Fn(..) => {
                     let opt_trait_span = tcx.hir().span_if_local(ty_trait_item.def_id);
-                    if ty_trait_item.kind == ty::AssocKind::Fn {
-                        compare_impl_method(
-                            tcx,
-                            &ty_impl_item,
-                            impl_item.span,
-                            &ty_trait_item,
-                            impl_trait_ref,
-                            opt_trait_span,
-                        );
-                    } else {
-                        let mut err = struct_span_err!(
-                            tcx.sess,
-                            impl_item.span,
-                            E0324,
-                            "item `{}` is an associated method, \
-                             which doesn't match its trait `{}`",
-                            ty_impl_item.ident,
-                            impl_trait_ref.print_only_trait_path()
-                        );
-                        err.span_label(impl_item.span, "does not match trait");
-                        if let Some(trait_span) = opt_trait_span {
-                            err.span_label(trait_span, "item in trait");
-                        }
-                        err.emit()
-                    }
+                    compare_impl_method(
+                        tcx,
+                        &ty_impl_item,
+                        impl_item.span,
+                        &ty_trait_item,
+                        impl_trait_ref,
+                        opt_trait_span,
+                    );
                 }
                 hir::ImplItemKind::TyAlias(_) => {
                     let opt_trait_span = tcx.hir().span_if_local(ty_trait_item.def_id);
-                    if ty_trait_item.kind == ty::AssocKind::Type {
-                        compare_ty_impl(
-                            tcx,
-                            &ty_impl_item,
-                            impl_item.span,
-                            &ty_trait_item,
-                            impl_trait_ref,
-                            opt_trait_span,
-                        );
-                    } else {
-                        let mut err = struct_span_err!(
-                            tcx.sess,
-                            impl_item.span,
-                            E0325,
-                            "item `{}` is an associated type, \
-                             which doesn't match its trait `{}`",
-                            ty_impl_item.ident,
-                            impl_trait_ref.print_only_trait_path()
-                        );
-                        err.span_label(impl_item.span, "does not match trait");
-                        if let Some(trait_span) = opt_trait_span {
-                            err.span_label(trait_span, "item in trait");
-                        }
-                        err.emit()
-                    }
+                    compare_ty_impl(
+                        tcx,
+                        &ty_impl_item,
+                        impl_item.span,
+                        &ty_trait_item,
+                        impl_trait_ref,
+                        opt_trait_span,
+                    );
                 }
             }
 
@@ -1046,12 +1000,22 @@ pub(super) fn check_impl_items_against_trait<'tcx>(
                 impl_id.to_def_id(),
                 impl_item,
             );
+        } else {
+            report_mismatch_error(
+                tcx,
+                ty_trait_item.def_id,
+                impl_trait_ref,
+                impl_item,
+                &ty_impl_item,
+            );
         }
     }
 
-    // Check for missing items from trait
-    let mut missing_items = Vec::new();
     if let Ok(ancestors) = trait_def.ancestors(tcx, impl_id.to_def_id()) {
+        let impl_span = tcx.sess.source_map().guess_head_span(full_impl_span);
+
+        // Check for missing items from trait
+        let mut missing_items = Vec::new();
         for trait_item in tcx.associated_items(impl_trait_ref.def_id).in_definition_order() {
             let is_implemented = ancestors
                 .leaf_def(tcx, trait_item.ident, trait_item.kind)
@@ -1064,11 +1028,63 @@ pub(super) fn check_impl_items_against_trait<'tcx>(
                 }
             }
         }
+
+        if !missing_items.is_empty() {
+            missing_items_err(tcx, impl_span, &missing_items, full_impl_span);
+        }
     }
+}
+
+#[inline(never)]
+#[cold]
+fn report_mismatch_error<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    trait_item_def_id: DefId,
+    impl_trait_ref: ty::TraitRef<'tcx>,
+    impl_item: &hir::ImplItem<'_>,
+    ty_impl_item: &ty::AssocItem,
+) {
+    let mut err = match impl_item.kind {
+        hir::ImplItemKind::Const(..) => {
+            // Find associated const definition.
+            struct_span_err!(
+                tcx.sess,
+                impl_item.span,
+                E0323,
+                "item `{}` is an associated const, which doesn't match its trait `{}`",
+                ty_impl_item.ident,
+                impl_trait_ref.print_only_trait_path()
+            )
+        }
+
+        hir::ImplItemKind::Fn(..) => {
+            struct_span_err!(
+                tcx.sess,
+                impl_item.span,
+                E0324,
+                "item `{}` is an associated method, which doesn't match its trait `{}`",
+                ty_impl_item.ident,
+                impl_trait_ref.print_only_trait_path()
+            )
+        }
 
-    if !missing_items.is_empty() {
-        missing_items_err(tcx, impl_span, &missing_items, full_impl_span);
+        hir::ImplItemKind::TyAlias(_) => {
+            struct_span_err!(
+                tcx.sess,
+                impl_item.span,
+                E0325,
+                "item `{}` is an associated type, which doesn't match its trait `{}`",
+                ty_impl_item.ident,
+                impl_trait_ref.print_only_trait_path()
+            )
+        }
+    };
+
+    err.span_label(impl_item.span, "does not match trait");
+    if let Some(trait_span) = tcx.hir().span_if_local(trait_item_def_id) {
+        err.span_label(trait_span, "item in trait");
     }
+    err.emit();
 }
 
 /// Checks whether a type can be represented in memory. In particular, it
diff --git a/library/core/src/time.rs b/library/core/src/time.rs
index 88b4e2a2436..b1443bc33d2 100644
--- a/library/core/src/time.rs
+++ b/library/core/src/time.rs
@@ -1067,13 +1067,23 @@ impl fmt::Debug for Duration {
         }
 
         if self.secs > 0 {
-            fmt_decimal(f, self.secs, self.nanos, 100_000_000)?;
+            fmt_decimal(f, self.secs, self.nanos, NANOS_PER_SEC / 10)?;
             f.write_str("s")
-        } else if self.nanos >= 1_000_000 {
-            fmt_decimal(f, self.nanos as u64 / 1_000_000, self.nanos % 1_000_000, 100_000)?;
+        } else if self.nanos >= NANOS_PER_MILLI {
+            fmt_decimal(
+                f,
+                (self.nanos / NANOS_PER_MILLI) as u64,
+                self.nanos % NANOS_PER_MILLI,
+                NANOS_PER_MILLI / 10,
+            )?;
             f.write_str("ms")
-        } else if self.nanos >= 1_000 {
-            fmt_decimal(f, self.nanos as u64 / 1_000, self.nanos % 1_000, 100)?;
+        } else if self.nanos >= NANOS_PER_MICRO {
+            fmt_decimal(
+                f,
+                (self.nanos / NANOS_PER_MICRO) as u64,
+                self.nanos % NANOS_PER_MICRO,
+                NANOS_PER_MICRO / 10,
+            )?;
             f.write_str("µs")
         } else {
             fmt_decimal(f, self.nanos as u64, 0, 1)?;
diff --git a/library/std/src/error.rs b/library/std/src/error.rs
index ca83c409822..605d953f5da 100644
--- a/library/std/src/error.rs
+++ b/library/std/src/error.rs
@@ -486,6 +486,27 @@ impl<T: Error> Error for Box<T> {
     }
 }
 
+#[stable(feature = "error_by_ref", since = "1.51.0")]
+impl<'a, T: Error + ?Sized> Error for &'a T {
+    #[allow(deprecated, deprecated_in_future)]
+    fn description(&self) -> &str {
+        Error::description(&**self)
+    }
+
+    #[allow(deprecated)]
+    fn cause(&self) -> Option<&dyn Error> {
+        Error::cause(&**self)
+    }
+
+    fn source(&self) -> Option<&(dyn Error + 'static)> {
+        Error::source(&**self)
+    }
+
+    fn backtrace(&self) -> Option<&Backtrace> {
+        Error::backtrace(&**self)
+    }
+}
+
 #[stable(feature = "fmt_error", since = "1.11.0")]
 impl Error for fmt::Error {
     #[allow(deprecated)]
diff --git a/library/std/src/future.rs b/library/std/src/future.rs
deleted file mode 100644
index 9d9c36e9afb..00000000000
--- a/library/std/src/future.rs
+++ /dev/null
@@ -1,17 +0,0 @@
-//! Asynchronous values.
-
-#[doc(inline)]
-#[stable(feature = "futures_api", since = "1.36.0")]
-pub use core::future::Future;
-
-#[doc(inline)]
-#[unstable(feature = "gen_future", issue = "50547")]
-pub use core::future::{from_generator, get_context, ResumeTy};
-
-#[doc(inline)]
-#[stable(feature = "future_readiness_fns", since = "1.48.0")]
-pub use core::future::{pending, ready, Pending, Ready};
-
-#[doc(inline)]
-#[unstable(feature = "into_future", issue = "67644")]
-pub use core::future::IntoFuture;
diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs
index 5ba13c2f913..92c8b7c1774 100644
--- a/library/std/src/lib.rs
+++ b/library/std/src/lib.rs
@@ -406,6 +406,8 @@ pub use core::cmp;
 pub use core::convert;
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use core::default;
+#[stable(feature = "futures_api", since = "1.36.0")]
+pub use core::future;
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use core::hash;
 #[stable(feature = "core_hint", since = "1.27.0")]
@@ -505,9 +507,6 @@ pub mod task {
     pub use alloc::task::*;
 }
 
-#[stable(feature = "futures_api", since = "1.36.0")]
-pub mod future;
-
 // Platform-abstraction modules
 #[macro_use]
 mod sys_common;
diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs
index 8006c3d2771..fee1bf4c3a6 100644
--- a/src/librustdoc/config.rs
+++ b/src/librustdoc/config.rs
@@ -103,6 +103,8 @@ crate struct Options {
     crate should_test: bool,
     /// List of arguments to pass to the test harness, if running tests.
     crate test_args: Vec<String>,
+    /// The working directory in which to run tests.
+    crate test_run_directory: Option<PathBuf>,
     /// Optional path to persist the doctest executables to, defaults to a
     /// temporary directory if not set.
     crate persist_doctests: Option<PathBuf>,
@@ -175,6 +177,7 @@ impl fmt::Debug for Options {
             .field("lint_cap", &self.lint_cap)
             .field("should_test", &self.should_test)
             .field("test_args", &self.test_args)
+            .field("test_run_directory", &self.test_run_directory)
             .field("persist_doctests", &self.persist_doctests)
             .field("default_passes", &self.default_passes)
             .field("manual_passes", &self.manual_passes)
@@ -572,6 +575,7 @@ impl Options {
         let enable_index_page = matches.opt_present("enable-index-page") || index_page.is_some();
         let static_root_path = matches.opt_str("static-root-path");
         let generate_search_filter = !matches.opt_present("disable-per-crate-search");
+        let test_run_directory = matches.opt_str("test-run-directory").map(PathBuf::from);
         let persist_doctests = matches.opt_str("persist-doctests").map(PathBuf::from);
         let test_builder = matches.opt_str("test-builder").map(PathBuf::from);
         let codegen_options_strs = matches.opt_strs("C");
@@ -613,6 +617,7 @@ impl Options {
             display_warnings,
             show_coverage,
             crate_version,
+            test_run_directory,
             persist_doctests,
             runtool,
             runtool_args,
diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs
index bbf4de5cdc9..30ff124dac6 100644
--- a/src/librustdoc/doctest.rs
+++ b/src/librustdoc/doctest.rs
@@ -365,6 +365,9 @@ fn run_test(
     } else {
         cmd = Command::new(output_file);
     }
+    if let Some(run_directory) = options.test_run_directory {
+        cmd.current_dir(run_directory);
+    }
 
     match cmd.output() {
         Err(e) => return Err(TestFailure::ExecutionError(e)),
diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs
index 8e010839ad8..ef45c98e406 100644
--- a/src/librustdoc/html/render/mod.rs
+++ b/src/librustdoc/html/render/mod.rs
@@ -2474,7 +2474,7 @@ fn item_function(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, f: &clean::
 fn render_implementor(
     cx: &Context<'_>,
     implementor: &Impl,
-    parent: &clean::Item,
+    trait_: &clean::Item,
     w: &mut Buffer,
     implementor_dups: &FxHashMap<Symbol, (DefId, bool)>,
     aliases: &[String],
@@ -2494,11 +2494,11 @@ fn render_implementor(
         w,
         cx,
         implementor,
-        parent,
+        trait_,
         AssocItemLink::Anchor(None),
         RenderMode::Normal,
-        implementor.impl_item.stable_since(cx.tcx()).as_deref(),
-        implementor.impl_item.const_stable_since(cx.tcx()).as_deref(),
+        trait_.stable_since(cx.tcx()).as_deref(),
+        trait_.const_stable_since(cx.tcx()).as_deref(),
         false,
         Some(use_absolute),
         false,
@@ -2937,34 +2937,25 @@ fn render_stability_since_raw(
     containing_ver: Option<&str>,
     containing_const_ver: Option<&str>,
 ) {
-    let ver = ver.and_then(|inner| if !inner.is_empty() { Some(inner) } else { None });
-
-    let const_ver = const_ver.and_then(|inner| if !inner.is_empty() { Some(inner) } else { None });
+    let ver = ver.filter(|inner| !inner.is_empty());
+    let const_ver = const_ver.filter(|inner| !inner.is_empty());
 
-    if let Some(v) = ver {
-        if let Some(cv) = const_ver {
-            if const_ver != containing_const_ver {
-                write!(
-                    w,
-                    "<span class=\"since\" title=\"Stable since Rust version {0}, const since {1}\">{0} (const: {1})</span>",
-                    v, cv
-                );
-            } else if ver != containing_ver {
-                write!(
-                    w,
-                    "<span class=\"since\" title=\"Stable since Rust version {0}\">{0}</span>",
-                    v
-                );
-            }
-        } else {
-            if ver != containing_ver {
-                write!(
-                    w,
-                    "<span class=\"since\" title=\"Stable since Rust version {0}\">{0}</span>",
-                    v
-                );
-            }
+    match (ver, const_ver) {
+        (Some(v), Some(cv)) if const_ver != containing_const_ver => {
+            write!(
+                w,
+                "<span class=\"since\" title=\"Stable since Rust version {0}, const since {1}\">{0} (const: {1})</span>",
+                v, cv
+            );
+        }
+        (Some(v), _) if ver != containing_ver => {
+            write!(
+                w,
+                "<span class=\"since\" title=\"Stable since Rust version {0}\">{0}</span>",
+                v
+            );
         }
+        _ => {}
     }
 }
 
diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index 83736295beb..c61cbf78f77 100644
--- a/src/librustdoc/lib.rs
+++ b/src/librustdoc/lib.rs
@@ -168,6 +168,14 @@ fn opts() -> Vec<RustcOptGroup> {
         stable("test-args", |o| {
             o.optmulti("", "test-args", "arguments to pass to the test runner", "ARGS")
         }),
+        unstable("test-run-directory", |o| {
+            o.optopt(
+                "",
+                "test-run-directory",
+                "The working directory in which to run tests",
+                "PATH",
+            )
+        }),
         stable("target", |o| o.optopt("", "target", "target triple to document", "TRIPLE")),
         stable("markdown-css", |o| {
             o.optmulti(
diff --git a/src/test/rustdoc-ui/run-directory.correct.stdout b/src/test/rustdoc-ui/run-directory.correct.stdout
new file mode 100644
index 00000000000..e9b2754794a
--- /dev/null
+++ b/src/test/rustdoc-ui/run-directory.correct.stdout
@@ -0,0 +1,6 @@
+
+running 1 test
+test $DIR/run-directory.rs - foo (line 10) ... ok
+
+test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME
+
diff --git a/src/test/rustdoc-ui/run-directory.incorrect.stdout b/src/test/rustdoc-ui/run-directory.incorrect.stdout
new file mode 100644
index 00000000000..97a5dbc5c0c
--- /dev/null
+++ b/src/test/rustdoc-ui/run-directory.incorrect.stdout
@@ -0,0 +1,6 @@
+
+running 1 test
+test $DIR/run-directory.rs - foo (line 19) ... ok
+
+test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME
+
diff --git a/src/test/rustdoc-ui/run-directory.rs b/src/test/rustdoc-ui/run-directory.rs
new file mode 100644
index 00000000000..78431c0e80b
--- /dev/null
+++ b/src/test/rustdoc-ui/run-directory.rs
@@ -0,0 +1,23 @@
+// this test asserts that the cwd of doctest invocations is set correctly.
+
+// revisions: correct incorrect
+// check-pass
+// [correct]compile-flags:--test --test-run-directory={{src-base}}
+// [incorrect]compile-flags:--test --test-run-directory={{src-base}}/coverage
+// normalize-stdout-test: "src/test/rustdoc-ui" -> "$$DIR"
+// normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME"
+
+/// ```
+/// assert_eq!(
+///     std::fs::read_to_string("run-directory.rs").unwrap(),
+///     include_str!("run-directory.rs"),
+/// );
+/// ```
+#[cfg(correct)]
+pub fn foo() {}
+
+/// ```
+/// assert!(std::fs::read_to_string("run-directory.rs").is_err());
+/// ```
+#[cfg(incorrect)]
+pub fn foo() {}
diff --git a/src/test/rustdoc/implementor-stable-version.rs b/src/test/rustdoc/implementor-stable-version.rs
new file mode 100644
index 00000000000..0a065d8095b
--- /dev/null
+++ b/src/test/rustdoc/implementor-stable-version.rs
@@ -0,0 +1,19 @@
+#![crate_name = "foo"]
+
+#![feature(staged_api)]
+
+#[stable(feature = "bar", since = "OLD 1.0")]
+pub trait Bar {}
+
+#[stable(feature = "baz", since = "OLD 1.0")]
+pub trait Baz {}
+
+pub struct Foo;
+
+// @has foo/trait.Bar.html '//div[@id="implementors-list"]//span[@class="since"]' 'NEW 2.0'
+#[stable(feature = "foobar", since = "NEW 2.0")]
+impl Bar for Foo {}
+
+// @!has foo/trait.Baz.html '//div[@id="implementors-list"]//span[@class="since"]' 'OLD 1.0'
+#[stable(feature = "foobaz", since = "OLD 1.0")]
+impl Baz for Foo {}
diff --git a/src/test/ui/check-static-immutable-mut-slices.rs b/src/test/ui/check-static-immutable-mut-slices.rs
index 3be02f6a0f6..8f9680778aa 100644
--- a/src/test/ui/check-static-immutable-mut-slices.rs
+++ b/src/test/ui/check-static-immutable-mut-slices.rs
@@ -1,6 +1,6 @@
 // Checks that immutable static items can't have mutable slices
 
 static TEST: &'static mut [isize] = &mut [];
-//~^ ERROR mutable references are not allowed in statics
+//~^ ERROR mutable references are not allowed
 
 pub fn main() { }
diff --git a/src/test/ui/check-static-immutable-mut-slices.stderr b/src/test/ui/check-static-immutable-mut-slices.stderr
index 9ffbb483d13..a32a94c1315 100644
--- a/src/test/ui/check-static-immutable-mut-slices.stderr
+++ b/src/test/ui/check-static-immutable-mut-slices.stderr
@@ -1,8 +1,8 @@
-error[E0764]: mutable references are not allowed in statics
+error[E0764]: mutable references are not allowed in the final value of statics
   --> $DIR/check-static-immutable-mut-slices.rs:3:37
    |
 LL | static TEST: &'static mut [isize] = &mut [];
-   |                                     ^^^^^^^ `&mut` is only allowed in `const fn`
+   |                                     ^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/consts/const-address-of-mut.stderr b/src/test/ui/consts/const-address-of-mut.stderr
index ec2dac5a7d1..60cdcc7df74 100644
--- a/src/test/ui/consts/const-address-of-mut.stderr
+++ b/src/test/ui/consts/const-address-of-mut.stderr
@@ -1,20 +1,29 @@
-error[E0764]: raw mutable references are not allowed in constants
+error[E0658]: raw mutable references are not allowed in constants
   --> $DIR/const-address-of-mut.rs:3:32
    |
 LL | const A: () = { let mut x = 2; &raw mut x; };
-   |                                ^^^^^^^^^^ `&raw mut` is only allowed in `const fn`
+   |                                ^^^^^^^^^^
+   |
+   = note: see issue #57349 <https://github.com/rust-lang/rust/issues/57349> for more information
+   = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
 
-error[E0764]: raw mutable references are not allowed in statics
+error[E0658]: raw mutable references are not allowed in statics
   --> $DIR/const-address-of-mut.rs:5:33
    |
 LL | static B: () = { let mut x = 2; &raw mut x; };
-   |                                 ^^^^^^^^^^ `&raw mut` is only allowed in `const fn`
+   |                                 ^^^^^^^^^^
+   |
+   = note: see issue #57349 <https://github.com/rust-lang/rust/issues/57349> for more information
+   = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
 
-error[E0764]: raw mutable references are not allowed in statics
+error[E0658]: raw mutable references are not allowed in statics
   --> $DIR/const-address-of-mut.rs:7:37
    |
 LL | static mut C: () = { let mut x = 2; &raw mut x; };
-   |                                     ^^^^^^^^^^ `&raw mut` is only allowed in `const fn`
+   |                                     ^^^^^^^^^^
+   |
+   = note: see issue #57349 <https://github.com/rust-lang/rust/issues/57349> for more information
+   = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
 
 error[E0658]: raw mutable references are not allowed in constant functions
   --> $DIR/const-address-of-mut.rs:11:13
@@ -27,5 +36,4 @@ LL |     let y = &raw mut x;
 
 error: aborting due to 4 previous errors
 
-Some errors have detailed explanations: E0658, E0764.
-For more information about an error, try `rustc --explain E0658`.
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/consts/const-eval/issue-65394.stderr b/src/test/ui/consts/const-eval/issue-65394.stderr
index 771d368d783..ec229d7f53a 100644
--- a/src/test/ui/consts/const-eval/issue-65394.stderr
+++ b/src/test/ui/consts/const-eval/issue-65394.stderr
@@ -1,8 +1,11 @@
-error[E0764]: mutable references are not allowed in constants
+error[E0658]: mutable references are not allowed in constants
   --> $DIR/issue-65394.rs:8:13
    |
 LL |     let r = &mut x;
-   |             ^^^^^^ `&mut` is only allowed in `const fn`
+   |             ^^^^^^
+   |
+   = note: see issue #57349 <https://github.com/rust-lang/rust/issues/57349> for more information
+   = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
 
 error[E0493]: destructors cannot be evaluated at compile-time
   --> $DIR/issue-65394.rs:7:9
@@ -15,5 +18,5 @@ LL | };
 
 error: aborting due to 2 previous errors
 
-Some errors have detailed explanations: E0493, E0764.
+Some errors have detailed explanations: E0493, E0658.
 For more information about an error, try `rustc --explain E0493`.
diff --git a/src/test/ui/consts/const-multi-ref.stderr b/src/test/ui/consts/const-multi-ref.stderr
index c0a320d46cb..dd5cadfe295 100644
--- a/src/test/ui/consts/const-multi-ref.stderr
+++ b/src/test/ui/consts/const-multi-ref.stderr
@@ -1,8 +1,11 @@
-error[E0764]: mutable references are not allowed in constants
+error[E0658]: mutable references are not allowed in constants
   --> $DIR/const-multi-ref.rs:6:13
    |
 LL |     let p = &mut a;
-   |             ^^^^^^ `&mut` is only allowed in `const fn`
+   |             ^^^^^^
+   |
+   = note: see issue #57349 <https://github.com/rust-lang/rust/issues/57349> for more information
+   = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
 
 error[E0658]: cannot borrow here, since the borrowed element may contain interior mutability
   --> $DIR/const-multi-ref.rs:16:13
@@ -15,5 +18,4 @@ LL |     let p = &a;
 
 error: aborting due to 2 previous errors
 
-Some errors have detailed explanations: E0658, E0764.
-For more information about an error, try `rustc --explain E0658`.
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/consts/const-mut-refs/const_mut_address_of.rs b/src/test/ui/consts/const-mut-refs/const_mut_address_of.rs
index 5819daa817a..24df647f05b 100644
--- a/src/test/ui/consts/const-mut-refs/const_mut_address_of.rs
+++ b/src/test/ui/consts/const-mut-refs/const_mut_address_of.rs
@@ -1,3 +1,4 @@
+// check-pass
 #![feature(const_mut_refs)]
 #![feature(const_fn)]
 #![feature(raw_ref_op)]
@@ -22,9 +23,7 @@ const fn baz(foo: &mut Foo)-> *mut usize {
 
 const _: () = {
     foo().bar();
-    //~^ ERROR mutable references are not allowed in constants
     baz(&mut foo());
-    //~^ ERROR mutable references are not allowed in constants
 };
 
 fn main() {}
diff --git a/src/test/ui/consts/const-mut-refs/const_mut_address_of.stderr b/src/test/ui/consts/const-mut-refs/const_mut_address_of.stderr
deleted file mode 100644
index 2214ce6ee1c..00000000000
--- a/src/test/ui/consts/const-mut-refs/const_mut_address_of.stderr
+++ /dev/null
@@ -1,15 +0,0 @@
-error[E0764]: mutable references are not allowed in constants
-  --> $DIR/const_mut_address_of.rs:24:5
-   |
-LL |     foo().bar();
-   |     ^^^^^ `&mut` is only allowed in `const fn`
-
-error[E0764]: mutable references are not allowed in constants
-  --> $DIR/const_mut_address_of.rs:26:9
-   |
-LL |     baz(&mut foo());
-   |         ^^^^^^^^^^ `&mut` is only allowed in `const fn`
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0764`.
diff --git a/src/test/ui/consts/const-mut-refs/const_mut_refs.rs b/src/test/ui/consts/const-mut-refs/const_mut_refs.rs
index 9099d5a1b8e..544458dfcd8 100644
--- a/src/test/ui/consts/const-mut-refs/const_mut_refs.rs
+++ b/src/test/ui/consts/const-mut-refs/const_mut_refs.rs
@@ -1,3 +1,4 @@
+// check-pass
 #![feature(const_mut_refs)]
 
 struct Foo {
@@ -29,9 +30,6 @@ const fn bazz(foo: &mut Foo) -> usize {
 
 fn main() {
     let _: [(); foo().bar()] = [(); 1];
-    //~^ ERROR mutable references are not allowed in constants
     let _: [(); baz(&mut foo())] = [(); 2];
-    //~^ ERROR mutable references are not allowed in constants
     let _: [(); bazz(&mut foo())] = [(); 3];
-    //~^ ERROR mutable references are not allowed in constants
 }
diff --git a/src/test/ui/consts/const-mut-refs/const_mut_refs.stderr b/src/test/ui/consts/const-mut-refs/const_mut_refs.stderr
deleted file mode 100644
index 4ca7b128b7c..00000000000
--- a/src/test/ui/consts/const-mut-refs/const_mut_refs.stderr
+++ /dev/null
@@ -1,21 +0,0 @@
-error[E0764]: mutable references are not allowed in constants
-  --> $DIR/const_mut_refs.rs:31:17
-   |
-LL |     let _: [(); foo().bar()] = [(); 1];
-   |                 ^^^^^ `&mut` is only allowed in `const fn`
-
-error[E0764]: mutable references are not allowed in constants
-  --> $DIR/const_mut_refs.rs:33:21
-   |
-LL |     let _: [(); baz(&mut foo())] = [(); 2];
-   |                     ^^^^^^^^^^ `&mut` is only allowed in `const fn`
-
-error[E0764]: mutable references are not allowed in constants
-  --> $DIR/const_mut_refs.rs:35:22
-   |
-LL |     let _: [(); bazz(&mut foo())] = [(); 3];
-   |                      ^^^^^^^^^^ `&mut` is only allowed in `const fn`
-
-error: aborting due to 3 previous errors
-
-For more information about this error, try `rustc --explain E0764`.
diff --git a/src/test/ui/consts/const-mut-refs/mut_ref_in_final.rs b/src/test/ui/consts/const-mut-refs/mut_ref_in_final.rs
new file mode 100644
index 00000000000..166ba20f124
--- /dev/null
+++ b/src/test/ui/consts/const-mut-refs/mut_ref_in_final.rs
@@ -0,0 +1,57 @@
+#![feature(const_mut_refs)]
+#![feature(const_fn)]
+#![feature(raw_ref_op)]
+#![feature(const_raw_ptr_deref)]
+
+const NULL: *mut i32 = std::ptr::null_mut();
+const A: *const i32 = &4;
+
+// It could be made sound to allow it to compile,
+// but we do not want to allow this to compile,
+// as that would be an enormous footgun in oli-obk's opinion.
+const B: *mut i32 = &mut 4; //~ ERROR mutable references are not allowed
+
+// Ok, no actual mutable allocation exists
+const B2: Option<&mut i32> = None;
+
+// Not ok, can't prove that no mutable allocation ends up in final value
+const B3: Option<&mut i32> = Some(&mut 42); //~ ERROR temporary value dropped while borrowed
+
+const fn helper(x: &mut i32) -> Option<&mut i32> { Some(x) }
+const B4: Option<&mut i32> = helper(&mut 42); //~ ERROR temporary value dropped while borrowed
+
+// Ok, because no references to mutable data exist here, since the `{}` moves
+// its value and then takes a reference to that.
+const C: *const i32 = &{
+    let mut x = 42;
+    x += 3;
+    x
+};
+
+use std::cell::UnsafeCell;
+struct NotAMutex<T>(UnsafeCell<T>);
+
+unsafe impl<T> Sync for NotAMutex<T> {}
+
+const FOO: NotAMutex<&mut i32> = NotAMutex(UnsafeCell::new(&mut 42));
+//~^ ERROR temporary value dropped while borrowed
+
+static FOO2: NotAMutex<&mut i32> = NotAMutex(UnsafeCell::new(&mut 42));
+//~^ ERROR temporary value dropped while borrowed
+
+static mut FOO3: NotAMutex<&mut i32> = NotAMutex(UnsafeCell::new(&mut 42));
+//~^ ERROR temporary value dropped while borrowed
+
+// `BAR` works, because `&42` promotes immediately instead of relying on
+// the enclosing scope rule.
+const BAR: NotAMutex<&i32> = NotAMutex(UnsafeCell::new(&42));
+
+fn main() {
+    println!("{}", unsafe { *A });
+    unsafe { *B = 4 } // Bad news
+
+    unsafe {
+        **FOO.0.get() = 99;
+        assert_eq!(**FOO.0.get(), 99);
+    }
+}
diff --git a/src/test/ui/consts/const-mut-refs/mut_ref_in_final.stderr b/src/test/ui/consts/const-mut-refs/mut_ref_in_final.stderr
new file mode 100644
index 00000000000..cbae74cce6f
--- /dev/null
+++ b/src/test/ui/consts/const-mut-refs/mut_ref_in_final.stderr
@@ -0,0 +1,60 @@
+error[E0764]: mutable references are not allowed in the final value of constants
+  --> $DIR/mut_ref_in_final.rs:12:21
+   |
+LL | const B: *mut i32 = &mut 4;
+   |                     ^^^^^^
+
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/mut_ref_in_final.rs:18:40
+   |
+LL | const B3: Option<&mut i32> = Some(&mut 42);
+   |                              ----------^^-
+   |                              |         | |
+   |                              |         | temporary value is freed at the end of this statement
+   |                              |         creates a temporary which is freed while still in use
+   |                              using this value as a constant requires that borrow lasts for `'static`
+
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/mut_ref_in_final.rs:21:42
+   |
+LL | const B4: Option<&mut i32> = helper(&mut 42);
+   |                              ------------^^-
+   |                              |           | |
+   |                              |           | temporary value is freed at the end of this statement
+   |                              |           creates a temporary which is freed while still in use
+   |                              using this value as a constant requires that borrow lasts for `'static`
+
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/mut_ref_in_final.rs:36:65
+   |
+LL | const FOO: NotAMutex<&mut i32> = NotAMutex(UnsafeCell::new(&mut 42));
+   |                                  -------------------------------^^--
+   |                                  |                              |  |
+   |                                  |                              |  temporary value is freed at the end of this statement
+   |                                  |                              creates a temporary which is freed while still in use
+   |                                  using this value as a constant requires that borrow lasts for `'static`
+
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/mut_ref_in_final.rs:39:67
+   |
+LL | static FOO2: NotAMutex<&mut i32> = NotAMutex(UnsafeCell::new(&mut 42));
+   |                                    -------------------------------^^--
+   |                                    |                              |  |
+   |                                    |                              |  temporary value is freed at the end of this statement
+   |                                    |                              creates a temporary which is freed while still in use
+   |                                    using this value as a static requires that borrow lasts for `'static`
+
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/mut_ref_in_final.rs:42:71
+   |
+LL | static mut FOO3: NotAMutex<&mut i32> = NotAMutex(UnsafeCell::new(&mut 42));
+   |                                        -------------------------------^^--
+   |                                        |                              |  |
+   |                                        |                              |  temporary value is freed at the end of this statement
+   |                                        |                              creates a temporary which is freed while still in use
+   |                                        using this value as a static requires that borrow lasts for `'static`
+
+error: aborting due to 6 previous errors
+
+Some errors have detailed explanations: E0716, E0764.
+For more information about an error, try `rustc --explain E0716`.
diff --git a/src/test/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.rs b/src/test/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.rs
new file mode 100644
index 00000000000..1e856ec0a0a
--- /dev/null
+++ b/src/test/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.rs
@@ -0,0 +1,28 @@
+#![feature(const_mut_refs)]
+#![feature(const_fn)]
+#![feature(raw_ref_op)]
+#![feature(const_raw_ptr_deref)]
+
+// This file checks that our dynamic checks catch things that the static checks miss.
+// We do not have static checks for these, because we do not look into function bodies.
+// We treat all functions as not returning a mutable reference, because there is no way to
+// do that without causing the borrow checker to complain (see the B4/helper test in
+// mut_ref_in_final.rs).
+
+const fn helper() -> Option<&'static mut i32> { unsafe {
+    // Undefined behaviour (integer as pointer), who doesn't love tests like this.
+    // This code never gets executed, because the static checks fail before that.
+    Some(&mut *(42 as *mut i32)) //~ ERROR any use of this value will cause an error
+} }
+// The error is an evaluation error and not a validation error, so the error is reported
+// directly at the site where it occurs.
+const A: Option<&mut i32> = helper();
+
+const fn helper2() -> Option<&'static mut i32> { unsafe {
+    // Undefined behaviour (dangling pointer), who doesn't love tests like this.
+    // This code never gets executed, because the static checks fail before that.
+    Some(&mut *(&mut 42 as *mut i32))
+} }
+const B: Option<&mut i32> = helper2(); //~ ERROR encountered dangling pointer in final constant
+
+fn main() {}
diff --git a/src/test/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.stderr b/src/test/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.stderr
new file mode 100644
index 00000000000..0bbf84b71bb
--- /dev/null
+++ b/src/test/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.stderr
@@ -0,0 +1,23 @@
+error: any use of this value will cause an error
+  --> $DIR/mut_ref_in_final_dynamic_check.rs:15:10
+   |
+LL |     Some(&mut *(42 as *mut i32))
+   |          ^^^^^^^^^^^^^^^^^^^^^^
+   |          |
+   |          unable to turn bytes into a pointer
+   |          inside `helper` at $DIR/mut_ref_in_final_dynamic_check.rs:15:10
+   |          inside `A` at $DIR/mut_ref_in_final_dynamic_check.rs:19:29
+...
+LL | const A: Option<&mut i32> = helper();
+   | -------------------------------------
+   |
+   = note: `#[deny(const_err)]` on by default
+
+error: encountered dangling pointer in final constant
+  --> $DIR/mut_ref_in_final_dynamic_check.rs:26:1
+   |
+LL | const B: Option<&mut i32> = helper2();
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/consts/const_let_assign3.stderr b/src/test/ui/consts/const_let_assign3.stderr
index dc86e178a42..3eac61c0ce6 100644
--- a/src/test/ui/consts/const_let_assign3.stderr
+++ b/src/test/ui/consts/const_let_assign3.stderr
@@ -7,19 +7,24 @@ LL |     const fn foo(&mut self, x: u32) {
    = note: see issue #57349 <https://github.com/rust-lang/rust/issues/57349> for more information
    = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
 
-error[E0764]: mutable references are not allowed in constants
+error[E0658]: mutable references are not allowed in constants
   --> $DIR/const_let_assign3.rs:16:5
    |
 LL |     s.foo(3);
-   |     ^ `&mut` is only allowed in `const fn`
+   |     ^
+   |
+   = note: see issue #57349 <https://github.com/rust-lang/rust/issues/57349> for more information
+   = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
 
-error[E0764]: mutable references are not allowed in constants
+error[E0658]: mutable references are not allowed in constants
   --> $DIR/const_let_assign3.rs:22:13
    |
 LL |     let y = &mut x;
-   |             ^^^^^^ `&mut` is only allowed in `const fn`
+   |             ^^^^^^
+   |
+   = note: see issue #57349 <https://github.com/rust-lang/rust/issues/57349> for more information
+   = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
 
 error: aborting due to 3 previous errors
 
-Some errors have detailed explanations: E0658, E0764.
-For more information about an error, try `rustc --explain E0658`.
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/consts/issue-17718-const-bad-values.rs b/src/test/ui/consts/issue-17718-const-bad-values.rs
index 49023f18ddb..62bbb3b569c 100644
--- a/src/test/ui/consts/issue-17718-const-bad-values.rs
+++ b/src/test/ui/consts/issue-17718-const-bad-values.rs
@@ -1,10 +1,9 @@
 const C1: &'static mut [usize] = &mut [];
-//~^ ERROR: mutable references are not allowed in constants
+//~^ ERROR: mutable references are not allowed
 
 static mut S: usize = 3;
 const C2: &'static mut usize = unsafe { &mut S };
 //~^ ERROR: constants cannot refer to statics
 //~| ERROR: constants cannot refer to statics
-//~| ERROR: mutable references are not allowed in constants
 
 fn main() {}
diff --git a/src/test/ui/consts/issue-17718-const-bad-values.stderr b/src/test/ui/consts/issue-17718-const-bad-values.stderr
index 7c50978d4eb..ce60aaa0797 100644
--- a/src/test/ui/consts/issue-17718-const-bad-values.stderr
+++ b/src/test/ui/consts/issue-17718-const-bad-values.stderr
@@ -1,8 +1,8 @@
-error[E0764]: mutable references are not allowed in constants
+error[E0764]: mutable references are not allowed in the final value of constants
   --> $DIR/issue-17718-const-bad-values.rs:1:34
    |
 LL | const C1: &'static mut [usize] = &mut [];
-   |                                  ^^^^^^^ `&mut` is only allowed in `const fn`
+   |                                  ^^^^^^^
 
 error[E0013]: constants cannot refer to statics
   --> $DIR/issue-17718-const-bad-values.rs:5:46
@@ -20,13 +20,7 @@ LL | const C2: &'static mut usize = unsafe { &mut S };
    |
    = help: consider extracting the value of the `static` to a `const`, and referring to that
 
-error[E0764]: mutable references are not allowed in constants
-  --> $DIR/issue-17718-const-bad-values.rs:5:41
-   |
-LL | const C2: &'static mut usize = unsafe { &mut S };
-   |                                         ^^^^^^ `&mut` is only allowed in `const fn`
-
-error: aborting due to 4 previous errors
+error: aborting due to 3 previous errors
 
 Some errors have detailed explanations: E0013, E0764.
 For more information about an error, try `rustc --explain E0013`.
diff --git a/src/test/ui/consts/projection_qualif.mut_refs.stderr b/src/test/ui/consts/projection_qualif.mut_refs.stderr
deleted file mode 100644
index fad8f011f75..00000000000
--- a/src/test/ui/consts/projection_qualif.mut_refs.stderr
+++ /dev/null
@@ -1,19 +0,0 @@
-error[E0764]: mutable references are not allowed in constants
-  --> $DIR/projection_qualif.rs:10:27
-   |
-LL |         let b: *mut u32 = &mut a;
-   |                           ^^^^^^ `&mut` is only allowed in `const fn`
-
-error[E0658]: dereferencing raw pointers in constants is unstable
-  --> $DIR/projection_qualif.rs:11:18
-   |
-LL |         unsafe { *b = 5; }
-   |                  ^^^^^^
-   |
-   = note: see issue #51911 <https://github.com/rust-lang/rust/issues/51911> for more information
-   = help: add `#![feature(const_raw_ptr_deref)]` to the crate attributes to enable
-
-error: aborting due to 2 previous errors
-
-Some errors have detailed explanations: E0658, E0764.
-For more information about an error, try `rustc --explain E0658`.
diff --git a/src/test/ui/consts/projection_qualif.stock.stderr b/src/test/ui/consts/projection_qualif.stock.stderr
deleted file mode 100644
index fad8f011f75..00000000000
--- a/src/test/ui/consts/projection_qualif.stock.stderr
+++ /dev/null
@@ -1,19 +0,0 @@
-error[E0764]: mutable references are not allowed in constants
-  --> $DIR/projection_qualif.rs:10:27
-   |
-LL |         let b: *mut u32 = &mut a;
-   |                           ^^^^^^ `&mut` is only allowed in `const fn`
-
-error[E0658]: dereferencing raw pointers in constants is unstable
-  --> $DIR/projection_qualif.rs:11:18
-   |
-LL |         unsafe { *b = 5; }
-   |                  ^^^^^^
-   |
-   = note: see issue #51911 <https://github.com/rust-lang/rust/issues/51911> for more information
-   = help: add `#![feature(const_raw_ptr_deref)]` to the crate attributes to enable
-
-error: aborting due to 2 previous errors
-
-Some errors have detailed explanations: E0658, E0764.
-For more information about an error, try `rustc --explain E0658`.
diff --git a/src/test/ui/consts/read_from_static_mut_ref.rs b/src/test/ui/consts/read_from_static_mut_ref.rs
deleted file mode 100644
index 5faa983ab09..00000000000
--- a/src/test/ui/consts/read_from_static_mut_ref.rs
+++ /dev/null
@@ -1,9 +0,0 @@
-// We are keeping this test in case we decide to allow mutable references in statics again
-#![feature(const_mut_refs)]
-#![allow(const_err)]
-
-static OH_NO: &mut i32 = &mut 42;
-//~^ ERROR mutable references are not allowed in statics
-fn main() {
-    assert_eq!(*OH_NO, 42);
-}
diff --git a/src/test/ui/consts/read_from_static_mut_ref.stderr b/src/test/ui/consts/read_from_static_mut_ref.stderr
deleted file mode 100644
index c936ac0b7d5..00000000000
--- a/src/test/ui/consts/read_from_static_mut_ref.stderr
+++ /dev/null
@@ -1,9 +0,0 @@
-error[E0764]: mutable references are not allowed in statics
-  --> $DIR/read_from_static_mut_ref.rs:5:26
-   |
-LL | static OH_NO: &mut i32 = &mut 42;
-   |                          ^^^^^^^ `&mut` is only allowed in `const fn`
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0764`.
diff --git a/src/test/ui/consts/static_mut_containing_mut_ref2.mut_refs.stderr b/src/test/ui/consts/static_mut_containing_mut_ref2.mut_refs.stderr
index 36c280ca5c6..8db75dd63cf 100644
--- a/src/test/ui/consts/static_mut_containing_mut_ref2.mut_refs.stderr
+++ b/src/test/ui/consts/static_mut_containing_mut_ref2.mut_refs.stderr
@@ -1,9 +1,9 @@
-error[E0764]: mutable references are not allowed in statics
-  --> $DIR/static_mut_containing_mut_ref2.rs:7:46
+error[E0080]: could not evaluate static initializer
+  --> $DIR/static_mut_containing_mut_ref2.rs:7:45
    |
 LL | pub static mut STDERR_BUFFER: () = unsafe { *(&mut STDERR_BUFFER_SPACE) = 42; };
-   |                                              ^^^^^^^^^^^^^^^^^^^^^^^^^^ `&mut` is only allowed in `const fn`
+   |                                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ modifying a static's initial value from another static's initializer
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0764`.
+For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/consts/static_mut_containing_mut_ref2.rs b/src/test/ui/consts/static_mut_containing_mut_ref2.rs
index 2821d1a0154..61368546083 100644
--- a/src/test/ui/consts/static_mut_containing_mut_ref2.rs
+++ b/src/test/ui/consts/static_mut_containing_mut_ref2.rs
@@ -5,6 +5,7 @@
 static mut STDERR_BUFFER_SPACE: u8 = 0;
 
 pub static mut STDERR_BUFFER: () = unsafe { *(&mut STDERR_BUFFER_SPACE) = 42; };
-//~^ ERROR  mutable references are not allowed in statics
+//[mut_refs]~^ ERROR could not evaluate static initializer
+//[stock]~^^ ERROR mutable references are not allowed in statics
 
 fn main() {}
diff --git a/src/test/ui/consts/static_mut_containing_mut_ref2.stock.stderr b/src/test/ui/consts/static_mut_containing_mut_ref2.stock.stderr
index 36c280ca5c6..5cdcea23231 100644
--- a/src/test/ui/consts/static_mut_containing_mut_ref2.stock.stderr
+++ b/src/test/ui/consts/static_mut_containing_mut_ref2.stock.stderr
@@ -1,9 +1,12 @@
-error[E0764]: mutable references are not allowed in statics
+error[E0658]: mutable references are not allowed in statics
   --> $DIR/static_mut_containing_mut_ref2.rs:7:46
    |
 LL | pub static mut STDERR_BUFFER: () = unsafe { *(&mut STDERR_BUFFER_SPACE) = 42; };
-   |                                              ^^^^^^^^^^^^^^^^^^^^^^^^^^ `&mut` is only allowed in `const fn`
+   |                                              ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #57349 <https://github.com/rust-lang/rust/issues/57349> for more information
+   = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0764`.
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/consts/write_to_mut_ref_dest.mut_refs.stderr b/src/test/ui/consts/write_to_mut_ref_dest.mut_refs.stderr
new file mode 100644
index 00000000000..3ee50907461
--- /dev/null
+++ b/src/test/ui/consts/write_to_mut_ref_dest.mut_refs.stderr
@@ -0,0 +1,12 @@
+error[E0658]: dereferencing raw pointers in constants is unstable
+  --> $DIR/write_to_mut_ref_dest.rs:11:18
+   |
+LL |         unsafe { *b = 5; }
+   |                  ^^^^^^
+   |
+   = note: see issue #51911 <https://github.com/rust-lang/rust/issues/51911> for more information
+   = help: add `#![feature(const_raw_ptr_deref)]` to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/consts/projection_qualif.rs b/src/test/ui/consts/write_to_mut_ref_dest.rs
index 5e2584a6e95..d35df330bb8 100644
--- a/src/test/ui/consts/projection_qualif.rs
+++ b/src/test/ui/consts/write_to_mut_ref_dest.rs
@@ -7,7 +7,7 @@ use std::cell::Cell;
 const FOO: &u32 = {
     let mut a = 42;
     {
-        let b: *mut u32 = &mut a; //~ ERROR mutable references are not allowed in constants
+        let b: *mut u32 = &mut a; //[stock]~ ERROR mutable references are not allowed in constants
         unsafe { *b = 5; } //~ ERROR dereferencing raw pointers in constants
     }
     &{a}
diff --git a/src/test/ui/consts/write_to_mut_ref_dest.stock.stderr b/src/test/ui/consts/write_to_mut_ref_dest.stock.stderr
new file mode 100644
index 00000000000..2b6d1d3267b
--- /dev/null
+++ b/src/test/ui/consts/write_to_mut_ref_dest.stock.stderr
@@ -0,0 +1,21 @@
+error[E0658]: mutable references are not allowed in constants
+  --> $DIR/write_to_mut_ref_dest.rs:10:27
+   |
+LL |         let b: *mut u32 = &mut a;
+   |                           ^^^^^^
+   |
+   = note: see issue #57349 <https://github.com/rust-lang/rust/issues/57349> for more information
+   = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
+
+error[E0658]: dereferencing raw pointers in constants is unstable
+  --> $DIR/write_to_mut_ref_dest.rs:11:18
+   |
+LL |         unsafe { *b = 5; }
+   |                  ^^^^^^
+   |
+   = note: see issue #51911 <https://github.com/rust-lang/rust/issues/51911> for more information
+   = help: add `#![feature(const_raw_ptr_deref)]` to the crate attributes to enable
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/consts/write_to_static_via_mut_ref.rs b/src/test/ui/consts/write_to_static_via_mut_ref.rs
new file mode 100644
index 00000000000..665c305e961
--- /dev/null
+++ b/src/test/ui/consts/write_to_static_via_mut_ref.rs
@@ -0,0 +1,8 @@
+#![feature(const_mut_refs)]
+#![allow(const_err)]
+
+static OH_NO: &mut i32 = &mut 42; //~ ERROR mutable references are not allowed
+fn main() {
+    assert_eq!(*OH_NO, 42);
+    *OH_NO = 43; //~ ERROR cannot assign to `*OH_NO`, as `OH_NO` is an immutable static
+}
diff --git a/src/test/ui/consts/write_to_static_via_mut_ref.stderr b/src/test/ui/consts/write_to_static_via_mut_ref.stderr
new file mode 100644
index 00000000000..d19e998d617
--- /dev/null
+++ b/src/test/ui/consts/write_to_static_via_mut_ref.stderr
@@ -0,0 +1,16 @@
+error[E0764]: mutable references are not allowed in the final value of statics
+  --> $DIR/write_to_static_via_mut_ref.rs:4:26
+   |
+LL | static OH_NO: &mut i32 = &mut 42;
+   |                          ^^^^^^^
+
+error[E0594]: cannot assign to `*OH_NO`, as `OH_NO` is an immutable static item
+  --> $DIR/write_to_static_via_mut_ref.rs:7:5
+   |
+LL |     *OH_NO = 43;
+   |     ^^^^^^^^^^^ cannot assign
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0594, E0764.
+For more information about an error, try `rustc --explain E0594`.
diff --git a/src/test/ui/error-codes/E0017.rs b/src/test/ui/error-codes/E0017.rs
index 262f7bc72c7..c211ad1a2f8 100644
--- a/src/test/ui/error-codes/E0017.rs
+++ b/src/test/ui/error-codes/E0017.rs
@@ -2,12 +2,13 @@ static X: i32 = 1;
 const C: i32 = 2;
 static mut M: i32 = 3;
 
-const CR: &'static mut i32 = &mut C; //~ ERROR E0764
+const CR: &'static mut i32 = &mut C; //~ ERROR mutable references are not allowed
                                      //~| WARN taking a mutable
-static STATIC_REF: &'static mut i32 = &mut X; //~ ERROR E0764
+static STATIC_REF: &'static mut i32 = &mut X; //~ ERROR E0658
                                               //~| ERROR cannot borrow
+                                              //~| ERROR mutable references are not allowed
 
-static CONST_REF: &'static mut i32 = &mut C; //~ ERROR E0764
+static CONST_REF: &'static mut i32 = &mut C; //~ ERROR mutable references are not allowed
                                               //~| WARN taking a mutable
-static STATIC_MUT_REF: &'static mut i32 = unsafe { &mut M }; //~ ERROR E0764
+static STATIC_MUT_REF: &'static mut i32 = unsafe { &mut M }; //~ ERROR mutable references are not
 fn main() {}
diff --git a/src/test/ui/error-codes/E0017.stderr b/src/test/ui/error-codes/E0017.stderr
index ea591587e6d..7d959b6d148 100644
--- a/src/test/ui/error-codes/E0017.stderr
+++ b/src/test/ui/error-codes/E0017.stderr
@@ -13,17 +13,26 @@ note: `const` item defined here
 LL | const C: i32 = 2;
    | ^^^^^^^^^^^^^^^^^
 
-error[E0764]: mutable references are not allowed in constants
+error[E0764]: mutable references are not allowed in the final value of constants
   --> $DIR/E0017.rs:5:30
    |
 LL | const CR: &'static mut i32 = &mut C;
-   |                              ^^^^^^ `&mut` is only allowed in `const fn`
+   |                              ^^^^^^
 
-error[E0764]: mutable references are not allowed in statics
+error[E0658]: mutation through a reference is not allowed in statics
   --> $DIR/E0017.rs:7:39
    |
 LL | static STATIC_REF: &'static mut i32 = &mut X;
-   |                                       ^^^^^^ `&mut` is only allowed in `const fn`
+   |                                       ^^^^^^
+   |
+   = note: see issue #57349 <https://github.com/rust-lang/rust/issues/57349> for more information
+   = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
+
+error[E0764]: mutable references are not allowed in the final value of statics
+  --> $DIR/E0017.rs:7:39
+   |
+LL | static STATIC_REF: &'static mut i32 = &mut X;
+   |                                       ^^^^^^
 
 error[E0596]: cannot borrow immutable static item `X` as mutable
   --> $DIR/E0017.rs:7:39
@@ -32,7 +41,7 @@ LL | static STATIC_REF: &'static mut i32 = &mut X;
    |                                       ^^^^^^ cannot borrow as mutable
 
 warning: taking a mutable reference to a `const` item
-  --> $DIR/E0017.rs:10:38
+  --> $DIR/E0017.rs:11:38
    |
 LL | static CONST_REF: &'static mut i32 = &mut C;
    |                                      ^^^^^^
@@ -45,19 +54,19 @@ note: `const` item defined here
 LL | const C: i32 = 2;
    | ^^^^^^^^^^^^^^^^^
 
-error[E0764]: mutable references are not allowed in statics
-  --> $DIR/E0017.rs:10:38
+error[E0764]: mutable references are not allowed in the final value of statics
+  --> $DIR/E0017.rs:11:38
    |
 LL | static CONST_REF: &'static mut i32 = &mut C;
-   |                                      ^^^^^^ `&mut` is only allowed in `const fn`
+   |                                      ^^^^^^
 
-error[E0764]: mutable references are not allowed in statics
-  --> $DIR/E0017.rs:12:52
+error[E0764]: mutable references are not allowed in the final value of statics
+  --> $DIR/E0017.rs:13:52
    |
 LL | static STATIC_MUT_REF: &'static mut i32 = unsafe { &mut M };
-   |                                                    ^^^^^^ `&mut` is only allowed in `const fn`
+   |                                                    ^^^^^^
 
-error: aborting due to 5 previous errors; 2 warnings emitted
+error: aborting due to 6 previous errors; 2 warnings emitted
 
-Some errors have detailed explanations: E0596, E0764.
+Some errors have detailed explanations: E0596, E0658, E0764.
 For more information about an error, try `rustc --explain E0596`.
diff --git a/src/test/ui/error-codes/E0388.rs b/src/test/ui/error-codes/E0388.rs
index bb0c4979b9a..6049d95f0d2 100644
--- a/src/test/ui/error-codes/E0388.rs
+++ b/src/test/ui/error-codes/E0388.rs
@@ -1,12 +1,13 @@
 static X: i32 = 1;
 const C: i32 = 2;
 
-const CR: &'static mut i32 = &mut C; //~ ERROR E0764
+const CR: &'static mut i32 = &mut C; //~ ERROR mutable references are not allowed
                                      //~| WARN taking a mutable
 static STATIC_REF: &'static mut i32 = &mut X; //~ ERROR cannot borrow
-                                              //~| ERROR E0764
+                                              //~| ERROR E0658
+                                              //~| ERROR mutable references are not allowed
 
-static CONST_REF: &'static mut i32 = &mut C; //~ ERROR E0764
+static CONST_REF: &'static mut i32 = &mut C; //~ ERROR mutable references are not allowed
                                              //~| WARN taking a mutable
 
 fn main() {}
diff --git a/src/test/ui/error-codes/E0388.stderr b/src/test/ui/error-codes/E0388.stderr
index 73e0b139cd0..4886a156d2e 100644
--- a/src/test/ui/error-codes/E0388.stderr
+++ b/src/test/ui/error-codes/E0388.stderr
@@ -13,17 +13,26 @@ note: `const` item defined here
 LL | const C: i32 = 2;
    | ^^^^^^^^^^^^^^^^^
 
-error[E0764]: mutable references are not allowed in constants
+error[E0764]: mutable references are not allowed in the final value of constants
   --> $DIR/E0388.rs:4:30
    |
 LL | const CR: &'static mut i32 = &mut C;
-   |                              ^^^^^^ `&mut` is only allowed in `const fn`
+   |                              ^^^^^^
 
-error[E0764]: mutable references are not allowed in statics
+error[E0658]: mutation through a reference is not allowed in statics
   --> $DIR/E0388.rs:6:39
    |
 LL | static STATIC_REF: &'static mut i32 = &mut X;
-   |                                       ^^^^^^ `&mut` is only allowed in `const fn`
+   |                                       ^^^^^^
+   |
+   = note: see issue #57349 <https://github.com/rust-lang/rust/issues/57349> for more information
+   = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
+
+error[E0764]: mutable references are not allowed in the final value of statics
+  --> $DIR/E0388.rs:6:39
+   |
+LL | static STATIC_REF: &'static mut i32 = &mut X;
+   |                                       ^^^^^^
 
 error[E0596]: cannot borrow immutable static item `X` as mutable
   --> $DIR/E0388.rs:6:39
@@ -32,7 +41,7 @@ LL | static STATIC_REF: &'static mut i32 = &mut X;
    |                                       ^^^^^^ cannot borrow as mutable
 
 warning: taking a mutable reference to a `const` item
-  --> $DIR/E0388.rs:9:38
+  --> $DIR/E0388.rs:10:38
    |
 LL | static CONST_REF: &'static mut i32 = &mut C;
    |                                      ^^^^^^
@@ -45,13 +54,13 @@ note: `const` item defined here
 LL | const C: i32 = 2;
    | ^^^^^^^^^^^^^^^^^
 
-error[E0764]: mutable references are not allowed in statics
-  --> $DIR/E0388.rs:9:38
+error[E0764]: mutable references are not allowed in the final value of statics
+  --> $DIR/E0388.rs:10:38
    |
 LL | static CONST_REF: &'static mut i32 = &mut C;
-   |                                      ^^^^^^ `&mut` is only allowed in `const fn`
+   |                                      ^^^^^^
 
-error: aborting due to 4 previous errors; 2 warnings emitted
+error: aborting due to 5 previous errors; 2 warnings emitted
 
-Some errors have detailed explanations: E0596, E0764.
+Some errors have detailed explanations: E0596, E0658, E0764.
 For more information about an error, try `rustc --explain E0596`.
diff --git a/src/test/ui/feature-gates/feature-gate-cfg-version.rs b/src/test/ui/feature-gates/feature-gate-cfg-version.rs
index c29ef99945e..e35784a68d1 100644
--- a/src/test/ui/feature-gates/feature-gate-cfg-version.rs
+++ b/src/test/ui/feature-gates/feature-gate-cfg-version.rs
@@ -1,3 +1,9 @@
+#[cfg(version(42))] //~ ERROR: expected a version literal
+//~^ ERROR `cfg(version)` is experimental and subject to change
+fn foo() {}
+#[cfg(version(1.20))] //~ ERROR: expected a version literal
+//~^ ERROR `cfg(version)` is experimental and subject to change
+fn foo() -> bool { true }
 #[cfg(version("1.44"))]
 //~^ ERROR `cfg(version)` is experimental and subject to change
 fn foo() -> bool { true }
@@ -11,30 +17,32 @@ fn bar() -> bool  { false }
 #[cfg(version(false))] //~ ERROR: expected a version literal
 //~^ ERROR `cfg(version)` is experimental and subject to change
 fn bar() -> bool  { false }
-#[cfg(version("foo"))] //~ ERROR: invalid version literal
+#[cfg(version("foo"))] //~ WARNING: unknown version literal format
 //~^ ERROR `cfg(version)` is experimental and subject to change
 fn bar() -> bool  { false }
-#[cfg(version("999"))]
+#[cfg(version("999"))] //~ WARNING: unknown version literal format
 //~^ ERROR `cfg(version)` is experimental and subject to change
 fn bar() -> bool  { false }
-#[cfg(version("-1"))] //~ ERROR: invalid version literal
+#[cfg(version("-1"))] //~ WARNING: unknown version literal format
 //~^ ERROR `cfg(version)` is experimental and subject to change
 fn bar() -> bool  { false }
-#[cfg(version("65536"))] //~ ERROR: invalid version literal
+#[cfg(version("65536"))] //~ WARNING: unknown version literal format
 //~^ ERROR `cfg(version)` is experimental and subject to change
 fn bar() -> bool  { false }
-#[cfg(version("0"))]
+#[cfg(version("0"))] //~ WARNING: unknown version literal format
 //~^ ERROR `cfg(version)` is experimental and subject to change
 fn bar() -> bool { true }
-
-#[cfg(version("1.65536.2"))]
+#[cfg(version("1.0"))]
+//~^ ERROR `cfg(version)` is experimental and subject to change
+fn bar() -> bool { true }
+#[cfg(version("1.65536.2"))] //~ WARNING: unknown version literal format
+//~^ ERROR `cfg(version)` is experimental and subject to change
+fn bar() -> bool  { false }
+#[cfg(version("1.20.0-stable"))] //~ WARNING: unknown version literal format
 //~^ ERROR `cfg(version)` is experimental and subject to change
-fn version_check_bug() {}
+fn bar() {}
 
 fn main() {
-    // This should fail but due to a bug in version_check `1.65536.2` is interpreted as `1.2`.
-    // See https://github.com/SergioBenitez/version_check/issues/11
-    version_check_bug();
     assert!(foo());
     assert!(bar());
     assert!(cfg!(version("1.42"))); //~ ERROR `cfg(version)` is experimental and subject to change
diff --git a/src/test/ui/feature-gates/feature-gate-cfg-version.stderr b/src/test/ui/feature-gates/feature-gate-cfg-version.stderr
index bdf160b5a02..ae899d409ec 100644
--- a/src/test/ui/feature-gates/feature-gate-cfg-version.stderr
+++ b/src/test/ui/feature-gates/feature-gate-cfg-version.stderr
@@ -1,6 +1,36 @@
 error[E0658]: `cfg(version)` is experimental and subject to change
   --> $DIR/feature-gate-cfg-version.rs:1:7
    |
+LL | #[cfg(version(42))]
+   |       ^^^^^^^^^^^
+   |
+   = note: see issue #64796 <https://github.com/rust-lang/rust/issues/64796> for more information
+   = help: add `#![feature(cfg_version)]` to the crate attributes to enable
+
+error: expected a version literal
+  --> $DIR/feature-gate-cfg-version.rs:1:15
+   |
+LL | #[cfg(version(42))]
+   |               ^^
+
+error[E0658]: `cfg(version)` is experimental and subject to change
+  --> $DIR/feature-gate-cfg-version.rs:4:7
+   |
+LL | #[cfg(version(1.20))]
+   |       ^^^^^^^^^^^^^
+   |
+   = note: see issue #64796 <https://github.com/rust-lang/rust/issues/64796> for more information
+   = help: add `#![feature(cfg_version)]` to the crate attributes to enable
+
+error: expected a version literal
+  --> $DIR/feature-gate-cfg-version.rs:4:15
+   |
+LL | #[cfg(version(1.20))]
+   |               ^^^^
+
+error[E0658]: `cfg(version)` is experimental and subject to change
+  --> $DIR/feature-gate-cfg-version.rs:7:7
+   |
 LL | #[cfg(version("1.44"))]
    |       ^^^^^^^^^^^^^^^
    |
@@ -8,7 +38,7 @@ LL | #[cfg(version("1.44"))]
    = help: add `#![feature(cfg_version)]` to the crate attributes to enable
 
 error[E0658]: `cfg(version)` is experimental and subject to change
-  --> $DIR/feature-gate-cfg-version.rs:4:11
+  --> $DIR/feature-gate-cfg-version.rs:10:11
    |
 LL | #[cfg(not(version("1.44")))]
    |           ^^^^^^^^^^^^^^^
@@ -17,7 +47,7 @@ LL | #[cfg(not(version("1.44")))]
    = help: add `#![feature(cfg_version)]` to the crate attributes to enable
 
 error[E0658]: `cfg(version)` is experimental and subject to change
-  --> $DIR/feature-gate-cfg-version.rs:8:7
+  --> $DIR/feature-gate-cfg-version.rs:14:7
    |
 LL | #[cfg(version("1.43", "1.44", "1.45"))]
    |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -26,13 +56,13 @@ LL | #[cfg(version("1.43", "1.44", "1.45"))]
    = help: add `#![feature(cfg_version)]` to the crate attributes to enable
 
 error: expected single version literal
-  --> $DIR/feature-gate-cfg-version.rs:8:7
+  --> $DIR/feature-gate-cfg-version.rs:14:7
    |
 LL | #[cfg(version("1.43", "1.44", "1.45"))]
    |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0658]: `cfg(version)` is experimental and subject to change
-  --> $DIR/feature-gate-cfg-version.rs:11:7
+  --> $DIR/feature-gate-cfg-version.rs:17:7
    |
 LL | #[cfg(version(false))]
    |       ^^^^^^^^^^^^^^
@@ -41,13 +71,13 @@ LL | #[cfg(version(false))]
    = help: add `#![feature(cfg_version)]` to the crate attributes to enable
 
 error: expected a version literal
-  --> $DIR/feature-gate-cfg-version.rs:11:15
+  --> $DIR/feature-gate-cfg-version.rs:17:15
    |
 LL | #[cfg(version(false))]
    |               ^^^^^
 
 error[E0658]: `cfg(version)` is experimental and subject to change
-  --> $DIR/feature-gate-cfg-version.rs:14:7
+  --> $DIR/feature-gate-cfg-version.rs:20:7
    |
 LL | #[cfg(version("foo"))]
    |       ^^^^^^^^^^^^^^
@@ -55,14 +85,14 @@ LL | #[cfg(version("foo"))]
    = note: see issue #64796 <https://github.com/rust-lang/rust/issues/64796> for more information
    = help: add `#![feature(cfg_version)]` to the crate attributes to enable
 
-error: invalid version literal
-  --> $DIR/feature-gate-cfg-version.rs:14:15
+warning: unknown version literal format, assuming it refers to a future version
+  --> $DIR/feature-gate-cfg-version.rs:20:15
    |
 LL | #[cfg(version("foo"))]
    |               ^^^^^
 
 error[E0658]: `cfg(version)` is experimental and subject to change
-  --> $DIR/feature-gate-cfg-version.rs:17:7
+  --> $DIR/feature-gate-cfg-version.rs:23:7
    |
 LL | #[cfg(version("999"))]
    |       ^^^^^^^^^^^^^^
@@ -70,8 +100,14 @@ LL | #[cfg(version("999"))]
    = note: see issue #64796 <https://github.com/rust-lang/rust/issues/64796> for more information
    = help: add `#![feature(cfg_version)]` to the crate attributes to enable
 
+warning: unknown version literal format, assuming it refers to a future version
+  --> $DIR/feature-gate-cfg-version.rs:23:15
+   |
+LL | #[cfg(version("999"))]
+   |               ^^^^^
+
 error[E0658]: `cfg(version)` is experimental and subject to change
-  --> $DIR/feature-gate-cfg-version.rs:20:7
+  --> $DIR/feature-gate-cfg-version.rs:26:7
    |
 LL | #[cfg(version("-1"))]
    |       ^^^^^^^^^^^^^
@@ -79,14 +115,14 @@ LL | #[cfg(version("-1"))]
    = note: see issue #64796 <https://github.com/rust-lang/rust/issues/64796> for more information
    = help: add `#![feature(cfg_version)]` to the crate attributes to enable
 
-error: invalid version literal
-  --> $DIR/feature-gate-cfg-version.rs:20:15
+warning: unknown version literal format, assuming it refers to a future version
+  --> $DIR/feature-gate-cfg-version.rs:26:15
    |
 LL | #[cfg(version("-1"))]
    |               ^^^^
 
 error[E0658]: `cfg(version)` is experimental and subject to change
-  --> $DIR/feature-gate-cfg-version.rs:23:7
+  --> $DIR/feature-gate-cfg-version.rs:29:7
    |
 LL | #[cfg(version("65536"))]
    |       ^^^^^^^^^^^^^^^^
@@ -94,14 +130,14 @@ LL | #[cfg(version("65536"))]
    = note: see issue #64796 <https://github.com/rust-lang/rust/issues/64796> for more information
    = help: add `#![feature(cfg_version)]` to the crate attributes to enable
 
-error: invalid version literal
-  --> $DIR/feature-gate-cfg-version.rs:23:15
+warning: unknown version literal format, assuming it refers to a future version
+  --> $DIR/feature-gate-cfg-version.rs:29:15
    |
 LL | #[cfg(version("65536"))]
    |               ^^^^^^^
 
 error[E0658]: `cfg(version)` is experimental and subject to change
-  --> $DIR/feature-gate-cfg-version.rs:26:7
+  --> $DIR/feature-gate-cfg-version.rs:32:7
    |
 LL | #[cfg(version("0"))]
    |       ^^^^^^^^^^^^
@@ -109,8 +145,23 @@ LL | #[cfg(version("0"))]
    = note: see issue #64796 <https://github.com/rust-lang/rust/issues/64796> for more information
    = help: add `#![feature(cfg_version)]` to the crate attributes to enable
 
+warning: unknown version literal format, assuming it refers to a future version
+  --> $DIR/feature-gate-cfg-version.rs:32:15
+   |
+LL | #[cfg(version("0"))]
+   |               ^^^
+
+error[E0658]: `cfg(version)` is experimental and subject to change
+  --> $DIR/feature-gate-cfg-version.rs:35:7
+   |
+LL | #[cfg(version("1.0"))]
+   |       ^^^^^^^^^^^^^^
+   |
+   = note: see issue #64796 <https://github.com/rust-lang/rust/issues/64796> for more information
+   = help: add `#![feature(cfg_version)]` to the crate attributes to enable
+
 error[E0658]: `cfg(version)` is experimental and subject to change
-  --> $DIR/feature-gate-cfg-version.rs:30:7
+  --> $DIR/feature-gate-cfg-version.rs:38:7
    |
 LL | #[cfg(version("1.65536.2"))]
    |       ^^^^^^^^^^^^^^^^^^^^
@@ -118,8 +169,29 @@ LL | #[cfg(version("1.65536.2"))]
    = note: see issue #64796 <https://github.com/rust-lang/rust/issues/64796> for more information
    = help: add `#![feature(cfg_version)]` to the crate attributes to enable
 
+warning: unknown version literal format, assuming it refers to a future version
+  --> $DIR/feature-gate-cfg-version.rs:38:15
+   |
+LL | #[cfg(version("1.65536.2"))]
+   |               ^^^^^^^^^^^
+
+error[E0658]: `cfg(version)` is experimental and subject to change
+  --> $DIR/feature-gate-cfg-version.rs:41:7
+   |
+LL | #[cfg(version("1.20.0-stable"))]
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #64796 <https://github.com/rust-lang/rust/issues/64796> for more information
+   = help: add `#![feature(cfg_version)]` to the crate attributes to enable
+
+warning: unknown version literal format, assuming it refers to a future version
+  --> $DIR/feature-gate-cfg-version.rs:41:15
+   |
+LL | #[cfg(version("1.20.0-stable"))]
+   |               ^^^^^^^^^^^^^^^
+
 error[E0658]: `cfg(version)` is experimental and subject to change
-  --> $DIR/feature-gate-cfg-version.rs:40:18
+  --> $DIR/feature-gate-cfg-version.rs:48:18
    |
 LL |     assert!(cfg!(version("1.42")));
    |                  ^^^^^^^^^^^^^^^
@@ -127,6 +199,6 @@ LL |     assert!(cfg!(version("1.42")));
    = note: see issue #64796 <https://github.com/rust-lang/rust/issues/64796> for more information
    = help: add `#![feature(cfg_version)]` to the crate attributes to enable
 
-error: aborting due to 16 previous errors
+error: aborting due to 19 previous errors; 7 warnings emitted
 
 For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/hygiene/no_implicit_prelude-2021.rs b/src/test/ui/hygiene/no_implicit_prelude-2021.rs
new file mode 100644
index 00000000000..0fe9ae56c65
--- /dev/null
+++ b/src/test/ui/hygiene/no_implicit_prelude-2021.rs
@@ -0,0 +1,9 @@
+// check-pass
+// edition:2021
+
+#![no_implicit_prelude]
+
+fn main() {
+    assert!(true, "hoi");
+    assert!(false, "hoi {}", 123);
+}
diff --git a/src/test/ui/issues/issue-46604.rs b/src/test/ui/issues/issue-46604.rs
index 273187a5a13..6ec6e7bdcb8 100644
--- a/src/test/ui/issues/issue-46604.rs
+++ b/src/test/ui/issues/issue-46604.rs
@@ -1,4 +1,4 @@
-static buf: &mut [u8] = &mut [1u8,2,3,4,5,7];   //~ ERROR E0764
+static buf: &mut [u8] = &mut [1u8,2,3,4,5,7];   //~ ERROR mutable references are not allowed
 fn write<T: AsRef<[u8]>>(buffer: T) { }
 
 fn main() {
diff --git a/src/test/ui/issues/issue-46604.stderr b/src/test/ui/issues/issue-46604.stderr
index 5421721dec2..7faa2d79ba4 100644
--- a/src/test/ui/issues/issue-46604.stderr
+++ b/src/test/ui/issues/issue-46604.stderr
@@ -1,8 +1,8 @@
-error[E0764]: mutable references are not allowed in statics
+error[E0764]: mutable references are not allowed in the final value of statics
   --> $DIR/issue-46604.rs:1:25
    |
 LL | static buf: &mut [u8] = &mut [1u8,2,3,4,5,7];
-   |                         ^^^^^^^^^^^^^^^^^^^^ `&mut` is only allowed in `const fn`
+   |                         ^^^^^^^^^^^^^^^^^^^^
 
 error[E0594]: cannot assign to `buf[_]`, as `buf` is an immutable static item
   --> $DIR/issue-46604.rs:6:5
diff --git a/src/test/ui/lint/dead-code/const-and-self.rs b/src/test/ui/lint/dead-code/const-and-self.rs
index 1a7b3f43cda..0bcdd6edf0d 100644
--- a/src/test/ui/lint/dead-code/const-and-self.rs
+++ b/src/test/ui/lint/dead-code/const-and-self.rs
@@ -1,6 +1,6 @@
 // check-pass
 
-#![deny(dead_code)]
+#![warn(dead_code)]
 
 const TLC: usize = 4;
 
@@ -28,8 +28,27 @@ impl Foo<Y> for X {
     }
 }
 
+enum E {
+    A,
+    B, //~ WARN variant is never constructed: `B`
+    C, //~ WARN variant is never constructed: `C`
+}
+
+type F = E;
+
+impl E {
+    fn check(&self) -> bool {
+        match self {
+            Self::A => true,
+            Self::B => false,
+            F::C => false,
+        }
+    }
+}
+
 fn main() {
     let s = [0,1,2,3];
     s.doit();
     X::foo();
+    E::A.check();
 }
diff --git a/src/test/ui/lint/dead-code/const-and-self.stderr b/src/test/ui/lint/dead-code/const-and-self.stderr
new file mode 100644
index 00000000000..c0e406189e8
--- /dev/null
+++ b/src/test/ui/lint/dead-code/const-and-self.stderr
@@ -0,0 +1,20 @@
+warning: variant is never constructed: `B`
+  --> $DIR/const-and-self.rs:33:5
+   |
+LL |     B,
+   |     ^
+   |
+note: the lint level is defined here
+  --> $DIR/const-and-self.rs:3:9
+   |
+LL | #![warn(dead_code)]
+   |         ^^^^^^^^^
+
+warning: variant is never constructed: `C`
+  --> $DIR/const-and-self.rs:34:5
+   |
+LL |     C,
+   |     ^
+
+warning: 2 warnings emitted
+
diff --git a/src/test/ui/never_type/issue-52443.stderr b/src/test/ui/never_type/issue-52443.stderr
index 051896cb89c..1683841e9d7 100644
--- a/src/test/ui/never_type/issue-52443.stderr
+++ b/src/test/ui/never_type/issue-52443.stderr
@@ -39,11 +39,14 @@ error[E0015]: calls in constants are limited to constant functions, tuple struct
 LL |     [(); { for _ in 0usize.. {}; 0}];
    |                     ^^^^^^^^
 
-error[E0764]: mutable references are not allowed in constants
+error[E0658]: mutable references are not allowed in constants
   --> $DIR/issue-52443.rs:9:21
    |
 LL |     [(); { for _ in 0usize.. {}; 0}];
-   |                     ^^^^^^^^ `&mut` is only allowed in `const fn`
+   |                     ^^^^^^^^
+   |
+   = note: see issue #57349 <https://github.com/rust-lang/rust/issues/57349> for more information
+   = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
 
 error[E0015]: calls in constants are limited to constant functions, tuple structs and tuple variants
   --> $DIR/issue-52443.rs:9:21
@@ -53,5 +56,5 @@ LL |     [(); { for _ in 0usize.. {}; 0}];
 
 error: aborting due to 6 previous errors; 1 warning emitted
 
-Some errors have detailed explanations: E0015, E0308, E0744, E0764.
+Some errors have detailed explanations: E0015, E0308, E0658, E0744.
 For more information about an error, try `rustc --explain E0015`.
diff --git a/src/test/ui/unsafe/ranged_ints2_const.rs b/src/test/ui/unsafe/ranged_ints2_const.rs
index 65e0d79308c..b7178c2b52b 100644
--- a/src/test/ui/unsafe/ranged_ints2_const.rs
+++ b/src/test/ui/unsafe/ranged_ints2_const.rs
@@ -18,3 +18,9 @@ const fn bar() -> NonZero<u32> {
     let y = unsafe { &mut x.0 }; //~ ERROR mutable references
     unsafe { NonZero(1) }
 }
+
+const fn boo() -> NonZero<u32> {
+    let mut x = unsafe { NonZero(1) };
+    unsafe { let y = &mut x.0; } //~ ERROR mutable references
+    unsafe { NonZero(1) }
+}
diff --git a/src/test/ui/unsafe/ranged_ints2_const.stderr b/src/test/ui/unsafe/ranged_ints2_const.stderr
index 5ce4296458e..a0dc950e76d 100644
--- a/src/test/ui/unsafe/ranged_ints2_const.stderr
+++ b/src/test/ui/unsafe/ranged_ints2_const.stderr
@@ -16,6 +16,15 @@ LL |     let y = unsafe { &mut x.0 };
    = note: see issue #57349 <https://github.com/rust-lang/rust/issues/57349> for more information
    = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
 
+error[E0658]: mutable references are not allowed in constant functions
+  --> $DIR/ranged_ints2_const.rs:24:22
+   |
+LL |     unsafe { let y = &mut x.0; }
+   |                      ^^^^^^^^
+   |
+   = note: see issue #57349 <https://github.com/rust-lang/rust/issues/57349> for more information
+   = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
+
 error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block
   --> $DIR/ranged_ints2_const.rs:11:13
    |
@@ -24,7 +33,7 @@ LL |     let y = &mut x.0;
    |
    = note: mutating layout constrained fields cannot statically be checked for valid values
 
-error: aborting due to 3 previous errors
+error: aborting due to 4 previous errors
 
 Some errors have detailed explanations: E0133, E0658.
 For more information about an error, try `rustc --explain E0133`.
diff --git a/src/tools/jsondocck/src/main.rs b/src/tools/jsondocck/src/main.rs
index 29131f686a9..6ec292aba64 100644
--- a/src/tools/jsondocck/src/main.rs
+++ b/src/tools/jsondocck/src/main.rs
@@ -149,7 +149,22 @@ fn get_commands(template: &str) -> Result<Vec<Command>, ()> {
             }
         }
 
-        let args = cap.name("args").map_or(vec![], |m| shlex::split(m.as_str()).unwrap());
+        let args = cap.name("args").map_or(Some(vec![]), |m| shlex::split(m.as_str()));
+
+        let args = match args {
+            Some(args) => args,
+            None => {
+                print_err(
+                    &format!(
+                        "Invalid arguments to shlex::split: `{}`",
+                        cap.name("args").unwrap().as_str()
+                    ),
+                    lineno,
+                );
+                errors = true;
+                continue;
+            }
+        };
 
         if !cmd.validate(&args, commands.len(), lineno) {
             errors = true;