about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock6
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/region_name.rs10
-rw-r--r--compiler/rustc_borrowck/src/type_check/mod.rs20
-rw-r--r--compiler/rustc_codegen_cranelift/src/base.rs6
-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/interpret/memory.rs4
-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_data_structures/src/sso/set.rs5
-rw-r--r--compiler/rustc_errors/src/emitter.rs37
-rw-r--r--compiler/rustc_hir/src/def.rs5
-rw-r--r--compiler/rustc_hir/src/hir.rs11
-rw-r--r--compiler/rustc_hir/src/lib.rs1
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/mod.rs62
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/nice_region_error/different_lifetimes.rs50
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/nice_region_error/named_anon_conflict.rs3
-rw-r--r--compiler/rustc_middle/src/mir/mod.rs11
-rw-r--r--compiler/rustc_middle/src/mir/tcx.rs17
-rw-r--r--compiler/rustc_middle/src/ty/print/pretty.rs71
-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_parse/src/parser/diagnostics.rs42
-rw-r--r--compiler/rustc_parse/src/parser/expr.rs16
-rw-r--r--compiler/rustc_parse/src/parser/pat.rs16
-rw-r--r--compiler/rustc_parse/src/parser/stmt.rs2
-rw-r--r--compiler/rustc_parse/src/parser/ty.rs15
-rw-r--r--compiler/rustc_resolve/src/diagnostics.rs15
-rw-r--r--compiler/rustc_resolve/src/imports.rs4
-rw-r--r--compiler/rustc_trait_selection/src/traits/project.rs28
-rw-r--r--compiler/rustc_trait_selection/src/traits/wf.rs13
-rw-r--r--compiler/rustc_typeck/src/check/check.rs177
-rw-r--r--compiler/rustc_typeck/src/check/compare_method.rs20
-rw-r--r--compiler/rustc_typeck/src/check/method/suggest.rs203
-rw-r--r--compiler/rustc_typeck/src/check/wfcheck.rs2
-rw-r--r--compiler/rustc_typeck/src/collect/type_of.rs47
-rw-r--r--library/alloc/src/boxed.rs23
-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.rs16
-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/num/dec2flt/mod.rs1
-rw-r--r--library/core/src/ptr/mut_ptr.rs119
-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.rs116
-rw-r--r--library/std/src/collections/hash/set.rs20
-rw-r--r--library/std/src/sync/mpsc/cache_aligned.rs3
-rw-r--r--src/librustdoc/clean/types.rs4
-rw-r--r--src/librustdoc/formats/mod.rs25
-rw-r--r--src/librustdoc/html/render/mod.rs4
-rw-r--r--src/librustdoc/html/render/print_item.rs5
-rw-r--r--src/librustdoc/html/render/search_index.rs35
-rw-r--r--src/librustdoc/passes/collect_trait_impls.rs31
-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-js/impl-trait.js51
-rw-r--r--src/test/rustdoc-js/impl-trait.rs21
-rw-r--r--src/test/rustdoc-js/raw-pointer.js55
-rw-r--r--src/test/rustdoc-js/raw-pointer.rs24
-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/rustdoc/inline_cross/auxiliary/implementors_inline.rs18
-rw-r--r--src/test/rustdoc/inline_cross/implementors-js.rs25
-rw-r--r--src/test/rustdoc/intra-doc/email-address.rs6
-rw-r--r--src/test/rustdoc/issue-75588.rs2
-rw-r--r--src/test/rustdoc/primitive-slice-auto-trait.rs14
-rw-r--r--src/test/ui/async-await/issue-76547.base.stderr12
-rw-r--r--src/test/ui/async-await/issue-76547.nll.stderr10
-rw-r--r--src/test/ui/async-await/issues/issue-63388-1.base.stderr10
-rw-r--r--src/test/ui/async-await/issues/issue-63388-1.nll.stderr9
-rw-r--r--src/test/ui/async-await/issues/issue-63388-1.rs4
-rw-r--r--src/test/ui/attributes/field-attributes-vis-unresolved.stderr4
-rw-r--r--src/test/ui/borrowck/issue-71546.rs19
-rw-r--r--src/test/ui/borrowck/issue-71546.stderr20
-rw-r--r--src/test/ui/codemap_tests/two_files.stderr1
-rw-r--r--src/test/ui/const-generics/generic_const_exprs/issue-94287.stderr1
-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/editions/edition-keywords-2015-2018-expansion.stderr1
-rw-r--r--src/test/ui/editions/edition-keywords-2018-2018-expansion.stderr1
-rw-r--r--src/test/ui/error-codes/E0308-2.stderr2
-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/generic-associated-types/parameter_number_and_kind_impl.stderr6
-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/issues/issue-17905-2.stderr4
-rw-r--r--src/test/ui/issues/issue-65230.stderr2
-rw-r--r--src/test/ui/issues/issue-70724-add_type_neq_err_label-unwrap.stderr1
-rw-r--r--src/test/ui/keyword/extern/keyword-extern-as-identifier-use.stderr2
-rw-r--r--src/test/ui/methods/method-on-ambiguous-numeric-type.stderr1
-rw-r--r--src/test/ui/nll/issue-52742.base.stderr2
-rw-r--r--src/test/ui/nll/issue-52742.nll.stderr2
-rw-r--r--src/test/ui/nll/issue-55394.base.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/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr4
-rw-r--r--src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch-async.base.stderr12
-rw-r--r--src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch-async.nll.stderr10
-rw-r--r--src/test/ui/self/elision/lt-ref-self-async.base.stderr36
-rw-r--r--src/test/ui/self/elision/lt-ref-self-async.nll.stderr30
-rw-r--r--src/test/ui/self/elision/ref-mut-self-async.base.stderr36
-rw-r--r--src/test/ui/self/elision/ref-mut-self-async.nll.stderr30
-rw-r--r--src/test/ui/self/elision/ref-mut-struct-async.base.stderr30
-rw-r--r--src/test/ui/self/elision/ref-mut-struct-async.nll.stderr25
-rw-r--r--src/test/ui/self/elision/ref-self-async.base.stderr42
-rw-r--r--src/test/ui/self/elision/ref-self-async.nll.stderr35
-rw-r--r--src/test/ui/self/elision/ref-struct-async.base.stderr30
-rw-r--r--src/test/ui/self/elision/ref-struct-async.nll.stderr25
-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
m---------src/tools/cargo0
-rw-r--r--src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs15
m---------src/tools/miri19
m---------src/tools/rust-analyzer31
144 files changed, 2774 insertions, 849 deletions
diff --git a/Cargo.lock b/Cargo.lock
index c066d1b0a5b..7ed327e9f4c 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",
@@ -5509,6 +5509,8 @@ dependencies = [
  "pretty_assertions 1.2.1",
  "regex",
  "rustc_version",
+ "serde",
+ "serde_json",
 ]
 
 [[package]]
diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs
index 4d2a16aa609..cb4b154d271 100644
--- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs
@@ -567,15 +567,17 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
         let lifetime =
             self.try_match_adt_and_generic_args(substs, needle_fr, args, search_stack)?;
         match lifetime.name {
-            hir::LifetimeName::Param(_)
+            hir::LifetimeName::Param(hir::ParamName::Plain(_) | hir::ParamName::Error)
             | hir::LifetimeName::Error
-            | hir::LifetimeName::Static
-            | hir::LifetimeName::Underscore => {
+            | hir::LifetimeName::Static => {
                 let lifetime_span = lifetime.span;
                 Some(RegionNameHighlight::MatchedAdtAndSegment(lifetime_span))
             }
 
-            hir::LifetimeName::ImplicitObjectLifetimeDefault | hir::LifetimeName::Implicit => {
+            hir::LifetimeName::Param(hir::ParamName::Fresh(_))
+            | hir::LifetimeName::ImplicitObjectLifetimeDefault
+            | hir::LifetimeName::Implicit
+            | hir::LifetimeName::Underscore => {
                 // In this case, the user left off the lifetime; so
                 // they wrote something like:
                 //
diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index 4a2b2942008..abf77acb8c7 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::PointerExposeAddress => {
+                        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..58bec183c94 100644
--- a/compiler/rustc_codegen_cranelift/src/base.rs
+++ b/compiler/rustc_codegen_cranelift/src/base.rs
@@ -607,7 +607,11 @@ 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::PointerExposeAddress,
+                    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..6ff8d4aa442 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::PointerExposeAddress => {
+                        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..520ae409e6b 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)?;
             }
 
+            PointerExposeAddress => {
+                let src = self.read_immediate(src)?;
+                let res = self.pointer_expose_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_expose_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/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs
index 977b55a0890..9c032c55fe5 100644
--- a/compiler/rustc_const_eval/src/interpret/memory.rs
+++ b/compiler/rustc_const_eval/src/interpret/memory.rs
@@ -441,6 +441,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                         msg,
                     })
                 }
+                // Ensure we never consider the null pointer dereferencable.
+                if M::PointerTag::OFFSET_IS_ADDR {
+                    assert_ne!(ptr.addr(), Size::ZERO);
+                }
                 // Test align. Check this last; if both bounds and alignment are violated
                 // we want the error to be about the bounds.
                 if let Some(align) = align {
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..c07680515f4 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::PointerExposeAddress, _, _) => {
+                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..cf5d7b6c70a 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::PointerExposeAddress, _, _) => 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_data_structures/src/sso/set.rs b/compiler/rustc_data_structures/src/sso/set.rs
index f71522d3714..4fda3adb7b8 100644
--- a/compiler/rustc_data_structures/src/sso/set.rs
+++ b/compiler/rustc_data_structures/src/sso/set.rs
@@ -126,9 +126,10 @@ impl<T: Eq + Hash> SsoHashSet<T> {
 
     /// Adds a value to the set.
     ///
-    /// If the set did not have this value present, `true` is returned.
+    /// Returns whether the value was newly inserted. That is:
     ///
-    /// If the set did have this value present, `false` is returned.
+    /// - If the set did not previously contain this value, `true` is returned.
+    /// - If the set already contained this value, `false` is returned.
     #[inline]
     pub fn insert(&mut self, elem: T) -> bool {
         self.map.insert(elem, ()).is_none()
diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs
index 3fdc8cf8ac2..e9e7065ec03 100644
--- a/compiler/rustc_errors/src/emitter.rs
+++ b/compiler/rustc_errors/src/emitter.rs
@@ -1715,6 +1715,7 @@ impl EmitterWriter {
 
     fn emit_suggestion_default(
         &mut self,
+        span: &MultiSpan,
         suggestion: &CodeSuggestion,
         args: &FluentArgs<'_>,
         level: &Level,
@@ -1766,6 +1767,30 @@ impl EmitterWriter {
                 None,
             }
 
+            if let Some(span) = span.primary_span() {
+                // Compare the primary span of the diagnostic with the span of the suggestion
+                // being emitted.  If they belong to the same file, we don't *need* to show the
+                // file name, saving in verbosity, but if it *isn't* we do need it, otherwise we're
+                // telling users to make a change but not clarifying *where*.
+                let loc = sm.lookup_char_pos(parts[0].span.lo());
+                if loc.file.name != sm.span_to_filename(span) && loc.file.name.is_real() {
+                    buffer.puts(row_num - 1, 0, "--> ", Style::LineNumber);
+                    buffer.append(
+                        row_num - 1,
+                        &format!(
+                            "{}:{}:{}",
+                            sm.filename_for_diagnostics(&loc.file.name),
+                            sm.doctest_offset_line(&loc.file.name, loc.line),
+                            loc.col.0 + 1,
+                        ),
+                        Style::LineAndColumn,
+                    );
+                    for _ in 0..max_line_num_len {
+                        buffer.prepend(row_num - 1, " ", Style::NoStyle);
+                    }
+                    row_num += 1;
+                }
+            }
             let show_code_change = if has_deletion && !is_multiline {
                 DisplaySuggestion::Diff
             } else if (parts.len() != 1 || parts[0].snippet.trim() != complete.trim())
@@ -1787,7 +1812,7 @@ impl EmitterWriter {
             assert!(!file_lines.lines.is_empty() || parts[0].span.is_dummy());
 
             let line_start = sm.lookup_char_pos(parts[0].span.lo()).line;
-            draw_col_separator_no_space(&mut buffer, 1, max_line_num_len + 1);
+            draw_col_separator_no_space(&mut buffer, row_num - 1, max_line_num_len + 1);
             let mut lines = complete.lines();
             if lines.clone().next().is_none() {
                 // Account for a suggestion to completely remove a line(s) with whitespace (#94192).
@@ -2046,9 +2071,13 @@ impl EmitterWriter {
                             ) {
                                 panic!("failed to emit error: {}", e);
                             }
-                        } else if let Err(e) =
-                            self.emit_suggestion_default(sugg, args, &Level::Help, max_line_num_len)
-                        {
+                        } else if let Err(e) = self.emit_suggestion_default(
+                            span,
+                            sugg,
+                            args,
+                            &Level::Help,
+                            max_line_num_len,
+                        ) {
                             panic!("failed to emit error: {}", e);
                         };
                     }
diff --git a/compiler/rustc_hir/src/def.rs b/compiler/rustc_hir/src/def.rs
index 68876e89c4b..414f6272591 100644
--- a/compiler/rustc_hir/src/def.rs
+++ b/compiler/rustc_hir/src/def.rs
@@ -671,7 +671,10 @@ impl<Id> Res<Id> {
 
     #[track_caller]
     pub fn expect_non_local<OtherId>(self) -> Res<OtherId> {
-        self.map_id(|_| panic!("unexpected `Res::Local`"))
+        self.map_id(
+            #[track_caller]
+            |_| panic!("unexpected `Res::Local`"),
+        )
     }
 
     pub fn macro_kind(self) -> Option<MacroKind> {
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index bda7affe529..dbe6fe6ea84 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -131,6 +131,17 @@ impl LifetimeName {
         }
     }
 
+    pub fn is_anonymous(&self) -> bool {
+        match *self {
+            LifetimeName::ImplicitObjectLifetimeDefault
+            | LifetimeName::Implicit
+            | LifetimeName::Underscore
+            | LifetimeName::Param(ParamName::Fresh(_))
+            | LifetimeName::Error => true,
+            LifetimeName::Static | LifetimeName::Param(_) => false,
+        }
+    }
+
     pub fn is_elided(&self) -> bool {
         match self {
             LifetimeName::ImplicitObjectLifetimeDefault
diff --git a/compiler/rustc_hir/src/lib.rs b/compiler/rustc_hir/src/lib.rs
index 7833571f88d..d845c433d8c 100644
--- a/compiler/rustc_hir/src/lib.rs
+++ b/compiler/rustc_hir/src/lib.rs
@@ -3,6 +3,7 @@
 //! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/hir.html
 
 #![feature(associated_type_defaults)]
+#![feature(closure_track_caller)]
 #![feature(const_btree_new)]
 #![feature(let_else)]
 #![feature(once_cell)]
diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
index e156930cc89..579d7efb568 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
@@ -72,7 +72,7 @@ use rustc_middle::ty::{
     subst::{GenericArgKind, Subst, SubstsRef},
     Binder, EarlyBinder, List, Region, Ty, TyCtxt, TypeFoldable,
 };
-use rustc_span::{sym, BytePos, DesugaringKind, Pos, Span};
+use rustc_span::{sym, symbol::kw, BytePos, DesugaringKind, Pos, Span};
 use rustc_target::spec::abi;
 use std::ops::ControlFlow;
 use std::{cmp, fmt, iter};
@@ -161,35 +161,45 @@ fn msg_span_from_early_bound_and_free_regions<'tcx>(
             {
                 sp = param.span;
             }
-            (format!("the lifetime `{}` as defined here", br.name), sp)
+            let text = if br.has_name() {
+                format!("the lifetime `{}` as defined here", br.name)
+            } else {
+                format!("the anonymous lifetime as defined here")
+            };
+            (text, sp)
         }
-        ty::ReFree(ty::FreeRegion {
-            bound_region: ty::BoundRegionKind::BrNamed(_, name), ..
-        }) => {
-            let mut sp = sm.guess_head_span(tcx.def_span(scope));
-            if let Some(param) =
-                tcx.hir().get_generics(scope).and_then(|generics| generics.get_named(name))
+        ty::ReFree(ref fr) => {
+            if !fr.bound_region.is_named()
+                && let Some((ty, _)) = find_anon_type(tcx, region, &fr.bound_region)
             {
-                sp = param.span;
-            }
-            (format!("the lifetime `{}` as defined here", name), sp)
-        }
-        ty::ReFree(ref fr) => match fr.bound_region {
-            ty::BrAnon(idx) => {
-                if let Some((ty, _)) = find_anon_type(tcx, region, &fr.bound_region) {
-                    ("the anonymous lifetime defined here".to_string(), ty.span)
-                } else {
-                    (
+                ("the anonymous lifetime defined here".to_string(), ty.span)
+            } else {
+                match fr.bound_region {
+                    ty::BoundRegionKind::BrNamed(_, name) => {
+                        let mut sp = sm.guess_head_span(tcx.def_span(scope));
+                        if let Some(param) =
+                            tcx.hir().get_generics(scope).and_then(|generics| generics.get_named(name))
+                        {
+                            sp = param.span;
+                        }
+                        let text = if name == kw::UnderscoreLifetime {
+                            format!("the anonymous lifetime as defined here")
+                        } else {
+                            format!("the lifetime `{}` as defined here", name)
+                        };
+                        (text, sp)
+                    }
+                    ty::BrAnon(idx) => (
                         format!("the anonymous lifetime #{} defined here", idx + 1),
-                        tcx.def_span(scope),
-                    )
+                        tcx.def_span(scope)
+                    ),
+                    _ => (
+                        format!("the lifetime `{}` as defined here", region),
+                        sm.guess_head_span(tcx.def_span(scope)),
+                    ),
                 }
             }
-            _ => (
-                format!("the lifetime `{}` as defined here", region),
-                sm.guess_head_span(tcx.def_span(scope)),
-            ),
-        },
+        }
         _ => bug!(),
     }
 }
@@ -2552,7 +2562,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
                 ty::ReEarlyBound(ty::EarlyBoundRegion { name, .. })
                 | ty::ReFree(ty::FreeRegion { bound_region: ty::BrNamed(_, name), .. }),
                 _,
-            ) => {
+            ) if name != kw::UnderscoreLifetime => {
                 // Does the required lifetime have a nice name we can print?
                 let mut err = struct_span_err!(
                     self.tcx.sess,
diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/different_lifetimes.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/different_lifetimes.rs
index cb72cb41a7c..b744594ddb7 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/different_lifetimes.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/different_lifetimes.rs
@@ -12,6 +12,7 @@ use rustc_errors::{struct_span_err, Applicability, Diagnostic, ErrorGuaranteed};
 use rustc_hir as hir;
 use rustc_hir::{GenericParamKind, Ty};
 use rustc_middle::ty::Region;
+use rustc_span::symbol::kw;
 
 impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
     /// Print the error message for lifetime errors when both the concerned regions are anonymous.
@@ -169,7 +170,7 @@ pub fn suggest_adding_lifetime_params<'tcx>(
         return false;
     };
 
-    if !lifetime_sub.name.is_elided() || !lifetime_sup.name.is_elided() {
+    if !lifetime_sub.name.is_anonymous() || !lifetime_sup.name.is_anonymous() {
         return false;
     };
 
@@ -188,32 +189,37 @@ pub fn suggest_adding_lifetime_params<'tcx>(
         _ => return false,
     };
 
-    let (suggestion_param_name, introduce_new) = generics
+    let suggestion_param_name = generics
         .params
         .iter()
-        .find(|p| matches!(p.kind, GenericParamKind::Lifetime { .. }))
-        .and_then(|p| tcx.sess.source_map().span_to_snippet(p.span).ok())
-        .map(|name| (name, false))
-        .unwrap_or_else(|| ("'a".to_string(), true));
-
-    let mut suggestions = vec![
-        if let hir::LifetimeName::Underscore = lifetime_sub.name {
-            (lifetime_sub.span, suggestion_param_name.clone())
+        .filter(|p| matches!(p.kind, GenericParamKind::Lifetime { .. }))
+        .map(|p| p.name.ident().name)
+        .find(|i| *i != kw::UnderscoreLifetime);
+    let introduce_new = suggestion_param_name.is_none();
+    let suggestion_param_name =
+        suggestion_param_name.map(|n| n.to_string()).unwrap_or_else(|| "'a".to_owned());
+
+    debug!(?lifetime_sup.span);
+    debug!(?lifetime_sub.span);
+    let make_suggestion = |span: rustc_span::Span| {
+        if span.is_empty() {
+            (span, format!("{}, ", suggestion_param_name))
+        } else if let Ok("&") = tcx.sess.source_map().span_to_snippet(span).as_deref() {
+            (span.shrink_to_hi(), format!("{} ", suggestion_param_name))
         } else {
-            (lifetime_sub.span.shrink_to_hi(), suggestion_param_name.clone() + " ")
-        },
-        if let hir::LifetimeName::Underscore = lifetime_sup.name {
-            (lifetime_sup.span, suggestion_param_name.clone())
-        } else {
-            (lifetime_sup.span.shrink_to_hi(), suggestion_param_name.clone() + " ")
-        },
-    ];
+            (span, suggestion_param_name.clone())
+        }
+    };
+    let mut suggestions =
+        vec![make_suggestion(lifetime_sub.span), make_suggestion(lifetime_sup.span)];
 
     if introduce_new {
-        let new_param_suggestion = match &generics.params {
-            [] => (generics.span, format!("<{}>", suggestion_param_name)),
-            [first, ..] => (first.span.shrink_to_lo(), format!("{}, ", suggestion_param_name)),
-        };
+        let new_param_suggestion =
+            if let Some(first) = generics.params.iter().find(|p| !p.name.ident().span.is_empty()) {
+                (first.span.shrink_to_lo(), format!("{}, ", suggestion_param_name))
+            } else {
+                (generics.span, format!("<{}>", suggestion_param_name))
+            };
 
         suggestions.push(new_param_suggestion);
     }
diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/named_anon_conflict.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/named_anon_conflict.rs
index 3de5273d8c7..375ad8d3736 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/named_anon_conflict.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/named_anon_conflict.rs
@@ -4,6 +4,7 @@ use crate::infer::error_reporting::nice_region_error::find_anon_type::find_anon_
 use crate::infer::error_reporting::nice_region_error::NiceRegionError;
 use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed};
 use rustc_middle::ty;
+use rustc_span::symbol::kw;
 
 impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
     /// When given a `ConcreteFailure` for a function with parameters containing a named region and
@@ -67,7 +68,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
         let is_impl_item = region_info.is_impl_item;
 
         match br {
-            ty::BrAnon(_) => {}
+            ty::BrNamed(_, kw::UnderscoreLifetime) | ty::BrAnon(_) => {}
             _ => {
                 /* not an anonymous region */
                 debug!("try_report_named_anon_conflict: not an anonymous region");
diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs
index b09d39996f4..d9cdca8bcb5 100644
--- a/compiler/rustc_middle/src/mir/mod.rs
+++ b/compiler/rustc_middle/src/mir/mod.rs
@@ -2604,9 +2604,20 @@ 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::PointerExposeAddress, _, _))
+    }
+}
+
 #[derive(Clone, Copy, Debug, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable)]
 pub enum CastKind {
     Misc,
+    /// An exposing pointer to address cast. A cast between a pointer and an integer type, or
+    /// between a function pointer and an integer type.
+    /// See the docs on `expose_addr` for more details.
+    PointerExposeAddress,
     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_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index 4c0bc2e4337..64c63e3d567 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -2177,61 +2177,47 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
         define_scoped_cx!(self);
 
         let mut region_index = self.region_index;
+        let mut next_name = |this: &Self| loop {
+            let name = name_by_region_index(region_index);
+            region_index += 1;
+            if !this.used_region_names.contains(&name) {
+                break name;
+            }
+        };
+
         // If we want to print verbosely, then print *all* binders, even if they
         // aren't named. Eventually, we might just want this as the default, but
         // this is not *quite* right and changes the ordering of some output
         // anyways.
         let (new_value, map) = if self.tcx().sess.verbose() {
             // anon index + 1 (BrEnv takes 0) -> name
-            let mut region_map: BTreeMap<u32, Symbol> = BTreeMap::default();
+            let mut region_map: FxHashMap<_, _> = Default::default();
             let bound_vars = value.bound_vars();
             for var in bound_vars {
+                let ty::BoundVariableKind::Region(var) = var else { continue };
                 match var {
-                    ty::BoundVariableKind::Region(ty::BrNamed(_, name)) => {
+                    ty::BrAnon(_) | ty::BrEnv => {
                         start_or_continue(&mut self, "for<", ", ");
+                        let name = next_name(&self);
                         do_continue(&mut self, name);
+                        region_map.insert(var, ty::BrNamed(CRATE_DEF_ID.to_def_id(), name));
                     }
-                    ty::BoundVariableKind::Region(ty::BrAnon(i)) => {
+                    ty::BrNamed(def_id, kw::UnderscoreLifetime) => {
                         start_or_continue(&mut self, "for<", ", ");
-                        let name = loop {
-                            let name = name_by_region_index(region_index);
-                            region_index += 1;
-                            if !self.used_region_names.contains(&name) {
-                                break name;
-                            }
-                        };
+                        let name = next_name(&self);
                         do_continue(&mut self, name);
-                        region_map.insert(i + 1, name);
+                        region_map.insert(var, ty::BrNamed(def_id, name));
                     }
-                    ty::BoundVariableKind::Region(ty::BrEnv) => {
+                    ty::BrNamed(_, name) => {
                         start_or_continue(&mut self, "for<", ", ");
-                        let name = loop {
-                            let name = name_by_region_index(region_index);
-                            region_index += 1;
-                            if !self.used_region_names.contains(&name) {
-                                break name;
-                            }
-                        };
                         do_continue(&mut self, name);
-                        region_map.insert(0, name);
                     }
-                    _ => continue,
                 }
             }
             start_or_continue(&mut self, "", "> ");
 
             self.tcx.replace_late_bound_regions(value.clone(), |br| {
-                let kind = match br.kind {
-                    ty::BrNamed(_, _) => br.kind,
-                    ty::BrAnon(i) => {
-                        let name = region_map[&(i + 1)];
-                        ty::BrNamed(CRATE_DEF_ID.to_def_id(), name)
-                    }
-                    ty::BrEnv => {
-                        let name = region_map[&0];
-                        ty::BrNamed(CRATE_DEF_ID.to_def_id(), name)
-                    }
-                };
+                let kind = region_map[&br.kind];
                 self.tcx.mk_region(ty::ReLateBound(
                     ty::INNERMOST,
                     ty::BoundRegion { var: br.var, kind },
@@ -2242,21 +2228,20 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
             let mut name = |br: ty::BoundRegion| {
                 start_or_continue(&mut self, "for<", ", ");
                 let kind = match br.kind {
-                    ty::BrNamed(_, name) => {
-                        do_continue(&mut self, name);
-                        br.kind
-                    }
                     ty::BrAnon(_) | ty::BrEnv => {
-                        let name = loop {
-                            let name = name_by_region_index(region_index);
-                            region_index += 1;
-                            if !self.used_region_names.contains(&name) {
-                                break name;
-                            }
-                        };
+                        let name = next_name(&self);
                         do_continue(&mut self, name);
                         ty::BrNamed(CRATE_DEF_ID.to_def_id(), name)
                     }
+                    ty::BrNamed(def_id, kw::UnderscoreLifetime) => {
+                        let name = next_name(&self);
+                        do_continue(&mut self, name);
+                        ty::BrNamed(def_id, name)
+                    }
+                    ty::BrNamed(_, name) => {
+                        do_continue(&mut self, name);
+                        br.kind
+                    }
                 };
                 tcx.mk_region(ty::ReLateBound(ty::INNERMOST, ty::BoundRegion { var: br.var, kind }))
             };
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..7d08b20631e 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::PointerExposeAddress
+                    }
+                    (_, _) => 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_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs
index 8198938da64..a4cdfdf55f9 100644
--- a/compiler/rustc_parse/src/parser/diagnostics.rs
+++ b/compiler/rustc_parse/src/parser/diagnostics.rs
@@ -1,8 +1,7 @@
 use super::pat::Expected;
-use super::ty::{AllowPlus, RecoverQuestionMark};
 use super::{
-    BlockMode, CommaRecoveryMode, Parser, PathStyle, RecoverColon, RecoverComma, Restrictions,
-    SemiColonMode, SeqSep, TokenExpectType, TokenType,
+    BlockMode, CommaRecoveryMode, Parser, PathStyle, Restrictions, SemiColonMode, SeqSep,
+    TokenExpectType, TokenType,
 };
 
 use crate::lexer::UnmatchedBrace;
@@ -1281,26 +1280,14 @@ impl<'a> Parser<'a> {
         }
     }
 
-    pub(super) fn maybe_report_ambiguous_plus(
-        &mut self,
-        allow_plus: AllowPlus,
-        impl_dyn_multi: bool,
-        ty: &Ty,
-    ) {
-        if matches!(allow_plus, AllowPlus::No) && impl_dyn_multi {
+    pub(super) fn maybe_report_ambiguous_plus(&mut self, impl_dyn_multi: bool, ty: &Ty) {
+        if impl_dyn_multi {
             self.sess.emit_err(AmbiguousPlus { sum_ty: pprust::ty_to_string(&ty), span: ty.span });
         }
     }
 
     /// Swift lets users write `Ty?` to mean `Option<Ty>`. Parse the construct and recover from it.
-    pub(super) fn maybe_recover_from_question_mark(
-        &mut self,
-        ty: P<Ty>,
-        recover_question_mark: RecoverQuestionMark,
-    ) -> P<Ty> {
-        if let RecoverQuestionMark::No = recover_question_mark {
-            return ty;
-        }
+    pub(super) fn maybe_recover_from_question_mark(&mut self, ty: P<Ty>) -> P<Ty> {
         if self.token == token::Question {
             self.bump();
             self.struct_span_err(self.prev_token.span, "invalid `?` in type")
@@ -1320,13 +1307,9 @@ impl<'a> Parser<'a> {
         }
     }
 
-    pub(super) fn maybe_recover_from_bad_type_plus(
-        &mut self,
-        allow_plus: AllowPlus,
-        ty: &Ty,
-    ) -> PResult<'a, ()> {
+    pub(super) fn maybe_recover_from_bad_type_plus(&mut self, ty: &Ty) -> PResult<'a, ()> {
         // Do not add `+` to expected tokens.
-        if matches!(allow_plus, AllowPlus::No) || !self.token.is_like_plus() {
+        if !self.token.is_like_plus() {
             return Ok(());
         }
 
@@ -1492,10 +1475,9 @@ impl<'a> Parser<'a> {
     pub(super) fn maybe_recover_from_bad_qpath<T: RecoverQPath>(
         &mut self,
         base: P<T>,
-        allow_recovery: bool,
     ) -> PResult<'a, P<T>> {
         // Do not add `::` to expected tokens.
-        if allow_recovery && self.token == token::ModSep {
+        if self.token == token::ModSep {
             if let Some(ty) = base.to_ty() {
                 return self.maybe_recover_from_bad_qpath_stage_2(ty.span, ty);
             }
@@ -1634,7 +1616,7 @@ impl<'a> Parser<'a> {
             _ => ExprKind::Await(expr),
         };
         let expr = self.mk_expr(lo.to(sp), kind, attrs);
-        self.maybe_recover_from_bad_qpath(expr, true)
+        self.maybe_recover_from_bad_qpath(expr)
     }
 
     fn recover_await_macro(&mut self) -> PResult<'a, (Span, P<Expr>, bool)> {
@@ -2490,10 +2472,9 @@ impl<'a> Parser<'a> {
     pub(crate) fn maybe_recover_colon_colon_in_pat_typo(
         &mut self,
         mut first_pat: P<Pat>,
-        ra: RecoverColon,
         expected: Expected,
     ) -> P<Pat> {
-        if RecoverColon::Yes != ra || token::Colon != self.token.kind {
+        if token::Colon != self.token.kind {
             return first_pat;
         }
         if !matches!(first_pat.kind, PatKind::Ident(_, _, None) | PatKind::Path(..))
@@ -2627,10 +2608,9 @@ impl<'a> Parser<'a> {
     pub(crate) fn maybe_recover_unexpected_comma(
         &mut self,
         lo: Span,
-        rc: RecoverComma,
         rt: CommaRecoveryMode,
     ) -> PResult<'a, ()> {
-        if rc == RecoverComma::No || self.token != token::Comma {
+        if self.token != token::Comma {
             return Ok(());
         }
 
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs
index bb6d892138a..63c7decbb2f 100644
--- a/compiler/rustc_parse/src/parser/expr.rs
+++ b/compiler/rustc_parse/src/parser/expr.rs
@@ -1417,7 +1417,7 @@ impl<'a> Parser<'a> {
         match self.parse_opt_lit() {
             Some(literal) => {
                 let expr = self.mk_expr(lo.to(self.prev_token.span), ExprKind::Lit(literal), attrs);
-                self.maybe_recover_from_bad_qpath(expr, true)
+                self.maybe_recover_from_bad_qpath(expr)
             }
             None => self.try_macro_suggestion(),
         }
@@ -1444,7 +1444,7 @@ impl<'a> Parser<'a> {
             ExprKind::Tup(es)
         };
         let expr = self.mk_expr(lo.to(self.prev_token.span), kind, attrs);
-        self.maybe_recover_from_bad_qpath(expr, true)
+        self.maybe_recover_from_bad_qpath(expr)
     }
 
     fn parse_array_or_repeat_expr(
@@ -1481,7 +1481,7 @@ impl<'a> Parser<'a> {
             }
         };
         let expr = self.mk_expr(lo.to(self.prev_token.span), kind, attrs);
-        self.maybe_recover_from_bad_qpath(expr, true)
+        self.maybe_recover_from_bad_qpath(expr)
     }
 
     fn parse_path_start_expr(&mut self, attrs: AttrVec) -> PResult<'a, P<Expr>> {
@@ -1519,7 +1519,7 @@ impl<'a> Parser<'a> {
         };
 
         let expr = self.mk_expr(lo.to(hi), kind, attrs);
-        self.maybe_recover_from_bad_qpath(expr, true)
+        self.maybe_recover_from_bad_qpath(expr)
     }
 
     /// Parse `'label: $expr`. The label is already parsed.
@@ -1604,7 +1604,7 @@ impl<'a> Parser<'a> {
         let lo = self.prev_token.span;
         let kind = ExprKind::Ret(self.parse_expr_opt()?);
         let expr = self.mk_expr(lo.to(self.prev_token.span), kind, attrs);
-        self.maybe_recover_from_bad_qpath(expr, true)
+        self.maybe_recover_from_bad_qpath(expr)
     }
 
     /// Parse `"do" "yeet" expr?`.
@@ -1619,7 +1619,7 @@ impl<'a> Parser<'a> {
         let span = lo.to(self.prev_token.span);
         self.sess.gated_spans.gate(sym::yeet_expr, span);
         let expr = self.mk_expr(span, kind, attrs);
-        self.maybe_recover_from_bad_qpath(expr, true)
+        self.maybe_recover_from_bad_qpath(expr)
     }
 
     /// Parse `"break" (('label (:? expr)?) | expr?)` with `"break"` token already eaten.
@@ -1679,7 +1679,7 @@ impl<'a> Parser<'a> {
             None
         };
         let expr = self.mk_expr(lo.to(self.prev_token.span), ExprKind::Break(label, kind), attrs);
-        self.maybe_recover_from_bad_qpath(expr, true)
+        self.maybe_recover_from_bad_qpath(expr)
     }
 
     /// Parse `"yield" expr?`.
@@ -1689,7 +1689,7 @@ impl<'a> Parser<'a> {
         let span = lo.to(self.prev_token.span);
         self.sess.gated_spans.gate(sym::generators, span);
         let expr = self.mk_expr(span, kind, attrs);
-        self.maybe_recover_from_bad_qpath(expr, true)
+        self.maybe_recover_from_bad_qpath(expr)
     }
 
     /// Returns a string literal if the next token is a string literal.
diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs
index 8019c5fb67c..2ad3f3ec19d 100644
--- a/compiler/rustc_parse/src/parser/pat.rs
+++ b/compiler/rustc_parse/src/parser/pat.rs
@@ -100,8 +100,10 @@ impl<'a> Parser<'a> {
         };
 
         // Parse the first pattern (`p_0`).
-        let first_pat = self.parse_pat_no_top_alt(expected)?;
-        self.maybe_recover_unexpected_comma(first_pat.span, rc, rt)?;
+        let mut first_pat = self.parse_pat_no_top_alt(expected)?;
+        if rc == RecoverComma::Yes {
+            self.maybe_recover_unexpected_comma(first_pat.span, rt)?;
+        }
 
         // If the next token is not a `|`,
         // this is not an or-pattern and we should exit here.
@@ -111,7 +113,9 @@ impl<'a> Parser<'a> {
             // This complicated procedure is done purely for diagnostics UX.
 
             // Check if the user wrote `foo:bar` instead of `foo::bar`.
-            let first_pat = self.maybe_recover_colon_colon_in_pat_typo(first_pat, ra, expected);
+            if ra == RecoverColon::Yes {
+                first_pat = self.maybe_recover_colon_colon_in_pat_typo(first_pat, expected);
+            }
 
             if let Some(leading_vert_span) = leading_vert_span {
                 // If there was a leading vert, treat this as an or-pattern. This improves
@@ -139,7 +143,9 @@ impl<'a> Parser<'a> {
                 err.span_label(lo, WHILE_PARSING_OR_MSG);
                 err
             })?;
-            self.maybe_recover_unexpected_comma(pat.span, rc, rt)?;
+            if rc == RecoverComma::Yes {
+                self.maybe_recover_unexpected_comma(pat.span, rt)?;
+            }
             pats.push(pat);
         }
         let or_pattern_span = lo.to(self.prev_token.span);
@@ -408,7 +414,7 @@ impl<'a> Parser<'a> {
         };
 
         let pat = self.mk_pat(lo.to(self.prev_token.span), pat);
-        let pat = self.maybe_recover_from_bad_qpath(pat, true)?;
+        let pat = self.maybe_recover_from_bad_qpath(pat)?;
         let pat = self.recover_intersection_pat(pat)?;
 
         if !allow_range_pat {
diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs
index 27a6a487474..7907ec44e98 100644
--- a/compiler/rustc_parse/src/parser/stmt.rs
+++ b/compiler/rustc_parse/src/parser/stmt.rs
@@ -180,7 +180,7 @@ impl<'a> Parser<'a> {
         } else {
             // Since none of the above applied, this is an expression statement macro.
             let e = self.mk_expr(lo.to(hi), ExprKind::MacCall(mac), AttrVec::new());
-            let e = self.maybe_recover_from_bad_qpath(e, true)?;
+            let e = self.maybe_recover_from_bad_qpath(e)?;
             let e = self.parse_dot_or_call_expr_with(e, lo, attrs.into())?;
             let e = self.parse_assoc_expr_with(0, LhsExpr::AlreadyParsed(e))?;
             StmtKind::Expr(e)
diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs
index fb3f5eb3f9f..dee025cfd3c 100644
--- a/compiler/rustc_parse/src/parser/ty.rs
+++ b/compiler/rustc_parse/src/parser/ty.rs
@@ -312,13 +312,18 @@ impl<'a> Parser<'a> {
         };
 
         let span = lo.to(self.prev_token.span);
-        let ty = self.mk_ty(span, kind);
+        let mut ty = self.mk_ty(span, kind);
 
         // Try to recover from use of `+` with incorrect priority.
-        self.maybe_report_ambiguous_plus(allow_plus, impl_dyn_multi, &ty);
-        self.maybe_recover_from_bad_type_plus(allow_plus, &ty)?;
-        let ty = self.maybe_recover_from_question_mark(ty, recover_question_mark);
-        self.maybe_recover_from_bad_qpath(ty, allow_qpath_recovery)
+        if matches!(allow_plus, AllowPlus::Yes) {
+            self.maybe_recover_from_bad_type_plus(&ty)?;
+        } else {
+            self.maybe_report_ambiguous_plus(impl_dyn_multi, &ty);
+        }
+        if let RecoverQuestionMark::Yes = recover_question_mark {
+            ty = self.maybe_recover_from_question_mark(ty);
+        }
+        if allow_qpath_recovery { self.maybe_recover_from_bad_qpath(ty) } else { Ok(ty) }
     }
 
     /// Parses either:
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_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs
index a71621a4d52..641b915f373 100644
--- a/compiler/rustc_trait_selection/src/traits/project.rs
+++ b/compiler/rustc_trait_selection/src/traits/project.rs
@@ -145,15 +145,28 @@ impl<'tcx> ProjectionCandidateSet<'tcx> {
     }
 }
 
-/// Takes the place of a
+/// States returned from `poly_project_and_unify_type`. Takes the place
+/// of the old return type, which was:
+/// ```ignore (not-rust)
 /// Result<
 ///     Result<Option<Vec<PredicateObligation<'tcx>>>, InProgress>,
 ///     MismatchedProjectionTypes<'tcx>,
 /// >
+/// ```
 pub(super) enum ProjectAndUnifyResult<'tcx> {
+    /// The projection bound holds subject to the given obligations. If the
+    /// projection cannot be normalized because the required trait bound does
+    /// not hold, this is returned, with `obligations` being a predicate that
+    /// cannot be proven.
     Holds(Vec<PredicateObligation<'tcx>>),
+    /// The projection cannot be normalized due to ambiguity. Resolving some
+    /// inference variables in the projection may fix this.
     FailedNormalization,
+    /// The project cannot be normalized because `poly_project_and_unify_type`
+    /// is called recursively while normalizing the same projection.
     Recursive,
+    // the projection can be normalized, but is not equal to the expected type.
+    // Returns the type error that arose from the mismatch.
     MismatchedProjectionTypes(MismatchedProjectionTypes<'tcx>),
 }
 
@@ -163,19 +176,6 @@ pub(super) enum ProjectAndUnifyResult<'tcx> {
 /// ```
 /// If successful, this may result in additional obligations. Also returns
 /// the projection cache key used to track these additional obligations.
-///
-/// ## Returns
-///
-/// - `Err(_)`: the projection can be normalized, but is not equal to the
-///   expected type.
-/// - `Ok(Err(InProgress))`: this is called recursively while normalizing
-///   the same projection.
-/// - `Ok(Ok(None))`: The projection cannot be normalized due to ambiguity
-///   (resolving some inference variables in the projection may fix this).
-/// - `Ok(Ok(Some(obligations)))`: The projection bound holds subject to
-///    the given obligations. If the projection cannot be normalized because
-///    the required trait bound doesn't hold this returned with `obligations`
-///    being a predicate that cannot be proven.
 #[instrument(level = "debug", skip(selcx))]
 pub(super) fn poly_project_and_unify_type<'cx, 'tcx>(
     selcx: &mut SelectionContext<'cx, 'tcx>,
diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs
index 0379b16334c..2ce2a44d3db 100644
--- a/compiler/rustc_trait_selection/src/traits/wf.rs
+++ b/compiler/rustc_trait_selection/src/traits/wf.rs
@@ -81,10 +81,17 @@ pub fn trait_obligations<'a, 'tcx>(
     body_id: hir::HirId,
     trait_ref: &ty::TraitRef<'tcx>,
     span: Span,
-    item: Option<&'tcx hir::Item<'tcx>>,
+    item: &'tcx hir::Item<'tcx>,
 ) -> Vec<traits::PredicateObligation<'tcx>> {
-    let mut wf =
-        WfPredicates { infcx, param_env, body_id, span, out: vec![], recursion_depth: 0, item };
+    let mut wf = WfPredicates {
+        infcx,
+        param_env,
+        body_id,
+        span,
+        out: vec![],
+        recursion_depth: 0,
+        item: Some(item),
+    };
     wf.compute_trait_ref(trait_ref, Elaborate::All);
     debug!(obligations = ?wf.out);
     wf.normalize()
diff --git a/compiler/rustc_typeck/src/check/check.rs b/compiler/rustc_typeck/src/check/check.rs
index 7499e5efdee..de5367ca27c 100644
--- a/compiler/rustc_typeck/src/check/check.rs
+++ b/compiler/rustc_typeck/src/check/check.rs
@@ -8,10 +8,11 @@ use super::*;
 use rustc_attr as attr;
 use rustc_errors::{Applicability, ErrorGuaranteed, MultiSpan};
 use rustc_hir as hir;
+use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::intravisit::Visitor;
 use rustc_hir::lang_items::LangItem;
-use rustc_hir::{def::Res, ItemKind, Node, PathSegment};
+use rustc_hir::{ItemKind, Node, PathSegment};
 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
 use rustc_infer::infer::{RegionVariableOrigin, TyCtxtInferExt};
 use rustc_infer::traits::Obligation;
@@ -29,7 +30,6 @@ use rustc_trait_selection::traits;
 use rustc_trait_selection::traits::error_reporting::InferCtxtExt as _;
 use rustc_ty_utils::representability::{self, Representability};
 
-use rustc_hir::def::DefKind;
 use std::iter;
 use std::ops::ControlFlow;
 
@@ -93,7 +93,6 @@ pub(super) fn check_fn<'a, 'tcx>(
     fcx.return_type_pre_known = return_type_pre_known;
 
     let tcx = fcx.tcx;
-    let sess = tcx.sess;
     let hir = tcx.hir();
 
     let declared_ret_ty = fn_sig.output();
@@ -259,85 +258,123 @@ pub(super) fn check_fn<'a, 'tcx>(
     if let Some(panic_impl_did) = tcx.lang_items().panic_impl()
         && panic_impl_did == hir.local_def_id(fn_id).to_def_id()
     {
-        if let Some(panic_info_did) = tcx.lang_items().panic_info() {
-            if *declared_ret_ty.kind() != ty::Never {
-                sess.span_err(decl.output.span(), "return type should be `!`");
-            }
-
-            let inputs = fn_sig.inputs();
-            let span = hir.span(fn_id);
-            if inputs.len() == 1 {
-                let arg_is_panic_info = match *inputs[0].kind() {
-                    ty::Ref(region, ty, mutbl) => match *ty.kind() {
-                        ty::Adt(ref adt, _) => {
-                            adt.did() == panic_info_did
-                                && mutbl == hir::Mutability::Not
-                                && !region.is_static()
-                        }
-                        _ => false,
-                    },
-                    _ => false,
-                };
-
-                if !arg_is_panic_info {
-                    sess.span_err(decl.inputs[0].span, "argument should be `&PanicInfo`");
-                }
-
-                if let Node::Item(item) = hir.get(fn_id)
-                    && let ItemKind::Fn(_, ref generics, _) = item.kind
-                    && !generics.params.is_empty()
-                {
-                            sess.span_err(span, "should have no type parameters");
-                        }
-            } else {
-                let span = sess.source_map().guess_head_span(span);
-                sess.span_err(span, "function should have one argument");
-            }
-        } else {
-            sess.err("language item required, but not found: `panic_info`");
-        }
+        check_panic_info_fn(tcx, panic_impl_did.expect_local(), fn_sig, decl, declared_ret_ty);
     }
 
     // Check that a function marked as `#[alloc_error_handler]` has signature `fn(Layout) -> !`
     if let Some(alloc_error_handler_did) = tcx.lang_items().oom()
         && alloc_error_handler_did == hir.local_def_id(fn_id).to_def_id()
     {
-        if let Some(alloc_layout_did) = tcx.lang_items().alloc_layout() {
-            if *declared_ret_ty.kind() != ty::Never {
-                sess.span_err(decl.output.span(), "return type should be `!`");
-            }
+        check_alloc_error_fn(tcx, alloc_error_handler_did.expect_local(), fn_sig, decl, declared_ret_ty);
+    }
 
-            let inputs = fn_sig.inputs();
-            let span = hir.span(fn_id);
-            if inputs.len() == 1 {
-                let arg_is_alloc_layout = match inputs[0].kind() {
-                    ty::Adt(ref adt, _) => adt.did() == alloc_layout_did,
-                    _ => false,
-                };
+    (fcx, gen_ty)
+}
 
-                if !arg_is_alloc_layout {
-                    sess.span_err(decl.inputs[0].span, "argument should be `Layout`");
-                }
+fn check_panic_info_fn(
+    tcx: TyCtxt<'_>,
+    fn_id: LocalDefId,
+    fn_sig: ty::FnSig<'_>,
+    decl: &hir::FnDecl<'_>,
+    declared_ret_ty: Ty<'_>,
+) {
+    let Some(panic_info_did) = tcx.lang_items().panic_info() else {
+        tcx.sess.err("language item required, but not found: `panic_info`");
+        return;
+    };
 
-                if let Node::Item(item) = hir.get(fn_id)
-                    && let ItemKind::Fn(_, ref generics, _) = item.kind
-                    && !generics.params.is_empty()
-                {
-                            sess.span_err(
-                                span,
-                        "`#[alloc_error_handler]` function should have no type parameters",
-                            );
-                        }
-            } else {
-                let span = sess.source_map().guess_head_span(span);
-                sess.span_err(span, "function should have one argument");
+    if *declared_ret_ty.kind() != ty::Never {
+        tcx.sess.span_err(decl.output.span(), "return type should be `!`");
+    }
+
+    let span = tcx.def_span(fn_id);
+    let inputs = fn_sig.inputs();
+    if inputs.len() != 1 {
+        let span = tcx.sess.source_map().guess_head_span(span);
+        tcx.sess.span_err(span, "function should have one argument");
+        return;
+    }
+
+    let arg_is_panic_info = match *inputs[0].kind() {
+        ty::Ref(region, ty, mutbl) => match *ty.kind() {
+            ty::Adt(ref adt, _) => {
+                adt.did() == panic_info_did && mutbl == hir::Mutability::Not && !region.is_static()
             }
-        } else {
-            sess.err("language item required, but not found: `alloc_layout`");
-        }
+            _ => false,
+        },
+        _ => false,
+    };
+
+    if !arg_is_panic_info {
+        tcx.sess.span_err(decl.inputs[0].span, "argument should be `&PanicInfo`");
     }
 
-    (fcx, gen_ty)
+    let DefKind::Fn = tcx.def_kind(fn_id) else {
+        let span = tcx.def_span(fn_id);
+        tcx.sess.span_err(span, "should be a function");
+        return;
+    };
+
+    let generic_counts = tcx.generics_of(fn_id).own_counts();
+    if generic_counts.types != 0 {
+        let span = tcx.def_span(fn_id);
+        tcx.sess.span_err(span, "should have no type parameters");
+    }
+    if generic_counts.consts != 0 {
+        let span = tcx.def_span(fn_id);
+        tcx.sess.span_err(span, "should have no const parameters");
+    }
+}
+
+fn check_alloc_error_fn(
+    tcx: TyCtxt<'_>,
+    fn_id: LocalDefId,
+    fn_sig: ty::FnSig<'_>,
+    decl: &hir::FnDecl<'_>,
+    declared_ret_ty: Ty<'_>,
+) {
+    let Some(alloc_layout_did) = tcx.lang_items().alloc_layout() else {
+        tcx.sess.err("language item required, but not found: `alloc_layout`");
+        return;
+    };
+
+    if *declared_ret_ty.kind() != ty::Never {
+        tcx.sess.span_err(decl.output.span(), "return type should be `!`");
+    }
+
+    let inputs = fn_sig.inputs();
+    if inputs.len() != 1 {
+        let span = tcx.def_span(fn_id);
+        let span = tcx.sess.source_map().guess_head_span(span);
+        tcx.sess.span_err(span, "function should have one argument");
+        return;
+    }
+
+    let arg_is_alloc_layout = match inputs[0].kind() {
+        ty::Adt(ref adt, _) => adt.did() == alloc_layout_did,
+        _ => false,
+    };
+
+    if !arg_is_alloc_layout {
+        tcx.sess.span_err(decl.inputs[0].span, "argument should be `Layout`");
+    }
+
+    let DefKind::Fn = tcx.def_kind(fn_id) else {
+        let span = tcx.def_span(fn_id);
+        tcx.sess.span_err(span, "`#[alloc_error_handler]` should be a function");
+        return;
+    };
+
+    let generic_counts = tcx.generics_of(fn_id).own_counts();
+    if generic_counts.types != 0 {
+        let span = tcx.def_span(fn_id);
+        tcx.sess.span_err(span, "`#[alloc_error_handler]` function should have no type parameters");
+    }
+    if generic_counts.consts != 0 {
+        let span = tcx.def_span(fn_id);
+        tcx.sess
+            .span_err(span, "`#[alloc_error_handler]` function should have no const parameters");
+    }
 }
 
 fn check_struct(tcx: TyCtxt<'_>, def_id: LocalDefId, span: Span) {
diff --git a/compiler/rustc_typeck/src/check/compare_method.rs b/compiler/rustc_typeck/src/check/compare_method.rs
index 277bc1cf0f0..4d17307ddb9 100644
--- a/compiler/rustc_typeck/src/check/compare_method.rs
+++ b/compiler/rustc_typeck/src/check/compare_method.rs
@@ -660,8 +660,24 @@ fn compare_number_of_generics<'tcx>(
                     _ => None,
                 })
                 .collect();
-            let spans = impl_item.generics.spans();
-            let span = spans.primary_span();
+            let spans = if impl_item.generics.params.is_empty() {
+                vec![impl_item.generics.span]
+            } else {
+                impl_item
+                    .generics
+                    .params
+                    .iter()
+                    .filter(|p| {
+                        matches!(
+                            p.kind,
+                            hir::GenericParamKind::Type { .. }
+                                | hir::GenericParamKind::Const { .. }
+                        )
+                    })
+                    .map(|p| p.span)
+                    .collect::<Vec<Span>>()
+            };
+            let span = spans.first().copied();
 
             let mut err = tcx.sess.struct_span_err_with_code(
                 spans,
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/compiler/rustc_typeck/src/check/wfcheck.rs b/compiler/rustc_typeck/src/check/wfcheck.rs
index a6c7573b787..20ef97c085f 100644
--- a/compiler/rustc_typeck/src/check/wfcheck.rs
+++ b/compiler/rustc_typeck/src/check/wfcheck.rs
@@ -1228,7 +1228,7 @@ fn check_impl<'tcx>(
                     fcx.body_id,
                     &trait_ref,
                     ast_trait_ref.path.span,
-                    Some(item),
+                    item,
                 );
                 debug!(?obligations);
                 for obligation in obligations {
diff --git a/compiler/rustc_typeck/src/collect/type_of.rs b/compiler/rustc_typeck/src/collect/type_of.rs
index 4b6f80ce57a..7e3fefe4502 100644
--- a/compiler/rustc_typeck/src/collect/type_of.rs
+++ b/compiler/rustc_typeck/src/collect/type_of.rs
@@ -161,38 +161,23 @@ pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<
             // We've encountered an `AnonConst` in some path, so we need to
             // figure out which generic parameter it corresponds to and return
             // the relevant type.
-            let filtered = path.segments.iter().find_map(|seg| {
-                seg.args?
-                    .args
+            let Some((arg_index, segment)) = path.segments.iter().find_map(|seg| {
+                let args = seg.args?;
+                args.args
+                .iter()
+                .filter(|arg| arg.is_ty_or_const())
+                .position(|arg| arg.id() == hir_id)
+                .map(|index| (index, seg)).or_else(|| args.bindings
                     .iter()
-                    .filter(|arg| arg.is_ty_or_const())
-                    .position(|arg| arg.id() == hir_id)
-                    .map(|index| (index, seg))
-            });
-
-            // FIXME(associated_const_generics): can we blend this with iteration above?
-            let (arg_index, segment) = match filtered {
-                None => {
-                    let binding_filtered = path.segments.iter().find_map(|seg| {
-                        seg.args?
-                            .bindings
-                            .iter()
-                            .filter_map(TypeBinding::opt_const)
-                            .position(|ct| ct.hir_id == hir_id)
-                            .map(|idx| (idx, seg))
-                    });
-                    match binding_filtered {
-                        Some(inner) => inner,
-                        None => {
-                            tcx.sess.delay_span_bug(
-                                tcx.def_span(def_id),
-                                "no arg matching AnonConst in path",
-                            );
-                            return None;
-                        }
-                    }
-                }
-                Some(inner) => inner,
+                    .filter_map(TypeBinding::opt_const)
+                    .position(|ct| ct.hir_id == hir_id)
+                    .map(|idx| (idx, seg)))
+            }) else {
+                tcx.sess.delay_span_bug(
+                    tcx.def_span(def_id),
+                    "no arg matching AnonConst in path",
+                );
+                return None;
             };
 
             // Try to use the segment resolution if it is valid, otherwise we
diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs
index 41f3b1fa3dd..e2c692b5299 100644
--- a/library/alloc/src/boxed.rs
+++ b/library/alloc/src/boxed.rs
@@ -1175,14 +1175,33 @@ impl<T: ?Sized, A: Allocator> Box<T, A> {
     /// This conversion does not allocate on the heap and happens in place.
     ///
     /// This is also available via [`From`].
-    #[unstable(feature = "box_into_pin", issue = "62370")]
+    ///
+    /// # Notes
+    ///
+    /// It's not recommended that crates add an impl like `From<Box<T>> for Pin<T>`,
+    /// as it'll introduce an ambiguity when calling `Pin::from`.
+    /// A demonstration of such a poor impl is shown below.
+    ///
+    /// ```compile_fail
+    /// # use std::pin::Pin;
+    /// struct Foo; // A type defined in this crate.
+    /// impl From<Box<()>> for Pin<Foo> {
+    ///     fn from(_: Box<()>) -> Pin<Foo> {
+    ///         Pin::new(Foo)
+    ///     }
+    /// }
+    ///
+    /// let foo = Box::new(());
+    /// let bar = Pin::from(foo);
+    /// ```
+    #[stable(feature = "box_into_pin", since = "1.63.0")]
     #[rustc_const_unstable(feature = "const_box", issue = "92521")]
     pub const fn into_pin(boxed: Self) -> Pin<Self>
     where
         A: 'static,
     {
         // It's not possible to move or replace the insides of a `Pin<Box<T>>`
-        // when `T: !Unpin`,  so it's safe to pin it directly without any
+        // when `T: !Unpin`, so it's safe to pin it directly without any
         // additional requirements.
         unsafe { Pin::new_unchecked(boxed) }
     }
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..caa629cf4e6 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.
@@ -770,10 +770,14 @@ impl<T> BTreeSet<T> {
 
     /// Adds a value to the set.
     ///
-    /// If the set did not have an equal element present, `true` is returned.
+    /// Returns whether the value was newly inserted. That is:
     ///
-    /// If the set did have an equal element present, `false` is returned, and
-    /// the entry is not updated. See the [module-level documentation] for more.
+    /// - If the set did not previously contain an equal value, `true` is
+    ///   returned.
+    /// - If the set already contained an equal value, `false` is returned, and
+    ///   the entry is not updated.
+    ///
+    /// See the [module-level documentation] for more.
     ///
     /// [module-level documentation]: index.html#insert-and-complex-keys
     ///
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/num/dec2flt/mod.rs b/library/core/src/num/dec2flt/mod.rs
index df0e7431f1f..a888ced49b3 100644
--- a/library/core/src/num/dec2flt/mod.rs
+++ b/library/core/src/num/dec2flt/mod.rs
@@ -126,7 +126,6 @@ macro_rules! from_str_float_impl {
             /// ```txt
             /// Float  ::= Sign? ( 'inf' | 'infinity' | 'nan' | Number )
             /// Number ::= ( Digit+ |
-            ///              '.' Digit* |
             ///              Digit+ '.' Digit* |
             ///              Digit* '.' Digit+ ) Exp?
             /// Exp    ::= 'e' Sign? Digit+
diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs
index 1aaa274a054..1fbf592c232 100644
--- a/library/core/src/ptr/mut_ptr.rs
+++ b/library/core/src/ptr/mut_ptr.rs
@@ -1622,6 +1622,122 @@ impl<T> *mut [T] {
         metadata(self)
     }
 
+    /// Returns `true` if the raw slice has a length of 0.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(slice_ptr_len)]
+    ///
+    /// let mut a = [1, 2, 3];
+    /// let ptr = &mut a as *mut [_];
+    /// assert!(!ptr.is_empty());
+    /// ```
+    #[inline(always)]
+    #[unstable(feature = "slice_ptr_len", issue = "71146")]
+    #[rustc_const_unstable(feature = "const_slice_ptr_len", issue = "71146")]
+    pub const fn is_empty(self) -> bool {
+        self.len() == 0
+    }
+
+    /// Divides one mutable raw slice into two at an index.
+    ///
+    /// The first will contain all indices from `[0, mid)` (excluding
+    /// the index `mid` itself) and the second will contain all
+    /// indices from `[mid, len)` (excluding the index `len` itself).
+    ///
+    /// # Panics
+    ///
+    /// Panics if `mid > len`.
+    ///
+    /// # Safety
+    ///
+    /// `mid` must be [in-bounds] of the underlying [allocated object].
+    /// Which means `self` must be dereferenceable and span a single allocation
+    /// that is at least `mid * size_of::<T>()` bytes long. Not upholding these
+    /// requirements is *[undefined behavior]* even if the resulting pointers are not used.
+    ///
+    /// Since `len` being in-bounds it is not a safety invariant of `*mut [T]` the
+    /// safety requirements of this method are the same as for [`split_at_mut_unchecked`].
+    /// The explicit bounds check is only as useful as `len` is correct.
+    ///
+    /// [`split_at_mut_unchecked`]: #method.split_at_mut_unchecked
+    /// [in-bounds]: #method.add
+    /// [allocated object]: crate::ptr#allocated-object
+    /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(raw_slice_split)]
+    /// #![feature(slice_ptr_get)]
+    ///
+    /// let mut v = [1, 0, 3, 0, 5, 6];
+    /// let ptr = &mut v as *mut [_];
+    /// unsafe {
+    ///     let (left, right) = ptr.split_at_mut(2);
+    ///     assert_eq!(&*left, [1, 0]);
+    ///     assert_eq!(&*right, [3, 0, 5, 6]);
+    /// }
+    /// ```
+    #[inline(always)]
+    #[track_caller]
+    #[unstable(feature = "raw_slice_split", issue = "95595")]
+    pub unsafe fn split_at_mut(self, mid: usize) -> (*mut [T], *mut [T]) {
+        assert!(mid <= self.len());
+        // SAFETY: The assert above is only a safety-net as long as `self.len()` is correct
+        // The actual safety requirements of this function are the same as for `split_at_mut_unchecked`
+        unsafe { self.split_at_mut_unchecked(mid) }
+    }
+
+    /// Divides one mutable raw slice into two at an index, without doing bounds checking.
+    ///
+    /// The first will contain all indices from `[0, mid)` (excluding
+    /// the index `mid` itself) and the second will contain all
+    /// indices from `[mid, len)` (excluding the index `len` itself).
+    ///
+    /// # Safety
+    ///
+    /// `mid` must be [in-bounds] of the underlying [allocated object].
+    /// Which means `self` must be dereferenceable and span a single allocation
+    /// that is at least `mid * size_of::<T>()` bytes long. Not upholding these
+    /// requirements is *[undefined behavior]* even if the resulting pointers are not used.
+    ///
+    /// [in-bounds]: #method.add
+    /// [out-of-bounds index]: #method.add
+    /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(raw_slice_split)]
+    ///
+    /// let mut v = [1, 0, 3, 0, 5, 6];
+    /// // scoped to restrict the lifetime of the borrows
+    /// unsafe {
+    ///     let ptr = &mut v as *mut [_];
+    ///     let (left, right) = ptr.split_at_mut_unchecked(2);
+    ///     assert_eq!(&*left, [1, 0]);
+    ///     assert_eq!(&*right, [3, 0, 5, 6]);
+    ///     (&mut *left)[1] = 2;
+    ///     (&mut *right)[1] = 4;
+    /// }
+    /// assert_eq!(v, [1, 2, 3, 4, 5, 6]);
+    /// ```
+    #[inline(always)]
+    #[unstable(feature = "raw_slice_split", issue = "95595")]
+    pub unsafe fn split_at_mut_unchecked(self, mid: usize) -> (*mut [T], *mut [T]) {
+        let len = self.len();
+        let ptr = self.as_mut_ptr();
+
+        // SAFETY: Caller must pass a valid pointer and an index that is in-bounds.
+        let tail = unsafe { ptr.add(mid) };
+        (
+            crate::ptr::slice_from_raw_parts_mut(ptr, mid),
+            crate::ptr::slice_from_raw_parts_mut(tail, len - mid),
+        )
+    }
+
     /// Returns a raw pointer to the slice's buffer.
     ///
     /// This is equivalent to casting `self` to `*mut T`, but more type-safe.
@@ -1645,9 +1761,10 @@ impl<T> *mut [T] {
     /// Returns a raw pointer to an element or subslice, without doing bounds
     /// checking.
     ///
-    /// Calling this method with an out-of-bounds index or when `self` is not dereferenceable
+    /// Calling this method with an [out-of-bounds index] or when `self` is not dereferenceable
     /// is *[undefined behavior]* even if the resulting pointer is not used.
     ///
+    /// [out-of-bounds index]: #method.add
     /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
     ///
     /// # Examples
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..11ccdd9ea1c 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].
@@ -895,6 +896,119 @@ where
         self.base.get_key_value(k)
     }
 
+    /// Attempts to get mutable references to `N` values in the map at once.
+    ///
+    /// Returns an array of length `N` with the results of each query. For soundness, at most one
+    /// mutable reference will be returned to any value. `None` will be returned if any of the
+    /// keys are duplicates or missing.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(map_many_mut)]
+    /// use std::collections::HashMap;
+    ///
+    /// let mut libraries = HashMap::new();
+    /// libraries.insert("Bodleian Library".to_string(), 1602);
+    /// libraries.insert("Athenæum".to_string(), 1807);
+    /// libraries.insert("Herzogin-Anna-Amalia-Bibliothek".to_string(), 1691);
+    /// libraries.insert("Library of Congress".to_string(), 1800);
+    ///
+    /// let got = libraries.get_many_mut([
+    ///     "Athenæum",
+    ///     "Library of Congress",
+    /// ]);
+    /// assert_eq!(
+    ///     got,
+    ///     Some([
+    ///         &mut 1807,
+    ///         &mut 1800,
+    ///     ]),
+    /// );
+    ///
+    /// // Missing keys result in None
+    /// let got = libraries.get_many_mut([
+    ///     "Athenæum",
+    ///     "New York Public Library",
+    /// ]);
+    /// assert_eq!(got, None);
+    ///
+    /// // Duplicate keys result in None
+    /// let got = libraries.get_many_mut([
+    ///     "Athenæum",
+    ///     "Athenæum",
+    /// ]);
+    /// assert_eq!(got, None);
+    /// ```
+    #[inline]
+    #[unstable(feature = "map_many_mut", issue = "97601")]
+    pub fn get_many_mut<Q: ?Sized, const N: usize>(&mut self, ks: [&Q; N]) -> Option<[&'_ mut V; N]>
+    where
+        K: Borrow<Q>,
+        Q: Hash + Eq,
+    {
+        self.base.get_many_mut(ks)
+    }
+
+    /// Attempts to get mutable references to `N` values in the map at once, without validating that
+    /// the values are unique.
+    ///
+    /// Returns an array of length `N` with the results of each query. `None` will be returned if
+    /// any of the keys are missing.
+    ///
+    /// For a safe alternative see [`get_many_mut`](Self::get_many_mut).
+    ///
+    /// # Safety
+    ///
+    /// Calling this method with overlapping keys is *[undefined behavior]* even if the resulting
+    /// references are not used.
+    ///
+    /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(map_many_mut)]
+    /// use std::collections::HashMap;
+    ///
+    /// let mut libraries = HashMap::new();
+    /// libraries.insert("Bodleian Library".to_string(), 1602);
+    /// libraries.insert("Athenæum".to_string(), 1807);
+    /// libraries.insert("Herzogin-Anna-Amalia-Bibliothek".to_string(), 1691);
+    /// libraries.insert("Library of Congress".to_string(), 1800);
+    ///
+    /// let got = libraries.get_many_mut([
+    ///     "Athenæum",
+    ///     "Library of Congress",
+    /// ]);
+    /// assert_eq!(
+    ///     got,
+    ///     Some([
+    ///         &mut 1807,
+    ///         &mut 1800,
+    ///     ]),
+    /// );
+    ///
+    /// // Missing keys result in None
+    /// let got = libraries.get_many_mut([
+    ///     "Athenæum",
+    ///     "New York Public Library",
+    /// ]);
+    /// assert_eq!(got, None);
+    /// ```
+    #[inline]
+    #[unstable(feature = "map_many_mut", issue = "97601")]
+    pub unsafe fn get_many_unchecked_mut<Q: ?Sized, const N: usize>(
+        &mut self,
+        ks: [&Q; N],
+    ) -> Option<[&'_ mut V; N]>
+    where
+        K: Borrow<Q>,
+        Q: Hash + Eq,
+    {
+        self.base.get_many_unchecked_mut(ks)
+    }
+
     /// Returns `true` if the map contains a value for the specified key.
     ///
     /// The key may be any borrowed form of the map's key type, but
diff --git a/library/std/src/collections/hash/set.rs b/library/std/src/collections/hash/set.rs
index 4ac0e081c2e..19428fe9a23 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
 ///
@@ -857,9 +858,10 @@ where
 
     /// Adds a value to the set.
     ///
-    /// If the set did not have this value present, `true` is returned.
+    /// Returns whether the value was newly inserted. That is:
     ///
-    /// If the set did have this value present, `false` is returned.
+    /// - If the set did not previously contain this value, `true` is returned.
+    /// - If the set already contained this value, `false` is returned.
     ///
     /// # Examples
     ///
diff --git a/library/std/src/sync/mpsc/cache_aligned.rs b/library/std/src/sync/mpsc/cache_aligned.rs
index f95b0ddd589..9197f0d6e6c 100644
--- a/library/std/src/sync/mpsc/cache_aligned.rs
+++ b/library/std/src/sync/mpsc/cache_aligned.rs
@@ -1,7 +1,8 @@
 use crate::ops::{Deref, DerefMut};
 
 #[derive(Copy, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
-#[repr(align(64))]
+#[cfg_attr(target_arch = "aarch64", repr(align(128)))]
+#[cfg_attr(not(target_arch = "aarch64"), repr(align(64)))]
 pub(super) struct CacheAligned<T>(pub T);
 
 impl<T> Deref for CacheAligned<T> {
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index 1e434458dce..4605793d0df 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -1667,6 +1667,10 @@ impl Type {
         matches!(self, Type::Generic(_))
     }
 
+    pub(crate) fn is_impl_trait(&self) -> bool {
+        matches!(self, Type::ImplTrait(_))
+    }
+
     pub(crate) fn is_primitive(&self) -> bool {
         self.primitive_type().is_some()
     }
diff --git a/src/librustdoc/formats/mod.rs b/src/librustdoc/formats/mod.rs
index 2367bde0167..9f26ccc74d1 100644
--- a/src/librustdoc/formats/mod.rs
+++ b/src/librustdoc/formats/mod.rs
@@ -7,6 +7,7 @@ use rustc_hir::def_id::DefId;
 pub(crate) use renderer::{run_format, FormatRenderer};
 
 use crate::clean::{self, ItemId};
+use cache::Cache;
 
 /// Specifies whether rendering directly implemented trait items or ones from a certain Deref
 /// impl.
@@ -60,4 +61,28 @@ impl Impl {
             }
         }
     }
+
+    // Returns true if this is an implementation on a "local" type, meaning:
+    // the type is in the current crate, or the type and the trait are both
+    // re-exported by the current crate.
+    pub(crate) fn is_on_local_type(&self, cache: &Cache) -> bool {
+        let for_type = &self.inner_impl().for_;
+        if let Some(for_type_did) = for_type.def_id(cache) {
+            // The "for" type is local if it's in the paths for the current crate.
+            if cache.paths.contains_key(&for_type_did) {
+                return true;
+            }
+            if let Some(trait_did) = self.trait_did() {
+                // The "for" type and the trait are from the same crate. That could
+                // be different from the current crate, for instance when both were
+                // re-exported from some other crate. But they are local with respect to
+                // each other.
+                if for_type_did.krate == trait_did.krate {
+                    return true;
+                }
+            }
+            return false;
+        };
+        true
+    }
 }
diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs
index b8d6b340b14..0b801a20995 100644
--- a/src/librustdoc/html/render/mod.rs
+++ b/src/librustdoc/html/render/mod.rs
@@ -2285,9 +2285,7 @@ fn sidebar_trait(cx: &Context<'_>, buf: &mut Buffer, it: &clean::Item, t: &clean
     if let Some(implementors) = cache.implementors.get(&it.item_id.expect_def_id()) {
         let mut res = implementors
             .iter()
-            .filter(|i| {
-                i.inner_impl().for_.def_id(cache).map_or(false, |d| !cache.paths.contains_key(&d))
-            })
+            .filter(|i| !i.is_on_local_type(cache))
             .filter_map(|i| extract_for_impl_name(&i.impl_item, cx))
             .collect::<Vec<_>>();
 
diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs
index dcf36b5e865..8683e6dfcd9 100644
--- a/src/librustdoc/html/render/print_item.rs
+++ b/src/librustdoc/html/render/print_item.rs
@@ -822,9 +822,8 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean:
             }
         }
 
-        let (local, foreign) = implementors.iter().partition::<Vec<_>, _>(|i| {
-            i.inner_impl().for_.def_id(cache).map_or(true, |d| cache.paths.contains_key(&d))
-        });
+        let (local, foreign) =
+            implementors.iter().partition::<Vec<_>, _>(|i| i.is_on_local_type(cache));
 
         let (mut synthetic, mut concrete): (Vec<&&Impl>, Vec<&&Impl>) =
             local.iter().partition(|i| i.inner_impl().kind.is_auto());
diff --git a/src/librustdoc/html/render/search_index.rs b/src/librustdoc/html/render/search_index.rs
index 25c70f0808c..9f302cc2566 100644
--- a/src/librustdoc/html/render/search_index.rs
+++ b/src/librustdoc/html/render/search_index.rs
@@ -226,17 +226,17 @@ fn get_index_type_name(clean_type: &clean::Type) -> Option<Symbol> {
             Some(path.segments.last().unwrap().name)
         }
         // We return an empty name because we don't care about the generic name itself.
-        clean::Generic(_) => Some(kw::Empty),
+        clean::Generic(_) | clean::ImplTrait(_) => Some(kw::Empty),
         clean::Primitive(ref p) => Some(p.as_sym()),
-        clean::BorrowedRef { ref type_, .. } => get_index_type_name(type_),
+        clean::BorrowedRef { ref type_, .. } | clean::RawPointer(_, ref type_) => {
+            get_index_type_name(type_)
+        }
         clean::BareFunction(_)
         | clean::Tuple(_)
         | clean::Slice(_)
         | clean::Array(_, _)
-        | clean::RawPointer(_, _)
         | clean::QPath { .. }
-        | clean::Infer
-        | clean::ImplTrait(_) => None,
+        | clean::Infer => None,
     }
 }
 
@@ -264,10 +264,12 @@ fn add_generics_and_bounds_as_types<'tcx, 'a>(
         mut generics: Vec<TypeWithKind>,
         cache: &Cache,
     ) {
-        let is_full_generic = ty.is_full_generic();
+        // generics and impl trait are both identified by their generics,
+        // rather than a type name itself
+        let anonymous = ty.is_full_generic() || ty.is_impl_trait();
         let generics_empty = generics.is_empty();
 
-        if is_full_generic {
+        if anonymous {
             if generics_empty {
                 // This is a type parameter with no trait bounds (for example: `T` in
                 // `fn f<T>(p: T)`, so not useful for the rustdoc search because we would end up
@@ -318,7 +320,7 @@ fn add_generics_and_bounds_as_types<'tcx, 'a>(
         if index_ty.name.as_ref().map(|s| s.is_empty() && generics_empty).unwrap_or(true) {
             return;
         }
-        if is_full_generic {
+        if anonymous {
             // We remove the name of the full generic because we have no use for it.
             index_ty.name = Some(String::new());
             res.push(TypeWithKind::from((index_ty, ItemType::Generic)));
@@ -398,6 +400,23 @@ fn add_generics_and_bounds_as_types<'tcx, 'a>(
             }
             insert_ty(res, tcx, arg.clone(), ty_generics, cache);
         }
+    } else if let Type::ImplTrait(ref bounds) = *arg {
+        let mut ty_generics = Vec::new();
+        for bound in bounds {
+            if let Some(path) = bound.get_trait_path() {
+                let ty = Type::Path { path };
+                add_generics_and_bounds_as_types(
+                    self_,
+                    generics,
+                    &ty,
+                    tcx,
+                    recurse + 1,
+                    &mut ty_generics,
+                    cache,
+                );
+            }
+        }
+        insert_ty(res, tcx, arg.clone(), ty_generics, cache);
     } else {
         // This is not a type parameter. So for example if we have `T, U: Option<T>`, and we're
         // looking at `Option`, we enter this "else" condition, otherwise if it's `T`, we don't.
diff --git a/src/librustdoc/passes/collect_trait_impls.rs b/src/librustdoc/passes/collect_trait_impls.rs
index aa7028247be..6ea33d763b1 100644
--- a/src/librustdoc/passes/collect_trait_impls.rs
+++ b/src/librustdoc/passes/collect_trait_impls.rs
@@ -9,7 +9,7 @@ use crate::visit::DocVisitor;
 
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_hir::def_id::DefId;
-use rustc_middle::ty::DefIdTree;
+use rustc_middle::ty::{self, DefIdTree};
 use rustc_span::symbol::sym;
 
 pub(crate) const COLLECT_TRAIT_IMPLS: Pass = Pass {
@@ -81,8 +81,35 @@ pub(crate) fn collect_trait_impls(mut krate: Crate, cx: &mut DocContext<'_>) ->
             // Do not calculate blanket impl list for docs that are not going to be rendered.
             // While the `impl` blocks themselves are only in `libcore`, the module with `doc`
             // attached is directly included in `libstd` as well.
+            let tcx = cx.tcx;
             if did.is_local() {
-                for def_id in prim.impls(cx.tcx) {
+                for def_id in prim.impls(tcx).filter(|def_id| {
+                    // Avoid including impl blocks with filled-in generics.
+                    // https://github.com/rust-lang/rust/issues/94937
+                    //
+                    // FIXME(notriddle): https://github.com/rust-lang/rust/issues/97129
+                    //
+                    // This tactic of using inherent impl blocks for getting
+                    // auto traits and blanket impls is a hack. What we really
+                    // want is to check if `[T]` impls `Send`, which has
+                    // nothing to do with the inherent impl.
+                    //
+                    // Rustdoc currently uses these `impl` block as a source of
+                    // the `Ty`, as well as the `ParamEnv`, `SubstsRef`, and
+                    // `Generics`. To avoid relying on the `impl` block, these
+                    // things would need to be created from wholecloth, in a
+                    // form that is valid for use in type inference.
+                    let ty = tcx.type_of(def_id);
+                    match ty.kind() {
+                        ty::Slice(ty)
+                        | ty::Ref(_, ty, _)
+                        | ty::RawPtr(ty::TypeAndMut { ty, .. }) => {
+                            matches!(ty.kind(), ty::Param(..))
+                        }
+                        ty::Tuple(tys) => tys.iter().all(|ty| matches!(ty.kind(), ty::Param(..))),
+                        _ => true,
+                    }
+                }) {
                     let impls = get_auto_trait_and_blanket_impls(cx, def_id);
                     new_items_external.extend(impls.filter(|i| cx.inlined.insert(i.item_id)));
                 }
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..84d72202d52 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 (PointerExposeAddress); // 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..04724b13ca6 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 (PointerExposeAddress); // 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..2331f63ecdd 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 (PointerExposeAddress); // 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 (PointerExposeAddress); // 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-js/impl-trait.js b/src/test/rustdoc-js/impl-trait.js
new file mode 100644
index 00000000000..8d594bf8aea
--- /dev/null
+++ b/src/test/rustdoc-js/impl-trait.js
@@ -0,0 +1,51 @@
+// ignore-order
+
+const QUERY = [
+    'Aaaaaaa -> i32',
+    'Aaaaaaa -> Aaaaaaa',
+    'Aaaaaaa -> usize',
+    '-> Aaaaaaa',
+    'Aaaaaaa',
+];
+
+const EXPECTED = [
+    {
+        // Aaaaaaa -> i32
+        'others': [
+            { 'path': 'impl_trait::Ccccccc', 'name': 'eeeeeee' },
+        ],
+    },
+    {
+        // Aaaaaaa -> Aaaaaaa
+        'others': [
+            { 'path': 'impl_trait::Ccccccc', 'name': 'fffffff' },
+        ],
+    },
+    {
+        // Aaaaaaa -> usize
+        'others': [],
+    },
+    {
+        // -> Aaaaaaa
+        'others': [
+            { 'path': 'impl_trait::Ccccccc', 'name': 'fffffff' },
+            { 'path': 'impl_trait::Ccccccc', 'name': 'ddddddd' },
+            { 'path': 'impl_trait', 'name': 'bbbbbbb' },
+        ],
+    },
+    {
+        // Aaaaaaa
+        'others': [
+            { 'path': 'impl_trait', 'name': 'Aaaaaaa' },
+        ],
+        'in_args': [
+            { 'path': 'impl_trait::Ccccccc', 'name': 'fffffff' },
+            { 'path': 'impl_trait::Ccccccc', 'name': 'eeeeeee' },
+        ],
+        'returned': [
+            { 'path': 'impl_trait::Ccccccc', 'name': 'fffffff' },
+            { 'path': 'impl_trait::Ccccccc', 'name': 'ddddddd' },
+            { 'path': 'impl_trait', 'name': 'bbbbbbb' },
+        ],
+    },
+];
diff --git a/src/test/rustdoc-js/impl-trait.rs b/src/test/rustdoc-js/impl-trait.rs
new file mode 100644
index 00000000000..fb8869b46f3
--- /dev/null
+++ b/src/test/rustdoc-js/impl-trait.rs
@@ -0,0 +1,21 @@
+pub trait Aaaaaaa {}
+
+impl Aaaaaaa for () {}
+
+pub fn bbbbbbb() -> impl Aaaaaaa {
+    ()
+}
+
+pub struct Ccccccc {}
+
+impl Ccccccc {
+    pub fn ddddddd(&self) -> impl Aaaaaaa {
+        ()
+    }
+    pub fn eeeeeee(&self, _x: impl Aaaaaaa) -> i32 {
+        0
+    }
+    pub fn fffffff(&self, x: impl Aaaaaaa) -> impl Aaaaaaa {
+        x
+    }
+}
diff --git a/src/test/rustdoc-js/raw-pointer.js b/src/test/rustdoc-js/raw-pointer.js
new file mode 100644
index 00000000000..140b955ea71
--- /dev/null
+++ b/src/test/rustdoc-js/raw-pointer.js
@@ -0,0 +1,55 @@
+// ignore-order
+
+const QUERY = [
+    'Aaaaaaa -> i32',
+    'Aaaaaaa -> Aaaaaaa',
+    'Aaaaaaa -> usize',
+    '-> Aaaaaaa',
+    'Aaaaaaa',
+];
+
+const EXPECTED = [
+    {
+        // Aaaaaaa -> i32
+        'others': [
+            { 'path': 'raw_pointer::Ccccccc', 'name': 'eeeeeee' },
+        ],
+    },
+    {
+        // Aaaaaaa -> Aaaaaaa
+        'others': [
+            { 'path': 'raw_pointer::Ccccccc', 'name': 'fffffff' },
+            { 'path': 'raw_pointer::Ccccccc', 'name': 'ggggggg' },
+        ],
+    },
+    {
+        // Aaaaaaa -> usize
+        'others': [],
+    },
+    {
+        // -> Aaaaaaa
+        'others': [
+            { 'path': 'raw_pointer::Ccccccc', 'name': 'fffffff' },
+            { 'path': 'raw_pointer::Ccccccc', 'name': 'ggggggg' },
+            { 'path': 'raw_pointer::Ccccccc', 'name': 'ddddddd' },
+            { 'path': 'raw_pointer', 'name': 'bbbbbbb' },
+        ],
+    },
+    {
+        // Aaaaaaa
+        'others': [
+            { 'path': 'raw_pointer', 'name': 'Aaaaaaa' },
+        ],
+        'in_args': [
+            { 'path': 'raw_pointer::Ccccccc', 'name': 'fffffff' },
+            { 'path': 'raw_pointer::Ccccccc', 'name': 'ggggggg' },
+            { 'path': 'raw_pointer::Ccccccc', 'name': 'eeeeeee' },
+        ],
+        'returned': [
+            { 'path': 'raw_pointer::Ccccccc', 'name': 'fffffff' },
+            { 'path': 'raw_pointer::Ccccccc', 'name': 'ggggggg' },
+            { 'path': 'raw_pointer::Ccccccc', 'name': 'ddddddd' },
+            { 'path': 'raw_pointer', 'name': 'bbbbbbb' },
+        ],
+    },
+];
diff --git a/src/test/rustdoc-js/raw-pointer.rs b/src/test/rustdoc-js/raw-pointer.rs
new file mode 100644
index 00000000000..b8ace2e0b7d
--- /dev/null
+++ b/src/test/rustdoc-js/raw-pointer.rs
@@ -0,0 +1,24 @@
+use std::ptr;
+
+pub struct Aaaaaaa {}
+
+pub fn bbbbbbb() -> *const Aaaaaaa {
+    ptr::null()
+}
+
+pub struct Ccccccc {}
+
+impl Ccccccc {
+    pub fn ddddddd(&self) -> *const Aaaaaaa {
+        ptr::null()
+    }
+    pub fn eeeeeee(&self, _x: *const Aaaaaaa) -> i32 {
+        0
+    }
+    pub fn fffffff(&self, x: *const Aaaaaaa) -> *const Aaaaaaa {
+        x
+    }
+    pub fn ggggggg(&self, x: *mut Aaaaaaa) -> *mut Aaaaaaa {
+        x
+    }
+}
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/rustdoc/inline_cross/auxiliary/implementors_inline.rs b/src/test/rustdoc/inline_cross/auxiliary/implementors_inline.rs
new file mode 100644
index 00000000000..b003fb357d0
--- /dev/null
+++ b/src/test/rustdoc/inline_cross/auxiliary/implementors_inline.rs
@@ -0,0 +1,18 @@
+pub mod my_trait {
+    pub trait MyTrait {
+        fn my_fn(&self) -> Self;
+    }
+}
+
+pub mod prelude {
+    #[doc(inline)]
+    pub use crate::my_trait::MyTrait;
+}
+
+pub struct SomeStruct;
+
+impl my_trait::MyTrait for SomeStruct {
+    fn my_fn(&self) -> SomeStruct {
+        SomeStruct
+    }
+}
diff --git a/src/test/rustdoc/inline_cross/implementors-js.rs b/src/test/rustdoc/inline_cross/implementors-js.rs
new file mode 100644
index 00000000000..c79f05d8d3c
--- /dev/null
+++ b/src/test/rustdoc/inline_cross/implementors-js.rs
@@ -0,0 +1,25 @@
+// aux-build:implementors_inline.rs
+// build-aux-docs
+// ignore-cross-compile
+
+extern crate implementors_inline;
+
+// @!has implementors/implementors_js/trait.MyTrait.js
+// @has implementors/implementors_inline/my_trait/trait.MyTrait.js
+// @!has implementors/implementors_inline/prelude/trait.MyTrait.js
+// @has implementors_inline/my_trait/trait.MyTrait.html
+// @has - '//script/@src' '../../implementors/implementors_inline/my_trait/trait.MyTrait.js'
+// @has implementors_js/trait.MyTrait.html
+// @has - '//script/@src' '../implementors/implementors_inline/my_trait/trait.MyTrait.js'
+/// When re-exporting this trait, the HTML will be inlined,
+/// but, vitally, the JavaScript will be located only at the
+/// one canonical path.
+pub use implementors_inline::prelude::MyTrait;
+
+pub struct OtherStruct;
+
+impl MyTrait for OtherStruct {
+    fn my_fn(&self) -> OtherStruct {
+        OtherStruct
+    }
+}
diff --git a/src/test/rustdoc/intra-doc/email-address.rs b/src/test/rustdoc/intra-doc/email-address.rs
index ae74fbbc892..24161c3bb48 100644
--- a/src/test/rustdoc/intra-doc/email-address.rs
+++ b/src/test/rustdoc/intra-doc/email-address.rs
@@ -1,8 +1,10 @@
-#![allow(rustdoc::broken_intra_doc_links)]
+#![forbid(rustdoc::broken_intra_doc_links)]
 
 //! Email me at <hello@example.com>.
 //! Email me at <hello-world@example.com>.
-//! Email me at <hello@localhost> (this warns but will still become a link).
+//! Email me at <hello@localhost>.
+//! Email me at <prim@i32>.
 // @has email_address/index.html '//a[@href="mailto:hello@example.com"]' 'hello@example.com'
 // @has email_address/index.html '//a[@href="mailto:hello-world@example.com"]' 'hello-world@example.com'
 // @has email_address/index.html '//a[@href="mailto:hello@localhost"]' 'hello@localhost'
+// @has email_address/index.html '//a[@href="mailto:prim@i32"]' 'prim@i32'
diff --git a/src/test/rustdoc/issue-75588.rs b/src/test/rustdoc/issue-75588.rs
index ac97b94fb35..a8cb16ec34c 100644
--- a/src/test/rustdoc/issue-75588.rs
+++ b/src/test/rustdoc/issue-75588.rs
@@ -13,5 +13,5 @@ extern crate real_gimli;
 // @!has foo/trait.Deref.html '//*[@id="impl-Deref-for-EndianSlice"]//h3[@class="code-header in-band"]' 'impl Deref for EndianSlice'
 pub use realcore::Deref;
 
-// @has foo/trait.Join.html '//*[@id="impl-Join-for-Foo"]//h3[@class="code-header in-band"]' 'impl Join for Foo'
+// @has foo/trait.Join.html '//*[@id="impl-Join"]//h3[@class="code-header in-band"]' 'impl Join for Foo'
 pub use realcore::Join;
diff --git a/src/test/rustdoc/primitive-slice-auto-trait.rs b/src/test/rustdoc/primitive-slice-auto-trait.rs
new file mode 100644
index 00000000000..b3f511bc1f1
--- /dev/null
+++ b/src/test/rustdoc/primitive-slice-auto-trait.rs
@@ -0,0 +1,14 @@
+// compile-flags: --crate-type lib --edition 2018
+
+#![crate_name = "foo"]
+#![feature(rustdoc_internals)]
+
+// @has foo/primitive.slice.html '//a[@class="primitive"]' 'slice'
+// @has - '//span[@class="in-band"]' 'Primitive Type slice'
+// @has - '//section[@id="main-content"]//div[@class="docblock"]//p' 'this is a test!'
+// @has - '//h2[@id="synthetic-implementations"]' 'Auto Trait Implementations'
+// @has - '//div[@id="synthetic-implementations-list"]//h3' 'impl<T> Send for [T] where T: Send'
+// @has - '//div[@id="synthetic-implementations-list"]//h3' 'impl<T> Sync for [T] where T: Sync'
+#[doc(primitive = "slice")]
+/// this is a test!
+mod slice_prim {}
diff --git a/src/test/ui/async-await/issue-76547.base.stderr b/src/test/ui/async-await/issue-76547.base.stderr
index 34705d4838e..109883fbeb7 100644
--- a/src/test/ui/async-await/issue-76547.base.stderr
+++ b/src/test/ui/async-await/issue-76547.base.stderr
@@ -5,6 +5,12 @@ LL | async fn fut(bufs: &mut [&mut [u8]]) {
    |                    ---------------- these two types are declared with different lifetimes...
 LL |     ListFut(bufs).await
    |             ^^^^ ...but data from `bufs` flows into `bufs` here
+   |
+   = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter
+   |
+LL | async fn fut<'a>(bufs: &'a mut [&'a mut [u8]]) {
+   |             ++++        ++       ++
 
 error[E0623]: lifetime mismatch
   --> $DIR/issue-76547.rs:39:14
@@ -13,6 +19,12 @@ LL | async fn fut2(bufs: &mut [&mut [u8]]) -> i32 {
    |                     ---------------- these two types are declared with different lifetimes...
 LL |     ListFut2(bufs).await
    |              ^^^^ ...but data from `bufs` flows into `bufs` here
+   |
+   = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter
+   |
+LL | async fn fut2<'a>(bufs: &'a mut [&'a mut [u8]]) -> i32 {
+   |              ++++        ++       ++
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/async-await/issue-76547.nll.stderr b/src/test/ui/async-await/issue-76547.nll.stderr
index bc30da1e389..0a5a52cb79e 100644
--- a/src/test/ui/async-await/issue-76547.nll.stderr
+++ b/src/test/ui/async-await/issue-76547.nll.stderr
@@ -7,6 +7,11 @@ LL | async fn fut(bufs: &mut [&mut [u8]]) {
    |                    let's call the lifetime of this reference `'1`
 LL |     ListFut(bufs).await
    |             ^^^^ this usage requires that `'1` must outlive `'2`
+   |
+help: consider introducing a named lifetime parameter
+   |
+LL | async fn fut<'a>(bufs: &'a mut [&'a mut [u8]]) {
+   |             ++++        ++       ++
 
 error: lifetime may not live long enough
   --> $DIR/issue-76547.rs:39:14
@@ -17,6 +22,11 @@ LL | async fn fut2(bufs: &mut [&mut [u8]]) -> i32 {
    |                     let's call the lifetime of this reference `'1`
 LL |     ListFut2(bufs).await
    |              ^^^^ this usage requires that `'1` must outlive `'2`
+   |
+help: consider introducing a named lifetime parameter
+   |
+LL | async fn fut2<'a>(bufs: &'a mut [&'a mut [u8]]) -> i32 {
+   |              ++++        ++       ++
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/async-await/issues/issue-63388-1.base.stderr b/src/test/ui/async-await/issues/issue-63388-1.base.stderr
index 2ff85a27a46..f5409a7ca5d 100644
--- a/src/test/ui/async-await/issues/issue-63388-1.base.stderr
+++ b/src/test/ui/async-await/issues/issue-63388-1.base.stderr
@@ -1,14 +1,12 @@
-error[E0623]: lifetime mismatch
+error[E0621]: explicit lifetime required in the type of `foo`
   --> $DIR/issue-63388-1.rs:19:9
    |
 LL |         &'a self, foo: &dyn Foo
-   |                        -------- this parameter and the return type are declared with different lifetimes...
-LL |     ) -> &dyn Foo
-   |          --------
+   |                        -------- help: add explicit lifetime `'a` to the type of `foo`: `&'a (dyn Foo + 'a)`
 ...
 LL |         foo
-   |         ^^^ ...but data from `foo` is returned here
+   |         ^^^ lifetime `'a` required
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0623`.
+For more information about this error, try `rustc --explain E0621`.
diff --git a/src/test/ui/async-await/issues/issue-63388-1.nll.stderr b/src/test/ui/async-await/issues/issue-63388-1.nll.stderr
index eee0cee278b..9263a81bb6a 100644
--- a/src/test/ui/async-await/issues/issue-63388-1.nll.stderr
+++ b/src/test/ui/async-await/issues/issue-63388-1.nll.stderr
@@ -1,17 +1,16 @@
-error: lifetime may not live long enough
+error[E0621]: explicit lifetime required in the type of `foo`
   --> $DIR/issue-63388-1.rs:17:5
    |
-LL |       async fn do_sth<'a>(
-   |                       -- lifetime `'a` defined here
 LL |           &'a self, foo: &dyn Foo
-   |                          - let's call the lifetime of this reference `'1`
+   |                          -------- help: add explicit lifetime `'a` to the type of `foo`: `&'a (dyn Foo + 'a)`
 LL |       ) -> &dyn Foo
 LL | /     {
 LL | |
 LL | |         foo
 LL | |
 LL | |     }
-   | |_____^ associated function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'1`
+   | |_____^ lifetime `'a` required
 
 error: aborting due to previous error
 
+For more information about this error, try `rustc --explain E0621`.
diff --git a/src/test/ui/async-await/issues/issue-63388-1.rs b/src/test/ui/async-await/issues/issue-63388-1.rs
index c45d2a42177..f00f9295406 100644
--- a/src/test/ui/async-await/issues/issue-63388-1.rs
+++ b/src/test/ui/async-await/issues/issue-63388-1.rs
@@ -15,9 +15,9 @@ impl Xyz {
         &'a self, foo: &dyn Foo
     ) -> &dyn Foo
     {
-        //[nll]~^ ERROR lifetime may not live long enough
+        //[nll]~^ ERROR explicit lifetime required in the type of `foo` [E0621]
         foo
-        //[base]~^ ERROR lifetime mismatch
+        //[base]~^ ERROR explicit lifetime required in the type of `foo` [E0621]
     }
 }
 
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/borrowck/issue-71546.rs b/src/test/ui/borrowck/issue-71546.rs
new file mode 100644
index 00000000000..943f7f86e55
--- /dev/null
+++ b/src/test/ui/borrowck/issue-71546.rs
@@ -0,0 +1,19 @@
+// Regression test for #71546.
+
+// ignore-compare-mode-nll
+// NLL stderr is different from the original one.
+
+pub fn serialize_as_csv<V>(value: &V) -> Result<String, &str>
+where
+    V: 'static,
+    for<'a> &'a V: IntoIterator,
+    for<'a> <&'a V as IntoIterator>::Item: ToString + 'static,
+{
+    let csv_str: String = value //~ ERROR: the associated type `<&'a V as IntoIterator>::Item` may not live long enough
+        .into_iter()
+        .map(|elem| elem.to_string())
+        .collect::<String>();
+    Ok(csv_str)
+}
+
+fn main() {}
diff --git a/src/test/ui/borrowck/issue-71546.stderr b/src/test/ui/borrowck/issue-71546.stderr
new file mode 100644
index 00000000000..d479ca8f1d8
--- /dev/null
+++ b/src/test/ui/borrowck/issue-71546.stderr
@@ -0,0 +1,20 @@
+error[E0310]: the associated type `<&'a V as IntoIterator>::Item` may not live long enough
+  --> $DIR/issue-71546.rs:12:27
+   |
+LL |       let csv_str: String = value
+   |  ___________________________^
+LL | |         .into_iter()
+LL | |         .map(|elem| elem.to_string())
+   | |_____________________________________^
+   |
+   = help: consider adding an explicit lifetime bound `<&'a V as IntoIterator>::Item: 'static`...
+   = note: ...so that the type `<&'a V as IntoIterator>::Item` will meet its required lifetime bounds...
+note: ...that is required by this bound
+  --> $DIR/issue-71546.rs:10:55
+   |
+LL |     for<'a> <&'a V as IntoIterator>::Item: ToString + 'static,
+   |                                                       ^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0310`.
diff --git a/src/test/ui/codemap_tests/two_files.stderr b/src/test/ui/codemap_tests/two_files.stderr
index aff51ee9e2f..2eb3fd56783 100644
--- a/src/test/ui/codemap_tests/two_files.stderr
+++ b/src/test/ui/codemap_tests/two_files.stderr
@@ -5,6 +5,7 @@ LL | impl Bar for Baz { }
    |      ^^^ type aliases cannot be used as traits
    |
 help: you might have meant to use `#![feature(trait_alias)]` instead of a `type` alias
+  --> $DIR/two_files_data.rs:5:1
    |
 LL | trait Bar = dyn Foo;
    |
diff --git a/src/test/ui/const-generics/generic_const_exprs/issue-94287.stderr b/src/test/ui/const-generics/generic_const_exprs/issue-94287.stderr
index c918651ba62..7390a007742 100644
--- a/src/test/ui/const-generics/generic_const_exprs/issue-94287.stderr
+++ b/src/test/ui/const-generics/generic_const_exprs/issue-94287.stderr
@@ -6,6 +6,7 @@ LL |     If<{ FRAC <= 32 }>: True,
    |
    = note: the crate this constant originates from uses `#![feature(generic_const_exprs)]`
 help: consider enabling this feature
+  --> $DIR/issue-94287.rs:1:1
    |
 LL | #![feature(generic_const_exprs)]
    |
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/editions/edition-keywords-2015-2018-expansion.stderr b/src/test/ui/editions/edition-keywords-2015-2018-expansion.stderr
index 23dad2c16b2..570bbac2b21 100644
--- a/src/test/ui/editions/edition-keywords-2015-2018-expansion.stderr
+++ b/src/test/ui/editions/edition-keywords-2015-2018-expansion.stderr
@@ -6,6 +6,7 @@ LL |     produces_async! {}
    |
    = note: this error originates in the macro `produces_async` (in Nightly builds, run with -Z macro-backtrace for more info)
 help: escape `async` to use it as an identifier
+  --> $DIR/auxiliary/edition-kw-macro-2018.rs:7:19
    |
 LL |     () => (pub fn r#async() {})
    |                   ++
diff --git a/src/test/ui/editions/edition-keywords-2018-2018-expansion.stderr b/src/test/ui/editions/edition-keywords-2018-2018-expansion.stderr
index 67f9aa60413..69f275746bd 100644
--- a/src/test/ui/editions/edition-keywords-2018-2018-expansion.stderr
+++ b/src/test/ui/editions/edition-keywords-2018-2018-expansion.stderr
@@ -6,6 +6,7 @@ LL |     produces_async! {}
    |
    = note: this error originates in the macro `produces_async` (in Nightly builds, run with -Z macro-backtrace for more info)
 help: escape `async` to use it as an identifier
+  --> $DIR/auxiliary/edition-kw-macro-2018.rs:7:19
    |
 LL |     () => (pub fn r#async() {})
    |                   ++
diff --git a/src/test/ui/error-codes/E0308-2.stderr b/src/test/ui/error-codes/E0308-2.stderr
index 5c1dcb4d4f9..de54a417253 100644
--- a/src/test/ui/error-codes/E0308-2.stderr
+++ b/src/test/ui/error-codes/E0308-2.stderr
@@ -6,7 +6,7 @@ LL | impl Eq for &dyn DynEq {}
    |
    = note: expected trait `<&dyn DynEq as PartialEq>`
               found trait `<&(dyn DynEq + 'static) as PartialEq>`
-note: the lifetime `'_` as defined here...
+note: the anonymous lifetime as defined here...
   --> $DIR/E0308-2.rs:9:13
    |
 LL | impl Eq for &dyn DynEq {}
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/generic-associated-types/parameter_number_and_kind_impl.stderr b/src/test/ui/generic-associated-types/parameter_number_and_kind_impl.stderr
index 1458bf0c4a4..76d39c88b61 100644
--- a/src/test/ui/generic-associated-types/parameter_number_and_kind_impl.stderr
+++ b/src/test/ui/generic-associated-types/parameter_number_and_kind_impl.stderr
@@ -8,7 +8,7 @@ LL |     type A = u32;
    |           ^ lifetimes do not match type in trait
 
 error[E0049]: type `B` has 1 type parameter but its trait declaration has 0 type parameters
-  --> $DIR/parameter_number_and_kind_impl.rs:17:12
+  --> $DIR/parameter_number_and_kind_impl.rs:17:16
    |
 LL |     type B<'a, 'b>;
    |            --  --
@@ -16,9 +16,7 @@ LL |     type B<'a, 'b>;
    |            expected 0 type parameters
 ...
 LL |     type B<'a, T> = Vec<T>;
-   |            ^^  ^
-   |            |
-   |            found 1 type parameter
+   |                ^ found 1 type parameter
 
 error[E0195]: lifetime parameters or bounds on type `C` do not match the trait declaration
   --> $DIR/parameter_number_and_kind_impl.rs:19:11
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/issues/issue-17905-2.stderr b/src/test/ui/issues/issue-17905-2.stderr
index c68265f71f2..88b5fbec6cf 100644
--- a/src/test/ui/issues/issue-17905-2.stderr
+++ b/src/test/ui/issues/issue-17905-2.stderr
@@ -11,7 +11,7 @@ note: the anonymous lifetime defined here...
    |
 LL |     fn say(self: &Pair<&str, isize>) {
    |                        ^^^^
-note: ...does not necessarily outlive the lifetime `'_` as defined here
+note: ...does not necessarily outlive the anonymous lifetime as defined here
   --> $DIR/issue-17905-2.rs:5:5
    |
 LL |     &str,
@@ -25,7 +25,7 @@ LL |     fn say(self: &Pair<&str, isize>) {
    |
    = note: expected struct `Pair<&str, _>`
               found struct `Pair<&str, _>`
-note: the lifetime `'_` as defined here...
+note: the anonymous lifetime as defined here...
   --> $DIR/issue-17905-2.rs:5:5
    |
 LL |     &str,
diff --git a/src/test/ui/issues/issue-65230.stderr b/src/test/ui/issues/issue-65230.stderr
index bfeb38d6471..fcabcdea74f 100644
--- a/src/test/ui/issues/issue-65230.stderr
+++ b/src/test/ui/issues/issue-65230.stderr
@@ -6,7 +6,7 @@ LL | impl T1 for &dyn T2 {}
    |
    = note: expected trait `<&dyn T2 as T0>`
               found trait `<&(dyn T2 + 'static) as T0>`
-note: the lifetime `'_` as defined here...
+note: the anonymous lifetime as defined here...
   --> $DIR/issue-65230.rs:8:13
    |
 LL | impl T1 for &dyn T2 {}
diff --git a/src/test/ui/issues/issue-70724-add_type_neq_err_label-unwrap.stderr b/src/test/ui/issues/issue-70724-add_type_neq_err_label-unwrap.stderr
index 4c11f354494..c6e6ea1e096 100644
--- a/src/test/ui/issues/issue-70724-add_type_neq_err_label-unwrap.stderr
+++ b/src/test/ui/issues/issue-70724-add_type_neq_err_label-unwrap.stderr
@@ -9,6 +9,7 @@ LL |     assert_eq!(a, 0);
    |
    = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
 help: you might have forgotten to call this function
+  --> $SRC_DIR/core/src/macros/mod.rs:LL:COL
    |
 LL |                 if !(*left_val() == *right_val) {
    |                               ++
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/methods/method-on-ambiguous-numeric-type.stderr b/src/test/ui/methods/method-on-ambiguous-numeric-type.stderr
index 09978b35f7e..0af58bc61f4 100644
--- a/src/test/ui/methods/method-on-ambiguous-numeric-type.stderr
+++ b/src/test/ui/methods/method-on-ambiguous-numeric-type.stderr
@@ -46,6 +46,7 @@ LL |     bar.pow(2);
    |         ^^^
    |
 help: you must specify a type for this binding, like `i32`
+  --> $DIR/auxiliary/macro-in-other-crate.rs:3:29
    |
 LL |     ($ident:ident) => { let $ident: i32 = 42; }
    |                             ~~~~~~~~~~~
diff --git a/src/test/ui/nll/issue-52742.base.stderr b/src/test/ui/nll/issue-52742.base.stderr
index 259f378f70b..7b1fac082e4 100644
--- a/src/test/ui/nll/issue-52742.base.stderr
+++ b/src/test/ui/nll/issue-52742.base.stderr
@@ -4,7 +4,7 @@ error[E0312]: lifetime of reference outlives lifetime of borrowed content...
 LL |         self.y = b.z
    |                  ^^^
    |
-note: ...the reference is valid for the lifetime `'_` as defined here...
+note: ...the reference is valid for the anonymous lifetime as defined here...
   --> $DIR/issue-52742.rs:15:10
    |
 LL | impl Foo<'_, '_> {
diff --git a/src/test/ui/nll/issue-52742.nll.stderr b/src/test/ui/nll/issue-52742.nll.stderr
index 6828418a78e..1a2165e0a9d 100644
--- a/src/test/ui/nll/issue-52742.nll.stderr
+++ b/src/test/ui/nll/issue-52742.nll.stderr
@@ -2,7 +2,7 @@ error: lifetime may not live long enough
   --> $DIR/issue-52742.rs:17:9
    |
 LL |     fn take_bar(&mut self, b: Bar<'_>) {
-   |                 ---------         -- let's call this `'1`
+   |                 ---------  - has type `Bar<'1>`
    |                 |
    |                 has type `&mut Foo<'_, '2>`
 LL |         self.y = b.z
diff --git a/src/test/ui/nll/issue-55394.base.stderr b/src/test/ui/nll/issue-55394.base.stderr
index cc87954732c..2ec6a7af3f2 100644
--- a/src/test/ui/nll/issue-55394.base.stderr
+++ b/src/test/ui/nll/issue-55394.base.stderr
@@ -14,7 +14,7 @@ note: ...so that reference does not outlive borrowed content
    |
 LL |         Foo { bar }
    |               ^^^
-note: but, the lifetime must be valid for the lifetime `'_` as defined here...
+note: but, the lifetime must be valid for the anonymous lifetime as defined here...
   --> $DIR/issue-55394.rs:11:10
    |
 LL | impl Foo<'_> {
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/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr
index 570a08cb587..5b8b9bb68ad 100644
--- a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr
+++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr
@@ -2,9 +2,9 @@ error[E0700]: hidden type for `impl Trait` captures lifetime that does not appea
   --> $DIR/arbitrary_self_types_pin_lifetime_impl_trait-async.rs:8:48
    |
 LL |     async fn f(self: Pin<&Self>) -> impl Clone { self }
-   |                          -                     ^^^^^^^^
+   |                          -----                 ^^^^^^^^
    |                          |
-   |                          hidden type `Pin<&Foo>` captures the lifetime `'_` as defined here
+   |                          hidden type `Pin<&Foo>` captures the anonymous lifetime defined here
    |
 help: to declare that the `impl Trait` captures `'_`, you can add an explicit `'_` lifetime bound
    |
diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch-async.base.stderr b/src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch-async.base.stderr
index 7985bf266d8..d2106630dfe 100644
--- a/src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch-async.base.stderr
+++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch-async.base.stderr
@@ -5,6 +5,12 @@ LL |     async fn a(self: Pin<&Foo>, f: &Foo) -> &Foo { f }
    |                                    ----     ----   ^ ...but data from `f` is returned here
    |                                    |
    |                                    this parameter and the return type are declared with different lifetimes...
+   |
+   = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     async fn a<'a>(self: Pin<&'a Foo>, f: &'a Foo) -> &Foo { f }
+   |               ++++            ++           ++
 
 error[E0623]: lifetime mismatch
   --> $DIR/arbitrary_self_types_pin_lifetime_mismatch-async.rs:15:82
@@ -13,6 +19,12 @@ LL |     async fn c(self: Pin<&Self>, f: &Foo, g: &Foo) -> (Pin<&Foo>, &Foo) { (
    |                                     ----              -----------------          ^ ...but data from `f` is returned here
    |                                     |
    |                                     this parameter and the return type are declared with different lifetimes...
+   |
+   = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     async fn c<'a>(self: Pin<&'a Self>, f: &'a Foo, g: &Foo) -> (Pin<&Foo>, &Foo) { (self, f) }
+   |               ++++            ++            ++
 
 error[E0623]: lifetime mismatch
   --> $DIR/arbitrary_self_types_pin_lifetime_mismatch-async.rs:22:64
diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch-async.nll.stderr b/src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch-async.nll.stderr
index 8a55a7c34d7..3fd58725d02 100644
--- a/src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch-async.nll.stderr
+++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch-async.nll.stderr
@@ -6,6 +6,11 @@ LL |     async fn a(self: Pin<&Foo>, f: &Foo) -> &Foo { f }
    |                          |         |
    |                          |         let's call the lifetime of this reference `'1`
    |                          let's call the lifetime of this reference `'2`
+   |
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     async fn a<'a>(self: Pin<&'a Foo>, f: &'a Foo) -> &Foo { f }
+   |               ++++            ++           ++
 
 error: lifetime may not live long enough
   --> $DIR/arbitrary_self_types_pin_lifetime_mismatch-async.rs:15:75
@@ -15,6 +20,11 @@ LL |     async fn c(self: Pin<&Self>, f: &Foo, g: &Foo) -> (Pin<&Foo>, &Foo) { (
    |                          |          |
    |                          |          let's call the lifetime of this reference `'1`
    |                          let's call the lifetime of this reference `'2`
+   |
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     async fn c<'a>(self: Pin<&'a Self>, f: &'a Foo, g: &Foo) -> (Pin<&Foo>, &Foo) { (self, f) }
+   |               ++++            ++            ++
 
 error: lifetime may not live long enough
   --> $DIR/arbitrary_self_types_pin_lifetime_mismatch-async.rs:22:64
diff --git a/src/test/ui/self/elision/lt-ref-self-async.base.stderr b/src/test/ui/self/elision/lt-ref-self-async.base.stderr
index b4385490614..0e2bbcc3c04 100644
--- a/src/test/ui/self/elision/lt-ref-self-async.base.stderr
+++ b/src/test/ui/self/elision/lt-ref-self-async.base.stderr
@@ -7,6 +7,12 @@ LL |     async fn ref_self(&self, f: &u32) -> &u32 {
    |                                 this parameter and the return type are declared with different lifetimes...
 LL |         f
    |         ^ ...but data from `f` is returned here
+   |
+   = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     async fn ref_self<'a>(&'a self, f: &'a u32) -> &u32 {
+   |                      ++++  ++           ++
 
 error[E0623]: lifetime mismatch
   --> $DIR/lt-ref-self-async.rs:24:9
@@ -17,6 +23,12 @@ LL |     async fn ref_Self(self: &Self, f: &u32) -> &u32 {
    |                                       this parameter and the return type are declared with different lifetimes...
 LL |         f
    |         ^ ...but data from `f` is returned here
+   |
+   = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     async fn ref_Self<'a>(self: &'a Self, f: &'a u32) -> &u32 {
+   |                      ++++        ++           ++
 
 error[E0623]: lifetime mismatch
   --> $DIR/lt-ref-self-async.rs:30:9
@@ -27,6 +39,12 @@ LL |     async fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 {
    |                                                this parameter and the return type are declared with different lifetimes...
 LL |         f
    |         ^ ...but data from `f` is returned here
+   |
+   = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     async fn box_ref_Self<'a>(self: Box<&'a Self>, f: &'a u32) -> &u32 {
+   |                          ++++            ++            ++
 
 error[E0623]: lifetime mismatch
   --> $DIR/lt-ref-self-async.rs:36:9
@@ -37,6 +55,12 @@ LL |     async fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 {
    |                                                this parameter and the return type are declared with different lifetimes...
 LL |         f
    |         ^ ...but data from `f` is returned here
+   |
+   = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     async fn pin_ref_Self<'a>(self: Pin<&'a Self>, f: &'a u32) -> &u32 {
+   |                          ++++            ++            ++
 
 error[E0623]: lifetime mismatch
   --> $DIR/lt-ref-self-async.rs:42:9
@@ -47,6 +71,12 @@ LL |     async fn box_box_ref_Self(self: Box<Box<&Self>>, f: &u32) -> &u32 {
    |                                                         this parameter and the return type are declared with different lifetimes...
 LL |         f
    |         ^ ...but data from `f` is returned here
+   |
+   = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     async fn box_box_ref_Self<'a>(self: Box<Box<&'a Self>>, f: &'a u32) -> &u32 {
+   |                              ++++                ++             ++
 
 error[E0623]: lifetime mismatch
   --> $DIR/lt-ref-self-async.rs:48:9
@@ -57,6 +87,12 @@ LL |     async fn box_pin_Self(self: Box<Pin<&Self>>, f: &u32) -> &u32 {
    |                                                     this parameter and the return type are declared with different lifetimes...
 LL |         f
    |         ^ ...but data from `f` is returned here
+   |
+   = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     async fn box_pin_Self<'a>(self: Box<Pin<&'a Self>>, f: &'a u32) -> &u32 {
+   |                          ++++                ++             ++
 
 error: aborting due to 6 previous errors
 
diff --git a/src/test/ui/self/elision/lt-ref-self-async.nll.stderr b/src/test/ui/self/elision/lt-ref-self-async.nll.stderr
index 2ba9a6596f6..1c889838e70 100644
--- a/src/test/ui/self/elision/lt-ref-self-async.nll.stderr
+++ b/src/test/ui/self/elision/lt-ref-self-async.nll.stderr
@@ -7,6 +7,11 @@ LL |     async fn ref_self(&self, f: &u32) -> &u32 {
    |                       let's call the lifetime of this reference `'2`
 LL |         f
    |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     async fn ref_self<'a>(&'a self, f: &'a u32) -> &u32 {
+   |                      ++++  ++           ++
 
 error: lifetime may not live long enough
   --> $DIR/lt-ref-self-async.rs:24:9
@@ -17,6 +22,11 @@ LL |     async fn ref_Self(self: &Self, f: &u32) -> &u32 {
    |                             let's call the lifetime of this reference `'2`
 LL |         f
    |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     async fn ref_Self<'a>(self: &'a Self, f: &'a u32) -> &u32 {
+   |                      ++++        ++           ++
 
 error: lifetime may not live long enough
   --> $DIR/lt-ref-self-async.rs:30:9
@@ -27,6 +37,11 @@ LL |     async fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 {
    |                                     let's call the lifetime of this reference `'2`
 LL |         f
    |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     async fn box_ref_Self<'a>(self: Box<&'a Self>, f: &'a u32) -> &u32 {
+   |                          ++++            ++            ++
 
 error: lifetime may not live long enough
   --> $DIR/lt-ref-self-async.rs:36:9
@@ -37,6 +52,11 @@ LL |     async fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 {
    |                                     let's call the lifetime of this reference `'2`
 LL |         f
    |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     async fn pin_ref_Self<'a>(self: Pin<&'a Self>, f: &'a u32) -> &u32 {
+   |                          ++++            ++            ++
 
 error: lifetime may not live long enough
   --> $DIR/lt-ref-self-async.rs:42:9
@@ -47,6 +67,11 @@ LL |     async fn box_box_ref_Self(self: Box<Box<&Self>>, f: &u32) -> &u32 {
    |                                             let's call the lifetime of this reference `'2`
 LL |         f
    |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     async fn box_box_ref_Self<'a>(self: Box<Box<&'a Self>>, f: &'a u32) -> &u32 {
+   |                              ++++                ++             ++
 
 error: lifetime may not live long enough
   --> $DIR/lt-ref-self-async.rs:48:9
@@ -57,6 +82,11 @@ LL |     async fn box_pin_Self(self: Box<Pin<&Self>>, f: &u32) -> &u32 {
    |                                         let's call the lifetime of this reference `'2`
 LL |         f
    |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     async fn box_pin_Self<'a>(self: Box<Pin<&'a Self>>, f: &'a u32) -> &u32 {
+   |                          ++++                ++             ++
 
 error: aborting due to 6 previous errors
 
diff --git a/src/test/ui/self/elision/ref-mut-self-async.base.stderr b/src/test/ui/self/elision/ref-mut-self-async.base.stderr
index 851337552c9..8ffc0d62242 100644
--- a/src/test/ui/self/elision/ref-mut-self-async.base.stderr
+++ b/src/test/ui/self/elision/ref-mut-self-async.base.stderr
@@ -7,6 +7,12 @@ LL |     async fn ref_self(&mut self, f: &u32) -> &u32 {
    |                                     this parameter and the return type are declared with different lifetimes...
 LL |         f
    |         ^ ...but data from `f` is returned here
+   |
+   = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     async fn ref_self<'a>(&'a mut self, f: &'a u32) -> &u32 {
+   |                      ++++  ++               ++
 
 error[E0623]: lifetime mismatch
   --> $DIR/ref-mut-self-async.rs:24:9
@@ -17,6 +23,12 @@ LL |     async fn ref_Self(self: &mut Self, f: &u32) -> &u32 {
    |                                           this parameter and the return type are declared with different lifetimes...
 LL |         f
    |         ^ ...but data from `f` is returned here
+   |
+   = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     async fn ref_Self<'a>(self: &'a mut Self, f: &'a u32) -> &u32 {
+   |                      ++++        ++               ++
 
 error[E0623]: lifetime mismatch
   --> $DIR/ref-mut-self-async.rs:30:9
@@ -27,6 +39,12 @@ LL |     async fn box_ref_Self(self: Box<&mut Self>, f: &u32) -> &u32 {
    |                                                    this parameter and the return type are declared with different lifetimes...
 LL |         f
    |         ^ ...but data from `f` is returned here
+   |
+   = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     async fn box_ref_Self<'a>(self: Box<&'a mut Self>, f: &'a u32) -> &u32 {
+   |                          ++++            ++                ++
 
 error[E0623]: lifetime mismatch
   --> $DIR/ref-mut-self-async.rs:36:9
@@ -37,6 +55,12 @@ LL |     async fn pin_ref_Self(self: Pin<&mut Self>, f: &u32) -> &u32 {
    |                                                    this parameter and the return type are declared with different lifetimes...
 LL |         f
    |         ^ ...but data from `f` is returned here
+   |
+   = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     async fn pin_ref_Self<'a>(self: Pin<&'a mut Self>, f: &'a u32) -> &u32 {
+   |                          ++++            ++                ++
 
 error[E0623]: lifetime mismatch
   --> $DIR/ref-mut-self-async.rs:42:9
@@ -47,6 +71,12 @@ LL |     async fn box_box_ref_Self(self: Box<Box<&mut Self>>, f: &u32) -> &u32 {
    |                                                             this parameter and the return type are declared with different lifetimes...
 LL |         f
    |         ^ ...but data from `f` is returned here
+   |
+   = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     async fn box_box_ref_Self<'a>(self: Box<Box<&'a mut Self>>, f: &'a u32) -> &u32 {
+   |                              ++++                ++                 ++
 
 error[E0623]: lifetime mismatch
   --> $DIR/ref-mut-self-async.rs:48:9
@@ -57,6 +87,12 @@ LL |     async fn box_pin_ref_Self(self: Box<Pin<&mut Self>>, f: &u32) -> &u32 {
    |                                                             this parameter and the return type are declared with different lifetimes...
 LL |         f
    |         ^ ...but data from `f` is returned here
+   |
+   = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     async fn box_pin_ref_Self<'a>(self: Box<Pin<&'a mut Self>>, f: &'a u32) -> &u32 {
+   |                              ++++                ++                 ++
 
 error: aborting due to 6 previous errors
 
diff --git a/src/test/ui/self/elision/ref-mut-self-async.nll.stderr b/src/test/ui/self/elision/ref-mut-self-async.nll.stderr
index cdd464039cd..9beafcd4ff9 100644
--- a/src/test/ui/self/elision/ref-mut-self-async.nll.stderr
+++ b/src/test/ui/self/elision/ref-mut-self-async.nll.stderr
@@ -7,6 +7,11 @@ LL |     async fn ref_self(&mut self, f: &u32) -> &u32 {
    |                       let's call the lifetime of this reference `'2`
 LL |         f
    |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     async fn ref_self<'a>(&'a mut self, f: &'a u32) -> &u32 {
+   |                      ++++  ++               ++
 
 error: lifetime may not live long enough
   --> $DIR/ref-mut-self-async.rs:24:9
@@ -17,6 +22,11 @@ LL |     async fn ref_Self(self: &mut Self, f: &u32) -> &u32 {
    |                             let's call the lifetime of this reference `'2`
 LL |         f
    |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     async fn ref_Self<'a>(self: &'a mut Self, f: &'a u32) -> &u32 {
+   |                      ++++        ++               ++
 
 error: lifetime may not live long enough
   --> $DIR/ref-mut-self-async.rs:30:9
@@ -27,6 +37,11 @@ LL |     async fn box_ref_Self(self: Box<&mut Self>, f: &u32) -> &u32 {
    |                                     let's call the lifetime of this reference `'2`
 LL |         f
    |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     async fn box_ref_Self<'a>(self: Box<&'a mut Self>, f: &'a u32) -> &u32 {
+   |                          ++++            ++                ++
 
 error: lifetime may not live long enough
   --> $DIR/ref-mut-self-async.rs:36:9
@@ -37,6 +52,11 @@ LL |     async fn pin_ref_Self(self: Pin<&mut Self>, f: &u32) -> &u32 {
    |                                     let's call the lifetime of this reference `'2`
 LL |         f
    |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     async fn pin_ref_Self<'a>(self: Pin<&'a mut Self>, f: &'a u32) -> &u32 {
+   |                          ++++            ++                ++
 
 error: lifetime may not live long enough
   --> $DIR/ref-mut-self-async.rs:42:9
@@ -47,6 +67,11 @@ LL |     async fn box_box_ref_Self(self: Box<Box<&mut Self>>, f: &u32) -> &u32 {
    |                                             let's call the lifetime of this reference `'2`
 LL |         f
    |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     async fn box_box_ref_Self<'a>(self: Box<Box<&'a mut Self>>, f: &'a u32) -> &u32 {
+   |                              ++++                ++                 ++
 
 error: lifetime may not live long enough
   --> $DIR/ref-mut-self-async.rs:48:9
@@ -57,6 +82,11 @@ LL |     async fn box_pin_ref_Self(self: Box<Pin<&mut Self>>, f: &u32) -> &u32 {
    |                                             let's call the lifetime of this reference `'2`
 LL |         f
    |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     async fn box_pin_ref_Self<'a>(self: Box<Pin<&'a mut Self>>, f: &'a u32) -> &u32 {
+   |                              ++++                ++                 ++
 
 error: aborting due to 6 previous errors
 
diff --git a/src/test/ui/self/elision/ref-mut-struct-async.base.stderr b/src/test/ui/self/elision/ref-mut-struct-async.base.stderr
index 0de11c24875..fefb3fc1944 100644
--- a/src/test/ui/self/elision/ref-mut-struct-async.base.stderr
+++ b/src/test/ui/self/elision/ref-mut-struct-async.base.stderr
@@ -7,6 +7,12 @@ LL |     async fn ref_Struct(self: &mut Struct, f: &u32) -> &u32 {
    |                                               this parameter and the return type are declared with different lifetimes...
 LL |         f
    |         ^ ...but data from `f` is returned here
+   |
+   = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     async fn ref_Struct<'a>(self: &'a mut Struct, f: &'a u32) -> &u32 {
+   |                        ++++        ++                 ++
 
 error[E0623]: lifetime mismatch
   --> $DIR/ref-mut-struct-async.rs:22:9
@@ -17,6 +23,12 @@ LL |     async fn box_ref_Struct(self: Box<&mut Struct>, f: &u32) -> &u32 {
    |                                                        this parameter and the return type are declared with different lifetimes...
 LL |         f
    |         ^ ...but data from `f` is returned here
+   |
+   = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     async fn box_ref_Struct<'a>(self: Box<&'a mut Struct>, f: &'a u32) -> &u32 {
+   |                            ++++            ++                  ++
 
 error[E0623]: lifetime mismatch
   --> $DIR/ref-mut-struct-async.rs:28:9
@@ -27,6 +39,12 @@ LL |     async fn pin_ref_Struct(self: Pin<&mut Struct>, f: &u32) -> &u32 {
    |                                                        this parameter and the return type are declared with different lifetimes...
 LL |         f
    |         ^ ...but data from `f` is returned here
+   |
+   = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     async fn pin_ref_Struct<'a>(self: Pin<&'a mut Struct>, f: &'a u32) -> &u32 {
+   |                            ++++            ++                  ++
 
 error[E0623]: lifetime mismatch
   --> $DIR/ref-mut-struct-async.rs:34:9
@@ -37,6 +55,12 @@ LL |     async fn box_box_ref_Struct(self: Box<Box<&mut Struct>>, f: &u32) -> &u
    |                                                                 this parameter and the return type are declared with different lifetimes...
 LL |         f
    |         ^ ...but data from `f` is returned here
+   |
+   = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     async fn box_box_ref_Struct<'a>(self: Box<Box<&'a mut Struct>>, f: &'a u32) -> &u32 {
+   |                                ++++                ++                   ++
 
 error[E0623]: lifetime mismatch
   --> $DIR/ref-mut-struct-async.rs:40:9
@@ -47,6 +71,12 @@ LL |     async fn box_pin_ref_Struct(self: Box<Pin<&mut Struct>>, f: &u32) -> &u
    |                                                                 this parameter and the return type are declared with different lifetimes...
 LL |         f
    |         ^ ...but data from `f` is returned here
+   |
+   = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     async fn box_pin_ref_Struct<'a>(self: Box<Pin<&'a mut Struct>>, f: &'a u32) -> &u32 {
+   |                                ++++                ++                   ++
 
 error: aborting due to 5 previous errors
 
diff --git a/src/test/ui/self/elision/ref-mut-struct-async.nll.stderr b/src/test/ui/self/elision/ref-mut-struct-async.nll.stderr
index 0ef410c8df1..7fbecbe76a5 100644
--- a/src/test/ui/self/elision/ref-mut-struct-async.nll.stderr
+++ b/src/test/ui/self/elision/ref-mut-struct-async.nll.stderr
@@ -7,6 +7,11 @@ LL |     async fn ref_Struct(self: &mut Struct, f: &u32) -> &u32 {
    |                               let's call the lifetime of this reference `'2`
 LL |         f
    |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     async fn ref_Struct<'a>(self: &'a mut Struct, f: &'a u32) -> &u32 {
+   |                        ++++        ++                 ++
 
 error: lifetime may not live long enough
   --> $DIR/ref-mut-struct-async.rs:22:9
@@ -17,6 +22,11 @@ LL |     async fn box_ref_Struct(self: Box<&mut Struct>, f: &u32) -> &u32 {
    |                                       let's call the lifetime of this reference `'2`
 LL |         f
    |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     async fn box_ref_Struct<'a>(self: Box<&'a mut Struct>, f: &'a u32) -> &u32 {
+   |                            ++++            ++                  ++
 
 error: lifetime may not live long enough
   --> $DIR/ref-mut-struct-async.rs:28:9
@@ -27,6 +37,11 @@ LL |     async fn pin_ref_Struct(self: Pin<&mut Struct>, f: &u32) -> &u32 {
    |                                       let's call the lifetime of this reference `'2`
 LL |         f
    |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     async fn pin_ref_Struct<'a>(self: Pin<&'a mut Struct>, f: &'a u32) -> &u32 {
+   |                            ++++            ++                  ++
 
 error: lifetime may not live long enough
   --> $DIR/ref-mut-struct-async.rs:34:9
@@ -37,6 +52,11 @@ LL |     async fn box_box_ref_Struct(self: Box<Box<&mut Struct>>, f: &u32) -> &u
    |                                               let's call the lifetime of this reference `'2`
 LL |         f
    |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     async fn box_box_ref_Struct<'a>(self: Box<Box<&'a mut Struct>>, f: &'a u32) -> &u32 {
+   |                                ++++                ++                   ++
 
 error: lifetime may not live long enough
   --> $DIR/ref-mut-struct-async.rs:40:9
@@ -47,6 +67,11 @@ LL |     async fn box_pin_ref_Struct(self: Box<Pin<&mut Struct>>, f: &u32) -> &u
    |                                               let's call the lifetime of this reference `'2`
 LL |         f
    |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     async fn box_pin_ref_Struct<'a>(self: Box<Pin<&'a mut Struct>>, f: &'a u32) -> &u32 {
+   |                                ++++                ++                   ++
 
 error: aborting due to 5 previous errors
 
diff --git a/src/test/ui/self/elision/ref-self-async.base.stderr b/src/test/ui/self/elision/ref-self-async.base.stderr
index fa13b69bb21..2b142b089d5 100644
--- a/src/test/ui/self/elision/ref-self-async.base.stderr
+++ b/src/test/ui/self/elision/ref-self-async.base.stderr
@@ -7,6 +7,12 @@ LL |     async fn ref_self(&self, f: &u32) -> &u32 {
    |                                 this parameter and the return type are declared with different lifetimes...
 LL |         f
    |         ^ ...but data from `f` is returned here
+   |
+   = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     async fn ref_self<'a>(&'a self, f: &'a u32) -> &u32 {
+   |                      ++++  ++           ++
 
 error[E0623]: lifetime mismatch
   --> $DIR/ref-self-async.rs:34:9
@@ -17,6 +23,12 @@ LL |     async fn ref_Self(self: &Self, f: &u32) -> &u32 {
    |                                       this parameter and the return type are declared with different lifetimes...
 LL |         f
    |         ^ ...but data from `f` is returned here
+   |
+   = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     async fn ref_Self<'a>(self: &'a Self, f: &'a u32) -> &u32 {
+   |                      ++++        ++           ++
 
 error[E0623]: lifetime mismatch
   --> $DIR/ref-self-async.rs:40:9
@@ -27,6 +39,12 @@ LL |     async fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 {
    |                                                this parameter and the return type are declared with different lifetimes...
 LL |         f
    |         ^ ...but data from `f` is returned here
+   |
+   = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     async fn box_ref_Self<'a>(self: Box<&'a Self>, f: &'a u32) -> &u32 {
+   |                          ++++            ++            ++
 
 error[E0623]: lifetime mismatch
   --> $DIR/ref-self-async.rs:46:9
@@ -37,6 +55,12 @@ LL |     async fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 {
    |                                                this parameter and the return type are declared with different lifetimes...
 LL |         f
    |         ^ ...but data from `f` is returned here
+   |
+   = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     async fn pin_ref_Self<'a>(self: Pin<&'a Self>, f: &'a u32) -> &u32 {
+   |                          ++++            ++            ++
 
 error[E0623]: lifetime mismatch
   --> $DIR/ref-self-async.rs:52:9
@@ -47,6 +71,12 @@ LL |     async fn box_box_ref_Self(self: Box<Box<&Self>>, f: &u32) -> &u32 {
    |                                                         this parameter and the return type are declared with different lifetimes...
 LL |         f
    |         ^ ...but data from `f` is returned here
+   |
+   = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     async fn box_box_ref_Self<'a>(self: Box<Box<&'a Self>>, f: &'a u32) -> &u32 {
+   |                              ++++                ++             ++
 
 error[E0623]: lifetime mismatch
   --> $DIR/ref-self-async.rs:58:9
@@ -57,6 +87,12 @@ LL |     async fn box_pin_ref_Self(self: Box<Pin<&Self>>, f: &u32) -> &u32 {
    |                                                         this parameter and the return type are declared with different lifetimes...
 LL |         f
    |         ^ ...but data from `f` is returned here
+   |
+   = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     async fn box_pin_ref_Self<'a>(self: Box<Pin<&'a Self>>, f: &'a u32) -> &u32 {
+   |                              ++++                ++             ++
 
 error[E0623]: lifetime mismatch
   --> $DIR/ref-self-async.rs:64:9
@@ -67,6 +103,12 @@ LL |     async fn wrap_ref_Self_Self(self: Wrap<&Self, Self>, f: &u8) -> &u8 {
    |                                                             this parameter and the return type are declared with different lifetimes...
 LL |         f
    |         ^ ...but data from `f` is returned here
+   |
+   = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     async fn wrap_ref_Self_Self<'a>(self: Wrap<&'a Self, Self>, f: &'a u8) -> &u8 {
+   |                                ++++             ++                  ++
 
 error: aborting due to 7 previous errors
 
diff --git a/src/test/ui/self/elision/ref-self-async.nll.stderr b/src/test/ui/self/elision/ref-self-async.nll.stderr
index 77faaa86650..f4e531a817c 100644
--- a/src/test/ui/self/elision/ref-self-async.nll.stderr
+++ b/src/test/ui/self/elision/ref-self-async.nll.stderr
@@ -7,6 +7,11 @@ LL |     async fn ref_self(&self, f: &u32) -> &u32 {
    |                       let's call the lifetime of this reference `'2`
 LL |         f
    |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     async fn ref_self<'a>(&'a self, f: &'a u32) -> &u32 {
+   |                      ++++  ++           ++
 
 error: lifetime may not live long enough
   --> $DIR/ref-self-async.rs:34:9
@@ -17,6 +22,11 @@ LL |     async fn ref_Self(self: &Self, f: &u32) -> &u32 {
    |                             let's call the lifetime of this reference `'2`
 LL |         f
    |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     async fn ref_Self<'a>(self: &'a Self, f: &'a u32) -> &u32 {
+   |                      ++++        ++           ++
 
 error: lifetime may not live long enough
   --> $DIR/ref-self-async.rs:40:9
@@ -27,6 +37,11 @@ LL |     async fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 {
    |                                     let's call the lifetime of this reference `'2`
 LL |         f
    |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     async fn box_ref_Self<'a>(self: Box<&'a Self>, f: &'a u32) -> &u32 {
+   |                          ++++            ++            ++
 
 error: lifetime may not live long enough
   --> $DIR/ref-self-async.rs:46:9
@@ -37,6 +52,11 @@ LL |     async fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 {
    |                                     let's call the lifetime of this reference `'2`
 LL |         f
    |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     async fn pin_ref_Self<'a>(self: Pin<&'a Self>, f: &'a u32) -> &u32 {
+   |                          ++++            ++            ++
 
 error: lifetime may not live long enough
   --> $DIR/ref-self-async.rs:52:9
@@ -47,6 +67,11 @@ LL |     async fn box_box_ref_Self(self: Box<Box<&Self>>, f: &u32) -> &u32 {
    |                                             let's call the lifetime of this reference `'2`
 LL |         f
    |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     async fn box_box_ref_Self<'a>(self: Box<Box<&'a Self>>, f: &'a u32) -> &u32 {
+   |                              ++++                ++             ++
 
 error: lifetime may not live long enough
   --> $DIR/ref-self-async.rs:58:9
@@ -57,6 +82,11 @@ LL |     async fn box_pin_ref_Self(self: Box<Pin<&Self>>, f: &u32) -> &u32 {
    |                                             let's call the lifetime of this reference `'2`
 LL |         f
    |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     async fn box_pin_ref_Self<'a>(self: Box<Pin<&'a Self>>, f: &'a u32) -> &u32 {
+   |                              ++++                ++             ++
 
 error: lifetime may not live long enough
   --> $DIR/ref-self-async.rs:64:9
@@ -67,6 +97,11 @@ LL |     async fn wrap_ref_Self_Self(self: Wrap<&Self, Self>, f: &u8) -> &u8 {
    |                                            let's call the lifetime of this reference `'2`
 LL |         f
    |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     async fn wrap_ref_Self_Self<'a>(self: Wrap<&'a Self, Self>, f: &'a u8) -> &u8 {
+   |                                ++++             ++                  ++
 
 error: aborting due to 7 previous errors
 
diff --git a/src/test/ui/self/elision/ref-struct-async.base.stderr b/src/test/ui/self/elision/ref-struct-async.base.stderr
index 8da673d4435..88ddca89804 100644
--- a/src/test/ui/self/elision/ref-struct-async.base.stderr
+++ b/src/test/ui/self/elision/ref-struct-async.base.stderr
@@ -7,6 +7,12 @@ LL |     async fn ref_Struct(self: &Struct, f: &u32) -> &u32 {
    |                                           this parameter and the return type are declared with different lifetimes...
 LL |         f
    |         ^ ...but data from `f` is returned here
+   |
+   = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     async fn ref_Struct<'a>(self: &'a Struct, f: &'a u32) -> &u32 {
+   |                        ++++        ++             ++
 
 error[E0623]: lifetime mismatch
   --> $DIR/ref-struct-async.rs:22:9
@@ -17,6 +23,12 @@ LL |     async fn box_ref_Struct(self: Box<&Struct>, f: &u32) -> &u32 {
    |                                                    this parameter and the return type are declared with different lifetimes...
 LL |         f
    |         ^ ...but data from `f` is returned here
+   |
+   = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     async fn box_ref_Struct<'a>(self: Box<&'a Struct>, f: &'a u32) -> &u32 {
+   |                            ++++            ++              ++
 
 error[E0623]: lifetime mismatch
   --> $DIR/ref-struct-async.rs:28:9
@@ -27,6 +39,12 @@ LL |     async fn pin_ref_Struct(self: Pin<&Struct>, f: &u32) -> &u32 {
    |                                                    this parameter and the return type are declared with different lifetimes...
 LL |         f
    |         ^ ...but data from `f` is returned here
+   |
+   = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     async fn pin_ref_Struct<'a>(self: Pin<&'a Struct>, f: &'a u32) -> &u32 {
+   |                            ++++            ++              ++
 
 error[E0623]: lifetime mismatch
   --> $DIR/ref-struct-async.rs:34:9
@@ -37,6 +55,12 @@ LL |     async fn box_box_ref_Struct(self: Box<Box<&Struct>>, f: &u32) -> &u32 {
    |                                                             this parameter and the return type are declared with different lifetimes...
 LL |         f
    |         ^ ...but data from `f` is returned here
+   |
+   = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     async fn box_box_ref_Struct<'a>(self: Box<Box<&'a Struct>>, f: &'a u32) -> &u32 {
+   |                                ++++                ++               ++
 
 error[E0623]: lifetime mismatch
   --> $DIR/ref-struct-async.rs:40:9
@@ -47,6 +71,12 @@ LL |     async fn box_pin_Struct(self: Box<Pin<&Struct>>, f: &u32) -> &u32 {
    |                                                         this parameter and the return type are declared with different lifetimes...
 LL |         f
    |         ^ ...but data from `f` is returned here
+   |
+   = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     async fn box_pin_Struct<'a>(self: Box<Pin<&'a Struct>>, f: &'a u32) -> &u32 {
+   |                            ++++                ++               ++
 
 error: aborting due to 5 previous errors
 
diff --git a/src/test/ui/self/elision/ref-struct-async.nll.stderr b/src/test/ui/self/elision/ref-struct-async.nll.stderr
index ad07c70df87..83c20329c3d 100644
--- a/src/test/ui/self/elision/ref-struct-async.nll.stderr
+++ b/src/test/ui/self/elision/ref-struct-async.nll.stderr
@@ -7,6 +7,11 @@ LL |     async fn ref_Struct(self: &Struct, f: &u32) -> &u32 {
    |                               let's call the lifetime of this reference `'2`
 LL |         f
    |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     async fn ref_Struct<'a>(self: &'a Struct, f: &'a u32) -> &u32 {
+   |                        ++++        ++             ++
 
 error: lifetime may not live long enough
   --> $DIR/ref-struct-async.rs:22:9
@@ -17,6 +22,11 @@ LL |     async fn box_ref_Struct(self: Box<&Struct>, f: &u32) -> &u32 {
    |                                       let's call the lifetime of this reference `'2`
 LL |         f
    |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     async fn box_ref_Struct<'a>(self: Box<&'a Struct>, f: &'a u32) -> &u32 {
+   |                            ++++            ++              ++
 
 error: lifetime may not live long enough
   --> $DIR/ref-struct-async.rs:28:9
@@ -27,6 +37,11 @@ LL |     async fn pin_ref_Struct(self: Pin<&Struct>, f: &u32) -> &u32 {
    |                                       let's call the lifetime of this reference `'2`
 LL |         f
    |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     async fn pin_ref_Struct<'a>(self: Pin<&'a Struct>, f: &'a u32) -> &u32 {
+   |                            ++++            ++              ++
 
 error: lifetime may not live long enough
   --> $DIR/ref-struct-async.rs:34:9
@@ -37,6 +52,11 @@ LL |     async fn box_box_ref_Struct(self: Box<Box<&Struct>>, f: &u32) -> &u32 {
    |                                               let's call the lifetime of this reference `'2`
 LL |         f
    |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     async fn box_box_ref_Struct<'a>(self: Box<Box<&'a Struct>>, f: &'a u32) -> &u32 {
+   |                                ++++                ++               ++
 
 error: lifetime may not live long enough
   --> $DIR/ref-struct-async.rs:40:9
@@ -47,6 +67,11 @@ LL |     async fn box_pin_Struct(self: Box<Pin<&Struct>>, f: &u32) -> &u32 {
    |                                           let's call the lifetime of this reference `'2`
 LL |         f
    |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     async fn box_pin_Struct<'a>(self: Box<Pin<&'a Struct>>, f: &'a u32) -> &u32 {
+   |                            ++++                ++               ++
 
 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/cargo b/src/tools/cargo
-Subproject 39ad1039d9e3e1746177bf5d134af4c164f9552
+Subproject 38472bc19f2f76e245eba54a6e97ee6821b3c1d
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..b1c82ac76e8 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::PointerExposeAddress, _, _) => {
+            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/miri b/src/tools/miri
-Subproject 065ff89e33b67b3527fcdd56cf8b432e593e32d
+Subproject 749efd29565a9b8f47afb441aaacfcc10bc145d
diff --git a/src/tools/rust-analyzer b/src/tools/rust-analyzer
-Subproject 5d5bbec9b60010dd7389a084c56693baf6bda78
+Subproject f94fa62d69faf5bd63b3772d3ec4f0c76cf2db5