about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock4
-rw-r--r--compiler/rustc_borrowck/src/type_check/mod.rs20
-rw-r--r--compiler/rustc_codegen_cranelift/src/base.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/rvalue.rs10
-rw-r--r--compiler/rustc_const_eval/src/interpret/cast.rs37
-rw-r--r--compiler/rustc_const_eval/src/transform/check_consts/check.rs13
-rw-r--r--compiler/rustc_const_eval/src/transform/promote_consts.rs16
-rw-r--r--compiler/rustc_middle/src/mir/mod.rs10
-rw-r--r--compiler/rustc_middle/src/mir/tcx.rs17
-rw-r--r--compiler/rustc_mir_build/src/build/expr/as_rvalue.rs15
-rw-r--r--compiler/rustc_mir_dataflow/src/impls/liveness.rs23
-rw-r--r--compiler/rustc_mir_transform/src/dead_store_elimination.rs4
-rw-r--r--compiler/rustc_resolve/src/diagnostics.rs15
-rw-r--r--compiler/rustc_resolve/src/imports.rs4
-rw-r--r--compiler/rustc_typeck/src/check/method/suggest.rs203
-rw-r--r--library/alloc/src/collections/binary_heap.rs7
-rw-r--r--library/alloc/src/collections/btree/map.rs6
-rw-r--r--library/alloc/src/collections/btree/set.rs6
-rw-r--r--library/alloc/src/lib.rs1
-rw-r--r--library/alloc/src/slice.rs2
-rw-r--r--library/alloc/src/vec/mod.rs4
-rw-r--r--library/core/src/slice/raw.rs6
-rw-r--r--library/std/Cargo.toml2
-rw-r--r--library/std/src/collections/hash/map.rs3
-rw-r--r--library/std/src/collections/hash/set.rs15
-rw-r--r--src/test/mir-opt/const_prop/const_prop_fails_gracefully.main.ConstProp.diff2
-rw-r--r--src/test/mir-opt/const_prop/reify_fn_ptr.main.ConstProp.diff2
-rw-r--r--src/test/mir-opt/dead-store-elimination/provenance_soundness.pointer_to_int.DeadStoreElimination.diff4
-rw-r--r--src/test/mir-opt/inst_combine_deref.deep_opt.InstCombine.diff92
-rw-r--r--src/test/mir-opt/inst_combine_deref.do_not_miscompile.InstCombine.diff85
-rw-r--r--src/test/mir-opt/inst_combine_deref.dont_opt.InstCombine.diff53
-rw-r--r--src/test/mir-opt/inst_combine_deref.opt_struct.InstCombine.diff44
-rw-r--r--src/test/mir-opt/inst_combine_deref.simple_opt.InstCombine.diff34
-rw-r--r--src/test/mir-opt/tls-access.rs6
-rw-r--r--src/test/mir-opt/tls_access.main.PreCodegen.after.mir (renamed from src/test/mir-opt/tls_access.main.SimplifyCfg-final.after.mir)33
-rw-r--r--src/test/rustdoc-ui/intra-doc/unresolved-import-recovery.stderr2
-rw-r--r--src/test/rustdoc-ui/issue-61732.stderr2
-rw-r--r--src/test/ui/attributes/field-attributes-vis-unresolved.stderr4
-rw-r--r--src/test/ui/const-ptr/allowed_slices.rs106
-rw-r--r--src/test/ui/const-ptr/forbidden_slices.32bit.stderr280
-rw-r--r--src/test/ui/const-ptr/forbidden_slices.64bit.stderr280
-rw-r--r--src/test/ui/const-ptr/forbidden_slices.rs99
-rw-r--r--src/test/ui/error-codes/E0432.stderr2
-rw-r--r--src/test/ui/feature-gates/feature-gate-extern_absolute_paths.stderr4
-rw-r--r--src/test/ui/imports/import3.stderr2
-rw-r--r--src/test/ui/imports/issue-1697.stderr2
-rw-r--r--src/test/ui/imports/issue-33464.stderr6
-rw-r--r--src/test/ui/imports/issue-36881.stderr2
-rw-r--r--src/test/ui/imports/issue-37887.stderr2
-rw-r--r--src/test/ui/imports/issue-53269.stderr2
-rw-r--r--src/test/ui/imports/issue-55457.stderr2
-rw-r--r--src/test/ui/imports/tool-mod-child.stderr8
-rw-r--r--src/test/ui/imports/unresolved-imports-used.stderr8
-rw-r--r--src/test/ui/keyword/extern/keyword-extern-as-identifier-use.stderr2
-rw-r--r--src/test/ui/privacy/restricted/test.stderr2
-rw-r--r--src/test/ui/resolve/editions-crate-root-2015.stderr4
-rw-r--r--src/test/ui/resolve/extern-prelude-fail.stderr4
-rw-r--r--src/test/ui/resolve/issue-82865.stderr2
-rw-r--r--src/test/ui/resolve/resolve-bad-visibility.stderr4
-rw-r--r--src/test/ui/simd/portable-intrinsics-arent-exposed.stderr2
-rw-r--r--src/test/ui/suggestions/enum-method-probe.fixed59
-rw-r--r--src/test/ui/suggestions/enum-method-probe.rs59
-rw-r--r--src/test/ui/suggestions/enum-method-probe.stderr99
-rw-r--r--src/test/ui/unresolved/unresolved-asterisk-imports.stderr2
-rw-r--r--src/test/ui/unresolved/unresolved-import.rs1
-rw-r--r--src/test/ui/unresolved/unresolved-import.stderr12
-rw-r--r--src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs15
m---------src/tools/rust-analyzer31
68 files changed, 1401 insertions, 510 deletions
diff --git a/Cargo.lock b/Cargo.lock
index c066d1b0a5b..3610d603767 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -746,9 +746,9 @@ dependencies = [
 
 [[package]]
 name = "compiler_builtins"
-version = "0.1.71"
+version = "0.1.73"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "163437f05ca8f29d7e9128ea728dedf5eb620e445fbca273641d3a3050305f23"
+checksum = "71b72fde1d7792ca3bd654f7c3ea4508f9e4d0c826e24179eabb7fcc97a90bc3"
 dependencies = [
  "cc",
  "rustc-std-workspace-core",
diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index 4a2b2942008..d9d31ab2c89 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -2147,6 +2147,18 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                         }
                     }
 
+                    CastKind::PointerAddress => {
+                        let ty_from = op.ty(body, tcx);
+                        let cast_ty_from = CastTy::from_ty(ty_from);
+                        let cast_ty_to = CastTy::from_ty(*ty);
+                        match (cast_ty_from, cast_ty_to) {
+                            (Some(CastTy::Ptr(_) | CastTy::FnPtr), Some(CastTy::Int(_))) => (),
+                            _ => {
+                                span_mirbug!(self, rvalue, "Invalid cast {:?} -> {:?}", ty_from, ty)
+                            }
+                        }
+                    }
+
                     CastKind::Misc => {
                         let ty_from = op.ty(body, tcx);
                         let cast_ty_from = CastTy::from_ty(ty_from);
@@ -2155,7 +2167,10 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                             (None, _)
                             | (_, None | Some(CastTy::FnPtr))
                             | (Some(CastTy::Float), Some(CastTy::Ptr(_)))
-                            | (Some(CastTy::Ptr(_) | CastTy::FnPtr), Some(CastTy::Float)) => {
+                            | (
+                                Some(CastTy::Ptr(_) | CastTy::FnPtr),
+                                Some(CastTy::Float | CastTy::Int(_)),
+                            ) => {
                                 span_mirbug!(self, rvalue, "Invalid cast {:?} -> {:?}", ty_from, ty,)
                             }
                             (
@@ -2163,8 +2178,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                                 Some(CastTy::Int(_) | CastTy::Float | CastTy::Ptr(_)),
                             )
                             | (Some(CastTy::Float), Some(CastTy::Int(_) | CastTy::Float))
-                            | (Some(CastTy::Ptr(_)), Some(CastTy::Int(_) | CastTy::Ptr(_)))
-                            | (Some(CastTy::FnPtr), Some(CastTy::Int(_) | CastTy::Ptr(_))) => (),
+                            | (Some(CastTy::Ptr(_) | CastTy::FnPtr), Some(CastTy::Ptr(_))) => (),
                         }
                     }
                 }
diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs
index 3fe112d794b..7c59ce354c0 100644
--- a/compiler/rustc_codegen_cranelift/src/base.rs
+++ b/compiler/rustc_codegen_cranelift/src/base.rs
@@ -607,7 +607,7 @@ fn codegen_stmt<'tcx>(
                     let operand = codegen_operand(fx, operand);
                     lval.write_cvalue(fx, operand.cast_pointer_to(to_layout));
                 }
-                Rvalue::Cast(CastKind::Misc, ref operand, to_ty) => {
+                Rvalue::Cast(CastKind::Misc | CastKind::PointerAddress, ref operand, to_ty) => {
                     let operand = codegen_operand(fx, operand);
                     let from_ty = operand.layout().ty;
                     let to_ty = fx.monomorphize(to_ty);
diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
index fd29c9e281b..bd88aa33372 100644
--- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
@@ -181,6 +181,13 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                 let cast = bx.cx().layout_of(self.monomorphize(mir_cast_ty));
 
                 let val = match *kind {
+                    mir::CastKind::PointerAddress => {
+                        assert!(bx.cx().is_backend_immediate(cast));
+                        let llptr = operand.immediate();
+                        let llcast_ty = bx.cx().immediate_backend_type(cast);
+                        let lladdr = bx.ptrtoint(llptr, llcast_ty);
+                        OperandValue::Immediate(lladdr)
+                    }
                     mir::CastKind::Pointer(PointerCast::ReifyFnPointer) => {
                         match *operand.layout.ty.kind() {
                             ty::FnDef(def_id, substs) => {
@@ -362,9 +369,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                             (CastTy::Ptr(_) | CastTy::FnPtr, CastTy::Ptr(_)) => {
                                 bx.pointercast(llval, ll_t_out)
                             }
-                            (CastTy::Ptr(_) | CastTy::FnPtr, CastTy::Int(_)) => {
-                                bx.ptrtoint(llval, ll_t_out)
-                            }
                             (CastTy::Int(_), CastTy::Ptr(_)) => {
                                 let usize_llval = bx.intcast(llval, bx.cx().type_isize(), signed);
                                 bx.inttoptr(usize_llval, ll_t_out)
diff --git a/compiler/rustc_const_eval/src/interpret/cast.rs b/compiler/rustc_const_eval/src/interpret/cast.rs
index be34a77bdba..af563c1450e 100644
--- a/compiler/rustc_const_eval/src/interpret/cast.rs
+++ b/compiler/rustc_const_eval/src/interpret/cast.rs
@@ -1,3 +1,4 @@
+use std::assert_matches::assert_matches;
 use std::convert::TryFrom;
 
 use rustc_apfloat::ieee::{Double, Single};
@@ -30,6 +31,12 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 self.unsize_into(src, cast_ty, dest)?;
             }
 
+            PointerAddress => {
+                let src = self.read_immediate(src)?;
+                let res = self.pointer_address_cast(&src, cast_ty)?;
+                self.write_immediate(res, dest)?;
+            }
+
             Misc => {
                 let src = self.read_immediate(src)?;
                 let res = self.misc_cast(&src, cast_ty)?;
@@ -174,23 +181,23 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
 
         // # The remaining source values are scalar and "int-like".
         let scalar = src.to_scalar()?;
+        Ok(self.cast_from_int_like(scalar, src.layout, cast_ty)?.into())
+    }
 
-        // If we are casting from a pointer to something
-        // that is not a pointer, mark the pointer as exposed
-        if src.layout.ty.is_any_ptr() && !cast_ty.is_any_ptr() {
-            let ptr = self.scalar_to_ptr(scalar)?;
-
-            match ptr.into_pointer_or_addr() {
-                Ok(ptr) => {
-                    M::expose_ptr(self, ptr)?;
-                }
-                Err(_) => {
-                    // do nothing, exposing an invalid pointer
-                    // has no meaning
-                }
-            };
-        }
+    pub fn pointer_address_cast(
+        &mut self,
+        src: &ImmTy<'tcx, M::PointerTag>,
+        cast_ty: Ty<'tcx>,
+    ) -> InterpResult<'tcx, Immediate<M::PointerTag>> {
+        assert_matches!(src.layout.ty.kind(), ty::RawPtr(_) | ty::FnPtr(_));
+        assert!(cast_ty.is_integral());
 
+        let scalar = src.to_scalar()?;
+        let ptr = self.scalar_to_ptr(scalar)?;
+        match ptr.into_pointer_or_addr() {
+            Ok(ptr) => M::expose_ptr(self, ptr)?,
+            Err(_) => {} // do nothing, exposing an invalid pointer has no meaning
+        };
         Ok(self.cast_from_int_like(scalar, src.layout, cast_ty)?.into())
     }
 
diff --git a/compiler/rustc_const_eval/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs
index eea6e2a47a9..4ef33d62a6b 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs
@@ -8,7 +8,6 @@ use rustc_infer::infer::TyCtxtInferExt;
 use rustc_infer::traits::{ImplSource, Obligation, ObligationCause};
 use rustc_middle::mir::visit::{MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor};
 use rustc_middle::mir::*;
-use rustc_middle::ty::cast::CastTy;
 use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts};
 use rustc_middle::ty::{self, adjustment::PointerCast, Instance, InstanceDef, Ty, TyCtxt};
 use rustc_middle::ty::{Binder, TraitPredicate, TraitRef, TypeFoldable};
@@ -543,16 +542,12 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
                 // in the type of any local, which also excludes casts).
             }
 
-            Rvalue::Cast(CastKind::Misc, ref operand, cast_ty) => {
-                let operand_ty = operand.ty(self.body, self.tcx);
-                let cast_in = CastTy::from_ty(operand_ty).expect("bad input type for cast");
-                let cast_out = CastTy::from_ty(cast_ty).expect("bad output type for cast");
-
-                if let (CastTy::Ptr(_) | CastTy::FnPtr, CastTy::Int(_)) = (cast_in, cast_out) {
-                    self.check_op(ops::RawPtrToIntCast);
-                }
+            Rvalue::Cast(CastKind::PointerAddress, _, _) => {
+                self.check_op(ops::RawPtrToIntCast);
             }
 
+            Rvalue::Cast(CastKind::Misc, _, _) => {}
+
             Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf, _) => {}
             Rvalue::ShallowInitBox(_, _) => {}
 
diff --git a/compiler/rustc_const_eval/src/transform/promote_consts.rs b/compiler/rustc_const_eval/src/transform/promote_consts.rs
index fc6b8a1a723..ea23bd14d25 100644
--- a/compiler/rustc_const_eval/src/transform/promote_consts.rs
+++ b/compiler/rustc_const_eval/src/transform/promote_consts.rs
@@ -16,7 +16,6 @@ use rustc_hir as hir;
 use rustc_middle::mir::traversal::ReversePostorderIter;
 use rustc_middle::mir::visit::{MutVisitor, MutatingUseContext, PlaceContext, Visitor};
 use rustc_middle::mir::*;
-use rustc_middle::ty::cast::CastTy;
 use rustc_middle::ty::subst::InternalSubsts;
 use rustc_middle::ty::{self, List, TyCtxt, TypeFoldable};
 use rustc_span::Span;
@@ -502,18 +501,11 @@ impl<'tcx> Validator<'_, 'tcx> {
 
             Rvalue::ThreadLocalRef(_) => return Err(Unpromotable),
 
-            Rvalue::Cast(kind, operand, cast_ty) => {
-                if matches!(kind, CastKind::Misc) {
-                    let operand_ty = operand.ty(self.body, self.tcx);
-                    let cast_in = CastTy::from_ty(operand_ty).expect("bad input type for cast");
-                    let cast_out = CastTy::from_ty(*cast_ty).expect("bad output type for cast");
-                    if let (CastTy::Ptr(_) | CastTy::FnPtr, CastTy::Int(_)) = (cast_in, cast_out) {
-                        // ptr-to-int casts are not possible in consts and thus not promotable
-                        return Err(Unpromotable);
-                    }
-                    // int-to-ptr casts are fine, they just use the integer value at pointer type.
-                }
+            // ptr-to-int casts are not possible in consts and thus not promotable
+            Rvalue::Cast(CastKind::PointerAddress, _, _) => return Err(Unpromotable),
 
+            // int-to-ptr casts are fine, they just use the integer value at pointer type.
+            Rvalue::Cast(_, operand, _) => {
                 self.validate_operand(operand)?;
             }
 
diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs
index b09d39996f4..1b63c8d67ca 100644
--- a/compiler/rustc_middle/src/mir/mod.rs
+++ b/compiler/rustc_middle/src/mir/mod.rs
@@ -2604,9 +2604,19 @@ pub enum Rvalue<'tcx> {
 #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
 static_assert_size!(Rvalue<'_>, 40);
 
+impl<'tcx> Rvalue<'tcx> {
+    #[inline]
+    pub fn is_pointer_int_cast(&self) -> bool {
+        matches!(self, Rvalue::Cast(CastKind::PointerAddress, _, _))
+    }
+}
+
 #[derive(Clone, Copy, Debug, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable)]
 pub enum CastKind {
     Misc,
+    /// A pointer to address cast. A cast between a pointer and an integer type,
+    /// or between a function pointer and an integer type.
+    PointerAddress,
     Pointer(PointerCast),
 }
 
diff --git a/compiler/rustc_middle/src/mir/tcx.rs b/compiler/rustc_middle/src/mir/tcx.rs
index f1fb484a801..c93b7a95502 100644
--- a/compiler/rustc_middle/src/mir/tcx.rs
+++ b/compiler/rustc_middle/src/mir/tcx.rs
@@ -4,7 +4,6 @@
  */
 
 use crate::mir::*;
-use crate::ty::cast::CastTy;
 use crate::ty::subst::Subst;
 use crate::ty::{self, Ty, TyCtxt};
 use rustc_hir as hir;
@@ -224,22 +223,6 @@ impl<'tcx> Rvalue<'tcx> {
             _ => RvalueInitializationState::Deep,
         }
     }
-
-    pub fn is_pointer_int_cast<D>(&self, local_decls: &D, tcx: TyCtxt<'tcx>) -> bool
-    where
-        D: HasLocalDecls<'tcx>,
-    {
-        if let Rvalue::Cast(CastKind::Misc, src_op, dest_ty) = self {
-            if let Some(CastTy::Int(_)) = CastTy::from_ty(*dest_ty) {
-                let src_ty = src_op.ty(local_decls, tcx);
-                if let Some(CastTy::FnPtr | CastTy::Ptr(_)) = CastTy::from_ty(src_ty) {
-                    return true;
-                }
-            }
-        }
-
-        false
-    }
 }
 
 impl<'tcx> Operand<'tcx> {
diff --git a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
index 0a0c7659b08..2b137046c7f 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
@@ -11,6 +11,7 @@ use rustc_middle::mir::AssertKind;
 use rustc_middle::mir::Place;
 use rustc_middle::mir::*;
 use rustc_middle::thir::*;
+use rustc_middle::ty::cast::CastTy;
 use rustc_middle::ty::{self, Ty, UpvarSubsts};
 use rustc_span::Span;
 
@@ -188,11 +189,19 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 block.and(Rvalue::Use(Operand::Move(Place::from(result))))
             }
             ExprKind::Cast { source } => {
+                let source = &this.thir[source];
+                let from_ty = CastTy::from_ty(source.ty);
+                let cast_ty = CastTy::from_ty(expr.ty);
+                let cast_kind = match (from_ty, cast_ty) {
+                    (Some(CastTy::Ptr(_) | CastTy::FnPtr), Some(CastTy::Int(_))) => {
+                        CastKind::PointerAddress
+                    }
+                    (_, _) => CastKind::Misc,
+                };
                 let source = unpack!(
-                    block =
-                        this.as_operand(block, scope, &this.thir[source], None, NeedsTemporary::No)
+                    block = this.as_operand(block, scope, source, None, NeedsTemporary::No)
                 );
-                block.and(Rvalue::Cast(CastKind::Misc, source, expr.ty))
+                block.and(Rvalue::Cast(cast_kind, source, expr.ty))
             }
             ExprKind::Pointer { cast, source } => {
                 let source = unpack!(
diff --git a/compiler/rustc_mir_dataflow/src/impls/liveness.rs b/compiler/rustc_mir_dataflow/src/impls/liveness.rs
index 4350eb6cdd3..7076fbe1bdb 100644
--- a/compiler/rustc_mir_dataflow/src/impls/liveness.rs
+++ b/compiler/rustc_mir_dataflow/src/impls/liveness.rs
@@ -1,7 +1,6 @@
 use rustc_index::bit_set::{BitSet, ChunkedBitSet};
 use rustc_middle::mir::visit::{MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor};
-use rustc_middle::mir::{self, Local, LocalDecls, Location, Place, StatementKind};
-use rustc_middle::ty::TyCtxt;
+use rustc_middle::mir::{self, Local, Location, Place, StatementKind};
 
 use crate::{Analysis, AnalysisDomain, Backward, CallReturnPlaces, GenKill, GenKillAnalysis};
 
@@ -193,27 +192,21 @@ impl DefUse {
 /// This is basically written for dead store elimination and nothing else.
 ///
 /// All of the caveats of `MaybeLiveLocals` apply.
-pub struct MaybeTransitiveLiveLocals<'a, 'tcx> {
+pub struct MaybeTransitiveLiveLocals<'a> {
     always_live: &'a BitSet<Local>,
-    local_decls: &'a LocalDecls<'tcx>,
-    tcx: TyCtxt<'tcx>,
 }
 
-impl<'a, 'tcx> MaybeTransitiveLiveLocals<'a, 'tcx> {
+impl<'a> MaybeTransitiveLiveLocals<'a> {
     /// The `always_alive` set is the set of locals to which all stores should unconditionally be
     /// considered live.
     ///
     /// This should include at least all locals that are ever borrowed.
-    pub fn new(
-        always_live: &'a BitSet<Local>,
-        local_decls: &'a LocalDecls<'tcx>,
-        tcx: TyCtxt<'tcx>,
-    ) -> Self {
-        MaybeTransitiveLiveLocals { always_live, local_decls, tcx }
+    pub fn new(always_live: &'a BitSet<Local>) -> Self {
+        MaybeTransitiveLiveLocals { always_live }
     }
 }
 
-impl<'a, 'tcx> AnalysisDomain<'tcx> for MaybeTransitiveLiveLocals<'a, 'tcx> {
+impl<'a, 'tcx> AnalysisDomain<'tcx> for MaybeTransitiveLiveLocals<'a> {
     type Domain = ChunkedBitSet<Local>;
     type Direction = Backward;
 
@@ -241,7 +234,7 @@ impl<'a> GenKill<Local> for TransferWrapper<'a> {
     }
 }
 
-impl<'a, 'tcx> Analysis<'tcx> for MaybeTransitiveLiveLocals<'a, 'tcx> {
+impl<'a, 'tcx> Analysis<'tcx> for MaybeTransitiveLiveLocals<'a> {
     fn apply_statement_effect(
         &self,
         trans: &mut Self::Domain,
@@ -251,7 +244,7 @@ impl<'a, 'tcx> Analysis<'tcx> for MaybeTransitiveLiveLocals<'a, 'tcx> {
         // Compute the place that we are storing to, if any
         let destination = match &statement.kind {
             StatementKind::Assign(assign) => {
-                if assign.1.is_pointer_int_cast(self.local_decls, self.tcx) {
+                if assign.1.is_pointer_int_cast() {
                     // Pointer to int casts may be side-effects due to exposing the provenance.
                     // While the model is undecided, we should be conservative. See
                     // <https://www.ralfj.de/blog/2022/04/11/provenance-exposed.html>
diff --git a/compiler/rustc_mir_transform/src/dead_store_elimination.rs b/compiler/rustc_mir_transform/src/dead_store_elimination.rs
index 84f2ee639e4..8becac34ed7 100644
--- a/compiler/rustc_mir_transform/src/dead_store_elimination.rs
+++ b/compiler/rustc_mir_transform/src/dead_store_elimination.rs
@@ -24,7 +24,7 @@ use rustc_mir_dataflow::{impls::MaybeTransitiveLiveLocals, Analysis};
 /// The `borrowed` set must be a `BitSet` of all the locals that are ever borrowed in this body. It
 /// can be generated via the [`get_borrowed_locals`] function.
 pub fn eliminate<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>, borrowed: &BitSet<Local>) {
-    let mut live = MaybeTransitiveLiveLocals::new(borrowed, &body.local_decls, tcx)
+    let mut live = MaybeTransitiveLiveLocals::new(borrowed)
         .into_engine(tcx, body)
         .iterate_to_fixpoint()
         .into_results_cursor(body);
@@ -34,7 +34,7 @@ pub fn eliminate<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>, borrowed: &BitS
         for (statement_index, statement) in bb_data.statements.iter().enumerate().rev() {
             let loc = Location { block: bb, statement_index };
             if let StatementKind::Assign(assign) = &statement.kind {
-                if assign.1.is_pointer_int_cast(&body.local_decls, tcx) {
+                if assign.1.is_pointer_int_cast() {
                     continue;
                 }
             }
diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs
index c199cff2038..b1fe418f687 100644
--- a/compiler/rustc_resolve/src/diagnostics.rs
+++ b/compiler/rustc_resolve/src/diagnostics.rs
@@ -1839,9 +1839,18 @@ impl<'a> Resolver<'a> {
                     )),
                 )
             } else if self.session.edition() == Edition::Edition2015 {
-                (format!("maybe a missing crate `{}`?", ident), None)
+                (
+                    format!("maybe a missing crate `{ident}`?"),
+                    Some((
+                        vec![],
+                        format!(
+                            "consider adding `extern crate {ident}` to use the `{ident}` crate"
+                        ),
+                        Applicability::MaybeIncorrect,
+                    )),
+                )
             } else {
-                (format!("could not find `{}` in the crate root", ident), None)
+                (format!("could not find `{ident}` in the crate root"), None)
             }
         } else if i > 0 {
             let parent = path[i - 1].ident.name;
@@ -1852,7 +1861,7 @@ impl<'a> Resolver<'a> {
                     "the list of imported crates".to_owned()
                 }
                 kw::PathRoot | kw::Crate => "the crate root".to_owned(),
-                _ => format!("`{}`", parent),
+                _ => format!("`{parent}`"),
             };
 
             let mut msg = format!("could not find `{}` in {}", ident, parent);
diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs
index a8c8c674d2d..de83a3a5932 100644
--- a/compiler/rustc_resolve/src/imports.rs
+++ b/compiler/rustc_resolve/src/imports.rs
@@ -475,6 +475,10 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
             }
 
             if let Some((suggestions, msg, applicability)) = err.suggestion {
+                if suggestions.is_empty() {
+                    diag.help(&msg);
+                    continue;
+                }
                 diag.multipart_suggestion(&msg, suggestions, applicability);
             }
         }
diff --git a/compiler/rustc_typeck/src/check/method/suggest.rs b/compiler/rustc_typeck/src/check/method/suggest.rs
index 4e54d554c6e..0e198907c8d 100644
--- a/compiler/rustc_typeck/src/check/method/suggest.rs
+++ b/compiler/rustc_typeck/src/check/method/suggest.rs
@@ -978,45 +978,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     label_span_not_found(&mut err);
                 }
 
-                if let SelfSource::MethodCall(expr) = source
-                    && let Some((fields, substs)) = self.get_field_candidates(span, actual)
-                {
-                    let call_expr =
-                        self.tcx.hir().expect_expr(self.tcx.hir().get_parent_node(expr.hir_id));
-                    for candidate_field in fields.iter() {
-                        if let Some(field_path) = self.check_for_nested_field_satisfying(
-                            span,
-                            &|_, field_ty| {
-                                self.lookup_probe(
-                                    span,
-                                    item_name,
-                                    field_ty,
-                                    call_expr,
-                                    ProbeScope::AllTraits,
-                                )
-                                .is_ok()
-                            },
-                            candidate_field,
-                            substs,
-                            vec![],
-                            self.tcx.parent_module(expr.hir_id).to_def_id(),
-                        ) {
-                            let field_path_str = field_path
-                                .iter()
-                                .map(|id| id.name.to_ident_string())
-                                .collect::<Vec<String>>()
-                                .join(".");
-                            debug!("field_path_str: {:?}", field_path_str);
+                self.check_for_field_method(&mut err, source, span, actual, item_name);
 
-                            err.span_suggestion_verbose(
-                                item_name.span.shrink_to_lo(),
-                                "one of the expressions' fields has a method of the same name",
-                                format!("{field_path_str}."),
-                                Applicability::MaybeIncorrect,
-                            );
-                        }
-                    }
-                }
+                self.check_for_unwrap_self(&mut err, source, span, actual, item_name);
 
                 bound_spans.sort();
                 bound_spans.dedup();
@@ -1343,6 +1307,145 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         false
     }
 
+    fn check_for_field_method(
+        &self,
+        err: &mut DiagnosticBuilder<'tcx, ErrorGuaranteed>,
+        source: SelfSource<'tcx>,
+        span: Span,
+        actual: Ty<'tcx>,
+        item_name: Ident,
+    ) {
+        if let SelfSource::MethodCall(expr) = source
+            && let Some((fields, substs)) = self.get_field_candidates(span, actual)
+        {
+            let call_expr = self.tcx.hir().expect_expr(self.tcx.hir().get_parent_node(expr.hir_id));
+            for candidate_field in fields.iter() {
+                if let Some(field_path) = self.check_for_nested_field_satisfying(
+                    span,
+                    &|_, field_ty| {
+                        self.lookup_probe(
+                            span,
+                            item_name,
+                            field_ty,
+                            call_expr,
+                            ProbeScope::AllTraits,
+                        )
+                        .is_ok()
+                    },
+                    candidate_field,
+                    substs,
+                    vec![],
+                    self.tcx.parent_module(expr.hir_id).to_def_id(),
+                ) {
+                    let field_path_str = field_path
+                        .iter()
+                        .map(|id| id.name.to_ident_string())
+                        .collect::<Vec<String>>()
+                        .join(".");
+                    debug!("field_path_str: {:?}", field_path_str);
+
+                    err.span_suggestion_verbose(
+                        item_name.span.shrink_to_lo(),
+                        "one of the expressions' fields has a method of the same name",
+                        format!("{field_path_str}."),
+                        Applicability::MaybeIncorrect,
+                    );
+                }
+            }
+        }
+    }
+
+    fn check_for_unwrap_self(
+        &self,
+        err: &mut DiagnosticBuilder<'tcx, ErrorGuaranteed>,
+        source: SelfSource<'tcx>,
+        span: Span,
+        actual: Ty<'tcx>,
+        item_name: Ident,
+    ) {
+        let tcx = self.tcx;
+        let SelfSource::MethodCall(expr) = source else { return; };
+        let call_expr = tcx.hir().expect_expr(tcx.hir().get_parent_node(expr.hir_id));
+
+        let ty::Adt(kind, substs) = actual.kind() else { return; };
+        if !kind.is_enum() {
+            return;
+        }
+
+        let matching_variants: Vec<_> = kind
+            .variants()
+            .iter()
+            .flat_map(|variant| {
+                let [field] = &variant.fields[..] else { return None; };
+                let field_ty = field.ty(tcx, substs);
+
+                // Skip `_`, since that'll just lead to ambiguity.
+                if self.resolve_vars_if_possible(field_ty).is_ty_var() {
+                    return None;
+                }
+
+                self.lookup_probe(span, item_name, field_ty, call_expr, ProbeScope::AllTraits)
+                    .ok()
+                    .map(|pick| (variant, field, pick))
+            })
+            .collect();
+
+        let ret_ty_matches = |diagnostic_item| {
+            if let Some(ret_ty) = self
+                .ret_coercion
+                .as_ref()
+                .map(|c| self.resolve_vars_if_possible(c.borrow().expected_ty()))
+                && let ty::Adt(kind, _) = ret_ty.kind()
+                && tcx.get_diagnostic_item(diagnostic_item) == Some(kind.did())
+            {
+                true
+            } else {
+                false
+            }
+        };
+
+        match &matching_variants[..] {
+            [(_, field, pick)] => {
+                let self_ty = field.ty(tcx, substs);
+                err.span_note(
+                    tcx.def_span(pick.item.def_id),
+                    &format!("the method `{item_name}` exists on the type `{self_ty}`"),
+                );
+                let (article, kind, variant, question) =
+                    if Some(kind.did()) == tcx.get_diagnostic_item(sym::Result) {
+                        ("a", "Result", "Err", ret_ty_matches(sym::Result))
+                    } else if Some(kind.did()) == tcx.get_diagnostic_item(sym::Option) {
+                        ("an", "Option", "None", ret_ty_matches(sym::Option))
+                    } else {
+                        return;
+                    };
+                if question {
+                    err.span_suggestion_verbose(
+                        expr.span.shrink_to_hi(),
+                        format!(
+                            "use the `?` operator to extract the `{self_ty}` value, propagating \
+                            {article} `{kind}::{variant}` value to the caller"
+                        ),
+                        "?".to_owned(),
+                        Applicability::MachineApplicable,
+                    );
+                } else {
+                    err.span_suggestion_verbose(
+                        expr.span.shrink_to_hi(),
+                        format!(
+                            "consider using `{kind}::expect` to unwrap the `{self_ty}` value, \
+                             panicking if the value is {article} `{kind}::{variant}`"
+                        ),
+                        ".expect(\"REASON\")".to_owned(),
+                        Applicability::HasPlaceholders,
+                    );
+                }
+            }
+            // FIXME(compiler-errors): Support suggestions for other matching enum variants
+            _ => {}
+        }
+    }
+
     pub(crate) fn note_unmet_impls_on_type(
         &self,
         err: &mut Diagnostic,
@@ -1662,13 +1765,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 (self.tcx.mk_mut_ref(self.tcx.lifetimes.re_erased, rcvr_ty), "&mut "),
                 (self.tcx.mk_imm_ref(self.tcx.lifetimes.re_erased, rcvr_ty), "&"),
             ] {
-                match self.lookup_probe(
-                    span,
-                    item_name,
-                    *rcvr_ty,
-                    rcvr,
-                    crate::check::method::probe::ProbeScope::AllTraits,
-                ) {
+                match self.lookup_probe(span, item_name, *rcvr_ty, rcvr, ProbeScope::AllTraits) {
                     Ok(pick) => {
                         // If the method is defined for the receiver we have, it likely wasn't `use`d.
                         // We point at the method, but we just skip the rest of the check for arbitrary
@@ -1700,13 +1797,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     (self.tcx.mk_diagnostic_item(*rcvr_ty, sym::Arc), "Arc::new"),
                     (self.tcx.mk_diagnostic_item(*rcvr_ty, sym::Rc), "Rc::new"),
                 ] {
-                    if let Some(new_rcvr_t) = *rcvr_ty && let Ok(pick) = self.lookup_probe(
-                        span,
-                        item_name,
-                        new_rcvr_t,
-                        rcvr,
-                        crate::check::method::probe::ProbeScope::AllTraits,
-                    ) {
+                    if let Some(new_rcvr_t) = *rcvr_ty
+                        && let Ok(pick) = self.lookup_probe(
+                            span,
+                            item_name,
+                            new_rcvr_t,
+                            rcvr,
+                            ProbeScope::AllTraits,
+                        )
+                    {
                         debug!("try_alt_rcvr: pick candidate {:?}", pick);
                         let did = Some(pick.item.container.id());
                         // We don't want to suggest a container type when the missing
diff --git a/library/alloc/src/collections/binary_heap.rs b/library/alloc/src/collections/binary_heap.rs
index c3c1d0c92a8..839088eac21 100644
--- a/library/alloc/src/collections/binary_heap.rs
+++ b/library/alloc/src/collections/binary_heap.rs
@@ -166,9 +166,10 @@ mod tests;
 /// item's ordering relative to any other item, as determined by the [`Ord`]
 /// trait, changes while it is in the heap. This is normally only possible
 /// through [`Cell`], [`RefCell`], global state, I/O, or unsafe code. The
-/// behavior resulting from such a logic error is not specified (it
-/// could include panics, incorrect results, aborts, memory leaks, or
-/// non-termination) but will not be undefined behavior.
+/// behavior resulting from such a logic error is not specified, but will
+/// be encapsulated to the `BinaryHeap` that observed the logic error and not
+/// result in undefined behavior. This could include panics, incorrect results,
+/// aborts, memory leaks, and non-termination.
 ///
 /// # Examples
 ///
diff --git a/library/alloc/src/collections/btree/map.rs b/library/alloc/src/collections/btree/map.rs
index 264c217c9ef..6027991a0ed 100644
--- a/library/alloc/src/collections/btree/map.rs
+++ b/library/alloc/src/collections/btree/map.rs
@@ -64,9 +64,9 @@ pub(super) const MIN_LEN: usize = node::MIN_LEN_AFTER_SPLIT;
 /// It is a logic error for a key to be modified in such a way that the key's ordering relative to
 /// any other key, as determined by the [`Ord`] trait, changes while it is in the map. This is
 /// normally only possible through [`Cell`], [`RefCell`], global state, I/O, or unsafe code.
-/// The behavior resulting from such a logic error is not specified (it could include panics,
-/// incorrect results, aborts, memory leaks, or non-termination) but will not be undefined
-/// behavior.
+/// The behavior resulting from such a logic error is not specified, but will be encapsulated to the
+/// `BTreeMap` that observed the logic error and not result in undefined behavior. This could
+/// include panics, incorrect results, aborts, memory leaks, and non-termination.
 ///
 /// Iterators obtained from functions such as [`BTreeMap::iter`], [`BTreeMap::values`], or
 /// [`BTreeMap::keys`] produce their items in order by key, and take worst-case logarithmic and
diff --git a/library/alloc/src/collections/btree/set.rs b/library/alloc/src/collections/btree/set.rs
index d6733425288..20ef834eaee 100644
--- a/library/alloc/src/collections/btree/set.rs
+++ b/library/alloc/src/collections/btree/set.rs
@@ -23,9 +23,9 @@ use super::Recover;
 /// It is a logic error for an item to be modified in such a way that the item's ordering relative
 /// to any other item, as determined by the [`Ord`] trait, changes while it is in the set. This is
 /// normally only possible through [`Cell`], [`RefCell`], global state, I/O, or unsafe code.
-/// The behavior resulting from such a logic error is not specified (it could include panics,
-/// incorrect results, aborts, memory leaks, or non-termination) but will not be undefined
-/// behavior.
+/// The behavior resulting from such a logic error is not specified, but will be encapsulated to the
+/// `BTreeSet` that observed the logic error and not result in undefined behavior. This could
+/// include panics, incorrect results, aborts, memory leaks, and non-termination.
 ///
 /// Iterators returned by [`BTreeSet::iter`] produce their items in order, and take worst-case
 /// logarithmic and amortized constant time per item returned.
diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs
index fd21b367118..35b8b386dce 100644
--- a/library/alloc/src/lib.rs
+++ b/library/alloc/src/lib.rs
@@ -130,6 +130,7 @@
 #![feature(ptr_sub_ptr)]
 #![feature(receiver_trait)]
 #![feature(set_ptr_value)]
+#![feature(slice_from_ptr_range)]
 #![feature(slice_group_by)]
 #![feature(slice_ptr_get)]
 #![feature(slice_ptr_len)]
diff --git a/library/alloc/src/slice.rs b/library/alloc/src/slice.rs
index 199b3c9d029..4a9cecd9b4e 100644
--- a/library/alloc/src/slice.rs
+++ b/library/alloc/src/slice.rs
@@ -114,6 +114,8 @@ pub use core::slice::EscapeAscii;
 pub use core::slice::SliceIndex;
 #[stable(feature = "from_ref", since = "1.28.0")]
 pub use core::slice::{from_mut, from_ref};
+#[unstable(feature = "slice_from_ptr_range", issue = "89792")]
+pub use core::slice::{from_mut_ptr_range, from_ptr_range};
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use core::slice::{from_raw_parts, from_raw_parts_mut};
 #[stable(feature = "rust1", since = "1.0.0")]
diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs
index 0f0692eed49..33cffa643e4 100644
--- a/library/alloc/src/vec/mod.rs
+++ b/library/alloc/src/vec/mod.rs
@@ -2472,7 +2472,7 @@ impl<T: Copy, A: Allocator> ExtendFromWithinSpec for Vec<T, A> {
             // SAFETY:
             // - Both pointers are created from unique slice references (`&mut [_]`)
             //   so they are valid and do not overlap.
-            // - Elements are :Copy so it's OK to to copy them, without doing
+            // - Elements are :Copy so it's OK to copy them, without doing
             //   anything with the original values
             // - `count` is equal to the len of `source`, so source is valid for
             //   `count` reads
@@ -2495,6 +2495,7 @@ impl<T: Copy, A: Allocator> ExtendFromWithinSpec for Vec<T, A> {
 impl<T, A: Allocator> ops::Deref for Vec<T, A> {
     type Target = [T];
 
+    #[inline]
     fn deref(&self) -> &[T] {
         unsafe { slice::from_raw_parts(self.as_ptr(), self.len) }
     }
@@ -2502,6 +2503,7 @@ impl<T, A: Allocator> ops::Deref for Vec<T, A> {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T, A: Allocator> ops::DerefMut for Vec<T, A> {
+    #[inline]
     fn deref_mut(&mut self) -> &mut [T] {
         unsafe { slice::from_raw_parts_mut(self.as_mut_ptr(), self.len) }
     }
diff --git a/library/core/src/slice/raw.rs b/library/core/src/slice/raw.rs
index 6bc60b04b5c..fcafcbeafbc 100644
--- a/library/core/src/slice/raw.rs
+++ b/library/core/src/slice/raw.rs
@@ -213,7 +213,8 @@ pub const fn from_mut<T>(s: &mut T) -> &mut [T] {
 ///
 /// [valid]: ptr#safety
 #[unstable(feature = "slice_from_ptr_range", issue = "89792")]
-pub unsafe fn from_ptr_range<'a, T>(range: Range<*const T>) -> &'a [T] {
+#[rustc_const_unstable(feature = "const_slice_from_ptr_range", issue = "89792")]
+pub const unsafe fn from_ptr_range<'a, T>(range: Range<*const T>) -> &'a [T] {
     // SAFETY: the caller must uphold the safety contract for `from_ptr_range`.
     unsafe { from_raw_parts(range.start, range.end.sub_ptr(range.start)) }
 }
@@ -263,7 +264,8 @@ pub unsafe fn from_ptr_range<'a, T>(range: Range<*const T>) -> &'a [T] {
 ///
 /// [valid]: ptr#safety
 #[unstable(feature = "slice_from_ptr_range", issue = "89792")]
-pub unsafe fn from_mut_ptr_range<'a, T>(range: Range<*mut T>) -> &'a mut [T] {
+#[rustc_const_unstable(feature = "const_slice_from_mut_ptr_range", issue = "89792")]
+pub const unsafe fn from_mut_ptr_range<'a, T>(range: Range<*mut T>) -> &'a mut [T] {
     // SAFETY: the caller must uphold the safety contract for `from_mut_ptr_range`.
     unsafe { from_raw_parts_mut(range.start, range.end.sub_ptr(range.start)) }
 }
diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml
index 95506fc1eb9..229e546e085 100644
--- a/library/std/Cargo.toml
+++ b/library/std/Cargo.toml
@@ -16,7 +16,7 @@ panic_unwind = { path = "../panic_unwind", optional = true }
 panic_abort = { path = "../panic_abort" }
 core = { path = "../core" }
 libc = { version = "0.2.126", default-features = false, features = ['rustc-dep-of-std'] }
-compiler_builtins = { version = "0.1.71" }
+compiler_builtins = { version = "0.1.73" }
 profiler_builtins = { path = "../profiler_builtins", optional = true }
 unwind = { path = "../unwind" }
 hashbrown = { version = "0.12", default-features = false, features = ['rustc-dep-of-std'] }
diff --git a/library/std/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs
index 969f5dde4f0..4ec423eb27f 100644
--- a/library/std/src/collections/hash/map.rs
+++ b/library/std/src/collections/hash/map.rs
@@ -54,7 +54,8 @@ use crate::sys;
 /// the [`Eq`] trait, changes while it is in the map. This is normally only
 /// possible through [`Cell`], [`RefCell`], global state, I/O, or unsafe code.
 /// The behavior resulting from such a logic error is not specified, but will
-/// not result in undefined behavior. This could include panics, incorrect results,
+/// be encapsulated to the `HashMap` that observed the logic error and not
+/// result in undefined behavior. This could include panics, incorrect results,
 /// aborts, memory leaks, and non-termination.
 ///
 /// The hash table implementation is a Rust port of Google's [SwissTable].
diff --git a/library/std/src/collections/hash/set.rs b/library/std/src/collections/hash/set.rs
index 4ac0e081c2e..da0572047ec 100644
--- a/library/std/src/collections/hash/set.rs
+++ b/library/std/src/collections/hash/set.rs
@@ -33,13 +33,14 @@ use super::map::{map_try_reserve_error, RandomState};
 /// In other words, if two keys are equal, their hashes must be equal.
 ///
 ///
-/// It is a logic error for an item to be modified in such a way that the
-/// item's hash, as determined by the [`Hash`] trait, or its equality, as
-/// determined by the [`Eq`] trait, changes while it is in the set. This is
-/// normally only possible through [`Cell`], [`RefCell`], global state, I/O, or
-/// unsafe code. The behavior resulting from such a logic error is not
-/// specified (it could include panics, incorrect results, aborts, memory
-/// leaks, or non-termination) but will not be undefined behavior.
+/// It is a logic error for a key to be modified in such a way that the key's
+/// hash, as determined by the [`Hash`] trait, or its equality, as determined by
+/// the [`Eq`] trait, changes while it is in the map. This is normally only
+/// possible through [`Cell`], [`RefCell`], global state, I/O, or unsafe code.
+/// The behavior resulting from such a logic error is not specified, but will
+/// be encapsulated to the `HashSet` that observed the logic error and not
+/// result in undefined behavior. This could include panics, incorrect results,
+/// aborts, memory leaks, and non-termination.
 ///
 /// # Examples
 ///
diff --git a/src/test/mir-opt/const_prop/const_prop_fails_gracefully.main.ConstProp.diff b/src/test/mir-opt/const_prop/const_prop_fails_gracefully.main.ConstProp.diff
index 466c286c9d7..4fdd4b2b4bb 100644
--- a/src/test/mir-opt/const_prop/const_prop_fails_gracefully.main.ConstProp.diff
+++ b/src/test/mir-opt/const_prop/const_prop_fails_gracefully.main.ConstProp.diff
@@ -21,7 +21,7 @@
                                            // + span: $DIR/const_prop_fails_gracefully.rs:7:13: 7:16
                                            // + literal: Const { ty: &i32, val: Unevaluated(FOO, [], None) }
           _2 = &raw const (*_3);           // scope 0 at $DIR/const_prop_fails_gracefully.rs:7:13: 7:16
-          _1 = move _2 as usize (Misc);    // scope 0 at $DIR/const_prop_fails_gracefully.rs:7:13: 7:39
+          _1 = move _2 as usize (PointerAddress); // scope 0 at $DIR/const_prop_fails_gracefully.rs:7:13: 7:39
           StorageDead(_2);                 // scope 0 at $DIR/const_prop_fails_gracefully.rs:7:38: 7:39
           StorageDead(_3);                 // scope 0 at $DIR/const_prop_fails_gracefully.rs:7:39: 7:40
           StorageLive(_4);                 // scope 1 at $DIR/const_prop_fails_gracefully.rs:8:5: 8:12
diff --git a/src/test/mir-opt/const_prop/reify_fn_ptr.main.ConstProp.diff b/src/test/mir-opt/const_prop/reify_fn_ptr.main.ConstProp.diff
index 1aeeae91d20..7eb34ed5469 100644
--- a/src/test/mir-opt/const_prop/reify_fn_ptr.main.ConstProp.diff
+++ b/src/test/mir-opt/const_prop/reify_fn_ptr.main.ConstProp.diff
@@ -17,7 +17,7 @@
                                            // mir::Constant
                                            // + span: $DIR/reify_fn_ptr.rs:4:13: 4:17
                                            // + literal: Const { ty: fn() {main}, val: Value(Scalar(<ZST>)) }
-          _2 = move _3 as usize (Misc);    // scope 0 at $DIR/reify_fn_ptr.rs:4:13: 4:26
+          _2 = move _3 as usize (PointerAddress); // scope 0 at $DIR/reify_fn_ptr.rs:4:13: 4:26
           StorageDead(_3);                 // scope 0 at $DIR/reify_fn_ptr.rs:4:25: 4:26
           _1 = move _2 as *const fn() (Misc); // scope 0 at $DIR/reify_fn_ptr.rs:4:13: 4:41
           StorageDead(_2);                 // scope 0 at $DIR/reify_fn_ptr.rs:4:40: 4:41
diff --git a/src/test/mir-opt/dead-store-elimination/provenance_soundness.pointer_to_int.DeadStoreElimination.diff b/src/test/mir-opt/dead-store-elimination/provenance_soundness.pointer_to_int.DeadStoreElimination.diff
index 2250159c816..bf32245e300 100644
--- a/src/test/mir-opt/dead-store-elimination/provenance_soundness.pointer_to_int.DeadStoreElimination.diff
+++ b/src/test/mir-opt/dead-store-elimination/provenance_soundness.pointer_to_int.DeadStoreElimination.diff
@@ -19,12 +19,12 @@
           StorageLive(_2);                 // scope 0 at $DIR/provenance_soundness.rs:8:9: 8:11
           StorageLive(_3);                 // scope 0 at $DIR/provenance_soundness.rs:8:14: 8:15
           _3 = _1;                         // scope 0 at $DIR/provenance_soundness.rs:8:14: 8:15
-          _2 = move _3 as usize (Misc);    // scope 0 at $DIR/provenance_soundness.rs:8:14: 8:24
+          _2 = move _3 as usize (PointerAddress); // scope 0 at $DIR/provenance_soundness.rs:8:14: 8:24
           StorageDead(_3);                 // scope 0 at $DIR/provenance_soundness.rs:8:23: 8:24
           StorageLive(_4);                 // scope 1 at $DIR/provenance_soundness.rs:9:9: 9:11
           StorageLive(_5);                 // scope 1 at $DIR/provenance_soundness.rs:9:14: 9:15
           _5 = _1;                         // scope 1 at $DIR/provenance_soundness.rs:9:14: 9:15
-          _4 = move _5 as isize (Misc);    // scope 1 at $DIR/provenance_soundness.rs:9:14: 9:24
+          _4 = move _5 as isize (PointerAddress); // scope 1 at $DIR/provenance_soundness.rs:9:14: 9:24
           StorageDead(_5);                 // scope 1 at $DIR/provenance_soundness.rs:9:23: 9:24
           _0 = const ();                   // scope 0 at $DIR/provenance_soundness.rs:7:32: 10:2
           StorageDead(_4);                 // scope 1 at $DIR/provenance_soundness.rs:10:1: 10:2
diff --git a/src/test/mir-opt/inst_combine_deref.deep_opt.InstCombine.diff b/src/test/mir-opt/inst_combine_deref.deep_opt.InstCombine.diff
deleted file mode 100644
index 1d20e17a849..00000000000
--- a/src/test/mir-opt/inst_combine_deref.deep_opt.InstCombine.diff
+++ /dev/null
@@ -1,92 +0,0 @@
-- // MIR for `deep_opt` before InstCombine
-+ // MIR for `deep_opt` after InstCombine
-  
-  fn deep_opt() -> (u64, u64, u64) {
-      let mut _0: (u64, u64, u64);         // return place in scope 0 at $DIR/inst_combine_deref.rs:11:18: 11:33
-      let _1: u64;                         // in scope 0 at $DIR/inst_combine_deref.rs:12:9: 12:11
-      let mut _10: u64;                    // in scope 0 at $DIR/inst_combine_deref.rs:21:6: 21:8
-      let mut _11: u64;                    // in scope 0 at $DIR/inst_combine_deref.rs:21:10: 21:12
-      let mut _12: u64;                    // in scope 0 at $DIR/inst_combine_deref.rs:21:14: 21:16
-      scope 1 {
-          debug x1 => _1;                  // in scope 1 at $DIR/inst_combine_deref.rs:12:9: 12:11
-          let _2: u64;                     // in scope 1 at $DIR/inst_combine_deref.rs:13:9: 13:11
-          scope 2 {
-              debug x2 => _2;              // in scope 2 at $DIR/inst_combine_deref.rs:13:9: 13:11
-              let _3: u64;                 // in scope 2 at $DIR/inst_combine_deref.rs:14:9: 14:11
-              scope 3 {
-                  debug x3 => _3;          // in scope 3 at $DIR/inst_combine_deref.rs:14:9: 14:11
-                  let _4: &u64;            // in scope 3 at $DIR/inst_combine_deref.rs:15:9: 15:11
-                  scope 4 {
-                      debug y1 => _4;      // in scope 4 at $DIR/inst_combine_deref.rs:15:9: 15:11
-                      let _5: &u64;        // in scope 4 at $DIR/inst_combine_deref.rs:16:9: 16:11
-                      scope 5 {
-                          debug y2 => _5;  // in scope 5 at $DIR/inst_combine_deref.rs:16:9: 16:11
-                          let _6: &u64;    // in scope 5 at $DIR/inst_combine_deref.rs:17:9: 17:11
-                          scope 6 {
-                              debug y3 => _6; // in scope 6 at $DIR/inst_combine_deref.rs:17:9: 17:11
-                              let _7: u64; // in scope 6 at $DIR/inst_combine_deref.rs:18:9: 18:11
-                              scope 7 {
-                                  debug z1 => _7; // in scope 7 at $DIR/inst_combine_deref.rs:18:9: 18:11
-                                  let _8: u64; // in scope 7 at $DIR/inst_combine_deref.rs:19:9: 19:11
-                                  scope 8 {
-                                      debug z2 => _8; // in scope 8 at $DIR/inst_combine_deref.rs:19:9: 19:11
-                                      let _9: u64; // in scope 8 at $DIR/inst_combine_deref.rs:20:9: 20:11
-                                      scope 9 {
-                                          debug z3 => _9; // in scope 9 at $DIR/inst_combine_deref.rs:20:9: 20:11
-                                      }
-                                  }
-                              }
-                          }
-                      }
-                  }
-              }
-          }
-      }
-  
-      bb0: {
-          StorageLive(_1);                 // scope 0 at $DIR/inst_combine_deref.rs:12:9: 12:11
-          _1 = const 1_u64;                // scope 0 at $DIR/inst_combine_deref.rs:12:14: 12:15
-          StorageLive(_2);                 // scope 1 at $DIR/inst_combine_deref.rs:13:9: 13:11
-          _2 = const 2_u64;                // scope 1 at $DIR/inst_combine_deref.rs:13:14: 13:15
-          StorageLive(_3);                 // scope 2 at $DIR/inst_combine_deref.rs:14:9: 14:11
-          _3 = const 3_u64;                // scope 2 at $DIR/inst_combine_deref.rs:14:14: 14:15
-          StorageLive(_4);                 // scope 3 at $DIR/inst_combine_deref.rs:15:9: 15:11
-          _4 = &_1;                        // scope 3 at $DIR/inst_combine_deref.rs:15:14: 15:17
-          StorageLive(_5);                 // scope 4 at $DIR/inst_combine_deref.rs:16:9: 16:11
-          _5 = &_2;                        // scope 4 at $DIR/inst_combine_deref.rs:16:14: 16:17
-          StorageLive(_6);                 // scope 5 at $DIR/inst_combine_deref.rs:17:9: 17:11
-          _6 = &_3;                        // scope 5 at $DIR/inst_combine_deref.rs:17:14: 17:17
-          StorageLive(_7);                 // scope 6 at $DIR/inst_combine_deref.rs:18:9: 18:11
--         _7 = (*_4);                      // scope 6 at $DIR/inst_combine_deref.rs:18:14: 18:17
-+         _7 = _1;                         // scope 6 at $DIR/inst_combine_deref.rs:18:14: 18:17
-          StorageLive(_8);                 // scope 7 at $DIR/inst_combine_deref.rs:19:9: 19:11
--         _8 = (*_5);                      // scope 7 at $DIR/inst_combine_deref.rs:19:14: 19:17
-+         _8 = _2;                         // scope 7 at $DIR/inst_combine_deref.rs:19:14: 19:17
-          StorageLive(_9);                 // scope 8 at $DIR/inst_combine_deref.rs:20:9: 20:11
--         _9 = (*_6);                      // scope 8 at $DIR/inst_combine_deref.rs:20:14: 20:17
-+         _9 = _3;                         // scope 8 at $DIR/inst_combine_deref.rs:20:14: 20:17
-          StorageLive(_10);                // scope 9 at $DIR/inst_combine_deref.rs:21:6: 21:8
-          _10 = _7;                        // scope 9 at $DIR/inst_combine_deref.rs:21:6: 21:8
-          StorageLive(_11);                // scope 9 at $DIR/inst_combine_deref.rs:21:10: 21:12
-          _11 = _8;                        // scope 9 at $DIR/inst_combine_deref.rs:21:10: 21:12
-          StorageLive(_12);                // scope 9 at $DIR/inst_combine_deref.rs:21:14: 21:16
-          _12 = _9;                        // scope 9 at $DIR/inst_combine_deref.rs:21:14: 21:16
-          (_0.0: u64) = move _10;          // scope 9 at $DIR/inst_combine_deref.rs:21:5: 21:17
-          (_0.1: u64) = move _11;          // scope 9 at $DIR/inst_combine_deref.rs:21:5: 21:17
-          (_0.2: u64) = move _12;          // scope 9 at $DIR/inst_combine_deref.rs:21:5: 21:17
-          StorageDead(_12);                // scope 9 at $DIR/inst_combine_deref.rs:21:16: 21:17
-          StorageDead(_11);                // scope 9 at $DIR/inst_combine_deref.rs:21:16: 21:17
-          StorageDead(_10);                // scope 9 at $DIR/inst_combine_deref.rs:21:16: 21:17
-          StorageDead(_9);                 // scope 8 at $DIR/inst_combine_deref.rs:22:1: 22:2
-          StorageDead(_8);                 // scope 7 at $DIR/inst_combine_deref.rs:22:1: 22:2
-          StorageDead(_7);                 // scope 6 at $DIR/inst_combine_deref.rs:22:1: 22:2
-          StorageDead(_6);                 // scope 5 at $DIR/inst_combine_deref.rs:22:1: 22:2
-          StorageDead(_5);                 // scope 4 at $DIR/inst_combine_deref.rs:22:1: 22:2
-          StorageDead(_4);                 // scope 3 at $DIR/inst_combine_deref.rs:22:1: 22:2
-          StorageDead(_3);                 // scope 2 at $DIR/inst_combine_deref.rs:22:1: 22:2
-          StorageDead(_2);                 // scope 1 at $DIR/inst_combine_deref.rs:22:1: 22:2
-          StorageDead(_1);                 // scope 0 at $DIR/inst_combine_deref.rs:22:1: 22:2
-          return;                          // scope 0 at $DIR/inst_combine_deref.rs:22:2: 22:2
-      }
-  }
-  
diff --git a/src/test/mir-opt/inst_combine_deref.do_not_miscompile.InstCombine.diff b/src/test/mir-opt/inst_combine_deref.do_not_miscompile.InstCombine.diff
deleted file mode 100644
index ee8fcdcde40..00000000000
--- a/src/test/mir-opt/inst_combine_deref.do_not_miscompile.InstCombine.diff
+++ /dev/null
@@ -1,85 +0,0 @@
-- // MIR for `do_not_miscompile` before InstCombine
-+ // MIR for `do_not_miscompile` after InstCombine
-  
-  fn do_not_miscompile() -> () {
-      let mut _0: ();                      // return place in scope 0 at $DIR/inst_combine_deref.rs:54:24: 54:24
-      let _1: i32;                         // in scope 0 at $DIR/inst_combine_deref.rs:55:9: 55:10
-      let mut _5: &i32;                    // in scope 0 at $DIR/inst_combine_deref.rs:59:10: 59:12
-      let _6: &i32;                        // in scope 0 at $DIR/inst_combine_deref.rs:59:10: 59:12
-      let _7: ();                          // in scope 0 at $DIR/inst_combine_deref.rs:60:5: 60:23
-      let mut _8: bool;                    // in scope 0 at $DIR/inst_combine_deref.rs:60:5: 60:23
-      let mut _9: bool;                    // in scope 0 at $DIR/inst_combine_deref.rs:60:13: 60:21
-      let mut _10: i32;                    // in scope 0 at $DIR/inst_combine_deref.rs:60:13: 60:15
-      let mut _11: !;                      // in scope 0 at $DIR/inst_combine_deref.rs:60:5: 60:23
-      scope 1 {
-          debug x => _1;                   // in scope 1 at $DIR/inst_combine_deref.rs:55:9: 55:10
-          let _2: i32;                     // in scope 1 at $DIR/inst_combine_deref.rs:56:9: 56:10
-          scope 2 {
-              debug a => _2;               // in scope 2 at $DIR/inst_combine_deref.rs:56:9: 56:10
-              let mut _3: &i32;            // in scope 2 at $DIR/inst_combine_deref.rs:57:9: 57:14
-              scope 3 {
-                  debug y => _3;           // in scope 3 at $DIR/inst_combine_deref.rs:57:9: 57:14
-                  let _4: &mut &i32;       // in scope 3 at $DIR/inst_combine_deref.rs:58:9: 58:10
-                  scope 4 {
-                      debug z => _4;       // in scope 4 at $DIR/inst_combine_deref.rs:58:9: 58:10
-                  }
-              }
-          }
-      }
-  
-      bb0: {
-          StorageLive(_1);                 // scope 0 at $DIR/inst_combine_deref.rs:55:9: 55:10
-          _1 = const 42_i32;               // scope 0 at $DIR/inst_combine_deref.rs:55:13: 55:15
-          StorageLive(_2);                 // scope 1 at $DIR/inst_combine_deref.rs:56:9: 56:10
-          _2 = const 99_i32;               // scope 1 at $DIR/inst_combine_deref.rs:56:13: 56:15
-          StorageLive(_3);                 // scope 2 at $DIR/inst_combine_deref.rs:57:9: 57:14
-          _3 = &_1;                        // scope 2 at $DIR/inst_combine_deref.rs:57:17: 57:19
-          StorageLive(_4);                 // scope 3 at $DIR/inst_combine_deref.rs:58:9: 58:10
-          _4 = &mut _3;                    // scope 3 at $DIR/inst_combine_deref.rs:58:13: 58:19
-          StorageLive(_5);                 // scope 4 at $DIR/inst_combine_deref.rs:59:10: 59:12
-          StorageLive(_6);                 // scope 4 at $DIR/inst_combine_deref.rs:59:10: 59:12
-          _6 = &_2;                        // scope 4 at $DIR/inst_combine_deref.rs:59:10: 59:12
--         _5 = &(*_6);                     // scope 4 at $DIR/inst_combine_deref.rs:59:10: 59:12
-+         _5 = _6;                         // scope 4 at $DIR/inst_combine_deref.rs:59:10: 59:12
-          (*_4) = move _5;                 // scope 4 at $DIR/inst_combine_deref.rs:59:5: 59:12
-          StorageDead(_5);                 // scope 4 at $DIR/inst_combine_deref.rs:59:11: 59:12
-          StorageDead(_6);                 // scope 4 at $DIR/inst_combine_deref.rs:59:12: 59:13
-          StorageLive(_7);                 // scope 4 at $DIR/inst_combine_deref.rs:60:5: 60:23
-          StorageLive(_8);                 // scope 4 at $DIR/inst_combine_deref.rs:60:5: 60:23
-          StorageLive(_9);                 // scope 4 at $DIR/inst_combine_deref.rs:60:13: 60:21
-          StorageLive(_10);                // scope 4 at $DIR/inst_combine_deref.rs:60:13: 60:15
-          _10 = (*_3);                     // scope 4 at $DIR/inst_combine_deref.rs:60:13: 60:15
-          _9 = Eq(move _10, const 99_i32); // scope 4 at $DIR/inst_combine_deref.rs:60:13: 60:21
-          StorageDead(_10);                // scope 4 at $DIR/inst_combine_deref.rs:60:20: 60:21
-          _8 = Not(move _9);               // scope 4 at $DIR/inst_combine_deref.rs:60:5: 60:23
-          StorageDead(_9);                 // scope 4 at $DIR/inst_combine_deref.rs:60:22: 60:23
-          switchInt(move _8) -> [false: bb2, otherwise: bb1]; // scope 4 at $DIR/inst_combine_deref.rs:60:5: 60:23
-      }
-  
-      bb1: {
-          StorageLive(_11);                // scope 4 at $DIR/inst_combine_deref.rs:60:5: 60:23
-          core::panicking::panic(const "assertion failed: *y == 99"); // scope 4 at $DIR/inst_combine_deref.rs:60:5: 60:23
-                                           // mir::Constant
-                                           // + span: $DIR/inst_combine_deref.rs:60:5: 60:23
-                                           // + literal: Const { ty: fn(&'static str) -> ! {core::panicking::panic}, val: Value(Scalar(<ZST>)) }
-                                           // ty::Const
-                                           // + ty: &str
-                                           // + val: Value(Slice { data: Allocation { bytes: [97, 115, 115, 101, 114, 116, 105, 111, 110, 32, 102, 97, 105, 108, 101, 100, 58, 32, 42, 121, 32, 61, 61, 32, 57, 57], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [67108863], len: Size { raw: 26 } }, size: Size { raw: 26 }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 26 })
-                                           // mir::Constant
-                                           // + span: $DIR/inst_combine_deref.rs:1:1: 1:1
-                                           // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [97, 115, 115, 101, 114, 116, 105, 111, 110, 32, 102, 97, 105, 108, 101, 100, 58, 32, 42, 121, 32, 61, 61, 32, 57, 57], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [67108863], len: Size { raw: 26 } }, size: Size { raw: 26 }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 26 }) }
-      }
-  
-      bb2: {
-          _7 = const ();                   // scope 4 at $DIR/inst_combine_deref.rs:60:23: 60:23
-          StorageDead(_8);                 // scope 4 at $DIR/inst_combine_deref.rs:60:22: 60:23
-          StorageDead(_7);                 // scope 4 at $DIR/inst_combine_deref.rs:60:22: 60:23
-          _0 = const ();                   // scope 0 at $DIR/inst_combine_deref.rs:54:24: 61:2
-          StorageDead(_4);                 // scope 3 at $DIR/inst_combine_deref.rs:61:1: 61:2
-          StorageDead(_3);                 // scope 2 at $DIR/inst_combine_deref.rs:61:1: 61:2
-          StorageDead(_2);                 // scope 1 at $DIR/inst_combine_deref.rs:61:1: 61:2
-          StorageDead(_1);                 // scope 0 at $DIR/inst_combine_deref.rs:61:1: 61:2
-          return;                          // scope 0 at $DIR/inst_combine_deref.rs:61:2: 61:2
-      }
-  }
-  
diff --git a/src/test/mir-opt/inst_combine_deref.dont_opt.InstCombine.diff b/src/test/mir-opt/inst_combine_deref.dont_opt.InstCombine.diff
deleted file mode 100644
index 69036491a10..00000000000
--- a/src/test/mir-opt/inst_combine_deref.dont_opt.InstCombine.diff
+++ /dev/null
@@ -1,53 +0,0 @@
-- // MIR for `dont_opt` before InstCombine
-+ // MIR for `dont_opt` after InstCombine
-  
-  fn dont_opt() -> u64 {
-      let mut _0: u64;                     // return place in scope 0 at $DIR/inst_combine_deref.rs:43:18: 43:21
-      let _1: i32;                         // in scope 0 at $DIR/inst_combine_deref.rs:44:9: 44:10
-      let mut _5: &i32;                    // in scope 0 at $DIR/inst_combine_deref.rs:48:10: 48:14
-      scope 1 {
-          debug y => _1;                   // in scope 1 at $DIR/inst_combine_deref.rs:44:9: 44:10
-          let _2: &i32;                    // in scope 1 at $DIR/inst_combine_deref.rs:45:9: 45:13
-          scope 2 {
-              debug _ref => _2;            // in scope 2 at $DIR/inst_combine_deref.rs:45:9: 45:13
-              let _3: i32;                 // in scope 2 at $DIR/inst_combine_deref.rs:46:9: 46:10
-              scope 3 {
-                  debug x => _3;           // in scope 3 at $DIR/inst_combine_deref.rs:46:9: 46:10
-                  let mut _4: &i32;        // in scope 3 at $DIR/inst_combine_deref.rs:47:9: 47:15
-                  scope 4 {
-                      debug _1 => _4;      // in scope 4 at $DIR/inst_combine_deref.rs:47:9: 47:15
-                      let _6: i32;         // in scope 4 at $DIR/inst_combine_deref.rs:49:9: 49:11
-                      scope 5 {
-                          debug _4 => _6;  // in scope 5 at $DIR/inst_combine_deref.rs:49:9: 49:11
-                      }
-                  }
-              }
-          }
-      }
-  
-      bb0: {
-          StorageLive(_1);                 // scope 0 at $DIR/inst_combine_deref.rs:44:9: 44:10
-          _1 = const 5_i32;                // scope 0 at $DIR/inst_combine_deref.rs:44:13: 44:14
-          StorageLive(_2);                 // scope 1 at $DIR/inst_combine_deref.rs:45:9: 45:13
-          _2 = &_1;                        // scope 1 at $DIR/inst_combine_deref.rs:45:16: 45:18
-          StorageLive(_3);                 // scope 2 at $DIR/inst_combine_deref.rs:46:9: 46:10
-          _3 = const 5_i32;                // scope 2 at $DIR/inst_combine_deref.rs:46:13: 46:14
-          StorageLive(_4);                 // scope 3 at $DIR/inst_combine_deref.rs:47:9: 47:15
-          _4 = &_3;                        // scope 3 at $DIR/inst_combine_deref.rs:47:18: 47:20
-          StorageLive(_5);                 // scope 4 at $DIR/inst_combine_deref.rs:48:10: 48:14
--         _5 = &(*_2);                     // scope 4 at $DIR/inst_combine_deref.rs:48:10: 48:14
-+         _5 = _2;                         // scope 4 at $DIR/inst_combine_deref.rs:48:10: 48:14
-          _4 = move _5;                    // scope 4 at $DIR/inst_combine_deref.rs:48:5: 48:14
-          StorageDead(_5);                 // scope 4 at $DIR/inst_combine_deref.rs:48:13: 48:14
-          StorageLive(_6);                 // scope 4 at $DIR/inst_combine_deref.rs:49:9: 49:11
-          _6 = (*_4);                      // scope 4 at $DIR/inst_combine_deref.rs:49:14: 49:17
-          _0 = const 0_u64;                // scope 5 at $DIR/inst_combine_deref.rs:50:5: 50:6
-          StorageDead(_6);                 // scope 4 at $DIR/inst_combine_deref.rs:51:1: 51:2
-          StorageDead(_4);                 // scope 3 at $DIR/inst_combine_deref.rs:51:1: 51:2
-          StorageDead(_3);                 // scope 2 at $DIR/inst_combine_deref.rs:51:1: 51:2
-          StorageDead(_2);                 // scope 1 at $DIR/inst_combine_deref.rs:51:1: 51:2
-          StorageDead(_1);                 // scope 0 at $DIR/inst_combine_deref.rs:51:1: 51:2
-          return;                          // scope 0 at $DIR/inst_combine_deref.rs:51:2: 51:2
-      }
-  }
-  
diff --git a/src/test/mir-opt/inst_combine_deref.opt_struct.InstCombine.diff b/src/test/mir-opt/inst_combine_deref.opt_struct.InstCombine.diff
deleted file mode 100644
index c867543d05e..00000000000
--- a/src/test/mir-opt/inst_combine_deref.opt_struct.InstCombine.diff
+++ /dev/null
@@ -1,44 +0,0 @@
-- // MIR for `opt_struct` before InstCombine
-+ // MIR for `opt_struct` after InstCombine
-  
-  fn opt_struct(_1: S) -> u64 {
-      debug s => _1;                       // in scope 0 at $DIR/inst_combine_deref.rs:30:15: 30:16
-      let mut _0: u64;                     // return place in scope 0 at $DIR/inst_combine_deref.rs:30:24: 30:27
-      let _2: &u64;                        // in scope 0 at $DIR/inst_combine_deref.rs:31:9: 31:10
-      let mut _5: u64;                     // in scope 0 at $DIR/inst_combine_deref.rs:34:5: 34:7
-      let mut _6: u64;                     // in scope 0 at $DIR/inst_combine_deref.rs:34:10: 34:11
-      scope 1 {
-          debug a => _2;                   // in scope 1 at $DIR/inst_combine_deref.rs:31:9: 31:10
-          let _3: &u64;                    // in scope 1 at $DIR/inst_combine_deref.rs:32:9: 32:10
-          scope 2 {
-              debug b => _3;               // in scope 2 at $DIR/inst_combine_deref.rs:32:9: 32:10
-              let _4: u64;                 // in scope 2 at $DIR/inst_combine_deref.rs:33:9: 33:10
-              scope 3 {
-                  debug x => _4;           // in scope 3 at $DIR/inst_combine_deref.rs:33:9: 33:10
-              }
-          }
-      }
-  
-      bb0: {
-          StorageLive(_2);                 // scope 0 at $DIR/inst_combine_deref.rs:31:9: 31:10
-          _2 = &(_1.0: u64);               // scope 0 at $DIR/inst_combine_deref.rs:31:13: 31:17
-          StorageLive(_3);                 // scope 1 at $DIR/inst_combine_deref.rs:32:9: 32:10
-          _3 = &(_1.1: u64);               // scope 1 at $DIR/inst_combine_deref.rs:32:13: 32:17
-          StorageLive(_4);                 // scope 2 at $DIR/inst_combine_deref.rs:33:9: 33:10
--         _4 = (*_2);                      // scope 2 at $DIR/inst_combine_deref.rs:33:13: 33:15
-+         _4 = (_1.0: u64);                // scope 2 at $DIR/inst_combine_deref.rs:33:13: 33:15
-          StorageLive(_5);                 // scope 3 at $DIR/inst_combine_deref.rs:34:5: 34:7
--         _5 = (*_3);                      // scope 3 at $DIR/inst_combine_deref.rs:34:5: 34:7
-+         _5 = (_1.1: u64);                // scope 3 at $DIR/inst_combine_deref.rs:34:5: 34:7
-          StorageLive(_6);                 // scope 3 at $DIR/inst_combine_deref.rs:34:10: 34:11
-          _6 = _4;                         // scope 3 at $DIR/inst_combine_deref.rs:34:10: 34:11
-          _0 = Add(move _5, move _6);      // scope 3 at $DIR/inst_combine_deref.rs:34:5: 34:11
-          StorageDead(_6);                 // scope 3 at $DIR/inst_combine_deref.rs:34:10: 34:11
-          StorageDead(_5);                 // scope 3 at $DIR/inst_combine_deref.rs:34:10: 34:11
-          StorageDead(_4);                 // scope 2 at $DIR/inst_combine_deref.rs:35:1: 35:2
-          StorageDead(_3);                 // scope 1 at $DIR/inst_combine_deref.rs:35:1: 35:2
-          StorageDead(_2);                 // scope 0 at $DIR/inst_combine_deref.rs:35:1: 35:2
-          return;                          // scope 0 at $DIR/inst_combine_deref.rs:35:2: 35:2
-      }
-  }
-  
diff --git a/src/test/mir-opt/inst_combine_deref.simple_opt.InstCombine.diff b/src/test/mir-opt/inst_combine_deref.simple_opt.InstCombine.diff
deleted file mode 100644
index f52dfe379ca..00000000000
--- a/src/test/mir-opt/inst_combine_deref.simple_opt.InstCombine.diff
+++ /dev/null
@@ -1,34 +0,0 @@
-- // MIR for `simple_opt` before InstCombine
-+ // MIR for `simple_opt` after InstCombine
-  
-  fn simple_opt() -> u64 {
-      let mut _0: u64;                     // return place in scope 0 at $DIR/inst_combine_deref.rs:3:20: 3:23
-      let _1: u64;                         // in scope 0 at $DIR/inst_combine_deref.rs:4:9: 4:10
-      scope 1 {
-          debug x => _1;                   // in scope 1 at $DIR/inst_combine_deref.rs:4:9: 4:10
-          let _2: &u64;                    // in scope 1 at $DIR/inst_combine_deref.rs:5:9: 5:10
-          scope 2 {
-              debug y => _2;               // in scope 2 at $DIR/inst_combine_deref.rs:5:9: 5:10
-              let _3: u64;                 // in scope 2 at $DIR/inst_combine_deref.rs:6:9: 6:10
-              scope 3 {
-                  debug z => _3;           // in scope 3 at $DIR/inst_combine_deref.rs:6:9: 6:10
-              }
-          }
-      }
-  
-      bb0: {
-          StorageLive(_1);                 // scope 0 at $DIR/inst_combine_deref.rs:4:9: 4:10
-          _1 = const 5_u64;                // scope 0 at $DIR/inst_combine_deref.rs:4:13: 4:14
-          StorageLive(_2);                 // scope 1 at $DIR/inst_combine_deref.rs:5:9: 5:10
-          _2 = &_1;                        // scope 1 at $DIR/inst_combine_deref.rs:5:13: 5:15
-          StorageLive(_3);                 // scope 2 at $DIR/inst_combine_deref.rs:6:9: 6:10
--         _3 = (*_2);                      // scope 2 at $DIR/inst_combine_deref.rs:6:13: 6:15
-+         _3 = _1;                         // scope 2 at $DIR/inst_combine_deref.rs:6:13: 6:15
-          _0 = _3;                         // scope 3 at $DIR/inst_combine_deref.rs:7:5: 7:6
-          StorageDead(_3);                 // scope 2 at $DIR/inst_combine_deref.rs:8:1: 8:2
-          StorageDead(_2);                 // scope 1 at $DIR/inst_combine_deref.rs:8:1: 8:2
-          StorageDead(_1);                 // scope 0 at $DIR/inst_combine_deref.rs:8:1: 8:2
-          return;                          // scope 0 at $DIR/inst_combine_deref.rs:8:2: 8:2
-      }
-  }
-  
diff --git a/src/test/mir-opt/tls-access.rs b/src/test/mir-opt/tls-access.rs
index 9036c57556d..19344c86862 100644
--- a/src/test/mir-opt/tls-access.rs
+++ b/src/test/mir-opt/tls-access.rs
@@ -1,3 +1,6 @@
+// EMIT_MIR tls_access.main.PreCodegen.after.mir
+// compile-flags: -Zmir-opt-level=0
+
 #![feature(thread_local)]
 
 #[thread_local]
@@ -9,6 +12,3 @@ fn main() {
         FOO = 42;
     }
 }
-
-// EMIT_MIR tls_access.main.SimplifyCfg-final.after.mir
-// compile-flags: -Zmir-opt-level=0
diff --git a/src/test/mir-opt/tls_access.main.SimplifyCfg-final.after.mir b/src/test/mir-opt/tls_access.main.PreCodegen.after.mir
index de19a226e8f..baa77497e38 100644
--- a/src/test/mir-opt/tls_access.main.SimplifyCfg-final.after.mir
+++ b/src/test/mir-opt/tls_access.main.PreCodegen.after.mir
@@ -1,25 +1,28 @@
-// MIR for `main` after SimplifyCfg-final
+// MIR for `main` after PreCodegen
 
 fn main() -> () {
-    let mut _0: ();                      // return place in scope 0 at $DIR/tls-access.rs:6:11: 6:11
-    let _2: *mut u8;                     // in scope 0 at $DIR/tls-access.rs:8:18: 8:21
-    let mut _3: *mut u8;                 // in scope 0 at $DIR/tls-access.rs:9:9: 9:12
+    let mut _0: ();                      // return place in scope 0 at $DIR/tls-access.rs:9:11: 9:11
+    let _2: *mut u8;                     // in scope 0 at $DIR/tls-access.rs:11:18: 11:21
+    let mut _3: *mut u8;                 // in scope 0 at $DIR/tls-access.rs:12:9: 12:12
     scope 1 {
-        let _1: &u8;                     // in scope 1 at $DIR/tls-access.rs:8:13: 8:14
+        let _1: &u8;                     // in scope 1 at $DIR/tls-access.rs:11:13: 11:14
         scope 2 {
-            debug a => _1;               // in scope 2 at $DIR/tls-access.rs:8:13: 8:14
+            debug a => _1;               // in scope 2 at $DIR/tls-access.rs:11:13: 11:14
         }
     }
 
     bb0: {
-        StorageLive(_1);                 // scope 1 at $DIR/tls-access.rs:8:13: 8:14
-        StorageLive(_2);                 // scope 1 at $DIR/tls-access.rs:8:18: 8:21
-        StorageLive(_3);                 // scope 2 at $DIR/tls-access.rs:9:9: 9:12
-        _3 = &/*tls*/ mut FOO;           // scope 2 at $DIR/tls-access.rs:9:9: 9:12
-        (*_3) = const 42_u8;             // scope 2 at $DIR/tls-access.rs:9:9: 9:17
-        StorageDead(_3);                 // scope 2 at $DIR/tls-access.rs:9:17: 9:18
-        StorageDead(_2);                 // scope 1 at $DIR/tls-access.rs:10:5: 10:6
-        StorageDead(_1);                 // scope 1 at $DIR/tls-access.rs:10:5: 10:6
-        return;                          // scope 0 at $DIR/tls-access.rs:11:2: 11:2
+        StorageLive(_1);                 // scope 1 at $DIR/tls-access.rs:11:13: 11:14
+        StorageLive(_2);                 // scope 1 at $DIR/tls-access.rs:11:18: 11:21
+        _2 = &/*tls*/ mut FOO;           // scope 1 at $DIR/tls-access.rs:11:18: 11:21
+        _1 = &(*_2);                     // scope 1 at $DIR/tls-access.rs:11:17: 11:21
+        StorageLive(_3);                 // scope 2 at $DIR/tls-access.rs:12:9: 12:12
+        _3 = &/*tls*/ mut FOO;           // scope 2 at $DIR/tls-access.rs:12:9: 12:12
+        (*_3) = const 42_u8;             // scope 2 at $DIR/tls-access.rs:12:9: 12:17
+        StorageDead(_3);                 // scope 2 at $DIR/tls-access.rs:12:17: 12:18
+        _0 = const ();                   // scope 1 at $DIR/tls-access.rs:10:5: 13:6
+        StorageDead(_2);                 // scope 1 at $DIR/tls-access.rs:13:5: 13:6
+        StorageDead(_1);                 // scope 1 at $DIR/tls-access.rs:13:5: 13:6
+        return;                          // scope 0 at $DIR/tls-access.rs:14:2: 14:2
     }
 }
diff --git a/src/test/rustdoc-ui/intra-doc/unresolved-import-recovery.stderr b/src/test/rustdoc-ui/intra-doc/unresolved-import-recovery.stderr
index b60ab6050d7..b54f8200666 100644
--- a/src/test/rustdoc-ui/intra-doc/unresolved-import-recovery.stderr
+++ b/src/test/rustdoc-ui/intra-doc/unresolved-import-recovery.stderr
@@ -3,6 +3,8 @@ error[E0433]: failed to resolve: maybe a missing crate `unresolved_crate`?
    |
 LL | use unresolved_crate::module::Name;
    |     ^^^^^^^^^^^^^^^^ maybe a missing crate `unresolved_crate`?
+   |
+   = help: consider adding `extern crate unresolved_crate` to use the `unresolved_crate` crate
 
 error: Compilation failed, aborting rustdoc
 
diff --git a/src/test/rustdoc-ui/issue-61732.stderr b/src/test/rustdoc-ui/issue-61732.stderr
index 82134224911..38fadaa4435 100644
--- a/src/test/rustdoc-ui/issue-61732.stderr
+++ b/src/test/rustdoc-ui/issue-61732.stderr
@@ -3,6 +3,8 @@ error[E0433]: failed to resolve: maybe a missing crate `r#mod`?
    |
 LL | pub(in crate::r#mod) fn main() {}
    |               ^^^^^ maybe a missing crate `r#mod`?
+   |
+   = help: consider adding `extern crate r#mod` to use the `r#mod` crate
 
 error: Compilation failed, aborting rustdoc
 
diff --git a/src/test/ui/attributes/field-attributes-vis-unresolved.stderr b/src/test/ui/attributes/field-attributes-vis-unresolved.stderr
index 41c3cea3021..43976254638 100644
--- a/src/test/ui/attributes/field-attributes-vis-unresolved.stderr
+++ b/src/test/ui/attributes/field-attributes-vis-unresolved.stderr
@@ -3,12 +3,16 @@ error[E0433]: failed to resolve: maybe a missing crate `nonexistent`?
    |
 LL |     pub(in nonexistent) field: u8
    |            ^^^^^^^^^^^ maybe a missing crate `nonexistent`?
+   |
+   = help: consider adding `extern crate nonexistent` to use the `nonexistent` crate
 
 error[E0433]: failed to resolve: maybe a missing crate `nonexistent`?
   --> $DIR/field-attributes-vis-unresolved.rs:22:12
    |
 LL |     pub(in nonexistent) u8
    |            ^^^^^^^^^^^ maybe a missing crate `nonexistent`?
+   |
+   = help: consider adding `extern crate nonexistent` to use the `nonexistent` crate
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/const-ptr/allowed_slices.rs b/src/test/ui/const-ptr/allowed_slices.rs
new file mode 100644
index 00000000000..645283d8fe5
--- /dev/null
+++ b/src/test/ui/const-ptr/allowed_slices.rs
@@ -0,0 +1,106 @@
+// run-pass
+#![feature(
+    const_slice_from_raw_parts,
+    slice_from_ptr_range,
+    const_slice_from_ptr_range,
+    pointer_byte_offsets,
+    const_pointer_byte_offsets
+)]
+use std::{
+    mem::MaybeUninit,
+    ptr,
+    slice::{from_ptr_range, from_raw_parts},
+};
+
+// Dangling is ok, as long as it's either for ZST reads or for no reads
+pub static S0: &[u32] = unsafe { from_raw_parts(dangling(), 0) };
+pub static S1: &[()] = unsafe { from_raw_parts(dangling(), 3) };
+
+// References are always valid of reads of a single element (basically `slice::from_ref`)
+pub static S2: &[u32] = unsafe { from_raw_parts(&D0, 1) };
+pub static S3: &[MaybeUninit<&u32>] = unsafe { from_raw_parts(&D1, 1) };
+
+// Reinterpreting data is fine, as long as layouts match
+pub static S4: &[u8] = unsafe { from_raw_parts((&D0) as *const _ as _, 3) };
+// This is only valid because D1 has uninitialized bytes, if it was an initialized pointer,
+// that would reinterpret pointers as integers which is UB in CTFE.
+pub static S5: &[MaybeUninit<u8>] = unsafe { from_raw_parts((&D1) as *const _ as _, 2) };
+// Even though u32 and [bool; 4] have different layouts, D0 has a value that
+// is valid as [bool; 4], so this is not UB (it's basically a transmute)
+pub static S6: &[bool] = unsafe { from_raw_parts((&D0) as *const _ as _, 4) };
+
+// Structs are considered single allocated objects,
+// as long as you don't reinterpret padding as initialized
+// data everything is ok.
+pub static S7: &[u16] = unsafe {
+    let ptr = (&D2 as *const Struct as *const u16).byte_add(4);
+
+    from_raw_parts(ptr, 3)
+};
+pub static S8: &[MaybeUninit<u16>] = unsafe {
+    let ptr = &D2 as *const Struct as *const MaybeUninit<u16>;
+
+    from_raw_parts(ptr, 6)
+};
+
+pub static R0: &[u32] = unsafe { from_ptr_range(dangling()..dangling()) };
+// from_ptr_range panics on zst
+//pub static R1: &[()] = unsafe { from_ptr_range(dangling(), dangling().byte_add(3)) };
+pub static R2: &[u32] = unsafe {
+    let ptr = &D0 as *const u32;
+    from_ptr_range(ptr..ptr.add(1))
+};
+pub static R3: &[MaybeUninit<&u32>] = unsafe {
+    let ptr = &D1 as *const MaybeUninit<&u32>;
+    from_ptr_range(ptr..ptr.add(1))
+};
+pub static R4: &[u8] = unsafe {
+    let ptr = &D0 as *const u32 as *const u8;
+    from_ptr_range(ptr..ptr.add(3))
+};
+pub static R5: &[MaybeUninit<u8>] = unsafe {
+    let ptr = &D1 as *const MaybeUninit<&u32> as *const MaybeUninit<u8>;
+    from_ptr_range(ptr..ptr.add(2))
+};
+pub static R6: &[bool] = unsafe {
+    let ptr = &D0 as *const u32 as *const bool;
+    from_ptr_range(ptr..ptr.add(4))
+};
+pub static R7: &[u16] = unsafe {
+    let d2 = &D2;
+    let l = &d2.b as *const u32 as *const u16;
+    let r = &d2.d as *const u8 as *const u16;
+
+    from_ptr_range(l..r)
+};
+pub static R8: &[MaybeUninit<u16>] = unsafe {
+    let d2 = &D2;
+    let l = d2 as *const Struct as *const MaybeUninit<u16>;
+    let r = &d2.d as *const u8 as *const MaybeUninit<u16>;
+
+    from_ptr_range(l..r)
+};
+
+// Using valid slice is always valid
+pub static R9: &[u32] = unsafe { from_ptr_range(R0.as_ptr_range()) };
+pub static R10: &[u32] = unsafe { from_ptr_range(R2.as_ptr_range()) };
+
+const D0: u32 = (1 << 16) | 1;
+const D1: MaybeUninit<&u32> = MaybeUninit::uninit();
+const D2: Struct = Struct { a: 1, b: 2, c: 3, d: 4 };
+
+const fn dangling<T>() -> *const T {
+    ptr::NonNull::dangling().as_ptr() as _
+}
+
+#[repr(C)]
+struct Struct {
+    a: u8,
+    // _pad: [MaybeUninit<u8>; 3]
+    b: u32,
+    c: u16,
+    d: u8,
+    // _pad: [MaybeUninit<u8>; 1]
+}
+
+fn main() {}
diff --git a/src/test/ui/const-ptr/forbidden_slices.32bit.stderr b/src/test/ui/const-ptr/forbidden_slices.32bit.stderr
new file mode 100644
index 00000000000..5b0b9aa9666
--- /dev/null
+++ b/src/test/ui/const-ptr/forbidden_slices.32bit.stderr
@@ -0,0 +1,280 @@
+error[E0080]: could not evaluate static initializer
+  --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
+   |
+LL |         &*ptr::slice_from_raw_parts(data, len)
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |         |
+   |         dereferencing pointer failed: null pointer is not a valid pointer
+   |         inside `std::slice::from_raw_parts::<u32>` at $SRC_DIR/core/src/slice/raw.rs:LL:COL
+   |
+  ::: $DIR/forbidden_slices.rs:19:34
+   |
+LL | pub static S0: &[u32] = unsafe { from_raw_parts(ptr::null(), 0) };
+   |                                  ------------------------------ inside `S0` at $DIR/forbidden_slices.rs:19:34
+
+error[E0080]: could not evaluate static initializer
+  --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
+   |
+LL |         &*ptr::slice_from_raw_parts(data, len)
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |         |
+   |         dereferencing pointer failed: null pointer is not a valid pointer
+   |         inside `std::slice::from_raw_parts::<()>` at $SRC_DIR/core/src/slice/raw.rs:LL:COL
+   |
+  ::: $DIR/forbidden_slices.rs:20:33
+   |
+LL | pub static S1: &[()] = unsafe { from_raw_parts(ptr::null(), 0) };
+   |                                 ------------------------------ inside `S1` at $DIR/forbidden_slices.rs:20:33
+
+error[E0080]: could not evaluate static initializer
+  --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
+   |
+LL |         &*ptr::slice_from_raw_parts(data, len)
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |         |
+   |         dereferencing pointer failed: ALLOC_ID has size 4, so pointer to 8 bytes starting at offset 0 is out-of-bounds
+   |         inside `std::slice::from_raw_parts::<u32>` at $SRC_DIR/core/src/slice/raw.rs:LL:COL
+   |
+  ::: $DIR/forbidden_slices.rs:23:34
+   |
+LL | pub static S2: &[u32] = unsafe { from_raw_parts(&D0, 2) };
+   |                                  ---------------------- inside `S2` at $DIR/forbidden_slices.rs:23:34
+
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/forbidden_slices.rs:26:1
+   |
+LL | pub static S4: &[u8] = unsafe { from_raw_parts((&D1) as *const _ as _, 1) };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .<deref>[0]: encountered uninitialized bytes
+   |
+   = 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.
+   = note: the raw bytes of the constant (size: 8, align: 4) {
+               ╾─ALLOC_ID─╼ 01 00 00 00                         │ ╾──╼....
+           }
+
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/forbidden_slices.rs:28:1
+   |
+LL | pub static S5: &[u8] = unsafe { from_raw_parts((&D3) as *const _ as _, size_of::<&u32>()) };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .<deref>: encountered a pointer, but expected plain (non-pointer) bytes
+   |
+   = 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.
+   = note: the raw bytes of the constant (size: 8, align: 4) {
+               ╾─ALLOC_ID─╼ 04 00 00 00                         │ ╾──╼....
+           }
+
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/forbidden_slices.rs:30:1
+   |
+LL | pub static S6: &[bool] = unsafe { from_raw_parts((&D0) as *const _ as _, 4) };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .<deref>[0]: encountered 0x11, but expected a boolean
+   |
+   = 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.
+   = note: the raw bytes of the constant (size: 8, align: 4) {
+               ╾─ALLOC_ID─╼ 04 00 00 00                         │ ╾──╼....
+           }
+
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/forbidden_slices.rs:33:1
+   |
+LL | / pub static S7: &[u16] = unsafe {
+LL | |
+LL | |     let ptr = (&D2 as *const Struct as *const u16).byte_add(1);
+LL | |
+LL | |     from_raw_parts(ptr, 4)
+LL | | };
+   | |__^ type validation failed: encountered an unaligned reference (required 2 byte alignment but found 1)
+   |
+   = 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.
+   = note: the raw bytes of the constant (size: 8, align: 4) {
+               ╾─A_ID+0x1─╼ 04 00 00 00                         │ ╾──╼....
+           }
+
+error[E0080]: could not evaluate static initializer
+  --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
+   |
+LL |         &*ptr::slice_from_raw_parts(data, len)
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |         |
+   |         dereferencing pointer failed: ALLOC_ID has size 8, so pointer to 8 bytes starting at offset 1 is out-of-bounds
+   |         inside `std::slice::from_raw_parts::<u64>` at $SRC_DIR/core/src/slice/raw.rs:LL:COL
+   |
+  ::: $DIR/forbidden_slices.rs:44:5
+   |
+LL |     from_raw_parts(ptr, 1)
+   |     ---------------------- inside `S8` at $DIR/forbidden_slices.rs:44:5
+
+error[E0080]: could not evaluate static initializer
+  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+   |
+LL |         unsafe { intrinsics::ptr_offset_from_unsigned(self, origin) }
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                  |
+   |                  out-of-bounds offset_from: null pointer is not a valid pointer
+   |                  inside `ptr::const_ptr::<impl *const u32>::sub_ptr` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+   |
+  ::: $SRC_DIR/core/src/slice/raw.rs:LL:COL
+   |
+LL |     unsafe { from_raw_parts(range.start, range.end.sub_ptr(range.start)) }
+   |                                          ------------------------------ inside `from_ptr_range::<u32>` at $SRC_DIR/core/src/slice/raw.rs:LL:COL
+   |
+  ::: $DIR/forbidden_slices.rs:47:34
+   |
+LL | pub static R0: &[u32] = unsafe { from_ptr_range(ptr::null()..ptr::null()) };
+   |                                  ---------------------------------------- inside `R0` at $DIR/forbidden_slices.rs:47:34
+
+error[E0080]: could not evaluate static initializer
+  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+   |
+LL |         assert!(0 < pointee_size && pointee_size <= isize::MAX as usize);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |         |
+   |         the evaluated program panicked at 'assertion failed: 0 < pointee_size && pointee_size <= isize::MAX as usize', $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+   |         inside `ptr::const_ptr::<impl *const ()>::sub_ptr` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+   |
+  ::: $SRC_DIR/core/src/slice/raw.rs:LL:COL
+   |
+LL |     unsafe { from_raw_parts(range.start, range.end.sub_ptr(range.start)) }
+   |                                          ------------------------------ inside `from_ptr_range::<()>` at $SRC_DIR/core/src/slice/raw.rs:LL:COL
+   |
+  ::: $DIR/forbidden_slices.rs:48:33
+   |
+LL | pub static R1: &[()] = unsafe { from_ptr_range(ptr::null()..ptr::null()) };
+   |                                 ---------------------------------------- inside `R1` at $DIR/forbidden_slices.rs:48:33
+   |
+   = note: this error originates in the macro `assert` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0080]: could not evaluate static initializer
+  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+   |
+LL |         unsafe { intrinsics::offset(self, count) }
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                  |
+   |                  pointer arithmetic failed: ALLOC_ID has size 4, so pointer to 8 bytes starting at offset 0 is out-of-bounds
+   |                  inside `ptr::const_ptr::<impl *const u32>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+...
+LL |         unsafe { self.offset(count as isize) }
+   |                  --------------------------- inside `ptr::const_ptr::<impl *const u32>::add` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+   |
+  ::: $DIR/forbidden_slices.rs:51:25
+   |
+LL |     from_ptr_range(ptr..ptr.add(2))
+   |                         ---------- inside `R2` at $DIR/forbidden_slices.rs:51:25
+
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/forbidden_slices.rs:53:1
+   |
+LL | / pub static R4: &[u8] = unsafe {
+LL | |
+LL | |     let ptr = (&D1) as *const MaybeUninit<&u32> as *const u8;
+LL | |     from_ptr_range(ptr..ptr.add(1))
+LL | | };
+   | |__^ type validation failed at .<deref>[0]: encountered uninitialized bytes
+   |
+   = 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.
+   = note: the raw bytes of the constant (size: 8, align: 4) {
+               ╾ALLOC_ID─╼ 01 00 00 00                         │ ╾──╼....
+           }
+
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/forbidden_slices.rs:58:1
+   |
+LL | / pub static R5: &[u8] = unsafe {
+LL | |
+LL | |     let ptr = &D3 as *const &u32;
+LL | |     from_ptr_range(ptr.cast()..ptr.add(1).cast())
+LL | | };
+   | |__^ type validation failed at .<deref>: encountered a pointer, but expected plain (non-pointer) bytes
+   |
+   = 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.
+   = note: the raw bytes of the constant (size: 8, align: 4) {
+               ╾ALLOC_ID─╼ 04 00 00 00                         │ ╾──╼....
+           }
+
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/forbidden_slices.rs:63:1
+   |
+LL | / pub static R6: &[bool] = unsafe {
+LL | |
+LL | |     let ptr = &D0 as *const u32 as *const bool;
+LL | |     from_ptr_range(ptr..ptr.add(4))
+LL | | };
+   | |__^ type validation failed at .<deref>[0]: encountered 0x11, but expected a boolean
+   |
+   = 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.
+   = note: the raw bytes of the constant (size: 8, align: 4) {
+               ╾ALLOC_ID─╼ 04 00 00 00                         │ ╾──╼....
+           }
+
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/forbidden_slices.rs:68:1
+   |
+LL | / pub static R7: &[u16] = unsafe {
+LL | |
+LL | |     let ptr = (&D2 as *const Struct as *const u16).byte_add(1);
+LL | |     from_ptr_range(ptr..ptr.add(4))
+LL | | };
+   | |__^ type validation failed: encountered an unaligned reference (required 2 byte alignment but found 1)
+   |
+   = 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.
+   = note: the raw bytes of the constant (size: 8, align: 4) {
+               ╾A_ID+0x1─╼ 04 00 00 00                         │ ╾──╼....
+           }
+
+error[E0080]: could not evaluate static initializer
+  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+   |
+LL |         unsafe { intrinsics::offset(self, count) }
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                  |
+   |                  pointer arithmetic failed: ALLOC_ID has size 8, so pointer to 8 bytes starting at offset 1 is out-of-bounds
+   |                  inside `ptr::const_ptr::<impl *const u64>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+...
+LL |         unsafe { self.offset(count as isize) }
+   |                  --------------------------- inside `ptr::const_ptr::<impl *const u64>::add` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+   |
+  ::: $DIR/forbidden_slices.rs:75:25
+   |
+LL |     from_ptr_range(ptr..ptr.add(1))
+   |                         ---------- inside `R8` at $DIR/forbidden_slices.rs:75:25
+
+error[E0080]: could not evaluate static initializer
+  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+   |
+LL |         unsafe { intrinsics::ptr_offset_from_unsigned(self, origin) }
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                  |
+   |                  ptr_offset_from_unsigned cannot compute offset of pointers into different allocations.
+   |                  inside `ptr::const_ptr::<impl *const u32>::sub_ptr` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+   |
+  ::: $SRC_DIR/core/src/slice/raw.rs:LL:COL
+   |
+LL |     unsafe { from_raw_parts(range.start, range.end.sub_ptr(range.start)) }
+   |                                          ------------------------------ inside `from_ptr_range::<u32>` at $SRC_DIR/core/src/slice/raw.rs:LL:COL
+   |
+  ::: $DIR/forbidden_slices.rs:80:34
+   |
+LL | pub static R9: &[u32] = unsafe { from_ptr_range(&D0..(&D0 as *const u32).add(1)) };
+   |                                  ----------------------------------------------- inside `R9` at $DIR/forbidden_slices.rs:80:34
+
+error[E0080]: could not evaluate static initializer
+  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+   |
+LL |         unsafe { intrinsics::ptr_offset_from_unsigned(self, origin) }
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                  |
+   |                  ptr_offset_from_unsigned cannot compute offset of pointers into different allocations.
+   |                  inside `ptr::const_ptr::<impl *const u32>::sub_ptr` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+   |
+  ::: $SRC_DIR/core/src/slice/raw.rs:LL:COL
+   |
+LL |     unsafe { from_raw_parts(range.start, range.end.sub_ptr(range.start)) }
+   |                                          ------------------------------ inside `from_ptr_range::<u32>` at $SRC_DIR/core/src/slice/raw.rs:LL:COL
+   |
+  ::: $DIR/forbidden_slices.rs:81:35
+   |
+LL | pub static R10: &[u32] = unsafe { from_ptr_range(&D0..&D0) };
+   |                                   ------------------------ inside `R10` at $DIR/forbidden_slices.rs:81:35
+
+error: aborting due to 18 previous errors
+
+For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/const-ptr/forbidden_slices.64bit.stderr b/src/test/ui/const-ptr/forbidden_slices.64bit.stderr
new file mode 100644
index 00000000000..b75e6c50246
--- /dev/null
+++ b/src/test/ui/const-ptr/forbidden_slices.64bit.stderr
@@ -0,0 +1,280 @@
+error[E0080]: could not evaluate static initializer
+  --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
+   |
+LL |         &*ptr::slice_from_raw_parts(data, len)
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |         |
+   |         dereferencing pointer failed: null pointer is not a valid pointer
+   |         inside `std::slice::from_raw_parts::<u32>` at $SRC_DIR/core/src/slice/raw.rs:LL:COL
+   |
+  ::: $DIR/forbidden_slices.rs:19:34
+   |
+LL | pub static S0: &[u32] = unsafe { from_raw_parts(ptr::null(), 0) };
+   |                                  ------------------------------ inside `S0` at $DIR/forbidden_slices.rs:19:34
+
+error[E0080]: could not evaluate static initializer
+  --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
+   |
+LL |         &*ptr::slice_from_raw_parts(data, len)
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |         |
+   |         dereferencing pointer failed: null pointer is not a valid pointer
+   |         inside `std::slice::from_raw_parts::<()>` at $SRC_DIR/core/src/slice/raw.rs:LL:COL
+   |
+  ::: $DIR/forbidden_slices.rs:20:33
+   |
+LL | pub static S1: &[()] = unsafe { from_raw_parts(ptr::null(), 0) };
+   |                                 ------------------------------ inside `S1` at $DIR/forbidden_slices.rs:20:33
+
+error[E0080]: could not evaluate static initializer
+  --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
+   |
+LL |         &*ptr::slice_from_raw_parts(data, len)
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |         |
+   |         dereferencing pointer failed: ALLOC_ID has size 4, so pointer to 8 bytes starting at offset 0 is out-of-bounds
+   |         inside `std::slice::from_raw_parts::<u32>` at $SRC_DIR/core/src/slice/raw.rs:LL:COL
+   |
+  ::: $DIR/forbidden_slices.rs:23:34
+   |
+LL | pub static S2: &[u32] = unsafe { from_raw_parts(&D0, 2) };
+   |                                  ---------------------- inside `S2` at $DIR/forbidden_slices.rs:23:34
+
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/forbidden_slices.rs:26:1
+   |
+LL | pub static S4: &[u8] = unsafe { from_raw_parts((&D1) as *const _ as _, 1) };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .<deref>[0]: encountered uninitialized bytes
+   |
+   = 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.
+   = note: the raw bytes of the constant (size: 16, align: 8) {
+               ╾───────ALLOC_ID───────╼ 01 00 00 00 00 00 00 00 │ ╾──────╼........
+           }
+
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/forbidden_slices.rs:28:1
+   |
+LL | pub static S5: &[u8] = unsafe { from_raw_parts((&D3) as *const _ as _, size_of::<&u32>()) };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .<deref>: encountered a pointer, but expected plain (non-pointer) bytes
+   |
+   = 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.
+   = note: the raw bytes of the constant (size: 16, align: 8) {
+               ╾───────ALLOC_ID───────╼ 08 00 00 00 00 00 00 00 │ ╾──────╼........
+           }
+
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/forbidden_slices.rs:30:1
+   |
+LL | pub static S6: &[bool] = unsafe { from_raw_parts((&D0) as *const _ as _, 4) };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .<deref>[0]: encountered 0x11, but expected a boolean
+   |
+   = 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.
+   = note: the raw bytes of the constant (size: 16, align: 8) {
+               ╾───────ALLOC_ID───────╼ 04 00 00 00 00 00 00 00 │ ╾──────╼........
+           }
+
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/forbidden_slices.rs:33:1
+   |
+LL | / pub static S7: &[u16] = unsafe {
+LL | |
+LL | |     let ptr = (&D2 as *const Struct as *const u16).byte_add(1);
+LL | |
+LL | |     from_raw_parts(ptr, 4)
+LL | | };
+   | |__^ type validation failed: encountered an unaligned reference (required 2 byte alignment but found 1)
+   |
+   = 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.
+   = note: the raw bytes of the constant (size: 16, align: 8) {
+               ╾─────ALLOC_ID+0x1─────╼ 04 00 00 00 00 00 00 00 │ ╾──────╼........
+           }
+
+error[E0080]: could not evaluate static initializer
+  --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
+   |
+LL |         &*ptr::slice_from_raw_parts(data, len)
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |         |
+   |         dereferencing pointer failed: ALLOC_ID has size 8, so pointer to 8 bytes starting at offset 1 is out-of-bounds
+   |         inside `std::slice::from_raw_parts::<u64>` at $SRC_DIR/core/src/slice/raw.rs:LL:COL
+   |
+  ::: $DIR/forbidden_slices.rs:44:5
+   |
+LL |     from_raw_parts(ptr, 1)
+   |     ---------------------- inside `S8` at $DIR/forbidden_slices.rs:44:5
+
+error[E0080]: could not evaluate static initializer
+  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+   |
+LL |         unsafe { intrinsics::ptr_offset_from_unsigned(self, origin) }
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                  |
+   |                  out-of-bounds offset_from: null pointer is not a valid pointer
+   |                  inside `ptr::const_ptr::<impl *const u32>::sub_ptr` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+   |
+  ::: $SRC_DIR/core/src/slice/raw.rs:LL:COL
+   |
+LL |     unsafe { from_raw_parts(range.start, range.end.sub_ptr(range.start)) }
+   |                                          ------------------------------ inside `from_ptr_range::<u32>` at $SRC_DIR/core/src/slice/raw.rs:LL:COL
+   |
+  ::: $DIR/forbidden_slices.rs:47:34
+   |
+LL | pub static R0: &[u32] = unsafe { from_ptr_range(ptr::null()..ptr::null()) };
+   |                                  ---------------------------------------- inside `R0` at $DIR/forbidden_slices.rs:47:34
+
+error[E0080]: could not evaluate static initializer
+  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+   |
+LL |         assert!(0 < pointee_size && pointee_size <= isize::MAX as usize);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |         |
+   |         the evaluated program panicked at 'assertion failed: 0 < pointee_size && pointee_size <= isize::MAX as usize', $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+   |         inside `ptr::const_ptr::<impl *const ()>::sub_ptr` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+   |
+  ::: $SRC_DIR/core/src/slice/raw.rs:LL:COL
+   |
+LL |     unsafe { from_raw_parts(range.start, range.end.sub_ptr(range.start)) }
+   |                                          ------------------------------ inside `from_ptr_range::<()>` at $SRC_DIR/core/src/slice/raw.rs:LL:COL
+   |
+  ::: $DIR/forbidden_slices.rs:48:33
+   |
+LL | pub static R1: &[()] = unsafe { from_ptr_range(ptr::null()..ptr::null()) };
+   |                                 ---------------------------------------- inside `R1` at $DIR/forbidden_slices.rs:48:33
+   |
+   = note: this error originates in the macro `assert` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0080]: could not evaluate static initializer
+  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+   |
+LL |         unsafe { intrinsics::offset(self, count) }
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                  |
+   |                  pointer arithmetic failed: ALLOC_ID has size 4, so pointer to 8 bytes starting at offset 0 is out-of-bounds
+   |                  inside `ptr::const_ptr::<impl *const u32>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+...
+LL |         unsafe { self.offset(count as isize) }
+   |                  --------------------------- inside `ptr::const_ptr::<impl *const u32>::add` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+   |
+  ::: $DIR/forbidden_slices.rs:51:25
+   |
+LL |     from_ptr_range(ptr..ptr.add(2))
+   |                         ---------- inside `R2` at $DIR/forbidden_slices.rs:51:25
+
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/forbidden_slices.rs:53:1
+   |
+LL | / pub static R4: &[u8] = unsafe {
+LL | |
+LL | |     let ptr = (&D1) as *const MaybeUninit<&u32> as *const u8;
+LL | |     from_ptr_range(ptr..ptr.add(1))
+LL | | };
+   | |__^ type validation failed at .<deref>[0]: encountered uninitialized bytes
+   |
+   = 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.
+   = note: the raw bytes of the constant (size: 16, align: 8) {
+               ╾──────ALLOC_ID───────╼ 01 00 00 00 00 00 00 00 │ ╾──────╼........
+           }
+
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/forbidden_slices.rs:58:1
+   |
+LL | / pub static R5: &[u8] = unsafe {
+LL | |
+LL | |     let ptr = &D3 as *const &u32;
+LL | |     from_ptr_range(ptr.cast()..ptr.add(1).cast())
+LL | | };
+   | |__^ type validation failed at .<deref>: encountered a pointer, but expected plain (non-pointer) bytes
+   |
+   = 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.
+   = note: the raw bytes of the constant (size: 16, align: 8) {
+               ╾──────ALLOC_ID───────╼ 08 00 00 00 00 00 00 00 │ ╾──────╼........
+           }
+
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/forbidden_slices.rs:63:1
+   |
+LL | / pub static R6: &[bool] = unsafe {
+LL | |
+LL | |     let ptr = &D0 as *const u32 as *const bool;
+LL | |     from_ptr_range(ptr..ptr.add(4))
+LL | | };
+   | |__^ type validation failed at .<deref>[0]: encountered 0x11, but expected a boolean
+   |
+   = 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.
+   = note: the raw bytes of the constant (size: 16, align: 8) {
+               ╾──────ALLOC_ID───────╼ 04 00 00 00 00 00 00 00 │ ╾──────╼........
+           }
+
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/forbidden_slices.rs:68:1
+   |
+LL | / pub static R7: &[u16] = unsafe {
+LL | |
+LL | |     let ptr = (&D2 as *const Struct as *const u16).byte_add(1);
+LL | |     from_ptr_range(ptr..ptr.add(4))
+LL | | };
+   | |__^ type validation failed: encountered an unaligned reference (required 2 byte alignment but found 1)
+   |
+   = 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.
+   = note: the raw bytes of the constant (size: 16, align: 8) {
+               ╾────ALLOC_ID+0x1─────╼ 04 00 00 00 00 00 00 00 │ ╾──────╼........
+           }
+
+error[E0080]: could not evaluate static initializer
+  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+   |
+LL |         unsafe { intrinsics::offset(self, count) }
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                  |
+   |                  pointer arithmetic failed: ALLOC_ID has size 8, so pointer to 8 bytes starting at offset 1 is out-of-bounds
+   |                  inside `ptr::const_ptr::<impl *const u64>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+...
+LL |         unsafe { self.offset(count as isize) }
+   |                  --------------------------- inside `ptr::const_ptr::<impl *const u64>::add` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+   |
+  ::: $DIR/forbidden_slices.rs:75:25
+   |
+LL |     from_ptr_range(ptr..ptr.add(1))
+   |                         ---------- inside `R8` at $DIR/forbidden_slices.rs:75:25
+
+error[E0080]: could not evaluate static initializer
+  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+   |
+LL |         unsafe { intrinsics::ptr_offset_from_unsigned(self, origin) }
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                  |
+   |                  ptr_offset_from_unsigned cannot compute offset of pointers into different allocations.
+   |                  inside `ptr::const_ptr::<impl *const u32>::sub_ptr` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+   |
+  ::: $SRC_DIR/core/src/slice/raw.rs:LL:COL
+   |
+LL |     unsafe { from_raw_parts(range.start, range.end.sub_ptr(range.start)) }
+   |                                          ------------------------------ inside `from_ptr_range::<u32>` at $SRC_DIR/core/src/slice/raw.rs:LL:COL
+   |
+  ::: $DIR/forbidden_slices.rs:80:34
+   |
+LL | pub static R9: &[u32] = unsafe { from_ptr_range(&D0..(&D0 as *const u32).add(1)) };
+   |                                  ----------------------------------------------- inside `R9` at $DIR/forbidden_slices.rs:80:34
+
+error[E0080]: could not evaluate static initializer
+  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+   |
+LL |         unsafe { intrinsics::ptr_offset_from_unsigned(self, origin) }
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                  |
+   |                  ptr_offset_from_unsigned cannot compute offset of pointers into different allocations.
+   |                  inside `ptr::const_ptr::<impl *const u32>::sub_ptr` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+   |
+  ::: $SRC_DIR/core/src/slice/raw.rs:LL:COL
+   |
+LL |     unsafe { from_raw_parts(range.start, range.end.sub_ptr(range.start)) }
+   |                                          ------------------------------ inside `from_ptr_range::<u32>` at $SRC_DIR/core/src/slice/raw.rs:LL:COL
+   |
+  ::: $DIR/forbidden_slices.rs:81:35
+   |
+LL | pub static R10: &[u32] = unsafe { from_ptr_range(&D0..&D0) };
+   |                                   ------------------------ inside `R10` at $DIR/forbidden_slices.rs:81:35
+
+error: aborting due to 18 previous errors
+
+For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/const-ptr/forbidden_slices.rs b/src/test/ui/const-ptr/forbidden_slices.rs
new file mode 100644
index 00000000000..4465da45468
--- /dev/null
+++ b/src/test/ui/const-ptr/forbidden_slices.rs
@@ -0,0 +1,99 @@
+// stderr-per-bitwidth
+// normalize-stderr-test "alloc[0-9]+" -> "ALLOC_ID"
+// normalize-stderr-test "a[0-9]+\+0x" -> "A_ID+0x"
+// error-pattern: could not evaluate static initializer
+#![feature(
+    const_slice_from_raw_parts,
+    slice_from_ptr_range,
+    const_slice_from_ptr_range,
+    pointer_byte_offsets,
+    const_pointer_byte_offsets
+)]
+use std::{
+    mem::{size_of, MaybeUninit},
+    ptr,
+    slice::{from_ptr_range, from_raw_parts},
+};
+
+// Null is never valid for reads
+pub static S0: &[u32] = unsafe { from_raw_parts(ptr::null(), 0) };
+pub static S1: &[()] = unsafe { from_raw_parts(ptr::null(), 0) };
+
+// Out of bounds
+pub static S2: &[u32] = unsafe { from_raw_parts(&D0, 2) };
+
+// Reading uninitialized  data
+pub static S4: &[u8] = unsafe { from_raw_parts((&D1) as *const _ as _, 1) }; //~ ERROR: it is undefined behavior to use this value
+// Reinterpret pointers as integers (UB in CTFE.)
+pub static S5: &[u8] = unsafe { from_raw_parts((&D3) as *const _ as _, size_of::<&u32>()) }; //~ ERROR: it is undefined behavior to use this value
+// Layout mismatch
+pub static S6: &[bool] = unsafe { from_raw_parts((&D0) as *const _ as _, 4) }; //~ ERROR: it is undefined behavior to use this value
+
+// Reading padding is not ok
+pub static S7: &[u16] = unsafe {
+    //~^ ERROR: it is undefined behavior to use this value
+    let ptr = (&D2 as *const Struct as *const u16).byte_add(1);
+
+    from_raw_parts(ptr, 4)
+};
+
+// Unaligned read
+pub static S8: &[u64] = unsafe {
+    let ptr = (&D4 as *const [u32; 2] as *const u32).byte_add(1).cast::<u64>();
+
+    from_raw_parts(ptr, 1)
+};
+
+pub static R0: &[u32] = unsafe { from_ptr_range(ptr::null()..ptr::null()) };
+pub static R1: &[()] = unsafe { from_ptr_range(ptr::null()..ptr::null()) };
+pub static R2: &[u32] = unsafe {
+    let ptr = &D0 as *const u32;
+    from_ptr_range(ptr..ptr.add(2))
+};
+pub static R4: &[u8] = unsafe {
+    //~^ ERROR: it is undefined behavior to use this value
+    let ptr = (&D1) as *const MaybeUninit<&u32> as *const u8;
+    from_ptr_range(ptr..ptr.add(1))
+};
+pub static R5: &[u8] = unsafe {
+    //~^ ERROR: it is undefined behavior to use this value
+    let ptr = &D3 as *const &u32;
+    from_ptr_range(ptr.cast()..ptr.add(1).cast())
+};
+pub static R6: &[bool] = unsafe {
+    //~^ ERROR: it is undefined behavior to use this value
+    let ptr = &D0 as *const u32 as *const bool;
+    from_ptr_range(ptr..ptr.add(4))
+};
+pub static R7: &[u16] = unsafe {
+    //~^ ERROR: it is undefined behavior to use this value
+    let ptr = (&D2 as *const Struct as *const u16).byte_add(1);
+    from_ptr_range(ptr..ptr.add(4))
+};
+pub static R8: &[u64] = unsafe {
+    let ptr = (&D4 as *const [u32; 2] as *const u32).byte_add(1).cast::<u64>();
+    from_ptr_range(ptr..ptr.add(1))
+};
+
+// This is sneaky: &D0 and &D0 point to different objects
+// (even if at runtime they have the same address)
+pub static R9: &[u32] = unsafe { from_ptr_range(&D0..(&D0 as *const u32).add(1)) };
+pub static R10: &[u32] = unsafe { from_ptr_range(&D0..&D0) };
+
+const D0: u32 = 0x11;
+const D1: MaybeUninit<&u32> = MaybeUninit::uninit();
+const D2: Struct = Struct { a: 1, b: 2, c: 3, d: 4 };
+const D3: &u32 = &42;
+const D4: [u32; 2] = [17, 42];
+
+#[repr(C)]
+struct Struct {
+    a: u8,
+    // _pad: [MaybeUninit<u8>; 3]
+    b: u32,
+    c: u16,
+    d: u8,
+    // _pad: [MaybeUninit<u8>; 1]
+}
+
+fn main() {}
diff --git a/src/test/ui/error-codes/E0432.stderr b/src/test/ui/error-codes/E0432.stderr
index afb031c2252..ed9536f164e 100644
--- a/src/test/ui/error-codes/E0432.stderr
+++ b/src/test/ui/error-codes/E0432.stderr
@@ -3,6 +3,8 @@ error[E0432]: unresolved import `something`
    |
 LL | use something::Foo;
    |     ^^^^^^^^^ maybe a missing crate `something`?
+   |
+   = help: consider adding `extern crate something` to use the `something` crate
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/feature-gates/feature-gate-extern_absolute_paths.stderr b/src/test/ui/feature-gates/feature-gate-extern_absolute_paths.stderr
index 2f4c220ee95..3bae23a4aaa 100644
--- a/src/test/ui/feature-gates/feature-gate-extern_absolute_paths.stderr
+++ b/src/test/ui/feature-gates/feature-gate-extern_absolute_paths.stderr
@@ -3,12 +3,16 @@ error[E0432]: unresolved import `core`
    |
 LL | use core::default;
    |     ^^^^ maybe a missing crate `core`?
+   |
+   = help: consider adding `extern crate core` to use the `core` crate
 
 error[E0433]: failed to resolve: maybe a missing crate `core`?
   --> $DIR/feature-gate-extern_absolute_paths.rs:4:19
    |
 LL |     let _: u8 = ::core::default::Default();
    |                   ^^^^ maybe a missing crate `core`?
+   |
+   = help: consider adding `extern crate core` to use the `core` crate
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/imports/import3.stderr b/src/test/ui/imports/import3.stderr
index 7bb413be59f..ca75c9c18bd 100644
--- a/src/test/ui/imports/import3.stderr
+++ b/src/test/ui/imports/import3.stderr
@@ -3,6 +3,8 @@ error[E0432]: unresolved import `main`
    |
 LL | use main::bar;
    |     ^^^^ maybe a missing crate `main`?
+   |
+   = help: consider adding `extern crate main` to use the `main` crate
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/imports/issue-1697.stderr b/src/test/ui/imports/issue-1697.stderr
index a76fd309914..019ef9ad56a 100644
--- a/src/test/ui/imports/issue-1697.stderr
+++ b/src/test/ui/imports/issue-1697.stderr
@@ -3,6 +3,8 @@ error[E0432]: unresolved import `unresolved`
    |
 LL | use unresolved::*;
    |     ^^^^^^^^^^ maybe a missing crate `unresolved`?
+   |
+   = help: consider adding `extern crate unresolved` to use the `unresolved` crate
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/imports/issue-33464.stderr b/src/test/ui/imports/issue-33464.stderr
index d3bf404c99a..c4e5c555899 100644
--- a/src/test/ui/imports/issue-33464.stderr
+++ b/src/test/ui/imports/issue-33464.stderr
@@ -3,18 +3,24 @@ error[E0432]: unresolved import `abc`
    |
 LL | use abc::one_el;
    |     ^^^ maybe a missing crate `abc`?
+   |
+   = help: consider adding `extern crate abc` to use the `abc` crate
 
 error[E0432]: unresolved import `abc`
   --> $DIR/issue-33464.rs:5:5
    |
 LL | use abc::{a, bbb, cccccc};
    |     ^^^ maybe a missing crate `abc`?
+   |
+   = help: consider adding `extern crate abc` to use the `abc` crate
 
 error[E0432]: unresolved import `a_very_long_name`
   --> $DIR/issue-33464.rs:7:5
    |
 LL | use a_very_long_name::{el, el2};
    |     ^^^^^^^^^^^^^^^^ maybe a missing crate `a_very_long_name`?
+   |
+   = help: consider adding `extern crate a_very_long_name` to use the `a_very_long_name` crate
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/imports/issue-36881.stderr b/src/test/ui/imports/issue-36881.stderr
index caf9d5d6d62..2e1b468603d 100644
--- a/src/test/ui/imports/issue-36881.stderr
+++ b/src/test/ui/imports/issue-36881.stderr
@@ -3,6 +3,8 @@ error[E0432]: unresolved import `issue_36881_aux`
    |
 LL |     use issue_36881_aux::Foo;
    |         ^^^^^^^^^^^^^^^ maybe a missing crate `issue_36881_aux`?
+   |
+   = help: consider adding `extern crate issue_36881_aux` to use the `issue_36881_aux` crate
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/imports/issue-37887.stderr b/src/test/ui/imports/issue-37887.stderr
index 944d544098a..75185cad3b7 100644
--- a/src/test/ui/imports/issue-37887.stderr
+++ b/src/test/ui/imports/issue-37887.stderr
@@ -3,6 +3,8 @@ error[E0432]: unresolved import `libc`
    |
 LL |     use libc::*;
    |         ^^^^ maybe a missing crate `libc`?
+   |
+   = help: consider adding `extern crate libc` to use the `libc` crate
 
 error[E0658]: use of unstable library feature 'rustc_private': this crate is being loaded from the sysroot, an unstable location; did you mean to load this crate from crates.io via `Cargo.toml` instead?
   --> $DIR/issue-37887.rs:2:5
diff --git a/src/test/ui/imports/issue-53269.stderr b/src/test/ui/imports/issue-53269.stderr
index a0e7bf8b61f..29c7556dac4 100644
--- a/src/test/ui/imports/issue-53269.stderr
+++ b/src/test/ui/imports/issue-53269.stderr
@@ -3,6 +3,8 @@ error[E0432]: unresolved import `nonexistent_module`
    |
 LL |     use nonexistent_module::mac;
    |         ^^^^^^^^^^^^^^^^^^ maybe a missing crate `nonexistent_module`?
+   |
+   = help: consider adding `extern crate nonexistent_module` to use the `nonexistent_module` crate
 
 error[E0659]: `mac` is ambiguous
   --> $DIR/issue-53269.rs:8:5
diff --git a/src/test/ui/imports/issue-55457.stderr b/src/test/ui/imports/issue-55457.stderr
index 07de3d95902..788fcc830ae 100644
--- a/src/test/ui/imports/issue-55457.stderr
+++ b/src/test/ui/imports/issue-55457.stderr
@@ -12,6 +12,8 @@ error[E0432]: unresolved import `non_existent`
    |
 LL | use non_existent::non_existent;
    |     ^^^^^^^^^^^^ maybe a missing crate `non_existent`?
+   |
+   = help: consider adding `extern crate non_existent` to use the `non_existent` crate
 
 error: cannot determine resolution for the derive macro `NonExistent`
   --> $DIR/issue-55457.rs:5:10
diff --git a/src/test/ui/imports/tool-mod-child.stderr b/src/test/ui/imports/tool-mod-child.stderr
index efab4f6a74f..6caf15bc724 100644
--- a/src/test/ui/imports/tool-mod-child.stderr
+++ b/src/test/ui/imports/tool-mod-child.stderr
@@ -3,24 +3,32 @@ error[E0433]: failed to resolve: maybe a missing crate `clippy`?
    |
 LL | use clippy::a::b;
    |     ^^^^^^ maybe a missing crate `clippy`?
+   |
+   = help: consider adding `extern crate clippy` to use the `clippy` crate
 
 error[E0432]: unresolved import `clippy`
   --> $DIR/tool-mod-child.rs:1:5
    |
 LL | use clippy::a;
    |     ^^^^^^ maybe a missing crate `clippy`?
+   |
+   = help: consider adding `extern crate clippy` to use the `clippy` crate
 
 error[E0433]: failed to resolve: maybe a missing crate `rustdoc`?
   --> $DIR/tool-mod-child.rs:5:5
    |
 LL | use rustdoc::a::b;
    |     ^^^^^^^ maybe a missing crate `rustdoc`?
+   |
+   = help: consider adding `extern crate rustdoc` to use the `rustdoc` crate
 
 error[E0432]: unresolved import `rustdoc`
   --> $DIR/tool-mod-child.rs:4:5
    |
 LL | use rustdoc::a;
    |     ^^^^^^^ maybe a missing crate `rustdoc`?
+   |
+   = help: consider adding `extern crate rustdoc` to use the `rustdoc` crate
 
 error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/imports/unresolved-imports-used.stderr b/src/test/ui/imports/unresolved-imports-used.stderr
index ddf36089339..73f9d1bfb6c 100644
--- a/src/test/ui/imports/unresolved-imports-used.stderr
+++ b/src/test/ui/imports/unresolved-imports-used.stderr
@@ -15,24 +15,32 @@ error[E0432]: unresolved import `foo`
    |
 LL | use foo::bar;
    |     ^^^ maybe a missing crate `foo`?
+   |
+   = help: consider adding `extern crate foo` to use the `foo` crate
 
 error[E0432]: unresolved import `baz`
   --> $DIR/unresolved-imports-used.rs:12:5
    |
 LL | use baz::*;
    |     ^^^ maybe a missing crate `baz`?
+   |
+   = help: consider adding `extern crate baz` to use the `baz` crate
 
 error[E0432]: unresolved import `foo2`
   --> $DIR/unresolved-imports-used.rs:14:5
    |
 LL | use foo2::bar2;
    |     ^^^^ maybe a missing crate `foo2`?
+   |
+   = help: consider adding `extern crate foo2` to use the `foo2` crate
 
 error[E0432]: unresolved import `baz2`
   --> $DIR/unresolved-imports-used.rs:15:5
    |
 LL | use baz2::*;
    |     ^^^^ maybe a missing crate `baz2`?
+   |
+   = help: consider adding `extern crate baz2` to use the `baz2` crate
 
 error[E0603]: function `quz` is private
   --> $DIR/unresolved-imports-used.rs:9:10
diff --git a/src/test/ui/keyword/extern/keyword-extern-as-identifier-use.stderr b/src/test/ui/keyword/extern/keyword-extern-as-identifier-use.stderr
index 247d6b0ed71..54ee45c2867 100644
--- a/src/test/ui/keyword/extern/keyword-extern-as-identifier-use.stderr
+++ b/src/test/ui/keyword/extern/keyword-extern-as-identifier-use.stderr
@@ -14,6 +14,8 @@ error[E0432]: unresolved import `r#extern`
    |
 LL | use extern::foo;
    |     ^^^^^^ maybe a missing crate `r#extern`?
+   |
+   = help: consider adding `extern crate r#extern` to use the `r#extern` crate
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/privacy/restricted/test.stderr b/src/test/ui/privacy/restricted/test.stderr
index 5a85aef2b17..c81520c35cd 100644
--- a/src/test/ui/privacy/restricted/test.stderr
+++ b/src/test/ui/privacy/restricted/test.stderr
@@ -3,6 +3,8 @@ error[E0433]: failed to resolve: maybe a missing crate `bad`?
    |
 LL |     pub(in bad::path) mod m1 {}
    |            ^^^ maybe a missing crate `bad`?
+   |
+   = help: consider adding `extern crate bad` to use the `bad` crate
 
 error[E0742]: visibilities can only be restricted to ancestor modules
   --> $DIR/test.rs:51:12
diff --git a/src/test/ui/resolve/editions-crate-root-2015.stderr b/src/test/ui/resolve/editions-crate-root-2015.stderr
index f8d65fec3d1..00cdd0c58f4 100644
--- a/src/test/ui/resolve/editions-crate-root-2015.stderr
+++ b/src/test/ui/resolve/editions-crate-root-2015.stderr
@@ -3,12 +3,16 @@ error[E0433]: failed to resolve: maybe a missing crate `nonexistant`?
    |
 LL |     fn global_inner(_: ::nonexistant::Foo) {
    |                          ^^^^^^^^^^^ maybe a missing crate `nonexistant`?
+   |
+   = help: consider adding `extern crate nonexistant` to use the `nonexistant` crate
 
 error[E0433]: failed to resolve: maybe a missing crate `nonexistant`?
   --> $DIR/editions-crate-root-2015.rs:7:30
    |
 LL |     fn crate_inner(_: crate::nonexistant::Foo) {
    |                              ^^^^^^^^^^^ maybe a missing crate `nonexistant`?
+   |
+   = help: consider adding `extern crate nonexistant` to use the `nonexistant` crate
 
 error[E0412]: cannot find type `nonexistant` in the crate root
   --> $DIR/editions-crate-root-2015.rs:11:25
diff --git a/src/test/ui/resolve/extern-prelude-fail.stderr b/src/test/ui/resolve/extern-prelude-fail.stderr
index a59f4c952bb..a1591914b4d 100644
--- a/src/test/ui/resolve/extern-prelude-fail.stderr
+++ b/src/test/ui/resolve/extern-prelude-fail.stderr
@@ -3,12 +3,16 @@ error[E0432]: unresolved import `extern_prelude`
    |
 LL |     use extern_prelude::S;
    |         ^^^^^^^^^^^^^^ maybe a missing crate `extern_prelude`?
+   |
+   = help: consider adding `extern crate extern_prelude` to use the `extern_prelude` crate
 
 error[E0433]: failed to resolve: maybe a missing crate `extern_prelude`?
   --> $DIR/extern-prelude-fail.rs:8:15
    |
 LL |     let s = ::extern_prelude::S;
    |               ^^^^^^^^^^^^^^ maybe a missing crate `extern_prelude`?
+   |
+   = help: consider adding `extern crate extern_prelude` to use the `extern_prelude` crate
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/resolve/issue-82865.stderr b/src/test/ui/resolve/issue-82865.stderr
index 7898c2a360f..730fd6d6026 100644
--- a/src/test/ui/resolve/issue-82865.stderr
+++ b/src/test/ui/resolve/issue-82865.stderr
@@ -3,6 +3,8 @@ error[E0433]: failed to resolve: maybe a missing crate `x`?
    |
 LL | use x::y::z;
    |     ^ maybe a missing crate `x`?
+   |
+   = help: consider adding `extern crate x` to use the `x` crate
 
 error[E0599]: no function or associated item named `z` found for struct `Box<_, _>` in the current scope
   --> $DIR/issue-82865.rs:8:10
diff --git a/src/test/ui/resolve/resolve-bad-visibility.stderr b/src/test/ui/resolve/resolve-bad-visibility.stderr
index 197ecf0cb00..2ac41b87562 100644
--- a/src/test/ui/resolve/resolve-bad-visibility.stderr
+++ b/src/test/ui/resolve/resolve-bad-visibility.stderr
@@ -21,12 +21,16 @@ error[E0433]: failed to resolve: maybe a missing crate `nonexistent`?
    |
 LL | pub(in nonexistent) struct G;
    |        ^^^^^^^^^^^ maybe a missing crate `nonexistent`?
+   |
+   = help: consider adding `extern crate nonexistent` to use the `nonexistent` crate
 
 error[E0433]: failed to resolve: maybe a missing crate `too_soon`?
   --> $DIR/resolve-bad-visibility.rs:8:8
    |
 LL | pub(in too_soon) struct H;
    |        ^^^^^^^^ maybe a missing crate `too_soon`?
+   |
+   = help: consider adding `extern crate too_soon` to use the `too_soon` crate
 
 error: aborting due to 5 previous errors
 
diff --git a/src/test/ui/simd/portable-intrinsics-arent-exposed.stderr b/src/test/ui/simd/portable-intrinsics-arent-exposed.stderr
index f568aa04295..870f4064de4 100644
--- a/src/test/ui/simd/portable-intrinsics-arent-exposed.stderr
+++ b/src/test/ui/simd/portable-intrinsics-arent-exposed.stderr
@@ -3,6 +3,8 @@ error[E0433]: failed to resolve: maybe a missing crate `core`?
    |
 LL | use core::simd::intrinsics;
    |     ^^^^ maybe a missing crate `core`?
+   |
+   = help: consider adding `extern crate core` to use the `core` crate
 
 error[E0432]: unresolved import `std::simd::intrinsics`
   --> $DIR/portable-intrinsics-arent-exposed.rs:5:5
diff --git a/src/test/ui/suggestions/enum-method-probe.fixed b/src/test/ui/suggestions/enum-method-probe.fixed
new file mode 100644
index 00000000000..6499c92bc6f
--- /dev/null
+++ b/src/test/ui/suggestions/enum-method-probe.fixed
@@ -0,0 +1,59 @@
+// compile-flags: --edition=2021
+// run-rustfix
+
+#![allow(unused)]
+
+struct Foo;
+
+impl Foo {
+    fn get(&self) -> u8 {
+        42
+    }
+}
+
+fn test_result_in_result() -> Result<(), ()> {
+    let res: Result<_, ()> = Ok(Foo);
+    res?.get();
+    //~^ ERROR no method named `get` found for enum `Result` in the current scope
+    //~| HELP use the `?` operator
+    Ok(())
+}
+
+async fn async_test_result_in_result() -> Result<(), ()> {
+    let res: Result<_, ()> = Ok(Foo);
+    res?.get();
+    //~^ ERROR no method named `get` found for enum `Result` in the current scope
+    //~| HELP use the `?` operator
+    Ok(())
+}
+
+fn test_result_in_unit_return() {
+    let res: Result<_, ()> = Ok(Foo);
+    res.expect("REASON").get();
+    //~^ ERROR no method named `get` found for enum `Result` in the current scope
+    //~| HELP consider using `Result::expect` to unwrap the `Foo` value, panicking if the value is a `Result::Err`
+}
+
+async fn async_test_result_in_unit_return() {
+    let res: Result<_, ()> = Ok(Foo);
+    res.expect("REASON").get();
+    //~^ ERROR no method named `get` found for enum `Result` in the current scope
+    //~| HELP consider using `Result::expect` to unwrap the `Foo` value, panicking if the value is a `Result::Err`
+}
+
+fn test_option_in_option() -> Option<()> {
+    let res: Option<_> = Some(Foo);
+    res?.get();
+    //~^ ERROR no method named `get` found for enum `Option` in the current scope
+    //~| HELP use the `?` operator
+    Some(())
+}
+
+fn test_option_in_unit_return() {
+    let res: Option<_> = Some(Foo);
+    res.expect("REASON").get();
+    //~^ ERROR no method named `get` found for enum `Option` in the current scope
+    //~| HELP consider using `Option::expect` to unwrap the `Foo` value, panicking if the value is an `Option::None`
+}
+
+fn main() {}
diff --git a/src/test/ui/suggestions/enum-method-probe.rs b/src/test/ui/suggestions/enum-method-probe.rs
new file mode 100644
index 00000000000..18ea8ed8a58
--- /dev/null
+++ b/src/test/ui/suggestions/enum-method-probe.rs
@@ -0,0 +1,59 @@
+// compile-flags: --edition=2021
+// run-rustfix
+
+#![allow(unused)]
+
+struct Foo;
+
+impl Foo {
+    fn get(&self) -> u8 {
+        42
+    }
+}
+
+fn test_result_in_result() -> Result<(), ()> {
+    let res: Result<_, ()> = Ok(Foo);
+    res.get();
+    //~^ ERROR no method named `get` found for enum `Result` in the current scope
+    //~| HELP use the `?` operator
+    Ok(())
+}
+
+async fn async_test_result_in_result() -> Result<(), ()> {
+    let res: Result<_, ()> = Ok(Foo);
+    res.get();
+    //~^ ERROR no method named `get` found for enum `Result` in the current scope
+    //~| HELP use the `?` operator
+    Ok(())
+}
+
+fn test_result_in_unit_return() {
+    let res: Result<_, ()> = Ok(Foo);
+    res.get();
+    //~^ ERROR no method named `get` found for enum `Result` in the current scope
+    //~| HELP consider using `Result::expect` to unwrap the `Foo` value, panicking if the value is a `Result::Err`
+}
+
+async fn async_test_result_in_unit_return() {
+    let res: Result<_, ()> = Ok(Foo);
+    res.get();
+    //~^ ERROR no method named `get` found for enum `Result` in the current scope
+    //~| HELP consider using `Result::expect` to unwrap the `Foo` value, panicking if the value is a `Result::Err`
+}
+
+fn test_option_in_option() -> Option<()> {
+    let res: Option<_> = Some(Foo);
+    res.get();
+    //~^ ERROR no method named `get` found for enum `Option` in the current scope
+    //~| HELP use the `?` operator
+    Some(())
+}
+
+fn test_option_in_unit_return() {
+    let res: Option<_> = Some(Foo);
+    res.get();
+    //~^ ERROR no method named `get` found for enum `Option` in the current scope
+    //~| HELP consider using `Option::expect` to unwrap the `Foo` value, panicking if the value is an `Option::None`
+}
+
+fn main() {}
diff --git a/src/test/ui/suggestions/enum-method-probe.stderr b/src/test/ui/suggestions/enum-method-probe.stderr
new file mode 100644
index 00000000000..6ed14984f47
--- /dev/null
+++ b/src/test/ui/suggestions/enum-method-probe.stderr
@@ -0,0 +1,99 @@
+error[E0599]: no method named `get` found for enum `Result` in the current scope
+  --> $DIR/enum-method-probe.rs:24:9
+   |
+LL |     res.get();
+   |         ^^^ method not found in `Result<Foo, ()>`
+   |
+note: the method `get` exists on the type `Foo`
+  --> $DIR/enum-method-probe.rs:9:5
+   |
+LL |     fn get(&self) -> u8 {
+   |     ^^^^^^^^^^^^^^^^^^^
+help: use the `?` operator to extract the `Foo` value, propagating a `Result::Err` value to the caller
+   |
+LL |     res?.get();
+   |        +
+
+error[E0599]: no method named `get` found for enum `Result` in the current scope
+  --> $DIR/enum-method-probe.rs:39:9
+   |
+LL |     res.get();
+   |         ^^^ method not found in `Result<Foo, ()>`
+   |
+note: the method `get` exists on the type `Foo`
+  --> $DIR/enum-method-probe.rs:9:5
+   |
+LL |     fn get(&self) -> u8 {
+   |     ^^^^^^^^^^^^^^^^^^^
+help: consider using `Result::expect` to unwrap the `Foo` value, panicking if the value is a `Result::Err`
+   |
+LL |     res.expect("REASON").get();
+   |        +++++++++++++++++
+
+error[E0599]: no method named `get` found for enum `Result` in the current scope
+  --> $DIR/enum-method-probe.rs:16:9
+   |
+LL |     res.get();
+   |         ^^^ method not found in `Result<Foo, ()>`
+   |
+note: the method `get` exists on the type `Foo`
+  --> $DIR/enum-method-probe.rs:9:5
+   |
+LL |     fn get(&self) -> u8 {
+   |     ^^^^^^^^^^^^^^^^^^^
+help: use the `?` operator to extract the `Foo` value, propagating a `Result::Err` value to the caller
+   |
+LL |     res?.get();
+   |        +
+
+error[E0599]: no method named `get` found for enum `Result` in the current scope
+  --> $DIR/enum-method-probe.rs:32:9
+   |
+LL |     res.get();
+   |         ^^^ method not found in `Result<Foo, ()>`
+   |
+note: the method `get` exists on the type `Foo`
+  --> $DIR/enum-method-probe.rs:9:5
+   |
+LL |     fn get(&self) -> u8 {
+   |     ^^^^^^^^^^^^^^^^^^^
+help: consider using `Result::expect` to unwrap the `Foo` value, panicking if the value is a `Result::Err`
+   |
+LL |     res.expect("REASON").get();
+   |        +++++++++++++++++
+
+error[E0599]: no method named `get` found for enum `Option` in the current scope
+  --> $DIR/enum-method-probe.rs:46:9
+   |
+LL |     res.get();
+   |         ^^^ method not found in `Option<Foo>`
+   |
+note: the method `get` exists on the type `Foo`
+  --> $DIR/enum-method-probe.rs:9:5
+   |
+LL |     fn get(&self) -> u8 {
+   |     ^^^^^^^^^^^^^^^^^^^
+help: use the `?` operator to extract the `Foo` value, propagating an `Option::None` value to the caller
+   |
+LL |     res?.get();
+   |        +
+
+error[E0599]: no method named `get` found for enum `Option` in the current scope
+  --> $DIR/enum-method-probe.rs:54:9
+   |
+LL |     res.get();
+   |         ^^^ method not found in `Option<Foo>`
+   |
+note: the method `get` exists on the type `Foo`
+  --> $DIR/enum-method-probe.rs:9:5
+   |
+LL |     fn get(&self) -> u8 {
+   |     ^^^^^^^^^^^^^^^^^^^
+help: consider using `Option::expect` to unwrap the `Foo` value, panicking if the value is an `Option::None`
+   |
+LL |     res.expect("REASON").get();
+   |        +++++++++++++++++
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/unresolved/unresolved-asterisk-imports.stderr b/src/test/ui/unresolved/unresolved-asterisk-imports.stderr
index a789179db65..8df8eab34a7 100644
--- a/src/test/ui/unresolved/unresolved-asterisk-imports.stderr
+++ b/src/test/ui/unresolved/unresolved-asterisk-imports.stderr
@@ -3,6 +3,8 @@ error[E0432]: unresolved import `not_existing_crate`
    |
 LL | use not_existing_crate::*;
    |     ^^^^^^^^^^^^^^^^^^ maybe a missing crate `not_existing_crate`?
+   |
+   = help: consider adding `extern crate not_existing_crate` to use the `not_existing_crate` crate
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/unresolved/unresolved-import.rs b/src/test/ui/unresolved/unresolved-import.rs
index b65c3dfb90b..4125c593c74 100644
--- a/src/test/ui/unresolved/unresolved-import.rs
+++ b/src/test/ui/unresolved/unresolved-import.rs
@@ -1,5 +1,6 @@
 use foo::bar; //~ ERROR unresolved import `foo` [E0432]
               //~^ maybe a missing crate `foo`?
+              //~| HELP consider adding `extern crate foo` to use the `foo` crate
 
 use bar::Baz as x; //~ ERROR unresolved import `bar::Baz` [E0432]
                    //~| no `Baz` in `bar`
diff --git a/src/test/ui/unresolved/unresolved-import.stderr b/src/test/ui/unresolved/unresolved-import.stderr
index d4bfea57809..0dd928c8b6f 100644
--- a/src/test/ui/unresolved/unresolved-import.stderr
+++ b/src/test/ui/unresolved/unresolved-import.stderr
@@ -3,9 +3,11 @@ error[E0432]: unresolved import `foo`
    |
 LL | use foo::bar;
    |     ^^^ maybe a missing crate `foo`?
+   |
+   = help: consider adding `extern crate foo` to use the `foo` crate
 
 error[E0432]: unresolved import `bar::Baz`
-  --> $DIR/unresolved-import.rs:4:5
+  --> $DIR/unresolved-import.rs:5:5
    |
 LL | use bar::Baz as x;
    |     ^^^^^---^^^^^
@@ -14,7 +16,7 @@ LL | use bar::Baz as x;
    |     no `Baz` in `bar`
 
 error[E0432]: unresolved import `food::baz`
-  --> $DIR/unresolved-import.rs:9:5
+  --> $DIR/unresolved-import.rs:10:5
    |
 LL | use food::baz;
    |     ^^^^^^---
@@ -23,7 +25,7 @@ LL | use food::baz;
    |     no `baz` in `food`
 
 error[E0432]: unresolved import `food::beens`
-  --> $DIR/unresolved-import.rs:14:12
+  --> $DIR/unresolved-import.rs:15:12
    |
 LL | use food::{beens as Foo};
    |            -----^^^^^^^
@@ -32,13 +34,13 @@ LL | use food::{beens as Foo};
    |            help: a similar name exists in the module: `beans`
 
 error[E0432]: unresolved import `MyEnum`
-  --> $DIR/unresolved-import.rs:38:9
+  --> $DIR/unresolved-import.rs:39:9
    |
 LL |     use MyEnum::*;
    |         ^^^^^^ help: a similar path exists: `self::MyEnum`
 
 error[E0432]: unresolved import `Enum`
-  --> $DIR/unresolved-import.rs:48:9
+  --> $DIR/unresolved-import.rs:49:9
    |
 LL |     use Enum::*;
    |         ^^^^ help: a similar path exists: `self::Enum`
diff --git a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
index 78d8f1e213a..283b20fc24d 100644
--- a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
+++ b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
@@ -125,16 +125,11 @@ fn check_rvalue<'tcx>(
         Rvalue::Len(place) | Rvalue::Discriminant(place) | Rvalue::Ref(_, _, place) | Rvalue::AddressOf(_, place) => {
             check_place(tcx, *place, span, body)
         },
-        Rvalue::Cast(CastKind::Misc, operand, cast_ty) => {
-            use rustc_middle::ty::cast::CastTy;
-            let cast_in = CastTy::from_ty(operand.ty(body, tcx)).expect("bad input type for cast");
-            let cast_out = CastTy::from_ty(*cast_ty).expect("bad output type for cast");
-            match (cast_in, cast_out) {
-                (CastTy::Ptr(_) | CastTy::FnPtr, CastTy::Int(_)) => {
-                    Err((span, "casting pointers to ints is unstable in const fn".into()))
-                },
-                _ => check_operand(tcx, operand, span, body),
-            }
+        Rvalue::Cast(CastKind::PointerAddress, _, _) => {
+            Err((span, "casting pointers to ints is unstable in const fn".into()))
+        },
+        Rvalue::Cast(CastKind::Misc, operand, _) => {
+            check_operand(tcx, operand, span, body)
         },
         Rvalue::Cast(CastKind::Pointer(PointerCast::MutToConstPointer | PointerCast::ArrayToPointer), operand, _) => {
             check_operand(tcx, operand, span, body)
diff --git a/src/tools/rust-analyzer b/src/tools/rust-analyzer
-Subproject 5d5bbec9b60010dd7389a084c56693baf6bda78
+Subproject f94fa62d69faf5bd63b3772d3ec4f0c76cf2db5