about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2019-12-24 03:40:33 +0000
committerbors <bors@rust-lang.org>2019-12-24 03:40:33 +0000
commit625375400cdd172877e81c3ce44ce68f2011af2d (patch)
tree2c80e84603e8cc5e868fe94406e6661baca703c0
parenta4cd03dee2b57216b5c95084a0b46de130946ad7 (diff)
parenta76d67f22f08abf355a1b6abd22b8e2b7db700eb (diff)
downloadrust-625375400cdd172877e81c3ce44ce68f2011af2d.tar.gz
rust-625375400cdd172877e81c3ce44ce68f2011af2d.zip
Auto merge of #67575 - Centril:rollup-feikoir, r=Centril
Rollup of 7 pull requests

Successful merges:

 - #67337 (Ensure that evaluating or validating a constant never reads from a static)
 - #67543 (Add regression tests for fixed ICEs)
 - #67547 (Cleanup err codes)
 - #67551 (Add long error code explanation message for E0627)
 - #67561 (remove `description` from `Error` impls in docs)
 - #67569 (Clean up unsafety in char::encode_utf8)
 - #67572 (Use the chocolatey CDN directly to avoid the flaky API)

Failed merges:

r? @ghost
-rwxr-xr-xsrc/ci/scripts/install-msys2.sh16
-rw-r--r--src/libcore/char/methods.rs59
-rw-r--r--src/libcore/lib.rs1
-rw-r--r--src/librustc/traits/error_reporting.rs2
-rw-r--r--src/librustc_error_codes/error_codes.rs2
-rw-r--r--src/librustc_error_codes/error_codes/E0124.md5
-rw-r--r--src/librustc_error_codes/error_codes/E0128.md9
-rw-r--r--src/librustc_error_codes/error_codes/E0627.md30
-rw-r--r--src/librustc_mir/borrow_check/mod.rs2
-rw-r--r--src/librustc_mir/borrow_check/path_utils.rs2
-rw-r--r--src/librustc_mir/const_eval.rs53
-rw-r--r--src/librustc_mir/interpret/intern.rs23
-rw-r--r--src/librustc_mir/interpret/machine.rs5
-rw-r--r--src/librustc_mir/interpret/memory.rs7
-rw-r--r--src/librustc_mir/transform/const_prop.rs1
-rw-r--r--src/librustc_typeck/check/expr.rs2
-rw-r--r--src/libstd/error.rs32
-rw-r--r--src/libstd/io/error.rs4
-rw-r--r--src/test/ui/const-generics/issues/issue-61747.rs16
-rw-r--r--src/test/ui/const-generics/issues/issue-61747.stderr8
-rw-r--r--src/test/ui/const-generics/issues/issue-66205.rs10
-rw-r--r--src/test/ui/consts/const-points-to-static.rs12
-rw-r--r--src/test/ui/consts/const-points-to-static.stderr17
-rw-r--r--src/test/ui/consts/const-prop-read-static-in-const.rs3
-rw-r--r--src/test/ui/consts/const-prop-read-static-in-const.stderr14
-rw-r--r--src/test/ui/consts/miri_unleashed/const_refers_to_static.rs38
-rw-r--r--src/test/ui/consts/miri_unleashed/const_refers_to_static.stderr100
-rw-r--r--src/test/ui/consts/miri_unleashed/mutable_const2.rs19
-rw-r--r--src/test/ui/consts/miri_unleashed/mutable_const2.stderr25
-rw-r--r--src/test/ui/feature-gates/feature-gate-generators.rs2
-rw-r--r--src/test/ui/feature-gates/feature-gate-generators.stderr5
-rw-r--r--src/test/ui/generator/yield-in-const.rs2
-rw-r--r--src/test/ui/generator/yield-in-const.stderr3
-rw-r--r--src/test/ui/generator/yield-in-function.rs2
-rw-r--r--src/test/ui/generator/yield-in-function.stderr3
-rw-r--r--src/test/ui/generator/yield-in-static.rs2
-rw-r--r--src/test/ui/generator/yield-in-static.stderr3
-rw-r--r--src/test/ui/generic-associated-types/issue-67424.rs13
-rw-r--r--src/test/ui/generic-associated-types/issue-67424.stderr20
-rw-r--r--src/test/ui/issues/issue-52060.rs1
-rw-r--r--src/test/ui/issues/issue-52060.stderr11
-rw-r--r--src/test/ui/pattern/issue-66270-pat-struct-parser-recovery.rs14
-rw-r--r--src/test/ui/pattern/issue-66270-pat-struct-parser-recovery.stderr8
43 files changed, 491 insertions, 115 deletions
diff --git a/src/ci/scripts/install-msys2.sh b/src/ci/scripts/install-msys2.sh
index 3a78ef209e4..9e899ba9d89 100755
--- a/src/ci/scripts/install-msys2.sh
+++ b/src/ci/scripts/install-msys2.sh
@@ -12,10 +12,14 @@ IFS=$'\n\t'
 source "$(cd "$(dirname "$0")" && pwd)/../shared.sh"
 
 if isWindows; then
-    for RETRY_COUNT in 1 2 3 4 5 6 7 8 9 10; do
-        choco install msys2 \
-            --params="/InstallDir:$(ciCheckoutPath)/msys2 /NoPath" -y --no-progress \
-            && mkdir -p "$(ciCheckoutPath)/msys2/home/${USERNAME}" \
-            && ciCommandAddPath "$(ciCheckoutPath)/msys2/usr/bin" && break
-    done
+    # Pre-followed the api/v2 URL to the CDN since the API can be a bit flakey
+    curl -sSL https://packages.chocolatey.org/msys2.20190524.0.0.20191030.nupkg > \
+        msys2.nupkg
+    curl -sSL https://packages.chocolatey.org/chocolatey-core.extension.1.3.5.1.nupkg > \
+        chocolatey-core.extension.nupkg
+    choco install -s . msys2 \
+        --params="/InstallDir:$(ciCheckoutPath)/msys2 /NoPath" -y --no-progress
+    rm msys2.nupkg chocolatey-core.extension.nupkg
+    mkdir -p "$(ciCheckoutPath)/msys2/home/${USERNAME}"
+    ciCommandAddPath "$(ciCheckoutPath)/msys2/usr/bin"
 fi
diff --git a/src/libcore/char/methods.rs b/src/libcore/char/methods.rs
index bb6d6db57d2..fe5d16862a6 100644
--- a/src/libcore/char/methods.rs
+++ b/src/libcore/char/methods.rs
@@ -434,36 +434,35 @@ impl char {
     #[inline]
     pub fn encode_utf8(self, dst: &mut [u8]) -> &mut str {
         let code = self as u32;
-        // SAFETY: each arm checks the size of the slice and only uses `get_unchecked` unsafe ops
-        unsafe {
-            let len = if code < MAX_ONE_B && !dst.is_empty() {
-                *dst.get_unchecked_mut(0) = code as u8;
-                1
-            } else if code < MAX_TWO_B && dst.len() >= 2 {
-                *dst.get_unchecked_mut(0) = (code >> 6 & 0x1F) as u8 | TAG_TWO_B;
-                *dst.get_unchecked_mut(1) = (code & 0x3F) as u8 | TAG_CONT;
-                2
-            } else if code < MAX_THREE_B && dst.len() >= 3 {
-                *dst.get_unchecked_mut(0) = (code >> 12 & 0x0F) as u8 | TAG_THREE_B;
-                *dst.get_unchecked_mut(1) = (code >> 6 & 0x3F) as u8 | TAG_CONT;
-                *dst.get_unchecked_mut(2) = (code & 0x3F) as u8 | TAG_CONT;
-                3
-            } else if dst.len() >= 4 {
-                *dst.get_unchecked_mut(0) = (code >> 18 & 0x07) as u8 | TAG_FOUR_B;
-                *dst.get_unchecked_mut(1) = (code >> 12 & 0x3F) as u8 | TAG_CONT;
-                *dst.get_unchecked_mut(2) = (code >> 6 & 0x3F) as u8 | TAG_CONT;
-                *dst.get_unchecked_mut(3) = (code & 0x3F) as u8 | TAG_CONT;
-                4
-            } else {
-                panic!(
-                    "encode_utf8: need {} bytes to encode U+{:X}, but the buffer has {}",
-                    from_u32_unchecked(code).len_utf8(),
-                    code,
-                    dst.len(),
-                )
-            };
-            from_utf8_unchecked_mut(dst.get_unchecked_mut(..len))
-        }
+        let len = self.len_utf8();
+        match (len, &mut dst[..]) {
+            (1, [a, ..]) => {
+                *a = code as u8;
+            }
+            (2, [a, b, ..]) => {
+                *a = (code >> 6 & 0x1F) as u8 | TAG_TWO_B;
+                *b = (code & 0x3F) as u8 | TAG_CONT;
+            }
+            (3, [a, b, c, ..]) => {
+                *a = (code >> 12 & 0x0F) as u8 | TAG_THREE_B;
+                *b = (code >> 6 & 0x3F) as u8 | TAG_CONT;
+                *c = (code & 0x3F) as u8 | TAG_CONT;
+            }
+            (4, [a, b, c, d, ..]) => {
+                *a = (code >> 18 & 0x07) as u8 | TAG_FOUR_B;
+                *b = (code >> 12 & 0x3F) as u8 | TAG_CONT;
+                *c = (code >> 6 & 0x3F) as u8 | TAG_CONT;
+                *d = (code & 0x3F) as u8 | TAG_CONT;
+            }
+            _ => panic!(
+                "encode_utf8: need {} bytes to encode U+{:X}, but the buffer has {}",
+                len,
+                code,
+                dst.len(),
+            ),
+        };
+        // SAFETY: We just wrote UTF-8 content in, so converting to str is fine.
+        unsafe { from_utf8_unchecked_mut(&mut dst[..len]) }
     }
 
     /// Encodes this character as UTF-16 into the provided `u16` buffer,
diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs
index d12aebb87b9..7d11dd2800f 100644
--- a/src/libcore/lib.rs
+++ b/src/libcore/lib.rs
@@ -129,6 +129,7 @@
 #![feature(associated_type_bounds)]
 #![feature(const_type_id)]
 #![feature(const_caller_location)]
+#![feature(slice_patterns)]
 
 #[prelude_import]
 #[allow(unused)]
diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs
index 2ac2d789b2d..42db64c7915 100644
--- a/src/librustc/traits/error_reporting.rs
+++ b/src/librustc/traits/error_reporting.rs
@@ -2373,7 +2373,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
         let span = self.tcx.def_span(generator_did);
 
         // Do not ICE on closure typeck (#66868).
-        if let None = self.tcx.hir().as_local_hir_id(generator_did) {
+        if self.tcx.hir().as_local_hir_id(generator_did).is_none() {
             return false;
         }
 
diff --git a/src/librustc_error_codes/error_codes.rs b/src/librustc_error_codes/error_codes.rs
index 9c1bec39b29..fbcc976bd49 100644
--- a/src/librustc_error_codes/error_codes.rs
+++ b/src/librustc_error_codes/error_codes.rs
@@ -346,6 +346,7 @@ E0622: include_str!("./error_codes/E0622.md"),
 E0623: include_str!("./error_codes/E0623.md"),
 E0624: include_str!("./error_codes/E0624.md"),
 E0626: include_str!("./error_codes/E0626.md"),
+E0627: include_str!("./error_codes/E0627.md"),
 E0631: include_str!("./error_codes/E0631.md"),
 E0633: include_str!("./error_codes/E0633.md"),
 E0635: include_str!("./error_codes/E0635.md"),
@@ -574,7 +575,6 @@ E0745: include_str!("./error_codes/E0745.md"),
 //  E0612, // merged into E0609
 //  E0613, // Removed (merged with E0609)
     E0625, // thread-local statics cannot be accessed at compile-time
-    E0627, // yield statement outside of generator literal
     E0628, // generators cannot have explicit parameters
     E0629, // missing 'feature' (rustc_const_unstable)
     // rustc_const_unstable attribute must be paired with stable/unstable
diff --git a/src/librustc_error_codes/error_codes/E0124.md b/src/librustc_error_codes/error_codes/E0124.md
index a7836526a7d..8af7cb819cf 100644
--- a/src/librustc_error_codes/error_codes/E0124.md
+++ b/src/librustc_error_codes/error_codes/E0124.md
@@ -1,5 +1,6 @@
-You declared two fields of a struct with the same name. Erroneous code
-example:
+A struct was declared with two fields having the same name.
+
+Erroneous code example:
 
 ```compile_fail,E0124
 struct Foo {
diff --git a/src/librustc_error_codes/error_codes/E0128.md b/src/librustc_error_codes/error_codes/E0128.md
index d0a4b32f968..6f8dfe3a73b 100644
--- a/src/librustc_error_codes/error_codes/E0128.md
+++ b/src/librustc_error_codes/error_codes/E0128.md
@@ -1,4 +1,5 @@
-Type parameter defaults can only use parameters that occur before them.
+A type parameter with default value is using forward declared identifier.
+
 Erroneous code example:
 
 ```compile_fail,E0128
@@ -7,11 +8,11 @@ struct Foo<T = U, U = ()> {
     field2: U,
 }
 // error: type parameters with a default cannot use forward declared
-// identifiers
+//        identifiers
 ```
 
-Since type parameters are evaluated in-order, you may be able to fix this issue
-by doing:
+Type parameter defaults can only use parameters that occur before them. Since
+type parameters are evaluated in-order, this issue could be fixed by doing:
 
 ```
 struct Foo<U = (), T = U> {
diff --git a/src/librustc_error_codes/error_codes/E0627.md b/src/librustc_error_codes/error_codes/E0627.md
new file mode 100644
index 00000000000..21358e1e567
--- /dev/null
+++ b/src/librustc_error_codes/error_codes/E0627.md
@@ -0,0 +1,30 @@
+A yield expression was used outside of the generator literal.
+
+Erroneous code example:
+
+```compile_fail,E0627
+#![feature(generators, generator_trait)]
+
+fn fake_generator() -> &'static str {
+    yield 1;
+    return "foo"
+}
+
+fn main() {
+    let mut generator = fake_generator;
+}
+```
+
+The error occurs because keyword `yield` can only be used inside the generator
+literal. This can be fixed by constructing the generator correctly.
+
+```
+#![feature(generators, generator_trait)]
+
+fn main() {
+    let mut generator = || {
+        yield 1;
+        return "foo"
+    };
+}
+```
diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs
index 4a6379e3bc1..0d136bd7d9c 100644
--- a/src/librustc_mir/borrow_check/mod.rs
+++ b/src/librustc_mir/borrow_check/mod.rs
@@ -1424,7 +1424,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
     }
 
     /// Reports an error if this is a borrow of local data.
-    /// This is called for all Yield statements on movable generators
+    /// This is called for all Yield expressions on movable generators
     fn check_for_local_borrow(&mut self, borrow: &BorrowData<'tcx>, yield_span: Span) {
         debug!("check_for_local_borrow({:?})", borrow);
 
diff --git a/src/librustc_mir/borrow_check/path_utils.rs b/src/librustc_mir/borrow_check/path_utils.rs
index ea541bd93bc..23b4799643a 100644
--- a/src/librustc_mir/borrow_check/path_utils.rs
+++ b/src/librustc_mir/borrow_check/path_utils.rs
@@ -131,7 +131,7 @@ pub(super) fn is_active<'tcx>(
 }
 
 /// Determines if a given borrow is borrowing local data
-/// This is called for all Yield statements on movable generators
+/// This is called for all Yield expressions on movable generators
 pub(super) fn borrow_of_local_data(place: &Place<'_>) -> bool {
     match place.base {
         PlaceBase::Static(_) => false,
diff --git a/src/librustc_mir/const_eval.rs b/src/librustc_mir/const_eval.rs
index a2f066bee08..4fa4e87e0ff 100644
--- a/src/librustc_mir/const_eval.rs
+++ b/src/librustc_mir/const_eval.rs
@@ -45,9 +45,15 @@ fn mk_eval_cx<'mir, 'tcx>(
     tcx: TyCtxt<'tcx>,
     span: Span,
     param_env: ty::ParamEnv<'tcx>,
+    can_access_statics: bool,
 ) -> CompileTimeEvalContext<'mir, 'tcx> {
     debug!("mk_eval_cx: {:?}", param_env);
-    InterpCx::new(tcx.at(span), param_env, CompileTimeInterpreter::new(), Default::default())
+    InterpCx::new(
+        tcx.at(span),
+        param_env,
+        CompileTimeInterpreter::new(),
+        MemoryExtra { can_access_statics },
+    )
 }
 
 fn op_to_const<'tcx>(
@@ -176,6 +182,7 @@ fn eval_body_using_ecx<'mir, 'tcx>(
 #[derive(Clone, Debug)]
 pub enum ConstEvalError {
     NeedsRfc(String),
+    ConstAccessesStatic,
 }
 
 impl<'tcx> Into<InterpErrorInfo<'tcx>> for ConstEvalError {
@@ -195,6 +202,7 @@ impl fmt::Display for ConstEvalError {
                     msg
                 )
             }
+            ConstAccessesStatic => write!(f, "constant accesses static"),
         }
     }
 }
@@ -204,6 +212,7 @@ impl Error for ConstEvalError {
         use self::ConstEvalError::*;
         match *self {
             NeedsRfc(_) => "this feature needs an rfc before being allowed inside constants",
+            ConstAccessesStatic => "constant accesses static",
         }
     }
 
@@ -224,6 +233,12 @@ pub struct CompileTimeInterpreter<'mir, 'tcx> {
     pub(super) loop_detector: snapshot::InfiniteLoopDetector<'mir, 'tcx>,
 }
 
+#[derive(Copy, Clone, Debug)]
+pub struct MemoryExtra {
+    /// Whether this machine may read from statics
+    can_access_statics: bool,
+}
+
 impl<'mir, 'tcx> CompileTimeInterpreter<'mir, 'tcx> {
     fn new() -> Self {
         CompileTimeInterpreter {
@@ -311,7 +326,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
     type ExtraFnVal = !;
 
     type FrameExtra = ();
-    type MemoryExtra = ();
+    type MemoryExtra = MemoryExtra;
     type AllocExtra = ();
 
     type MemoryMap = FxHashMap<AllocId, (MemoryKind<!>, Allocation)>;
@@ -473,7 +488,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
 
     #[inline(always)]
     fn init_allocation_extra<'b>(
-        _memory_extra: &(),
+        _memory_extra: &MemoryExtra,
         _id: AllocId,
         alloc: Cow<'b, Allocation>,
         _kind: Option<MemoryKind<!>>,
@@ -484,7 +499,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
 
     #[inline(always)]
     fn tag_static_base_pointer(
-        _memory_extra: &(),
+        _memory_extra: &MemoryExtra,
         _id: AllocId,
     ) -> Self::PointerTag {
         ()
@@ -527,6 +542,17 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
     fn stack_push(_ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx> {
         Ok(())
     }
+
+    fn before_access_static(
+        memory_extra: &MemoryExtra,
+        _allocation: &Allocation,
+    ) -> InterpResult<'tcx> {
+        if memory_extra.can_access_statics {
+            Ok(())
+        } else {
+            Err(ConstEvalError::ConstAccessesStatic.into())
+        }
+    }
 }
 
 /// Extracts a field of a (variant of a) const.
@@ -540,7 +566,7 @@ pub fn const_field<'tcx>(
     value: &'tcx ty::Const<'tcx>,
 ) -> &'tcx ty::Const<'tcx> {
     trace!("const_field: {:?}, {:?}", field, value);
-    let ecx = mk_eval_cx(tcx, DUMMY_SP, param_env);
+    let ecx = mk_eval_cx(tcx, DUMMY_SP, param_env, false);
     // get the operand again
     let op = ecx.eval_const_to_op(value, None).unwrap();
     // downcast
@@ -560,7 +586,7 @@ pub fn const_caller_location<'tcx>(
     (file, line, col): (Symbol, u32, u32),
 ) -> &'tcx ty::Const<'tcx> {
     trace!("const_caller_location: {}:{}:{}", file, line, col);
-    let mut ecx = mk_eval_cx(tcx, DUMMY_SP, ty::ParamEnv::reveal_all());
+    let mut ecx = mk_eval_cx(tcx, DUMMY_SP, ty::ParamEnv::reveal_all(), false);
 
     let loc_ty = tcx.caller_location_ty();
     let loc_place = ecx.alloc_caller_location(file, line, col);
@@ -581,7 +607,7 @@ pub fn const_variant_index<'tcx>(
     val: &'tcx ty::Const<'tcx>,
 ) -> VariantIdx {
     trace!("const_variant_index: {:?}", val);
-    let ecx = mk_eval_cx(tcx, DUMMY_SP, param_env);
+    let ecx = mk_eval_cx(tcx, DUMMY_SP, param_env, false);
     let op = ecx.eval_const_to_op(val, None).unwrap();
     ecx.read_discriminant(op).unwrap().1
 }
@@ -610,7 +636,9 @@ fn validate_and_turn_into_const<'tcx>(
     key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>,
 ) -> ::rustc::mir::interpret::ConstEvalResult<'tcx> {
     let cid = key.value;
-    let ecx = mk_eval_cx(tcx, tcx.def_span(key.value.instance.def_id()), key.param_env);
+    let def_id = cid.instance.def.def_id();
+    let is_static = tcx.is_static(def_id);
+    let ecx = mk_eval_cx(tcx, tcx.def_span(key.value.instance.def_id()), key.param_env, is_static);
     let val = (|| {
         let mplace = ecx.raw_const_to_mplace(constant)?;
         let mut ref_tracking = RefTracking::new(mplace);
@@ -624,8 +652,7 @@ fn validate_and_turn_into_const<'tcx>(
         // Now that we validated, turn this into a proper constant.
         // Statics/promoteds are always `ByRef`, for the rest `op_to_const` decides
         // whether they become immediates.
-        let def_id = cid.instance.def.def_id();
-        if tcx.is_static(def_id) || cid.promoted.is_some() {
+        if is_static || cid.promoted.is_some() {
             let ptr = mplace.ptr.to_ptr()?;
             Ok(tcx.mk_const(ty::Const {
                 val: ty::ConstKind::Value(ConstValue::ByRef {
@@ -732,12 +759,14 @@ pub fn const_eval_raw_provider<'tcx>(
         return Err(ErrorHandled::Reported);
     }
 
+    let is_static = tcx.is_static(def_id);
+
     let span = tcx.def_span(cid.instance.def_id());
     let mut ecx = InterpCx::new(
         tcx.at(span),
         key.param_env,
         CompileTimeInterpreter::new(),
-        Default::default()
+        MemoryExtra { can_access_statics: is_static },
     );
 
     let res = ecx.load_mir(cid.instance.def, cid.promoted);
@@ -751,7 +780,7 @@ pub fn const_eval_raw_provider<'tcx>(
     }).map_err(|error| {
         let err = error_to_const_error(&ecx, error);
         // errors in statics are always emitted as fatal errors
-        if tcx.is_static(def_id) {
+        if is_static {
             // Ensure that if the above error was either `TooGeneric` or `Reported`
             // an error must be reported.
             let v = err.report_as_error(ecx.tcx, "could not evaluate static initializer");
diff --git a/src/librustc_mir/interpret/intern.rs b/src/librustc_mir/interpret/intern.rs
index c99f39977fe..b53741e9e43 100644
--- a/src/librustc_mir/interpret/intern.rs
+++ b/src/librustc_mir/interpret/intern.rs
@@ -20,7 +20,6 @@ pub trait CompileTimeMachine<'mir, 'tcx> = Machine<
     PointerTag = (),
     ExtraFnVal = !,
     FrameExtra = (),
-    MemoryExtra = (),
     AllocExtra = (),
     MemoryMap = FxHashMap<AllocId, (MemoryKind<!>, Allocation)>,
 >;
@@ -320,12 +319,20 @@ pub fn intern_const_alloc_recursive<M: CompileTimeMachine<'mir, 'tcx>>(
             // We can't call the `intern_shallow` method here, as its logic is tailored to safe
             // references and a `leftover_allocations` set (where we only have a todo-list here).
             // So we hand-roll the interning logic here again.
-            if base_intern_mode != InternMode::Static {
-                // If it's not a static, it *must* be immutable.
-                // We cannot have mutable memory inside a constant.
-                // FIXME: ideally we would assert that they already are immutable, to double-
-                // check our static checks.
-                alloc.mutability = Mutability::Not;
+            match base_intern_mode {
+                InternMode::Static => {}
+                InternMode::Const | InternMode::ConstBase => {
+                    // If it's not a static, it *must* be immutable.
+                    // We cannot have mutable memory inside a constant.
+                    // We use `delay_span_bug` here, because this can be reached in the presence
+                    // of fancy transmutes.
+                    if alloc.mutability == Mutability::Mut {
+                        // For better errors later, mark the allocation as immutable
+                        // (on top of the delayed ICE).
+                        alloc.mutability = Mutability::Not;
+                        ecx.tcx.sess.delay_span_bug(ecx.tcx.span, "mutable allocation in constant");
+                    }
+                }
             }
             let alloc = tcx.intern_const_alloc(alloc);
             tcx.alloc_map.lock().set_alloc_id_memory(alloc_id, alloc);
@@ -337,6 +344,8 @@ pub fn intern_const_alloc_recursive<M: CompileTimeMachine<'mir, 'tcx>>(
         } else if ecx.memory.dead_alloc_map.contains_key(&alloc_id) {
             // dangling pointer
             throw_unsup!(ValidationFailure("encountered dangling pointer in final constant".into()))
+        } else if ecx.tcx.alloc_map.lock().get(alloc_id).is_none() {
+            span_bug!(ecx.tcx.span, "encountered unknown alloc id {:?}", alloc_id);
         }
     }
     Ok(())
diff --git a/src/librustc_mir/interpret/machine.rs b/src/librustc_mir/interpret/machine.rs
index 32de01d9208..e77ba9fa4cb 100644
--- a/src/librustc_mir/interpret/machine.rs
+++ b/src/librustc_mir/interpret/machine.rs
@@ -212,7 +212,10 @@ pub trait Machine<'mir, 'tcx>: Sized {
     }
 
     /// Called before a `StaticKind::Static` value is accessed.
-    fn before_access_static(_allocation: &Allocation) -> InterpResult<'tcx> {
+    fn before_access_static(
+        _memory_extra: &Self::MemoryExtra,
+        _allocation: &Allocation,
+    ) -> InterpResult<'tcx> {
         Ok(())
     }
 
diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs
index 0ba79e4bba2..71e6d3e8ca1 100644
--- a/src/librustc_mir/interpret/memory.rs
+++ b/src/librustc_mir/interpret/memory.rs
@@ -116,7 +116,8 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> HasDataLayout for Memory<'mir, 'tcx, M>
 // carefully copy only the reachable parts.
 impl<'mir, 'tcx, M> Clone for Memory<'mir, 'tcx, M>
 where
-    M: Machine<'mir, 'tcx, PointerTag = (), AllocExtra = (), MemoryExtra = ()>,
+    M: Machine<'mir, 'tcx, PointerTag = (), AllocExtra = ()>,
+    M::MemoryExtra: Copy,
     M::MemoryMap: AllocMap<AllocId, (MemoryKind<M::MemoryKinds>, Allocation)>,
 {
     fn clone(&self) -> Self {
@@ -124,7 +125,7 @@ where
             alloc_map: self.alloc_map.clone(),
             extra_fn_ptr_map: self.extra_fn_ptr_map.clone(),
             dead_alloc_map: self.dead_alloc_map.clone(),
-            extra: (),
+            extra: self.extra,
             tcx: self.tcx,
         }
     }
@@ -455,7 +456,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
                     let id = raw_const.alloc_id;
                     let allocation = tcx.alloc_map.lock().unwrap_memory(id);
 
-                    M::before_access_static(allocation)?;
+                    M::before_access_static(memory_extra, allocation)?;
                     Cow::Borrowed(allocation)
                 }
             }
diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs
index c36cdc98323..a6b30ab5e68 100644
--- a/src/librustc_mir/transform/const_prop.rs
+++ b/src/librustc_mir/transform/const_prop.rs
@@ -224,6 +224,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine {
     }
 
     fn before_access_static(
+        _memory_extra: &(),
         allocation: &Allocation<Self::PointerTag, Self::AllocExtra>,
     ) -> InterpResult<'tcx> {
         // if the static allocation is mutable or if it has relocations (it may be legal to mutate
diff --git a/src/librustc_typeck/check/expr.rs b/src/librustc_typeck/check/expr.rs
index 5c602ad76cd..e862971c9e2 100644
--- a/src/librustc_typeck/check/expr.rs
+++ b/src/librustc_typeck/check/expr.rs
@@ -1810,7 +1810,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     self.tcx.sess,
                     expr.span,
                     E0627,
-                    "yield statement outside of generator literal"
+                    "yield expression outside of generator literal"
                 )
                 .emit();
             }
diff --git a/src/libstd/error.rs b/src/libstd/error.rs
index 18ebd0f1a67..0992e40121a 100644
--- a/src/libstd/error.rs
+++ b/src/libstd/error.rs
@@ -91,10 +91,6 @@ pub trait Error: Debug + Display {
     /// }
     ///
     /// impl Error for SuperError {
-    ///     fn description(&self) -> &str {
-    ///         "I'm the superhero of errors"
-    ///     }
-    ///
     ///     fn cause(&self) -> Option<&dyn Error> {
     ///         Some(&self.side)
     ///     }
@@ -109,11 +105,7 @@ pub trait Error: Debug + Display {
     ///     }
     /// }
     ///
-    /// impl Error for SuperErrorSideKick {
-    ///     fn description(&self) -> &str {
-    ///         "I'm SuperError side kick"
-    ///     }
-    /// }
+    /// impl Error for SuperErrorSideKick {}
     ///
     /// fn get_super_error() -> Result<(), SuperError> {
     ///     Err(SuperError { side: SuperErrorSideKick })
@@ -159,10 +151,6 @@ pub trait Error: Debug + Display {
     /// }
     ///
     /// impl Error for SuperError {
-    ///     fn description(&self) -> &str {
-    ///         "I'm the superhero of errors"
-    ///     }
-    ///
     ///     fn source(&self) -> Option<&(dyn Error + 'static)> {
     ///         Some(&self.side)
     ///     }
@@ -177,11 +165,7 @@ pub trait Error: Debug + Display {
     ///     }
     /// }
     ///
-    /// impl Error for SuperErrorSideKick {
-    ///     fn description(&self) -> &str {
-    ///         "I'm SuperError side kick"
-    ///     }
-    /// }
+    /// impl Error for SuperErrorSideKick {}
     ///
     /// fn get_super_error() -> Result<(), SuperError> {
     ///     Err(SuperError { side: SuperErrorSideKick })
@@ -261,11 +245,7 @@ impl<'a, E: Error + 'a> From<E> for Box<dyn Error + 'a> {
     ///     }
     /// }
     ///
-    /// impl Error for AnError {
-    ///     fn description(&self) -> &str {
-    ///         "Description of an error"
-    ///     }
-    /// }
+    /// impl Error for AnError {}
     ///
     /// let an_error = AnError;
     /// assert!(0 == mem::size_of_val(&an_error));
@@ -300,11 +280,7 @@ impl<'a, E: Error + Send + Sync + 'a> From<E> for Box<dyn Error + Send + Sync +
     ///     }
     /// }
     ///
-    /// impl Error for AnError {
-    ///     fn description(&self) -> &str {
-    ///         "Description of an error"
-    ///     }
-    /// }
+    /// impl Error for AnError {}
     ///
     /// unsafe impl Send for AnError {}
     ///
diff --git a/src/libstd/io/error.rs b/src/libstd/io/error.rs
index c20bd3097b2..efe839d1302 100644
--- a/src/libstd/io/error.rs
+++ b/src/libstd/io/error.rs
@@ -402,9 +402,7 @@ impl Error {
     ///     }
     /// }
     ///
-    /// impl error::Error for MyError {
-    ///     fn description(&self) -> &str { &self.v }
-    /// }
+    /// impl error::Error for MyError {}
     ///
     /// impl Display for MyError {
     ///     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
diff --git a/src/test/ui/const-generics/issues/issue-61747.rs b/src/test/ui/const-generics/issues/issue-61747.rs
new file mode 100644
index 00000000000..64674bb894e
--- /dev/null
+++ b/src/test/ui/const-generics/issues/issue-61747.rs
@@ -0,0 +1,16 @@
+// check-pass
+
+#![feature(const_generics)]
+//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
+
+struct Const<const N: usize>;
+
+impl<const C: usize> Const<{C}> {
+    fn successor() -> Const<{C + 1}> {
+        Const
+    }
+}
+
+fn main() {
+    let _x: Const::<2> = Const::<1>::successor();
+}
diff --git a/src/test/ui/const-generics/issues/issue-61747.stderr b/src/test/ui/const-generics/issues/issue-61747.stderr
new file mode 100644
index 00000000000..ccf36a7f805
--- /dev/null
+++ b/src/test/ui/const-generics/issues/issue-61747.stderr
@@ -0,0 +1,8 @@
+warning: the feature `const_generics` is incomplete and may cause the compiler to crash
+  --> $DIR/issue-61747.rs:3:12
+   |
+LL | #![feature(const_generics)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+
diff --git a/src/test/ui/const-generics/issues/issue-66205.rs b/src/test/ui/const-generics/issues/issue-66205.rs
new file mode 100644
index 00000000000..2e47b4d1882
--- /dev/null
+++ b/src/test/ui/const-generics/issues/issue-66205.rs
@@ -0,0 +1,10 @@
+// check-pass
+
+#![allow(incomplete_features, dead_code, unconditional_recursion)]
+#![feature(const_generics)]
+
+fn fact<const N: usize>() {
+    fact::<{ N - 1 }>();
+}
+
+fn main() {}
diff --git a/src/test/ui/consts/const-points-to-static.rs b/src/test/ui/consts/const-points-to-static.rs
new file mode 100644
index 00000000000..b998b7a97be
--- /dev/null
+++ b/src/test/ui/consts/const-points-to-static.rs
@@ -0,0 +1,12 @@
+// compile-flags: -Zunleash-the-miri-inside-of-you
+
+#![allow(dead_code)]
+
+const TEST: &u8 = &MY_STATIC;
+//~^ skipping const checks
+//~| it is undefined behavior to use this value
+
+static MY_STATIC: u8 = 4;
+
+fn main() {
+}
diff --git a/src/test/ui/consts/const-points-to-static.stderr b/src/test/ui/consts/const-points-to-static.stderr
new file mode 100644
index 00000000000..8949358e293
--- /dev/null
+++ b/src/test/ui/consts/const-points-to-static.stderr
@@ -0,0 +1,17 @@
+warning: skipping const checks
+  --> $DIR/const-points-to-static.rs:5:20
+   |
+LL | const TEST: &u8 = &MY_STATIC;
+   |                    ^^^^^^^^^
+
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/const-points-to-static.rs:5:1
+   |
+LL | const TEST: &u8 = &MY_STATIC;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constant accesses static
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/consts/const-prop-read-static-in-const.rs b/src/test/ui/consts/const-prop-read-static-in-const.rs
index 7504fd52595..14ec064e4ce 100644
--- a/src/test/ui/consts/const-prop-read-static-in-const.rs
+++ b/src/test/ui/consts/const-prop-read-static-in-const.rs
@@ -1,9 +1,8 @@
 // compile-flags: -Zunleash-the-miri-inside-of-you
-// run-pass
 
 #![allow(dead_code)]
 
-const TEST: u8 = MY_STATIC;
+const TEST: u8 = MY_STATIC; //~ ERROR any use of this value will cause an error
 //~^ skipping const checks
 
 static MY_STATIC: u8 = 4;
diff --git a/src/test/ui/consts/const-prop-read-static-in-const.stderr b/src/test/ui/consts/const-prop-read-static-in-const.stderr
index bbd5b12ed7d..bfaa0f934ad 100644
--- a/src/test/ui/consts/const-prop-read-static-in-const.stderr
+++ b/src/test/ui/consts/const-prop-read-static-in-const.stderr
@@ -1,6 +1,18 @@
 warning: skipping const checks
-  --> $DIR/const-prop-read-static-in-const.rs:6:18
+  --> $DIR/const-prop-read-static-in-const.rs:5:18
    |
 LL | const TEST: u8 = MY_STATIC;
    |                  ^^^^^^^^^
 
+error: any use of this value will cause an error
+  --> $DIR/const-prop-read-static-in-const.rs:5:18
+   |
+LL | const TEST: u8 = MY_STATIC;
+   | -----------------^^^^^^^^^-
+   |                  |
+   |                  constant accesses static
+   |
+   = note: `#[deny(const_err)]` on by default
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/consts/miri_unleashed/const_refers_to_static.rs b/src/test/ui/consts/miri_unleashed/const_refers_to_static.rs
new file mode 100644
index 00000000000..55f3f1c8488
--- /dev/null
+++ b/src/test/ui/consts/miri_unleashed/const_refers_to_static.rs
@@ -0,0 +1,38 @@
+// compile-flags: -Zunleash-the-miri-inside-of-you
+#![warn(const_err)]
+
+#![feature(const_raw_ptr_deref)]
+
+use std::sync::atomic::AtomicUsize;
+use std::sync::atomic::Ordering;
+
+const BOO: &usize = { //~ ERROR undefined behavior to use this value
+    static FOO: AtomicUsize = AtomicUsize::new(0);
+    unsafe { &*(&FOO as *const _ as *const usize) }
+    //~^ WARN skipping const checks
+};
+
+const FOO: usize = {
+    static FOO: AtomicUsize = AtomicUsize::new(0);
+    FOO.fetch_add(1, Ordering::Relaxed) //~ WARN any use of this value will cause an error
+    //~^ WARN skipping const checks
+    //~| WARN skipping const checks
+};
+
+const BAR: usize = {
+    static FOO: AtomicUsize = AtomicUsize::new(0);
+    unsafe { *(&FOO as *const _ as *const usize) } //~ WARN any use of this value will cause an err
+    //~^ WARN skipping const checks
+};
+
+static mut MUTABLE: u32 = 0;
+const BAD: u32 = unsafe { MUTABLE }; //~ WARN any use of this value will cause an error
+//~^ WARN skipping const checks
+
+// ok some day perhaps
+const BOO_OK: &usize = { //~ ERROR it is undefined behavior to use this value
+    static FOO: usize = 0;
+    &FOO
+    //~^ WARN skipping const checks
+};
+fn main() {}
diff --git a/src/test/ui/consts/miri_unleashed/const_refers_to_static.stderr b/src/test/ui/consts/miri_unleashed/const_refers_to_static.stderr
new file mode 100644
index 00000000000..6ae88558d70
--- /dev/null
+++ b/src/test/ui/consts/miri_unleashed/const_refers_to_static.stderr
@@ -0,0 +1,100 @@
+warning: skipping const checks
+  --> $DIR/const_refers_to_static.rs:11:18
+   |
+LL |     unsafe { &*(&FOO as *const _ as *const usize) }
+   |                  ^^^
+
+warning: skipping const checks
+  --> $DIR/const_refers_to_static.rs:17:5
+   |
+LL |     FOO.fetch_add(1, Ordering::Relaxed)
+   |     ^^^
+
+warning: skipping const checks
+  --> $DIR/const_refers_to_static.rs:17:5
+   |
+LL |     FOO.fetch_add(1, Ordering::Relaxed)
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: skipping const checks
+  --> $DIR/const_refers_to_static.rs:24:17
+   |
+LL |     unsafe { *(&FOO as *const _ as *const usize) }
+   |                 ^^^
+
+warning: skipping const checks
+  --> $DIR/const_refers_to_static.rs:29:27
+   |
+LL | const BAD: u32 = unsafe { MUTABLE };
+   |                           ^^^^^^^
+
+warning: skipping const checks
+  --> $DIR/const_refers_to_static.rs:35:6
+   |
+LL |     &FOO
+   |      ^^^
+
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/const_refers_to_static.rs:9:1
+   |
+LL | / const BOO: &usize = {
+LL | |     static FOO: AtomicUsize = AtomicUsize::new(0);
+LL | |     unsafe { &*(&FOO as *const _ as *const usize) }
+LL | |
+LL | | };
+   | |__^ constant accesses static
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
+
+warning: any use of this value will cause an error
+  --> $DIR/const_refers_to_static.rs:17:5
+   |
+LL | / const FOO: usize = {
+LL | |     static FOO: AtomicUsize = AtomicUsize::new(0);
+LL | |     FOO.fetch_add(1, Ordering::Relaxed)
+   | |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ calling non-const function `std::sync::atomic::AtomicUsize::fetch_add`
+LL | |
+LL | |
+LL | | };
+   | |__-
+   |
+note: lint level defined here
+  --> $DIR/const_refers_to_static.rs:2:9
+   |
+LL | #![warn(const_err)]
+   |         ^^^^^^^^^
+
+warning: any use of this value will cause an error
+  --> $DIR/const_refers_to_static.rs:24:14
+   |
+LL | / const BAR: usize = {
+LL | |     static FOO: AtomicUsize = AtomicUsize::new(0);
+LL | |     unsafe { *(&FOO as *const _ as *const usize) }
+   | |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constant accesses static
+LL | |
+LL | | };
+   | |__-
+
+warning: any use of this value will cause an error
+  --> $DIR/const_refers_to_static.rs:29:27
+   |
+LL | const BAD: u32 = unsafe { MUTABLE };
+   | --------------------------^^^^^^^---
+   |                           |
+   |                           constant accesses static
+
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/const_refers_to_static.rs:33:1
+   |
+LL | / const BOO_OK: &usize = {
+LL | |     static FOO: usize = 0;
+LL | |     &FOO
+LL | |
+LL | | };
+   | |__^ constant accesses static
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/consts/miri_unleashed/mutable_const2.rs b/src/test/ui/consts/miri_unleashed/mutable_const2.rs
new file mode 100644
index 00000000000..97af1f2f993
--- /dev/null
+++ b/src/test/ui/consts/miri_unleashed/mutable_const2.rs
@@ -0,0 +1,19 @@
+// compile-flags: -Zunleash-the-miri-inside-of-you
+// failure-status: 101
+// rustc-env:RUST_BACKTRACE=0
+// normalize-stderr-test "note: rustc 1.* running on .*" -> "note: rustc VERSION running on TARGET"
+// normalize-stderr-test "note: compiler flags: .*" -> "note: compiler flags: FLAGS"
+// normalize-stderr-test "interpret/intern.rs:[0-9]*:[0-9]*" -> "interpret/intern.rs:LL:CC"
+
+#![feature(const_raw_ptr_deref)]
+#![feature(const_mut_refs)]
+#![deny(const_err)]
+
+use std::cell::UnsafeCell;
+
+// make sure we do not just intern this as mutable
+const MUTABLE_BEHIND_RAW: *mut i32 = &UnsafeCell::new(42) as *const _ as *mut _;
+//~^ WARN: skipping const checks
+//~| ERROR: mutable allocation in constant
+
+fn main() {}
diff --git a/src/test/ui/consts/miri_unleashed/mutable_const2.stderr b/src/test/ui/consts/miri_unleashed/mutable_const2.stderr
new file mode 100644
index 00000000000..2b4e23cd46e
--- /dev/null
+++ b/src/test/ui/consts/miri_unleashed/mutable_const2.stderr
@@ -0,0 +1,25 @@
+warning: skipping const checks
+  --> $DIR/mutable_const2.rs:15:38
+   |
+LL | const MUTABLE_BEHIND_RAW: *mut i32 = &UnsafeCell::new(42) as *const _ as *mut _;
+   |                                      ^^^^^^^^^^^^^^^^^^^^
+
+error: internal compiler error: mutable allocation in constant
+  --> $DIR/mutable_const2.rs:15:1
+   |
+LL | const MUTABLE_BEHIND_RAW: *mut i32 = &UnsafeCell::new(42) as *const _ as *mut _;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+thread 'rustc' panicked at 'no errors encountered even though `delay_span_bug` issued', src/librustc_errors/lib.rs:349:17
+note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace.
+
+error: internal compiler error: unexpected panic
+
+note: the compiler unexpectedly panicked. this is a bug.
+
+note: we would appreciate a bug report: https://github.com/rust-lang/rust/blob/master/CONTRIBUTING.md#bug-reports
+
+note: rustc VERSION running on TARGET
+
+note: compiler flags: FLAGS
+
diff --git a/src/test/ui/feature-gates/feature-gate-generators.rs b/src/test/ui/feature-gates/feature-gate-generators.rs
index 382d891feed..931fee13471 100644
--- a/src/test/ui/feature-gates/feature-gate-generators.rs
+++ b/src/test/ui/feature-gates/feature-gate-generators.rs
@@ -1,6 +1,6 @@
 fn main() {
     yield true; //~ ERROR yield syntax is experimental
-                //~^ ERROR yield statement outside of generator literal
+                //~^ ERROR yield expression outside of generator literal
 }
 
 #[cfg(FALSE)]
diff --git a/src/test/ui/feature-gates/feature-gate-generators.stderr b/src/test/ui/feature-gates/feature-gate-generators.stderr
index 24b814b410c..4adc21efc6a 100644
--- a/src/test/ui/feature-gates/feature-gate-generators.stderr
+++ b/src/test/ui/feature-gates/feature-gate-generators.stderr
@@ -25,7 +25,7 @@ LL |     yield 0;
    = note: for more information, see https://github.com/rust-lang/rust/issues/43122
    = help: add `#![feature(generators)]` to the crate attributes to enable
 
-error[E0627]: yield statement outside of generator literal
+error[E0627]: yield expression outside of generator literal
   --> $DIR/feature-gate-generators.rs:2:5
    |
 LL |     yield true;
@@ -33,4 +33,5 @@ LL |     yield true;
 
 error: aborting due to 4 previous errors
 
-For more information about this error, try `rustc --explain E0658`.
+Some errors have detailed explanations: E0627, E0658.
+For more information about an error, try `rustc --explain E0627`.
diff --git a/src/test/ui/generator/yield-in-const.rs b/src/test/ui/generator/yield-in-const.rs
index f6f11b9cb13..fe5ca822cec 100644
--- a/src/test/ui/generator/yield-in-const.rs
+++ b/src/test/ui/generator/yield-in-const.rs
@@ -1,6 +1,6 @@
 #![feature(generators)]
 
 const A: u8 = { yield 3u8; 3u8};
-//~^ ERROR yield statement outside
+//~^ ERROR yield expression outside
 
 fn main() {}
diff --git a/src/test/ui/generator/yield-in-const.stderr b/src/test/ui/generator/yield-in-const.stderr
index 663bb70d7a0..dcf4fe63e64 100644
--- a/src/test/ui/generator/yield-in-const.stderr
+++ b/src/test/ui/generator/yield-in-const.stderr
@@ -1,4 +1,4 @@
-error[E0627]: yield statement outside of generator literal
+error[E0627]: yield expression outside of generator literal
   --> $DIR/yield-in-const.rs:3:17
    |
 LL | const A: u8 = { yield 3u8; 3u8};
@@ -6,3 +6,4 @@ LL | const A: u8 = { yield 3u8; 3u8};
 
 error: aborting due to previous error
 
+For more information about this error, try `rustc --explain E0627`.
diff --git a/src/test/ui/generator/yield-in-function.rs b/src/test/ui/generator/yield-in-function.rs
index b737d3b2240..29b811621de 100644
--- a/src/test/ui/generator/yield-in-function.rs
+++ b/src/test/ui/generator/yield-in-function.rs
@@ -1,4 +1,4 @@
 #![feature(generators)]
 
 fn main() { yield; }
-//~^ ERROR yield statement outside
+//~^ ERROR yield expression outside
diff --git a/src/test/ui/generator/yield-in-function.stderr b/src/test/ui/generator/yield-in-function.stderr
index e12b0e6843e..51cce198ca3 100644
--- a/src/test/ui/generator/yield-in-function.stderr
+++ b/src/test/ui/generator/yield-in-function.stderr
@@ -1,4 +1,4 @@
-error[E0627]: yield statement outside of generator literal
+error[E0627]: yield expression outside of generator literal
   --> $DIR/yield-in-function.rs:3:13
    |
 LL | fn main() { yield; }
@@ -6,3 +6,4 @@ LL | fn main() { yield; }
 
 error: aborting due to previous error
 
+For more information about this error, try `rustc --explain E0627`.
diff --git a/src/test/ui/generator/yield-in-static.rs b/src/test/ui/generator/yield-in-static.rs
index 12c9ccea4cb..d27fbb33ba1 100644
--- a/src/test/ui/generator/yield-in-static.rs
+++ b/src/test/ui/generator/yield-in-static.rs
@@ -1,6 +1,6 @@
 #![feature(generators)]
 
 static B: u8 = { yield 3u8; 3u8};
-//~^ ERROR yield statement outside
+//~^ ERROR yield expression outside
 
 fn main() {}
diff --git a/src/test/ui/generator/yield-in-static.stderr b/src/test/ui/generator/yield-in-static.stderr
index 220520c3862..d867f3ad345 100644
--- a/src/test/ui/generator/yield-in-static.stderr
+++ b/src/test/ui/generator/yield-in-static.stderr
@@ -1,4 +1,4 @@
-error[E0627]: yield statement outside of generator literal
+error[E0627]: yield expression outside of generator literal
   --> $DIR/yield-in-static.rs:3:18
    |
 LL | static B: u8 = { yield 3u8; 3u8};
@@ -6,3 +6,4 @@ LL | static B: u8 = { yield 3u8; 3u8};
 
 error: aborting due to previous error
 
+For more information about this error, try `rustc --explain E0627`.
diff --git a/src/test/ui/generic-associated-types/issue-67424.rs b/src/test/ui/generic-associated-types/issue-67424.rs
new file mode 100644
index 00000000000..9b616b8abc2
--- /dev/null
+++ b/src/test/ui/generic-associated-types/issue-67424.rs
@@ -0,0 +1,13 @@
+// Fixed by #67160
+
+trait Trait1 {
+    type A;
+}
+
+trait Trait2 {
+    type Type1<B>: Trait1<A=B>;
+    //~^ ERROR: generic associated types are unstable
+    //~| ERROR: type-generic associated types are not yet implemented
+}
+
+fn main() {}
diff --git a/src/test/ui/generic-associated-types/issue-67424.stderr b/src/test/ui/generic-associated-types/issue-67424.stderr
new file mode 100644
index 00000000000..59ff8ac0a3a
--- /dev/null
+++ b/src/test/ui/generic-associated-types/issue-67424.stderr
@@ -0,0 +1,20 @@
+error[E0658]: generic associated types are unstable
+  --> $DIR/issue-67424.rs:8:5
+   |
+LL |     type Type1<B>: Trait1<A=B>;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/44265
+   = help: add `#![feature(generic_associated_types)]` to the crate attributes to enable
+
+error: type-generic associated types are not yet implemented
+  --> $DIR/issue-67424.rs:8:5
+   |
+LL |     type Type1<B>: Trait1<A=B>;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/44265
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/issues/issue-52060.rs b/src/test/ui/issues/issue-52060.rs
index 13b914c0331..fed08902c8b 100644
--- a/src/test/ui/issues/issue-52060.rs
+++ b/src/test/ui/issues/issue-52060.rs
@@ -3,5 +3,6 @@
 static A: &'static [u32] = &[1];
 static B: [u32; 1] = [0; A.len()];
 //~^ ERROR [E0013]
+//~| ERROR evaluation of constant value failed
 
 fn main() {}
diff --git a/src/test/ui/issues/issue-52060.stderr b/src/test/ui/issues/issue-52060.stderr
index 2f90f7f9e03..c69145c1fe8 100644
--- a/src/test/ui/issues/issue-52060.stderr
+++ b/src/test/ui/issues/issue-52060.stderr
@@ -4,6 +4,13 @@ error[E0013]: constants cannot refer to statics, use a constant instead
 LL | static B: [u32; 1] = [0; A.len()];
    |                          ^
 
-error: aborting due to previous error
+error[E0080]: evaluation of constant value failed
+  --> $DIR/issue-52060.rs:4:26
+   |
+LL | static B: [u32; 1] = [0; A.len()];
+   |                          ^ constant accesses static
+
+error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0013`.
+Some errors have detailed explanations: E0013, E0080.
+For more information about an error, try `rustc --explain E0013`.
diff --git a/src/test/ui/pattern/issue-66270-pat-struct-parser-recovery.rs b/src/test/ui/pattern/issue-66270-pat-struct-parser-recovery.rs
new file mode 100644
index 00000000000..48a8e04829a
--- /dev/null
+++ b/src/test/ui/pattern/issue-66270-pat-struct-parser-recovery.rs
@@ -0,0 +1,14 @@
+// Regression test for #66270, fixed by #66246
+
+struct Bug {
+    incorrect_field: 0,
+    //~^ ERROR expected type
+}
+
+struct Empty {}
+
+fn main() {
+    let Bug {
+        any_field: Empty {},
+    } = Bug {};
+}
diff --git a/src/test/ui/pattern/issue-66270-pat-struct-parser-recovery.stderr b/src/test/ui/pattern/issue-66270-pat-struct-parser-recovery.stderr
new file mode 100644
index 00000000000..fef0f3c0e06
--- /dev/null
+++ b/src/test/ui/pattern/issue-66270-pat-struct-parser-recovery.stderr
@@ -0,0 +1,8 @@
+error: expected type, found `0`
+  --> $DIR/issue-66270-pat-struct-parser-recovery.rs:4:22
+   |
+LL |     incorrect_field: 0,
+   |                      ^ expected type
+
+error: aborting due to previous error
+