about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2024-07-08 16:01:38 +0000
committerbors <bors@rust-lang.org>2024-07-08 16:01:38 +0000
commita06e9c83f6bc6b9b69f1b0d9f1ab659f8f03db4d (patch)
tree5cfc3f26bad3ba0c2e488a4ab4902166a3eb7783
parentcfd7cf5a0e497c238dcf9947e2eeec01837beeb4 (diff)
parenta659f7a2bcefccb1a945656743a853ca0ac98c67 (diff)
downloadrust-a06e9c83f6bc6b9b69f1b0d9f1ab659f8f03db4d.tar.gz
rust-a06e9c83f6bc6b9b69f1b0d9f1ab659f8f03db4d.zip
Auto merge of #127486 - matthiaskrgr:rollup-lvv018b, r=matthiaskrgr
Rollup of 5 pull requests

Successful merges:

 - #120248 (Make casts of pointers to trait objects stricter)
 - #127355 (Mark format! with must_use hint)
 - #127399 (Verify that allocations output by GVN are sufficiently aligned.)
 - #127460 (clarify `sys::unix::fd::FileDesc::drop` comment)
 - #127467 (bootstrap: once_cell::sync::Lazy -> std::sync::LazyLock)

Failed merges:

 - #127357 (Remove `StructuredDiag`)

r? `@ghost`
`@rustbot` modify labels: rollup
-rw-r--r--compiler/rustc_borrowck/src/type_check/mod.rs67
-rw-r--r--compiler/rustc_errors/src/diagnostic_impls.rs14
-rw-r--r--compiler/rustc_hir_typeck/messages.ftl5
-rw-r--r--compiler/rustc_hir_typeck/src/cast.rs148
-rw-r--r--compiler/rustc_hir_typeck/src/errors.rs11
-rw-r--r--compiler/rustc_lint_defs/src/builtin.rs53
-rw-r--r--compiler/rustc_middle/src/ty/predicate.rs8
-rw-r--r--compiler/rustc_mir_transform/src/gvn.rs14
-rw-r--r--library/alloc/src/boxed.rs6
-rw-r--r--library/alloc/src/collections/btree/map/tests.rs18
-rw-r--r--library/alloc/src/collections/btree/set/tests.rs6
-rw-r--r--library/alloc/src/fmt.rs4
-rw-r--r--library/alloc/src/lib.rs1
-rw-r--r--library/alloc/src/macros.rs12
-rw-r--r--library/alloc/tests/fmt.rs10
-rw-r--r--library/core/tests/fmt/builders.rs6
-rw-r--r--library/std/src/os/fd/owned.rs5
-rw-r--r--src/bootstrap/Cargo.lock1
-rw-r--r--src/bootstrap/Cargo.toml1
-rw-r--r--src/bootstrap/src/core/build_steps/llvm.rs6
-rw-r--r--src/bootstrap/src/core/builder.rs9
-rw-r--r--src/bootstrap/src/utils/cache.rs7
-rw-r--r--src/tools/clippy/tests/ui/or_fun_call.fixed2
-rw-r--r--src/tools/clippy/tests/ui/or_fun_call.stderr8
-rw-r--r--src/tools/miri/tests/pass/intptrcast.rs4
-rw-r--r--src/tools/miri/tests/pass/packed_struct.rs2
-rw-r--r--src/tools/miri/tests/pass/shims/fs.rs4
-rw-r--r--src/tools/miri/tests/pass/shims/io.rs2
-rw-r--r--src/tools/miri/tests/pass/vecdeque.rs4
-rw-r--r--src/tools/rust-analyzer/crates/stdx/src/anymap.rs71
-rw-r--r--tests/pretty/issue-4264.pp21
-rw-r--r--tests/ui/cast/cast-rfc0401-vtable-kinds.rs18
-rw-r--r--tests/ui/cast/cast-rfc0401-vtable-kinds.stderr2
-rw-r--r--tests/ui/cast/ptr-to-trait-obj-add-auto.rs18
-rw-r--r--tests/ui/cast/ptr-to-trait-obj-add-auto.stderr43
-rw-r--r--tests/ui/cast/ptr-to-trait-obj-add-super-auto.rs9
-rw-r--r--tests/ui/cast/ptr-to-trait-obj-different-args.rs37
-rw-r--r--tests/ui/cast/ptr-to-trait-obj-different-args.stderr53
-rw-r--r--tests/ui/cast/ptr-to-trait-obj-different-regions-id-trait.rs27
-rw-r--r--tests/ui/cast/ptr-to-trait-obj-different-regions-id-trait.stderr15
-rw-r--r--tests/ui/cast/ptr-to-trait-obj-different-regions-lt-ext.rs31
-rw-r--r--tests/ui/cast/ptr-to-trait-obj-different-regions-lt-ext.stderr10
-rw-r--r--tests/ui/cast/ptr-to-trait-obj-different-regions-misc.rs37
-rw-r--r--tests/ui/cast/ptr-to-trait-obj-different-regions-misc.stderr136
-rw-r--r--tests/ui/cast/ptr-to-trait-obj-ok.rs17
-rw-r--r--tests/ui/cast/ptr-to-trait-obj-wrap-upcast.rs14
-rw-r--r--tests/ui/cast/ptr-to-trait-obj-wrap-upcast.stderr11
-rw-r--r--tests/ui/deriving/deriving-in-fn.rs2
-rw-r--r--tests/ui/fmt/struct-field-as-captured-argument.fixed14
-rw-r--r--tests/ui/fmt/struct-field-as-captured-argument.rs14
-rw-r--r--tests/ui/fmt/struct-field-as-captured-argument.stderr70
-rw-r--r--tests/ui/issues/issue-20676.rs2
-rw-r--r--tests/ui/mir/alignment/misaligned-constant-gvn.rs8
-rw-r--r--tests/ui/mismatched_types/cast-rfc0401.rs2
-rw-r--r--tests/ui/suggestions/issue-114797-bad-parentheses-dyn-trait.fixed4
-rw-r--r--tests/ui/suggestions/issue-114797-bad-parentheses-dyn-trait.rs4
-rw-r--r--tests/ui/suggestions/issue-114797-bad-parentheses-dyn-trait.stderr10
-rw-r--r--tests/ui/traits/upcast_soundness_bug.rs8
-rw-r--r--tests/ui/traits/upcast_soundness_bug.stderr13
59 files changed, 900 insertions, 259 deletions
diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index 8bba7ef4255..db4b5209145 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -38,6 +38,7 @@ use rustc_span::def_id::CRATE_DEF_ID;
 use rustc_span::source_map::Spanned;
 use rustc_span::symbol::sym;
 use rustc_span::Span;
+use rustc_span::DUMMY_SP;
 use rustc_target::abi::{FieldIdx, FIRST_VARIANT};
 use rustc_trait_selection::traits::query::type_op::custom::scrape_region_constraints;
 use rustc_trait_selection::traits::query::type_op::custom::CustomTypeOp;
@@ -49,6 +50,7 @@ use rustc_mir_dataflow::impls::MaybeInitializedPlaces;
 use rustc_mir_dataflow::move_paths::MoveData;
 use rustc_mir_dataflow::ResultsCursor;
 
+use crate::renumber::RegionCtxt;
 use crate::session_diagnostics::{MoveUnsized, SimdIntrinsicArgConst};
 use crate::{
     borrow_set::BorrowSet,
@@ -2333,7 +2335,57 @@ impl<'a, 'tcx> TypeChecker<'a, '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(_)), Some(CastTy::Ptr(_))) => (),
+                            (Some(CastTy::Ptr(src)), Some(CastTy::Ptr(dst))) => {
+                                let mut normalize = |t| self.normalize(t, location);
+                                let src_tail =
+                                    tcx.struct_tail_with_normalize(src.ty, &mut normalize, || ());
+                                let dst_tail =
+                                    tcx.struct_tail_with_normalize(dst.ty, &mut normalize, || ());
+
+                                // This checks (lifetime part of) vtable validity for pointer casts,
+                                // which is irrelevant when there are aren't principal traits on both sides (aka only auto traits).
+                                //
+                                // Note that other checks (such as denying `dyn Send` -> `dyn Debug`) are in `rustc_hir_typeck`.
+                                if let ty::Dynamic(src_tty, ..) = src_tail.kind()
+                                    && let ty::Dynamic(dst_tty, ..) = dst_tail.kind()
+                                    && src_tty.principal().is_some()
+                                    && dst_tty.principal().is_some()
+                                {
+                                    // Remove auto traits.
+                                    // Auto trait checks are handled in `rustc_hir_typeck` as FCW.
+                                    let src_obj = tcx.mk_ty_from_kind(ty::Dynamic(
+                                        tcx.mk_poly_existential_predicates(
+                                            &src_tty.without_auto_traits().collect::<Vec<_>>(),
+                                        ),
+                                        tcx.lifetimes.re_static,
+                                        ty::Dyn,
+                                    ));
+                                    let dst_obj = tcx.mk_ty_from_kind(ty::Dynamic(
+                                        tcx.mk_poly_existential_predicates(
+                                            &dst_tty.without_auto_traits().collect::<Vec<_>>(),
+                                        ),
+                                        tcx.lifetimes.re_static,
+                                        ty::Dyn,
+                                    ));
+
+                                    // Replace trait object lifetimes with fresh vars, to allow casts like
+                                    // `*mut dyn FnOnce() + 'a` -> `*mut dyn FnOnce() + 'static`,
+                                    let src_obj =
+                                        freshen_single_trait_object_lifetime(self.infcx, src_obj);
+                                    let dst_obj =
+                                        freshen_single_trait_object_lifetime(self.infcx, dst_obj);
+
+                                    debug!(?src_tty, ?dst_tty, ?src_obj, ?dst_obj);
+
+                                    self.eq_types(
+                                        src_obj,
+                                        dst_obj,
+                                        location.to_locations(),
+                                        ConstraintCategory::Cast { unsize_to: None },
+                                    )
+                                    .unwrap();
+                                }
+                            }
                             _ => {
                                 span_mirbug!(
                                     self,
@@ -2856,3 +2908,16 @@ impl<'tcx> TypeOp<'tcx> for InstantiateOpaqueType<'tcx> {
         Ok(output)
     }
 }
+
+fn freshen_single_trait_object_lifetime<'tcx>(
+    infcx: &BorrowckInferCtxt<'tcx>,
+    ty: Ty<'tcx>,
+) -> Ty<'tcx> {
+    let &ty::Dynamic(tty, _, dyn_kind @ ty::Dyn) = ty.kind() else { bug!("expected trait object") };
+
+    let fresh = infcx
+        .next_region_var(rustc_infer::infer::RegionVariableOrigin::MiscVariable(DUMMY_SP), || {
+            RegionCtxt::Unknown
+        });
+    infcx.tcx.mk_ty_from_kind(ty::Dynamic(tty, fresh, dyn_kind))
+}
diff --git a/compiler/rustc_errors/src/diagnostic_impls.rs b/compiler/rustc_errors/src/diagnostic_impls.rs
index 0af80bc5c67..e6ca1bf7bc4 100644
--- a/compiler/rustc_errors/src/diagnostic_impls.rs
+++ b/compiler/rustc_errors/src/diagnostic_impls.rs
@@ -298,15 +298,21 @@ impl IntoDiagArg for hir::def::Namespace {
 }
 
 #[derive(Clone)]
-pub struct DiagSymbolList(Vec<Symbol>);
+pub struct DiagSymbolList<S = Symbol>(Vec<S>);
 
-impl From<Vec<Symbol>> for DiagSymbolList {
-    fn from(v: Vec<Symbol>) -> Self {
+impl<S> From<Vec<S>> for DiagSymbolList<S> {
+    fn from(v: Vec<S>) -> Self {
         DiagSymbolList(v)
     }
 }
 
-impl IntoDiagArg for DiagSymbolList {
+impl<S> FromIterator<S> for DiagSymbolList<S> {
+    fn from_iter<T: IntoIterator<Item = S>>(iter: T) -> Self {
+        iter.into_iter().collect::<Vec<_>>().into()
+    }
+}
+
+impl<S: std::fmt::Display> IntoDiagArg for DiagSymbolList<S> {
     fn into_diag_arg(self) -> DiagArgValue {
         DiagArgValue::StrListSepByAnd(
             self.0.into_iter().map(|sym| Cow::Owned(format!("`{sym}`"))).collect(),
diff --git a/compiler/rustc_hir_typeck/messages.ftl b/compiler/rustc_hir_typeck/messages.ftl
index 3c5070bd006..239b0c44690 100644
--- a/compiler/rustc_hir_typeck/messages.ftl
+++ b/compiler/rustc_hir_typeck/messages.ftl
@@ -138,6 +138,11 @@ hir_typeck_option_result_asref = use `{$def_path}::as_ref` to convert `{$expecte
 hir_typeck_option_result_cloned = use `{$def_path}::cloned` to clone the value inside the `{$def_path}`
 hir_typeck_option_result_copied = use `{$def_path}::copied` to copy the value inside the `{$def_path}`
 
+hir_typeck_ptr_cast_add_auto_to_object = adding {$traits_len ->
+    [1] an auto trait {$traits}
+    *[other] auto traits {$traits}
+} to a trait object in a pointer cast may cause UB later on
+
 hir_typeck_remove_semi_for_coerce = you might have meant to return the `match` expression
 hir_typeck_remove_semi_for_coerce_expr = this could be implicitly returned but it is a statement, not a tail expression
 hir_typeck_remove_semi_for_coerce_ret = the `match` arms can conform to this return type
diff --git a/compiler/rustc_hir_typeck/src/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs
index 53e44d6bcae..341d533492d 100644
--- a/compiler/rustc_hir_typeck/src/cast.rs
+++ b/compiler/rustc_hir_typeck/src/cast.rs
@@ -32,9 +32,9 @@ use super::FnCtxt;
 
 use crate::errors;
 use crate::type_error_struct;
-use hir::ExprKind;
+use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::{codes::*, Applicability, Diag, ErrorGuaranteed};
-use rustc_hir as hir;
+use rustc_hir::{self as hir, ExprKind};
 use rustc_macros::{TypeFoldable, TypeVisitable};
 use rustc_middle::bug;
 use rustc_middle::mir::Mutability;
@@ -44,7 +44,7 @@ use rustc_middle::ty::error::TypeError;
 use rustc_middle::ty::TyCtxt;
 use rustc_middle::ty::{self, Ty, TypeAndMut, TypeVisitableExt, VariantDef};
 use rustc_session::lint;
-use rustc_span::def_id::{DefId, LOCAL_CRATE};
+use rustc_span::def_id::LOCAL_CRATE;
 use rustc_span::symbol::sym;
 use rustc_span::Span;
 use rustc_span::DUMMY_SP;
@@ -73,7 +73,7 @@ enum PointerKind<'tcx> {
     /// No metadata attached, ie pointer to sized type or foreign type
     Thin,
     /// A trait object
-    VTable(Option<DefId>),
+    VTable(&'tcx ty::List<ty::Binder<'tcx, ty::ExistentialPredicate<'tcx>>>),
     /// Slice
     Length,
     /// The unsize info of this projection or opaque type
@@ -101,7 +101,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
         Ok(match *t.kind() {
             ty::Slice(_) | ty::Str => Some(PointerKind::Length),
-            ty::Dynamic(tty, _, ty::Dyn) => Some(PointerKind::VTable(tty.principal_def_id())),
+            ty::Dynamic(tty, _, ty::Dyn) => Some(PointerKind::VTable(tty)),
             ty::Adt(def, args) if def.is_struct() => match def.non_enum_variant().tail_opt() {
                 None => Some(PointerKind::Thin),
                 Some(f) => {
@@ -755,7 +755,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
                 Err(CastError::IllegalCast)
             }
 
-            // ptr -> *
+            // ptr -> ptr
             (Ptr(m_e), Ptr(m_c)) => self.check_ptr_ptr_cast(fcx, m_e, m_c), // ptr-ptr-cast
 
             // ptr-addr-cast
@@ -799,40 +799,126 @@ impl<'a, 'tcx> CastCheck<'tcx> {
     fn check_ptr_ptr_cast(
         &self,
         fcx: &FnCtxt<'a, 'tcx>,
-        m_expr: ty::TypeAndMut<'tcx>,
-        m_cast: ty::TypeAndMut<'tcx>,
+        m_src: ty::TypeAndMut<'tcx>,
+        m_dst: ty::TypeAndMut<'tcx>,
     ) -> Result<CastKind, CastError> {
-        debug!("check_ptr_ptr_cast m_expr={:?} m_cast={:?}", m_expr, m_cast);
+        debug!("check_ptr_ptr_cast m_src={m_src:?} m_dst={m_dst:?}");
         // ptr-ptr cast. vtables must match.
 
-        let expr_kind = fcx.pointer_kind(m_expr.ty, self.span)?;
-        let cast_kind = fcx.pointer_kind(m_cast.ty, self.span)?;
+        let src_kind = fcx.tcx.erase_regions(fcx.pointer_kind(m_src.ty, self.span)?);
+        let dst_kind = fcx.tcx.erase_regions(fcx.pointer_kind(m_dst.ty, self.span)?);
 
-        let Some(cast_kind) = cast_kind else {
+        match (src_kind, dst_kind) {
             // We can't cast if target pointer kind is unknown
-            return Err(CastError::UnknownCastPtrKind);
-        };
+            (_, None) => Err(CastError::UnknownCastPtrKind),
+            // Cast to thin pointer is OK
+            (_, Some(PointerKind::Thin)) => Ok(CastKind::PtrPtrCast),
 
-        // Cast to thin pointer is OK
-        if cast_kind == PointerKind::Thin {
-            return Ok(CastKind::PtrPtrCast);
-        }
-
-        let Some(expr_kind) = expr_kind else {
             // We can't cast to fat pointer if source pointer kind is unknown
-            return Err(CastError::UnknownExprPtrKind);
-        };
+            (None, _) => Err(CastError::UnknownExprPtrKind),
+
+            // thin -> fat? report invalid cast (don't complain about vtable kinds)
+            (Some(PointerKind::Thin), _) => Err(CastError::SizedUnsizedCast),
+
+            // trait object -> trait object? need to do additional checks
+            (Some(PointerKind::VTable(src_tty)), Some(PointerKind::VTable(dst_tty))) => {
+                match (src_tty.principal(), dst_tty.principal()) {
+                    // A<dyn Src<...> + SrcAuto> -> B<dyn Dst<...> + DstAuto>. need to make sure
+                    // - `Src` and `Dst` traits are the same
+                    // - traits have the same generic arguments
+                    // - `SrcAuto` is a superset of `DstAuto`
+                    (Some(src_principal), Some(dst_principal)) => {
+                        let tcx = fcx.tcx;
+
+                        // Check that the traits are actually the same.
+                        // The `dyn Src = dyn Dst` check below would suffice,
+                        // but this may produce a better diagnostic.
+                        //
+                        // Note that trait upcasting goes through a different mechanism (`coerce_unsized`)
+                        // and is unaffected by this check.
+                        if src_principal.def_id() != dst_principal.def_id() {
+                            return Err(CastError::DifferingKinds);
+                        }
 
-        // thin -> fat? report invalid cast (don't complain about vtable kinds)
-        if expr_kind == PointerKind::Thin {
-            return Err(CastError::SizedUnsizedCast);
-        }
+                        // We need to reconstruct trait object types.
+                        // `m_src` and `m_dst` won't work for us here because they will potentially
+                        // contain wrappers, which we do not care about.
+                        //
+                        // e.g. we want to allow `dyn T -> (dyn T,)`, etc.
+                        //
+                        // We also need to skip auto traits to emit an FCW and not an error.
+                        let src_obj = tcx.mk_ty_from_kind(ty::Dynamic(
+                            tcx.mk_poly_existential_predicates(
+                                &src_tty.without_auto_traits().collect::<Vec<_>>(),
+                            ),
+                            tcx.lifetimes.re_erased,
+                            ty::Dyn,
+                        ));
+                        let dst_obj = tcx.mk_ty_from_kind(ty::Dynamic(
+                            tcx.mk_poly_existential_predicates(
+                                &dst_tty.without_auto_traits().collect::<Vec<_>>(),
+                            ),
+                            tcx.lifetimes.re_erased,
+                            ty::Dyn,
+                        ));
 
-        // vtable kinds must match
-        if fcx.tcx.erase_regions(cast_kind) == fcx.tcx.erase_regions(expr_kind) {
-            Ok(CastKind::PtrPtrCast)
-        } else {
-            Err(CastError::DifferingKinds)
+                        // `dyn Src = dyn Dst`, this checks for matching traits/generics
+                        fcx.demand_eqtype(self.span, src_obj, dst_obj);
+
+                        // Check that `SrcAuto` (+auto traits implied by `Src`) is a superset of `DstAuto`.
+                        // Emit an FCW otherwise.
+                        let src_auto: FxHashSet<_> = src_tty
+                            .auto_traits()
+                            .chain(
+                                tcx.supertrait_def_ids(src_principal.def_id())
+                                    .filter(|def_id| tcx.trait_is_auto(*def_id)),
+                            )
+                            .collect();
+
+                        let added = dst_tty
+                            .auto_traits()
+                            .filter(|trait_did| !src_auto.contains(trait_did))
+                            .collect::<Vec<_>>();
+
+                        if !added.is_empty() {
+                            tcx.emit_node_span_lint(
+                                lint::builtin::PTR_CAST_ADD_AUTO_TO_OBJECT,
+                                self.expr.hir_id,
+                                self.span,
+                                errors::PtrCastAddAutoToObject {
+                                    traits_len: added.len(),
+                                    traits: {
+                                        let mut traits: Vec<_> = added
+                                            .into_iter()
+                                            .map(|trait_did| tcx.def_path_str(trait_did))
+                                            .collect();
+
+                                        traits.sort();
+                                        traits.into()
+                                    },
+                                },
+                            )
+                        }
+
+                        Ok(CastKind::PtrPtrCast)
+                    }
+
+                    // dyn Auto -> dyn Auto'? ok.
+                    (None, None) => Ok(CastKind::PtrPtrCast),
+
+                    // dyn Trait -> dyn Auto? should be ok, but we used to not allow it.
+                    // FIXME: allow this
+                    (Some(_), None) => Err(CastError::DifferingKinds),
+
+                    // dyn Auto -> dyn Trait? not ok.
+                    (None, Some(_)) => Err(CastError::DifferingKinds),
+                }
+            }
+
+            // fat -> fat? metadata kinds must match
+            (Some(src_kind), Some(dst_kind)) if src_kind == dst_kind => Ok(CastKind::PtrPtrCast),
+
+            (_, _) => Err(CastError::DifferingKinds),
         }
     }
 
diff --git a/compiler/rustc_hir_typeck/src/errors.rs b/compiler/rustc_hir_typeck/src/errors.rs
index f1ed2ade3d4..8b5b0a9b92f 100644
--- a/compiler/rustc_hir_typeck/src/errors.rs
+++ b/compiler/rustc_hir_typeck/src/errors.rs
@@ -4,8 +4,8 @@ use std::borrow::Cow;
 
 use crate::fluent_generated as fluent;
 use rustc_errors::{
-    codes::*, Applicability, Diag, DiagArgValue, EmissionGuarantee, IntoDiagArg, MultiSpan,
-    SubdiagMessageOp, Subdiagnostic,
+    codes::*, Applicability, Diag, DiagArgValue, DiagSymbolList, EmissionGuarantee, IntoDiagArg,
+    MultiSpan, SubdiagMessageOp, Subdiagnostic,
 };
 use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
 use rustc_middle::ty::{self, Ty};
@@ -253,6 +253,13 @@ pub struct LossyProvenanceInt2Ptr<'tcx> {
     pub sugg: LossyProvenanceInt2PtrSuggestion,
 }
 
+#[derive(LintDiagnostic)]
+#[diag(hir_typeck_ptr_cast_add_auto_to_object)]
+pub struct PtrCastAddAutoToObject {
+    pub traits_len: usize,
+    pub traits: DiagSymbolList<String>,
+}
+
 #[derive(Subdiagnostic)]
 #[multipart_suggestion(hir_typeck_suggestion, applicability = "has-placeholders")]
 pub struct LossyProvenanceInt2PtrSuggestion {
diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs
index 048c2fb4e67..bc93248252d 100644
--- a/compiler/rustc_lint_defs/src/builtin.rs
+++ b/compiler/rustc_lint_defs/src/builtin.rs
@@ -80,6 +80,7 @@ declare_lint_pass! {
         PRIVATE_BOUNDS,
         PRIVATE_INTERFACES,
         PROC_MACRO_DERIVE_RESOLUTION_FALLBACK,
+        PTR_CAST_ADD_AUTO_TO_OBJECT,
         PUB_USE_OF_PRIVATE_EXTERN_CRATE,
         REDUNDANT_LIFETIMES,
         REFINING_IMPL_TRAIT_INTERNAL,
@@ -4939,6 +4940,58 @@ declare_lint! {
 }
 
 declare_lint! {
+    /// The `ptr_cast_add_auto_to_object` lint detects casts of raw pointers to trait
+    /// objects, which add auto traits.
+    ///
+    /// ### Example
+    ///
+    /// ```rust,edition2021,compile_fail
+    /// let ptr: *const dyn core::any::Any = &();
+    /// _ = ptr as *const dyn core::any::Any + Send;
+    /// ```
+    ///
+    /// {{produces}}
+    ///
+    /// ### Explanation
+    ///
+    /// Adding an auto trait can make the vtable invalid, potentially causing
+    /// UB in safe code afterwards. For example:
+    ///
+    /// ```ignore (causes a warning)
+    /// #![feature(arbitrary_self_types)]
+    ///
+    /// trait Trait {
+    ///     fn f(self: *const Self)
+    ///     where
+    ///         Self: Send;
+    /// }
+    ///
+    /// impl Trait for *const () {
+    ///     fn f(self: *const Self) {
+    ///         unreachable!()
+    ///     }
+    /// }
+    ///
+    /// fn main() {
+    ///     let unsend: *const () = &();
+    ///     let unsend: *const dyn Trait = &unsend;
+    ///     let send_bad: *const (dyn Trait + Send) = unsend as _;
+    ///     send_bad.f(); // this crashes, since vtable for `*const ()` does not have an entry for `f`
+    /// }
+    /// ```
+    ///
+    /// Generally you must ensure that vtable is right for the pointer's type,
+    /// before passing the pointer to safe code.
+    pub PTR_CAST_ADD_AUTO_TO_OBJECT,
+    Warn,
+    "detects `as` casts from pointers to `dyn Trait` to pointers to `dyn Trait + Auto`",
+    @future_incompatible = FutureIncompatibleInfo {
+        reason: FutureIncompatibilityReason::FutureReleaseErrorReportInDeps,
+        reference: "issue #127323 <https://github.com/rust-lang/rust/issues/127323>",
+    };
+}
+
+declare_lint! {
     /// The `out_of_scope_macro_calls` lint detects `macro_rules` called when they are not in scope,
     /// above their definition, which may happen in key-value attributes.
     ///
diff --git a/compiler/rustc_middle/src/ty/predicate.rs b/compiler/rustc_middle/src/ty/predicate.rs
index c2cc3be3aaa..5d6352c57ce 100644
--- a/compiler/rustc_middle/src/ty/predicate.rs
+++ b/compiler/rustc_middle/src/ty/predicate.rs
@@ -349,6 +349,14 @@ impl<'tcx> ty::List<ty::PolyExistentialPredicate<'tcx>> {
             _ => None,
         })
     }
+
+    pub fn without_auto_traits(
+        &self,
+    ) -> impl Iterator<Item = ty::PolyExistentialPredicate<'tcx>> + '_ {
+        self.iter().filter(|predicate| {
+            !matches!(predicate.as_ref().skip_binder(), ExistentialPredicate::AutoTrait(_))
+        })
+    }
 }
 
 pub type PolyTraitRef<'tcx> = ty::Binder<'tcx, TraitRef<'tcx>>;
diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs
index 2b7d9be6d35..1002746e553 100644
--- a/compiler/rustc_mir_transform/src/gvn.rs
+++ b/compiler/rustc_mir_transform/src/gvn.rs
@@ -1391,11 +1391,15 @@ fn op_to_prop_const<'tcx>(
         let (prov, offset) = pointer.into_parts();
         let alloc_id = prov.alloc_id();
         intern_const_alloc_for_constprop(ecx, alloc_id).ok()?;
-        if matches!(ecx.tcx.global_alloc(alloc_id), GlobalAlloc::Memory(_)) {
-            // `alloc_id` may point to a static. Codegen will choke on an `Indirect` with anything
-            // by `GlobalAlloc::Memory`, so do fall through to copying if needed.
-            // FIXME: find a way to treat this more uniformly
-            // (probably by fixing codegen)
+
+        // `alloc_id` may point to a static. Codegen will choke on an `Indirect` with anything
+        // by `GlobalAlloc::Memory`, so do fall through to copying if needed.
+        // FIXME: find a way to treat this more uniformly (probably by fixing codegen)
+        if let GlobalAlloc::Memory(alloc) = ecx.tcx.global_alloc(alloc_id)
+            // Transmuting a constant is just an offset in the allocation. If the alignment of the
+            // allocation is not enough, fallback to copying into a properly aligned value.
+            && alloc.inner().align >= op.layout.align.abi
+        {
             return Some(ConstValue::Indirect { alloc_id, offset });
         }
     }
diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs
index 1ec095a46f7..65bcb241e4a 100644
--- a/library/alloc/src/boxed.rs
+++ b/library/alloc/src/boxed.rs
@@ -2374,7 +2374,7 @@ impl dyn Error + Send {
         let err: Box<dyn Error> = self;
         <dyn Error>::downcast(err).map_err(|s| unsafe {
             // Reapply the `Send` marker.
-            Box::from_raw(Box::into_raw(s) as *mut (dyn Error + Send))
+            mem::transmute::<Box<dyn Error>, Box<dyn Error + Send>>(s)
         })
     }
 }
@@ -2387,8 +2387,8 @@ impl dyn Error + Send + Sync {
     pub fn downcast<T: Error + 'static>(self: Box<Self>) -> Result<Box<T>, Box<Self>> {
         let err: Box<dyn Error> = self;
         <dyn Error>::downcast(err).map_err(|s| unsafe {
-            // Reapply the `Send + Sync` marker.
-            Box::from_raw(Box::into_raw(s) as *mut (dyn Error + Send + Sync))
+            // Reapply the `Send + Sync` markers.
+            mem::transmute::<Box<dyn Error>, Box<dyn Error + Send + Sync>>(s)
         })
     }
 }
diff --git a/library/alloc/src/collections/btree/map/tests.rs b/library/alloc/src/collections/btree/map/tests.rs
index 56620cf890d..ba1f38dcc3e 100644
--- a/library/alloc/src/collections/btree/map/tests.rs
+++ b/library/alloc/src/collections/btree/map/tests.rs
@@ -1796,18 +1796,18 @@ fn test_ord_absence() {
     }
 
     fn map_debug<K: Debug>(mut map: BTreeMap<K, ()>) {
-        format!("{map:?}");
-        format!("{:?}", map.iter());
-        format!("{:?}", map.iter_mut());
-        format!("{:?}", map.keys());
-        format!("{:?}", map.values());
-        format!("{:?}", map.values_mut());
+        let _ = format!("{map:?}");
+        let _ = format!("{:?}", map.iter());
+        let _ = format!("{:?}", map.iter_mut());
+        let _ = format!("{:?}", map.keys());
+        let _ = format!("{:?}", map.values());
+        let _ = format!("{:?}", map.values_mut());
         if true {
-            format!("{:?}", map.into_iter());
+            let _ = format!("{:?}", map.into_iter());
         } else if true {
-            format!("{:?}", map.into_keys());
+            let _ = format!("{:?}", map.into_keys());
         } else {
-            format!("{:?}", map.into_values());
+            let _ = format!("{:?}", map.into_values());
         }
     }
 
diff --git a/library/alloc/src/collections/btree/set/tests.rs b/library/alloc/src/collections/btree/set/tests.rs
index 688ce57e9da..48bf7674138 100644
--- a/library/alloc/src/collections/btree/set/tests.rs
+++ b/library/alloc/src/collections/btree/set/tests.rs
@@ -705,9 +705,9 @@ fn test_ord_absence() {
     }
 
     fn set_debug<K: Debug>(set: BTreeSet<K>) {
-        format!("{set:?}");
-        format!("{:?}", set.iter());
-        format!("{:?}", set.into_iter());
+        let _ = format!("{set:?}");
+        let _ = format!("{:?}", set.iter());
+        let _ = format!("{:?}", set.into_iter());
     }
 
     fn set_clone<K: Clone>(mut set: BTreeSet<K>) {
diff --git a/library/alloc/src/fmt.rs b/library/alloc/src/fmt.rs
index ae44cab8131..c6bba619ae6 100644
--- a/library/alloc/src/fmt.rs
+++ b/library/alloc/src/fmt.rs
@@ -12,6 +12,7 @@
 //! Some examples of the [`format!`] extension are:
 //!
 //! ```
+//! # #![allow(unused_must_use)]
 //! format!("Hello");                 // => "Hello"
 //! format!("Hello, {}!", "world");   // => "Hello, world!"
 //! format!("The number is {}", 1);   // => "The number is 1"
@@ -50,6 +51,7 @@
 //! the iterator advances. This leads to behavior like this:
 //!
 //! ```
+//! # #![allow(unused_must_use)]
 //! format!("{1} {} {0} {}", 1, 2); // => "2 1 1 2"
 //! ```
 //!
@@ -77,6 +79,7 @@
 //! For example, the following [`format!`] expressions all use named arguments:
 //!
 //! ```
+//! # #![allow(unused_must_use)]
 //! format!("{argument}", argument = "test");   // => "test"
 //! format!("{name} {}", 1, name = 2);          // => "2 1"
 //! format!("{a} {c} {b}", a="a", b='b', c=3);  // => "a 3 b"
@@ -86,6 +89,7 @@
 //! reference a variable with that name in the current scope.
 //!
 //! ```
+//! # #![allow(unused_must_use)]
 //! let argument = 2 + 2;
 //! format!("{argument}");   // => "4"
 //!
diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs
index 3237d8654c2..a7715740cbd 100644
--- a/library/alloc/src/lib.rs
+++ b/library/alloc/src/lib.rs
@@ -257,6 +257,7 @@ pub mod vec;
 #[unstable(feature = "liballoc_internals", issue = "none", reason = "implementation detail")]
 pub mod __export {
     pub use core::format_args;
+    pub use core::hint::must_use;
 }
 
 #[cfg(test)]
diff --git a/library/alloc/src/macros.rs b/library/alloc/src/macros.rs
index d5ca5c4ed27..8c6a367869c 100644
--- a/library/alloc/src/macros.rs
+++ b/library/alloc/src/macros.rs
@@ -111,6 +111,7 @@ macro_rules! vec {
 /// # Examples
 ///
 /// ```
+/// # #![allow(unused_must_use)]
 /// format!("test");                             // => "test"
 /// format!("hello {}", "world!");               // => "hello world!"
 /// format!("x = {}, y = {val}", 10, val = 30);  // => "x = 10, y = 30"
@@ -119,10 +120,13 @@ macro_rules! vec {
 /// ```
 #[macro_export]
 #[stable(feature = "rust1", since = "1.0.0")]
+#[allow_internal_unstable(hint_must_use, liballoc_internals)]
 #[cfg_attr(not(test), rustc_diagnostic_item = "format_macro")]
 macro_rules! format {
-    ($($arg:tt)*) => {{
-        let res = $crate::fmt::format($crate::__export::format_args!($($arg)*));
-        res
-    }}
+    ($($arg:tt)*) => {
+        $crate::__export::must_use({
+            let res = $crate::fmt::format($crate::__export::format_args!($($arg)*));
+            res
+        })
+    }
 }
diff --git a/library/alloc/tests/fmt.rs b/library/alloc/tests/fmt.rs
index 379e09ab69a..ce24a40f4c0 100644
--- a/library/alloc/tests/fmt.rs
+++ b/library/alloc/tests/fmt.rs
@@ -217,19 +217,19 @@ fn test_format_macro_interface() {
 
     // make sure that format! doesn't move out of local variables
     let a = Box::new(3);
-    format!("{a}");
-    format!("{a}");
+    let _ = format!("{a}");
+    let _ = format!("{a}");
 
     // make sure that format! doesn't cause spurious unused-unsafe warnings when
     // it's inside of an outer unsafe block
     unsafe {
         let a: isize = ::std::mem::transmute(3_usize);
-        format!("{a}");
+        let _ = format!("{a}");
     }
 
     // test that trailing commas are acceptable
-    format!("{}", "test",);
-    format!("{foo}", foo = "test",);
+    let _ = format!("{}", "test",);
+    let _ = format!("{foo}", foo = "test",);
 }
 
 // Basic test to make sure that we can invoke the `write!` macro with an
diff --git a/library/core/tests/fmt/builders.rs b/library/core/tests/fmt/builders.rs
index 487ce46be28..2bdc334b7c0 100644
--- a/library/core/tests/fmt/builders.rs
+++ b/library/core/tests/fmt/builders.rs
@@ -441,7 +441,7 @@ mod debug_map {
             }
         }
 
-        format!("{Foo:?}");
+        let _ = format!("{Foo:?}");
     }
 
     #[test]
@@ -455,7 +455,7 @@ mod debug_map {
             }
         }
 
-        format!("{Foo:?}");
+        let _ = format!("{Foo:?}");
     }
 
     #[test]
@@ -469,7 +469,7 @@ mod debug_map {
             }
         }
 
-        format!("{Foo:?}");
+        let _ = format!("{Foo:?}");
     }
 }
 
diff --git a/library/std/src/os/fd/owned.rs b/library/std/src/os/fd/owned.rs
index 8c7fc4cb2e4..a1f83029d27 100644
--- a/library/std/src/os/fd/owned.rs
+++ b/library/std/src/os/fd/owned.rs
@@ -175,6 +175,11 @@ impl Drop for OwnedFd {
             // the file descriptor was closed or not, and if we retried (for
             // something like EINTR), we might close another valid file descriptor
             // opened after we closed ours.
+            // However, this is usually justified, as some of the major Unices
+            // do make sure to always close the FD, even when `close()` is interrupted,
+            // and the scenario is rare to begin with.
+            // Helpful link to an epic discussion by POSIX workgroup:
+            // http://austingroupbugs.net/view.php?id=529
             #[cfg(not(target_os = "hermit"))]
             {
                 #[cfg(unix)]
diff --git a/src/bootstrap/Cargo.lock b/src/bootstrap/Cargo.lock
index 9c24742cff1..c095127da14 100644
--- a/src/bootstrap/Cargo.lock
+++ b/src/bootstrap/Cargo.lock
@@ -54,7 +54,6 @@ dependencies = [
  "junction",
  "libc",
  "object",
- "once_cell",
  "opener",
  "pretty_assertions",
  "semver",
diff --git a/src/bootstrap/Cargo.toml b/src/bootstrap/Cargo.toml
index 32dd3efa7a6..df7b5b88193 100644
--- a/src/bootstrap/Cargo.toml
+++ b/src/bootstrap/Cargo.toml
@@ -49,7 +49,6 @@ home = "0.5"
 ignore = "0.4"
 libc = "0.2"
 object = { version = "0.32", default-features = false, features = ["archive", "coff", "read_core", "unaligned"] }
-once_cell = "1.19"
 opener = "0.5"
 semver = "1.0"
 serde = "1.0"
diff --git a/src/bootstrap/src/core/build_steps/llvm.rs b/src/bootstrap/src/core/build_steps/llvm.rs
index bff731e13b0..872823506f8 100644
--- a/src/bootstrap/src/core/build_steps/llvm.rs
+++ b/src/bootstrap/src/core/build_steps/llvm.rs
@@ -753,7 +753,7 @@ fn configure_cmake(
     }
 
     if builder.config.llvm_clang_cl.is_some() {
-        cflags.push(&format!(" --target={target}"));
+        cflags.push(format!(" --target={target}"));
     }
     cfg.define("CMAKE_C_FLAGS", cflags);
     let mut cxxflags: OsString = builder
@@ -772,7 +772,7 @@ fn configure_cmake(
         cxxflags.push(s);
     }
     if builder.config.llvm_clang_cl.is_some() {
-        cxxflags.push(&format!(" --target={target}"));
+        cxxflags.push(format!(" --target={target}"));
     }
     cfg.define("CMAKE_CXX_FLAGS", cxxflags);
     if let Some(ar) = builder.ar(target) {
@@ -913,7 +913,7 @@ impl Step for Lld {
                 // Find clang's runtime library directory and push that as a search path to the
                 // cmake linker flags.
                 let clang_rt_dir = get_clang_cl_resource_dir(clang_cl_path);
-                ldflags.push_all(&format!("/libpath:{}", clang_rt_dir.display()));
+                ldflags.push_all(format!("/libpath:{}", clang_rt_dir.display()));
             }
         }
 
diff --git a/src/bootstrap/src/core/builder.rs b/src/bootstrap/src/core/builder.rs
index 24bb96c6b88..65cc1fa7478 100644
--- a/src/bootstrap/src/core/builder.rs
+++ b/src/bootstrap/src/core/builder.rs
@@ -8,6 +8,7 @@ use std::fs;
 use std::hash::Hash;
 use std::ops::Deref;
 use std::path::{Path, PathBuf};
+use std::sync::LazyLock;
 use std::time::{Duration, Instant};
 
 use crate::core::build_steps::tool::{self, SourceType};
@@ -27,8 +28,6 @@ use crate::utils::exec::{command, BootstrapCommand};
 pub use crate::Compiler;
 
 use clap::ValueEnum;
-// FIXME: replace with std::lazy after it gets stabilized and reaches beta
-use once_cell::sync::Lazy;
 
 #[cfg(test)]
 mod tests;
@@ -498,7 +497,7 @@ impl StepDescription {
 
 enum ReallyDefault<'a> {
     Bool(bool),
-    Lazy(Lazy<bool, Box<dyn Fn() -> bool + 'a>>),
+    Lazy(LazyLock<bool, Box<dyn Fn() -> bool + 'a>>),
 }
 
 pub struct ShouldRun<'a> {
@@ -529,7 +528,7 @@ impl<'a> ShouldRun<'a> {
     }
 
     pub fn lazy_default_condition(mut self, lazy_cond: Box<dyn Fn() -> bool + 'a>) -> Self {
-        self.is_really_default = ReallyDefault::Lazy(Lazy::new(lazy_cond));
+        self.is_really_default = ReallyDefault::Lazy(LazyLock::new(lazy_cond));
         self
     }
 
@@ -2526,7 +2525,7 @@ impl Cargo {
 
         if let Some(target_linker) = builder.linker(target) {
             let target = crate::envify(&target.triple);
-            self.command.env(&format!("CARGO_TARGET_{target}_LINKER"), target_linker);
+            self.command.env(format!("CARGO_TARGET_{target}_LINKER"), target_linker);
         }
         // We want to set -Clinker using Cargo, therefore we only call `linker_flags` and not
         // `linker_args` here.
diff --git a/src/bootstrap/src/utils/cache.rs b/src/bootstrap/src/utils/cache.rs
index e18dcbb47be..d60b54dc703 100644
--- a/src/bootstrap/src/utils/cache.rs
+++ b/src/bootstrap/src/utils/cache.rs
@@ -9,10 +9,7 @@ use std::marker::PhantomData;
 use std::mem;
 use std::ops::Deref;
 use std::path::PathBuf;
-use std::sync::Mutex;
-
-// FIXME: replace with std::lazy after it gets stabilized and reaches beta
-use once_cell::sync::Lazy;
+use std::sync::{LazyLock, Mutex};
 
 use crate::core::builder::Step;
 
@@ -196,7 +193,7 @@ impl Interner {
     }
 }
 
-pub static INTERNER: Lazy<Interner> = Lazy::new(Interner::default);
+pub static INTERNER: LazyLock<Interner> = LazyLock::new(Interner::default);
 
 /// This is essentially a `HashMap` which allows storing any type in its input and
 /// any type in its output. It is a write-once cache; values are never evicted,
diff --git a/src/tools/clippy/tests/ui/or_fun_call.fixed b/src/tools/clippy/tests/ui/or_fun_call.fixed
index 7657ef470c5..c76f7a81843 100644
--- a/src/tools/clippy/tests/ui/or_fun_call.fixed
+++ b/src/tools/clippy/tests/ui/or_fun_call.fixed
@@ -98,7 +98,7 @@ fn or_fun_call() {
 
     let opt = Some(1);
     let hello = "Hello";
-    let _ = opt.ok_or(format!("{} world.", hello));
+    let _ = opt.ok_or_else(|| format!("{} world.", hello));
 
     // index
     let map = HashMap::<u64, u64>::new();
diff --git a/src/tools/clippy/tests/ui/or_fun_call.stderr b/src/tools/clippy/tests/ui/or_fun_call.stderr
index b5a30f29923..3070db22fc5 100644
--- a/src/tools/clippy/tests/ui/or_fun_call.stderr
+++ b/src/tools/clippy/tests/ui/or_fun_call.stderr
@@ -100,6 +100,12 @@ error: use of `unwrap_or` to construct default value
 LL |     let _ = stringy.unwrap_or(String::new());
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()`
 
+error: use of `ok_or` followed by a function call
+  --> tests/ui/or_fun_call.rs:101:17
+   |
+LL |     let _ = opt.ok_or(format!("{} world.", hello));
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `ok_or_else(|| format!("{} world.", hello))`
+
 error: use of `unwrap_or` followed by a function call
   --> tests/ui/or_fun_call.rs:105:21
    |
@@ -190,5 +196,5 @@ error: use of `unwrap_or_else` to construct default value
 LL |         let _ = stringy.unwrap_or_else(String::new);
    |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()`
 
-error: aborting due to 31 previous errors
+error: aborting due to 32 previous errors
 
diff --git a/src/tools/miri/tests/pass/intptrcast.rs b/src/tools/miri/tests/pass/intptrcast.rs
index 4e9fa12c181..fb1a1dfae5d 100644
--- a/src/tools/miri/tests/pass/intptrcast.rs
+++ b/src/tools/miri/tests/pass/intptrcast.rs
@@ -35,7 +35,7 @@ fn cast_dangling() {
 fn format() {
     // Pointer string formatting! We can't check the output as it changes when libstd changes,
     // but we can make sure Miri does not error.
-    format!("{:?}", &mut 13 as *mut _);
+    let _ = format!("{:?}", &mut 13 as *mut _);
 }
 
 fn transmute() {
@@ -52,7 +52,7 @@ fn ptr_bitops1() {
     let one = bytes.as_ptr().wrapping_offset(1);
     let three = bytes.as_ptr().wrapping_offset(3);
     let res = (one as usize) | (three as usize);
-    format!("{}", res);
+    let _ = format!("{}", res);
 }
 
 fn ptr_bitops2() {
diff --git a/src/tools/miri/tests/pass/packed_struct.rs b/src/tools/miri/tests/pass/packed_struct.rs
index b86235e0c67..039eb5adef0 100644
--- a/src/tools/miri/tests/pass/packed_struct.rs
+++ b/src/tools/miri/tests/pass/packed_struct.rs
@@ -138,7 +138,7 @@ fn test_derive() {
     assert_eq!(x.partial_cmp(&y).unwrap(), x.cmp(&y));
     x.hash(&mut DefaultHasher::new());
     P::default();
-    format!("{:?}", x);
+    let _ = format!("{:?}", x);
 }
 
 fn main() {
diff --git a/src/tools/miri/tests/pass/shims/fs.rs b/src/tools/miri/tests/pass/shims/fs.rs
index 35980fad15d..16d3e8cab30 100644
--- a/src/tools/miri/tests/pass/shims/fs.rs
+++ b/src/tools/miri/tests/pass/shims/fs.rs
@@ -202,7 +202,7 @@ fn test_errors() {
     // Opening a non-existing file should fail with a "not found" error.
     assert_eq!(ErrorKind::NotFound, File::open(&path).unwrap_err().kind());
     // Make sure we can also format this.
-    format!("{0}: {0:?}", File::open(&path).unwrap_err());
+    let _ = format!("{0}: {0:?}", File::open(&path).unwrap_err());
     // Removing a non-existing file should fail with a "not found" error.
     assert_eq!(ErrorKind::NotFound, remove_file(&path).unwrap_err().kind());
     // Reading the metadata of a non-existing file should fail with a "not found" error.
@@ -301,5 +301,5 @@ fn test_from_raw_os_error() {
     let error = Error::from_raw_os_error(code);
     assert!(matches!(error.kind(), ErrorKind::Uncategorized));
     // Make sure we can also format this.
-    format!("{error:?}");
+    let _ = format!("{error:?}");
 }
diff --git a/src/tools/miri/tests/pass/shims/io.rs b/src/tools/miri/tests/pass/shims/io.rs
index d20fc75b793..420ef95a0cb 100644
--- a/src/tools/miri/tests/pass/shims/io.rs
+++ b/src/tools/miri/tests/pass/shims/io.rs
@@ -15,5 +15,5 @@ fn main() {
         panic!("unsupported OS")
     };
     let err = io::Error::from_raw_os_error(raw_os_error);
-    format!("{err}: {err:?}");
+    let _ = format!("{err}: {err:?}");
 }
diff --git a/src/tools/miri/tests/pass/vecdeque.rs b/src/tools/miri/tests/pass/vecdeque.rs
index 77c4ca5a04e..9153c428e18 100644
--- a/src/tools/miri/tests/pass/vecdeque.rs
+++ b/src/tools/miri/tests/pass/vecdeque.rs
@@ -31,8 +31,8 @@ fn main() {
     }
 
     // Regression test for Debug impl's
-    format!("{:?} {:?}", dst, dst.iter());
-    format!("{:?}", VecDeque::<u32>::new().iter());
+    let _ = format!("{:?} {:?}", dst, dst.iter());
+    let _ = format!("{:?}", VecDeque::<u32>::new().iter());
 
     for a in dst {
         assert_eq!(*a, 2);
diff --git a/src/tools/rust-analyzer/crates/stdx/src/anymap.rs b/src/tools/rust-analyzer/crates/stdx/src/anymap.rs
index d189b56a468..4eafcfb060f 100644
--- a/src/tools/rust-analyzer/crates/stdx/src/anymap.rs
+++ b/src/tools/rust-analyzer/crates/stdx/src/anymap.rs
@@ -68,8 +68,6 @@ pub type RawMap<A> = hash_map::HashMap<TypeId, Box<A>, BuildHasherDefault<TypeId
 /// The type parameter `A` allows you to use a different value type; normally you will want
 /// it to be `core::any::Any` (also known as `std::any::Any`), but there are other choices:
 ///
-/// - If you want the entire map to be cloneable, use `CloneAny` instead of `Any`; with
-///   that, you can only add types that implement `Clone` to the map.
 /// - You can add on `+ Send` or `+ Send + Sync` (e.g. `Map<dyn Any + Send>`) to add those
 ///   auto traits.
 ///
@@ -79,9 +77,6 @@ pub type RawMap<A> = hash_map::HashMap<TypeId, Box<A>, BuildHasherDefault<TypeId
 ///   also spelled [`AnyMap`] for convenience.
 /// - <code>[Map]&lt;dyn [core::any::Any] + Send&gt;</code>
 /// - <code>[Map]&lt;dyn [core::any::Any] + Send + Sync&gt;</code>
-/// - <code>[Map]&lt;dyn [CloneAny]&gt;</code>
-/// - <code>[Map]&lt;dyn [CloneAny] + Send&gt;</code>
-/// - <code>[Map]&lt;dyn [CloneAny] + Send + Sync&gt;</code>
 ///
 /// ## Example
 ///
@@ -205,12 +200,6 @@ mod tests {
         assert_debug::<Map<dyn Any>>();
         assert_debug::<Map<dyn Any + Send>>();
         assert_debug::<Map<dyn Any + Send + Sync>>();
-        assert_send::<Map<dyn CloneAny + Send>>();
-        assert_send::<Map<dyn CloneAny + Send + Sync>>();
-        assert_sync::<Map<dyn CloneAny + Send + Sync>>();
-        assert_debug::<Map<dyn CloneAny>>();
-        assert_debug::<Map<dyn CloneAny + Send>>();
-        assert_debug::<Map<dyn CloneAny + Send + Sync>>();
     }
 
     #[test]
@@ -232,53 +221,6 @@ mod tests {
     }
 }
 
-// impl some traits for dyn Any
-use core::fmt;
-
-#[doc(hidden)]
-pub trait CloneToAny {
-    /// Clone `self` into a new `Box<dyn CloneAny>` object.
-    fn clone_to_any(&self) -> Box<dyn CloneAny>;
-}
-
-impl<T: Any + Clone> CloneToAny for T {
-    #[inline]
-    fn clone_to_any(&self) -> Box<dyn CloneAny> {
-        Box::new(self.clone())
-    }
-}
-
-macro_rules! impl_clone {
-    ($t:ty) => {
-        impl Clone for Box<$t> {
-            #[inline]
-            fn clone(&self) -> Box<$t> {
-                // SAFETY: this dance is to reapply any Send/Sync marker. I’m not happy about this
-                // approach, given that I used to do it in safe code, but then came a dodgy
-                // future-compatibility warning where_clauses_object_safety, which is spurious for
-                // auto traits but still super annoying (future-compatibility lints seem to mean
-                // your bin crate needs a corresponding allow!). Although I explained my plight¹
-                // and it was all explained and agreed upon, no action has been taken. So I finally
-                // caved and worked around it by doing it this way, which matches what’s done for
-                // core::any², so it’s probably not *too* bad.
-                //
-                // ¹ https://github.com/rust-lang/rust/issues/51443#issuecomment-421988013
-                // ² https://github.com/rust-lang/rust/blob/e7825f2b690c9a0d21b6f6d84c404bb53b151b38/library/alloc/src/boxed.rs#L1613-L1616
-                let clone: Box<dyn CloneAny> = (**self).clone_to_any();
-                let raw: *mut dyn CloneAny = Box::into_raw(clone);
-                unsafe { Box::from_raw(raw as *mut $t) }
-            }
-        }
-
-        impl fmt::Debug for $t {
-            #[inline]
-            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-                f.pad(stringify!($t))
-            }
-        }
-    };
-}
-
 /// Methods for downcasting from an `Any`-like trait object.
 ///
 /// This should only be implemented on trait objects for subtraits of `Any`, though you can
@@ -350,16 +292,3 @@ macro_rules! implement {
 implement!(Any);
 implement!(Any + Send);
 implement!(Any + Send + Sync);
-
-/// [`Any`], but with cloning.
-///
-/// Every type with no non-`'static` references that implements `Clone` implements `CloneAny`.
-/// See [`core::any`] for more details on `Any` in general.
-pub trait CloneAny: Any + CloneToAny {}
-impl<T: Any + Clone> CloneAny for T {}
-implement!(CloneAny);
-implement!(CloneAny + Send);
-implement!(CloneAny + Send + Sync);
-impl_clone!(dyn CloneAny);
-impl_clone!(dyn CloneAny + Send);
-impl_clone!(dyn CloneAny + Send + Sync);
diff --git a/tests/pretty/issue-4264.pp b/tests/pretty/issue-4264.pp
index 018ccf82dae..fa958d9f1e8 100644
--- a/tests/pretty/issue-4264.pp
+++ b/tests/pretty/issue-4264.pp
@@ -29,16 +29,17 @@ fn bar() ({
 
 
 
-    ({
-        let res =
-            ((::alloc::fmt::format as
-                    for<'a> fn(Arguments<'a>) -> String {format})(((format_arguments::new_const
-                        as
-                        fn(&[&'static str; 1]) -> Arguments<'_> {Arguments::<'_>::new_const::<1>})((&([("test"
-                                    as &str)] as [&str; 1]) as &[&str; 1])) as Arguments<'_>))
-                as String);
-        (res as String)
-    } as String);
+    ((::alloc::__export::must_use as
+            fn(String) -> String {must_use::<String>})(({
+            let res =
+                ((::alloc::fmt::format as
+                        for<'a> fn(Arguments<'a>) -> String {format})(((format_arguments::new_const
+                            as
+                            fn(&[&'static str; 1]) -> Arguments<'_> {Arguments::<'_>::new_const::<1>})((&([("test"
+                                        as &str)] as [&str; 1]) as &[&str; 1])) as Arguments<'_>))
+                    as String);
+            (res as String)
+        } as String)) as String);
 } as ())
 type Foo = [i32; (3 as usize)];
 struct Bar {
diff --git a/tests/ui/cast/cast-rfc0401-vtable-kinds.rs b/tests/ui/cast/cast-rfc0401-vtable-kinds.rs
index 0d8f92f013f..5704a33cc87 100644
--- a/tests/ui/cast/cast-rfc0401-vtable-kinds.rs
+++ b/tests/ui/cast/cast-rfc0401-vtable-kinds.rs
@@ -4,25 +4,12 @@
 
 #![feature(unsized_tuple_coercion)]
 
-trait Foo<T> {
-    fn foo(&self, _: T) -> u32 { 42 }
-}
-
 trait Bar { //~ WARN trait `Bar` is never used
     fn bar(&self) { println!("Bar!"); }
 }
 
-impl<T> Foo<T> for () {}
-impl Foo<u32> for u32 { fn foo(&self, _: u32) -> u32 { self+43 } }
 impl Bar for () {}
 
-unsafe fn round_trip_and_call<'a>(t: *const (dyn Foo<u32>+'a)) -> u32 {
-    let foo_e : *const dyn Foo<u32> = t as *const _;
-    let r_1 = foo_e as *mut dyn Foo<u32>;
-
-    (&*r_1).foo(0)
-}
-
 #[repr(C)]
 struct FooS<T:?Sized>(T);
 #[repr(C)]
@@ -38,11 +25,6 @@ fn tuple_i32_to_u32<T:?Sized>(u: *const (i32, T)) -> *const (u32, T) {
 
 
 fn main() {
-    let x = 4u32;
-    let y : &dyn Foo<u32> = &x;
-    let fl = unsafe { round_trip_and_call(y as *const dyn Foo<u32>) };
-    assert_eq!(fl, (43+4));
-
     let s = FooS([0,1,2]);
     let u: &FooS<[u32]> = &s;
     let u: *const FooS<[u32]> = u;
diff --git a/tests/ui/cast/cast-rfc0401-vtable-kinds.stderr b/tests/ui/cast/cast-rfc0401-vtable-kinds.stderr
index 952687e98d0..4f57e2e7df7 100644
--- a/tests/ui/cast/cast-rfc0401-vtable-kinds.stderr
+++ b/tests/ui/cast/cast-rfc0401-vtable-kinds.stderr
@@ -1,5 +1,5 @@
 warning: trait `Bar` is never used
-  --> $DIR/cast-rfc0401-vtable-kinds.rs:11:7
+  --> $DIR/cast-rfc0401-vtable-kinds.rs:7:7
    |
 LL | trait Bar {
    |       ^^^
diff --git a/tests/ui/cast/ptr-to-trait-obj-add-auto.rs b/tests/ui/cast/ptr-to-trait-obj-add-auto.rs
new file mode 100644
index 00000000000..46e72ea0877
--- /dev/null
+++ b/tests/ui/cast/ptr-to-trait-obj-add-auto.rs
@@ -0,0 +1,18 @@
+//@ check-pass
+
+trait Trait<'a> {}
+
+fn add_auto<'a>(x: *mut dyn Trait<'a>) -> *mut (dyn Trait<'a> + Send) {
+    x as _
+    //~^ warning: adding an auto trait `Send` to a trait object in a pointer cast may cause UB later on
+    //~| warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+}
+
+// (to test diagnostic list formatting)
+fn add_multiple_auto<'a>(x: *mut dyn Trait<'a>) -> *mut (dyn Trait<'a> + Send + Sync + Unpin) {
+    x as _
+    //~^ warning: adding auto traits `Send`, `Sync`, and `Unpin` to a trait object in a pointer cast may cause UB later on
+    //~| warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+}
+
+fn main() {}
diff --git a/tests/ui/cast/ptr-to-trait-obj-add-auto.stderr b/tests/ui/cast/ptr-to-trait-obj-add-auto.stderr
new file mode 100644
index 00000000000..e5ef8bf76b4
--- /dev/null
+++ b/tests/ui/cast/ptr-to-trait-obj-add-auto.stderr
@@ -0,0 +1,43 @@
+warning: adding an auto trait `Send` to a trait object in a pointer cast may cause UB later on
+  --> $DIR/ptr-to-trait-obj-add-auto.rs:6:5
+   |
+LL |     x as _
+   |     ^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #127323 <https://github.com/rust-lang/rust/issues/127323>
+   = note: `#[warn(ptr_cast_add_auto_to_object)]` on by default
+
+warning: adding auto traits `Send`, `Sync`, and `Unpin` to a trait object in a pointer cast may cause UB later on
+  --> $DIR/ptr-to-trait-obj-add-auto.rs:13:5
+   |
+LL |     x as _
+   |     ^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #127323 <https://github.com/rust-lang/rust/issues/127323>
+
+warning: 2 warnings emitted
+
+Future incompatibility report: Future breakage diagnostic:
+warning: adding an auto trait `Send` to a trait object in a pointer cast may cause UB later on
+  --> $DIR/ptr-to-trait-obj-add-auto.rs:6:5
+   |
+LL |     x as _
+   |     ^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #127323 <https://github.com/rust-lang/rust/issues/127323>
+   = note: `#[warn(ptr_cast_add_auto_to_object)]` on by default
+
+Future breakage diagnostic:
+warning: adding auto traits `Send`, `Sync`, and `Unpin` to a trait object in a pointer cast may cause UB later on
+  --> $DIR/ptr-to-trait-obj-add-auto.rs:13:5
+   |
+LL |     x as _
+   |     ^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #127323 <https://github.com/rust-lang/rust/issues/127323>
+   = note: `#[warn(ptr_cast_add_auto_to_object)]` on by default
+
diff --git a/tests/ui/cast/ptr-to-trait-obj-add-super-auto.rs b/tests/ui/cast/ptr-to-trait-obj-add-super-auto.rs
new file mode 100644
index 00000000000..ac8108d8ec4
--- /dev/null
+++ b/tests/ui/cast/ptr-to-trait-obj-add-super-auto.rs
@@ -0,0 +1,9 @@
+//@ check-pass
+
+trait Trait: Send {}
+impl Trait for () {}
+
+fn main() {
+    // This is OK: `Trait` has `Send` super trait.
+    &() as *const dyn Trait as *const (dyn Trait + Send);
+}
diff --git a/tests/ui/cast/ptr-to-trait-obj-different-args.rs b/tests/ui/cast/ptr-to-trait-obj-different-args.rs
new file mode 100644
index 00000000000..c6038cfe864
--- /dev/null
+++ b/tests/ui/cast/ptr-to-trait-obj-different-args.rs
@@ -0,0 +1,37 @@
+//@ check-fail
+//
+// issue: <https://github.com/rust-lang/rust/issues/120222>
+
+trait A {}
+impl<T> A for T {}
+trait B {}
+impl<T> B for T {}
+
+trait Trait<G> {}
+struct X;
+impl<T> Trait<X> for T {}
+struct Y;
+impl<T> Trait<Y> for T {}
+
+fn main() {
+    let a: *const dyn A = &();
+    let b: *const dyn B = a as _; //~ error: casting `*const dyn A` as `*const dyn B` is invalid
+
+    let x: *const dyn Trait<X> = &();
+    let y: *const dyn Trait<Y> = x as _; //~ error: mismatched types
+
+    _ = (b, y);
+}
+
+fn generic<T>(x: *const dyn Trait<X>, t: *const dyn Trait<T>) {
+    let _: *const dyn Trait<T> = x as _; //~ error: mismatched types
+    let _: *const dyn Trait<X> = t as _; //~ error: mismatched types
+}
+
+trait Assocked {
+    type Assoc: ?Sized;
+}
+
+fn change_assoc(x: *mut dyn Assocked<Assoc = u8>) -> *mut dyn Assocked<Assoc = u32> {
+    x as _ //~ error: mismatched types
+}
diff --git a/tests/ui/cast/ptr-to-trait-obj-different-args.stderr b/tests/ui/cast/ptr-to-trait-obj-different-args.stderr
new file mode 100644
index 00000000000..b04289ae747
--- /dev/null
+++ b/tests/ui/cast/ptr-to-trait-obj-different-args.stderr
@@ -0,0 +1,53 @@
+error[E0606]: casting `*const dyn A` as `*const dyn B` is invalid
+  --> $DIR/ptr-to-trait-obj-different-args.rs:18:27
+   |
+LL |     let b: *const dyn B = a as _;
+   |                           ^^^^^^
+   |
+   = note: vtable kinds may not match
+
+error[E0308]: mismatched types
+  --> $DIR/ptr-to-trait-obj-different-args.rs:21:34
+   |
+LL |     let y: *const dyn Trait<Y> = x as _;
+   |                                  ^^^^^^ expected `X`, found `Y`
+   |
+   = note: expected trait object `dyn Trait<X>`
+              found trait object `dyn Trait<Y>`
+
+error[E0308]: mismatched types
+  --> $DIR/ptr-to-trait-obj-different-args.rs:27:34
+   |
+LL | fn generic<T>(x: *const dyn Trait<X>, t: *const dyn Trait<T>) {
+   |            - found this type parameter
+LL |     let _: *const dyn Trait<T> = x as _;
+   |                                  ^^^^^^ expected `X`, found type parameter `T`
+   |
+   = note: expected trait object `dyn Trait<X>`
+              found trait object `dyn Trait<T>`
+
+error[E0308]: mismatched types
+  --> $DIR/ptr-to-trait-obj-different-args.rs:28:34
+   |
+LL | fn generic<T>(x: *const dyn Trait<X>, t: *const dyn Trait<T>) {
+   |            - expected this type parameter
+LL |     let _: *const dyn Trait<T> = x as _;
+LL |     let _: *const dyn Trait<X> = t as _;
+   |                                  ^^^^^^ expected type parameter `T`, found `X`
+   |
+   = note: expected trait object `dyn Trait<T>`
+              found trait object `dyn Trait<X>`
+
+error[E0308]: mismatched types
+  --> $DIR/ptr-to-trait-obj-different-args.rs:36:5
+   |
+LL |     x as _
+   |     ^^^^^^ expected `u8`, found `u32`
+   |
+   = note: expected trait object `dyn Assocked<Assoc = u8>`
+              found trait object `dyn Assocked<Assoc = u32>`
+
+error: aborting due to 5 previous errors
+
+Some errors have detailed explanations: E0308, E0606.
+For more information about an error, try `rustc --explain E0308`.
diff --git a/tests/ui/cast/ptr-to-trait-obj-different-regions-id-trait.rs b/tests/ui/cast/ptr-to-trait-obj-different-regions-id-trait.rs
new file mode 100644
index 00000000000..cdd55e24392
--- /dev/null
+++ b/tests/ui/cast/ptr-to-trait-obj-different-regions-id-trait.rs
@@ -0,0 +1,27 @@
+//@ check-fail
+//
+// Make sure we can't trick the compiler by using a projection.
+
+trait Cat<'a> {}
+impl Cat<'_> for () {}
+
+trait Id {
+    type Id: ?Sized;
+}
+impl<T: ?Sized> Id for T {
+    type Id = T;
+}
+
+struct S<T: ?Sized> {
+    tail: <T as Id>::Id,
+}
+
+fn m<'a>() {
+    let unsend: *const dyn Cat<'a> = &();
+    let _send = unsend as *const S<dyn Cat<'static>>;
+    //~^ error: lifetime may not live long enough
+}
+
+fn main() {
+    m();
+}
diff --git a/tests/ui/cast/ptr-to-trait-obj-different-regions-id-trait.stderr b/tests/ui/cast/ptr-to-trait-obj-different-regions-id-trait.stderr
new file mode 100644
index 00000000000..d1d598e603f
--- /dev/null
+++ b/tests/ui/cast/ptr-to-trait-obj-different-regions-id-trait.stderr
@@ -0,0 +1,15 @@
+error: lifetime may not live long enough
+  --> $DIR/ptr-to-trait-obj-different-regions-id-trait.rs:21:17
+   |
+LL | fn m<'a>() {
+   |      -- lifetime `'a` defined here
+LL |     let unsend: *const dyn Cat<'a> = &();
+LL |     let _send = unsend as *const S<dyn Cat<'static>>;
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static`
+   |
+   = note: requirement occurs because of the type `S<dyn Cat<'_>>`, which makes the generic argument `dyn Cat<'_>` invariant
+   = note: the struct `S<T>` is invariant over the parameter `T`
+   = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/cast/ptr-to-trait-obj-different-regions-lt-ext.rs b/tests/ui/cast/ptr-to-trait-obj-different-regions-lt-ext.rs
new file mode 100644
index 00000000000..96345de01c9
--- /dev/null
+++ b/tests/ui/cast/ptr-to-trait-obj-different-regions-lt-ext.rs
@@ -0,0 +1,31 @@
+//@ check-fail
+//
+// issue: <https://github.com/rust-lang/rust/issues/120217>
+
+#![feature(arbitrary_self_types)]
+
+trait Static<'a> {
+    fn proof(self: *const Self, s: &'a str) -> &'static str;
+}
+
+fn bad_cast<'a>(x: *const dyn Static<'static>) -> *const dyn Static<'a> {
+    x as _ //~ error: lifetime may not live long enough
+}
+
+impl Static<'static> for () {
+    fn proof(self: *const Self, s: &'static str) -> &'static str {
+        s
+    }
+}
+
+fn extend_lifetime(s: &str) -> &'static str {
+    bad_cast(&()).proof(s)
+}
+
+fn main() {
+    let s = String::from("Hello World");
+    let slice = extend_lifetime(&s);
+    println!("Now it exists: {slice}");
+    drop(s);
+    println!("Now it’s gone: {slice}");
+}
diff --git a/tests/ui/cast/ptr-to-trait-obj-different-regions-lt-ext.stderr b/tests/ui/cast/ptr-to-trait-obj-different-regions-lt-ext.stderr
new file mode 100644
index 00000000000..b7319e3356b
--- /dev/null
+++ b/tests/ui/cast/ptr-to-trait-obj-different-regions-lt-ext.stderr
@@ -0,0 +1,10 @@
+error: lifetime may not live long enough
+  --> $DIR/ptr-to-trait-obj-different-regions-lt-ext.rs:12:5
+   |
+LL | fn bad_cast<'a>(x: *const dyn Static<'static>) -> *const dyn Static<'a> {
+   |             -- lifetime `'a` defined here
+LL |     x as _
+   |     ^^^^^^ returning this value requires that `'a` must outlive `'static`
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/cast/ptr-to-trait-obj-different-regions-misc.rs b/tests/ui/cast/ptr-to-trait-obj-different-regions-misc.rs
new file mode 100644
index 00000000000..01c347bfae5
--- /dev/null
+++ b/tests/ui/cast/ptr-to-trait-obj-different-regions-misc.rs
@@ -0,0 +1,37 @@
+//@ check-fail
+
+trait Trait<'a> {}
+
+fn change_lt<'a, 'b>(x: *mut dyn Trait<'a>) -> *mut dyn Trait<'b> {
+    x as _ //~ error: lifetime may not live long enough
+           //~| error: lifetime may not live long enough
+}
+
+fn change_lt_ab<'a: 'b, 'b>(x: *mut dyn Trait<'a>) -> *mut dyn Trait<'b> {
+    x as _ //~ error: lifetime may not live long enough
+}
+
+fn change_lt_ba<'a, 'b: 'a>(x: *mut dyn Trait<'a>) -> *mut dyn Trait<'b> {
+    x as _ //~ error: lifetime may not live long enough
+}
+
+trait Assocked {
+    type Assoc: ?Sized;
+}
+
+fn change_assoc_0<'a, 'b>(
+    x: *mut dyn Assocked<Assoc = dyn Send + 'a>,
+) -> *mut dyn Assocked<Assoc = dyn Send + 'b> {
+    x as _ //~ error: lifetime may not live long enough
+           //~| error: lifetime may not live long enough
+}
+
+fn change_assoc_1<'a, 'b>(
+    x: *mut dyn Assocked<Assoc = dyn Trait<'a>>,
+) -> *mut dyn Assocked<Assoc = dyn Trait<'b>> {
+    x as _ //~ error: lifetime may not live long enough
+           //~| error: lifetime may not live long enough
+}
+
+
+fn main() {}
diff --git a/tests/ui/cast/ptr-to-trait-obj-different-regions-misc.stderr b/tests/ui/cast/ptr-to-trait-obj-different-regions-misc.stderr
new file mode 100644
index 00000000000..7044e4dec1f
--- /dev/null
+++ b/tests/ui/cast/ptr-to-trait-obj-different-regions-misc.stderr
@@ -0,0 +1,136 @@
+error: lifetime may not live long enough
+  --> $DIR/ptr-to-trait-obj-different-regions-misc.rs:6:5
+   |
+LL | fn change_lt<'a, 'b>(x: *mut dyn Trait<'a>) -> *mut dyn Trait<'b> {
+   |              --  -- lifetime `'b` defined here
+   |              |
+   |              lifetime `'a` defined here
+LL |     x as _
+   |     ^^^^^^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b`
+   |
+   = help: consider adding the following bound: `'b: 'a`
+   = note: requirement occurs because of a mutable pointer to `dyn Trait<'_>`
+   = note: mutable pointers are invariant over their type parameter
+   = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
+
+error: lifetime may not live long enough
+  --> $DIR/ptr-to-trait-obj-different-regions-misc.rs:6:5
+   |
+LL | fn change_lt<'a, 'b>(x: *mut dyn Trait<'a>) -> *mut dyn Trait<'b> {
+   |              --  -- lifetime `'b` defined here
+   |              |
+   |              lifetime `'a` defined here
+LL |     x as _
+   |     ^^^^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a`
+   |
+   = help: consider adding the following bound: `'a: 'b`
+   = note: requirement occurs because of a mutable pointer to `dyn Trait<'_>`
+   = note: mutable pointers are invariant over their type parameter
+   = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
+
+help: `'b` and `'a` must be the same: replace one with the other
+
+error: lifetime may not live long enough
+  --> $DIR/ptr-to-trait-obj-different-regions-misc.rs:11:5
+   |
+LL | fn change_lt_ab<'a: 'b, 'b>(x: *mut dyn Trait<'a>) -> *mut dyn Trait<'b> {
+   |                 --      -- lifetime `'b` defined here
+   |                 |
+   |                 lifetime `'a` defined here
+LL |     x as _
+   |     ^^^^^^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b`
+   |
+   = help: consider adding the following bound: `'b: 'a`
+   = note: requirement occurs because of a mutable pointer to `dyn Trait<'_>`
+   = note: mutable pointers are invariant over their type parameter
+   = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
+
+error: lifetime may not live long enough
+  --> $DIR/ptr-to-trait-obj-different-regions-misc.rs:15:5
+   |
+LL | fn change_lt_ba<'a, 'b: 'a>(x: *mut dyn Trait<'a>) -> *mut dyn Trait<'b> {
+   |                 --  -- lifetime `'b` defined here
+   |                 |
+   |                 lifetime `'a` defined here
+LL |     x as _
+   |     ^^^^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a`
+   |
+   = help: consider adding the following bound: `'a: 'b`
+   = note: requirement occurs because of a mutable pointer to `dyn Trait<'_>`
+   = note: mutable pointers are invariant over their type parameter
+   = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
+
+error: lifetime may not live long enough
+  --> $DIR/ptr-to-trait-obj-different-regions-misc.rs:25:5
+   |
+LL | fn change_assoc_0<'a, 'b>(
+   |                   --  -- lifetime `'b` defined here
+   |                   |
+   |                   lifetime `'a` defined here
+...
+LL |     x as _
+   |     ^^^^^^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b`
+   |
+   = help: consider adding the following bound: `'b: 'a`
+   = note: requirement occurs because of a mutable pointer to `dyn Assocked<Assoc = dyn Send>`
+   = note: mutable pointers are invariant over their type parameter
+   = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
+
+error: lifetime may not live long enough
+  --> $DIR/ptr-to-trait-obj-different-regions-misc.rs:25:5
+   |
+LL | fn change_assoc_0<'a, 'b>(
+   |                   --  -- lifetime `'b` defined here
+   |                   |
+   |                   lifetime `'a` defined here
+...
+LL |     x as _
+   |     ^^^^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a`
+   |
+   = help: consider adding the following bound: `'a: 'b`
+   = note: requirement occurs because of a mutable pointer to `dyn Assocked<Assoc = dyn Send>`
+   = note: mutable pointers are invariant over their type parameter
+   = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
+
+help: `'b` and `'a` must be the same: replace one with the other
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error: lifetime may not live long enough
+  --> $DIR/ptr-to-trait-obj-different-regions-misc.rs:32:5
+   |
+LL | fn change_assoc_1<'a, 'b>(
+   |                   --  -- lifetime `'b` defined here
+   |                   |
+   |                   lifetime `'a` defined here
+...
+LL |     x as _
+   |     ^^^^^^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b`
+   |
+   = help: consider adding the following bound: `'b: 'a`
+   = note: requirement occurs because of a mutable pointer to `dyn Assocked<Assoc = dyn Trait<'_>>`
+   = note: mutable pointers are invariant over their type parameter
+   = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
+
+error: lifetime may not live long enough
+  --> $DIR/ptr-to-trait-obj-different-regions-misc.rs:32:5
+   |
+LL | fn change_assoc_1<'a, 'b>(
+   |                   --  -- lifetime `'b` defined here
+   |                   |
+   |                   lifetime `'a` defined here
+...
+LL |     x as _
+   |     ^^^^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a`
+   |
+   = help: consider adding the following bound: `'a: 'b`
+   = note: requirement occurs because of a mutable pointer to `dyn Assocked<Assoc = dyn Trait<'_>>`
+   = note: mutable pointers are invariant over their type parameter
+   = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
+
+help: `'b` and `'a` must be the same: replace one with the other
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error: aborting due to 8 previous errors
+
diff --git a/tests/ui/cast/ptr-to-trait-obj-ok.rs b/tests/ui/cast/ptr-to-trait-obj-ok.rs
new file mode 100644
index 00000000000..656c99c58dc
--- /dev/null
+++ b/tests/ui/cast/ptr-to-trait-obj-ok.rs
@@ -0,0 +1,17 @@
+//@ check-pass
+
+trait Trait<'a> {}
+
+fn remove_auto<'a>(x: *mut (dyn Trait<'a> + Send)) -> *mut dyn Trait<'a> {
+    x as _
+}
+
+fn cast_inherent_lt<'a, 'b>(x: *mut (dyn Trait<'static> + 'a)) -> *mut (dyn Trait<'static> + 'b) {
+    x as _
+}
+
+fn unprincipled<'a, 'b>(x: *mut (dyn Send + 'a)) -> *mut (dyn Sync + 'b) {
+    x as _
+}
+
+fn main() {}
diff --git a/tests/ui/cast/ptr-to-trait-obj-wrap-upcast.rs b/tests/ui/cast/ptr-to-trait-obj-wrap-upcast.rs
new file mode 100644
index 00000000000..ff2c4cacfb1
--- /dev/null
+++ b/tests/ui/cast/ptr-to-trait-obj-wrap-upcast.rs
@@ -0,0 +1,14 @@
+trait Super {}
+trait Sub: Super {}
+
+struct Wrapper<T: ?Sized>(T);
+
+// This cast should not compile.
+// Upcasting can't work here, because we are also changing the type (`Wrapper`),
+// and reinterpreting would be confusing/surprising.
+// See <https://github.com/rust-lang/rust/pull/120248#discussion_r1487739518>
+fn cast(ptr: *const dyn Sub) -> *const Wrapper<dyn Super> {
+    ptr as _ //~ error: casting `*const (dyn Sub + 'static)` as `*const Wrapper<dyn Super>` is invalid
+}
+
+fn main() {}
diff --git a/tests/ui/cast/ptr-to-trait-obj-wrap-upcast.stderr b/tests/ui/cast/ptr-to-trait-obj-wrap-upcast.stderr
new file mode 100644
index 00000000000..38c8ba96bc5
--- /dev/null
+++ b/tests/ui/cast/ptr-to-trait-obj-wrap-upcast.stderr
@@ -0,0 +1,11 @@
+error[E0606]: casting `*const (dyn Sub + 'static)` as `*const Wrapper<dyn Super>` is invalid
+  --> $DIR/ptr-to-trait-obj-wrap-upcast.rs:11:5
+   |
+LL |     ptr as _
+   |     ^^^^^^^^
+   |
+   = note: vtable kinds may not match
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0606`.
diff --git a/tests/ui/deriving/deriving-in-fn.rs b/tests/ui/deriving/deriving-in-fn.rs
index 72da2148350..13f3d39597c 100644
--- a/tests/ui/deriving/deriving-in-fn.rs
+++ b/tests/ui/deriving/deriving-in-fn.rs
@@ -9,5 +9,5 @@ pub fn main() {
     }
 
     let f = Foo { foo: 10 };
-    format!("{:?}", f);
+    let _ = format!("{:?}", f);
 }
diff --git a/tests/ui/fmt/struct-field-as-captured-argument.fixed b/tests/ui/fmt/struct-field-as-captured-argument.fixed
index e13af744ec8..0da40737354 100644
--- a/tests/ui/fmt/struct-field-as-captured-argument.fixed
+++ b/tests/ui/fmt/struct-field-as-captured-argument.fixed
@@ -8,11 +8,11 @@ struct Foo {
 fn main() {
     let foo = Foo { field: 0 };
     let bar = 3;
-    format!("{0}", foo.field); //~ ERROR invalid format string: field access isn't supported
-    format!("{1} {} {bar}", "aa", foo.field); //~ ERROR invalid format string: field access isn't supported
-    format!("{2} {} {1} {bar}", "aa", "bb", foo.field); //~ ERROR invalid format string: field access isn't supported
-    format!("{1} {} {baz}", "aa", foo.field, baz = 3); //~ ERROR invalid format string: field access isn't supported
-    format!("{1:?} {} {baz}", "aa", foo.field, baz = 3); //~ ERROR invalid format string: field access isn't supported
-    format!("{1:#?} {} {baz}", "aa", foo.field, baz = 3); //~ ERROR invalid format string: field access isn't supported
-    format!("{1:.3} {} {baz}", "aa", foo.field, baz = 3); //~ ERROR invalid format string: field access isn't supported
+    let _ = format!("{0}", foo.field); //~ ERROR invalid format string: field access isn't supported
+    let _ = format!("{1} {} {bar}", "aa", foo.field); //~ ERROR invalid format string: field access isn't supported
+    let _ = format!("{2} {} {1} {bar}", "aa", "bb", foo.field); //~ ERROR invalid format string: field access isn't supported
+    let _ = format!("{1} {} {baz}", "aa", foo.field, baz = 3); //~ ERROR invalid format string: field access isn't supported
+    let _ = format!("{1:?} {} {baz}", "aa", foo.field, baz = 3); //~ ERROR invalid format string: field access isn't supported
+    let _ = format!("{1:#?} {} {baz}", "aa", foo.field, baz = 3); //~ ERROR invalid format string: field access isn't supported
+    let _ = format!("{1:.3} {} {baz}", "aa", foo.field, baz = 3); //~ ERROR invalid format string: field access isn't supported
 }
diff --git a/tests/ui/fmt/struct-field-as-captured-argument.rs b/tests/ui/fmt/struct-field-as-captured-argument.rs
index 6a875a85848..325b4e3a218 100644
--- a/tests/ui/fmt/struct-field-as-captured-argument.rs
+++ b/tests/ui/fmt/struct-field-as-captured-argument.rs
@@ -8,11 +8,11 @@ struct Foo {
 fn main() {
     let foo = Foo { field: 0 };
     let bar = 3;
-    format!("{foo.field}"); //~ ERROR invalid format string: field access isn't supported
-    format!("{foo.field} {} {bar}", "aa"); //~ ERROR invalid format string: field access isn't supported
-    format!("{foo.field} {} {1} {bar}", "aa", "bb"); //~ ERROR invalid format string: field access isn't supported
-    format!("{foo.field} {} {baz}", "aa", baz = 3); //~ ERROR invalid format string: field access isn't supported
-    format!("{foo.field:?} {} {baz}", "aa", baz = 3); //~ ERROR invalid format string: field access isn't supported
-    format!("{foo.field:#?} {} {baz}", "aa", baz = 3); //~ ERROR invalid format string: field access isn't supported
-    format!("{foo.field:.3} {} {baz}", "aa", baz = 3); //~ ERROR invalid format string: field access isn't supported
+    let _ = format!("{foo.field}"); //~ ERROR invalid format string: field access isn't supported
+    let _ = format!("{foo.field} {} {bar}", "aa"); //~ ERROR invalid format string: field access isn't supported
+    let _ = format!("{foo.field} {} {1} {bar}", "aa", "bb"); //~ ERROR invalid format string: field access isn't supported
+    let _ = format!("{foo.field} {} {baz}", "aa", baz = 3); //~ ERROR invalid format string: field access isn't supported
+    let _ = format!("{foo.field:?} {} {baz}", "aa", baz = 3); //~ ERROR invalid format string: field access isn't supported
+    let _ = format!("{foo.field:#?} {} {baz}", "aa", baz = 3); //~ ERROR invalid format string: field access isn't supported
+    let _ = format!("{foo.field:.3} {} {baz}", "aa", baz = 3); //~ ERROR invalid format string: field access isn't supported
 }
diff --git a/tests/ui/fmt/struct-field-as-captured-argument.stderr b/tests/ui/fmt/struct-field-as-captured-argument.stderr
index 7ea8b4068f2..4ef022cecb0 100644
--- a/tests/ui/fmt/struct-field-as-captured-argument.stderr
+++ b/tests/ui/fmt/struct-field-as-captured-argument.stderr
@@ -1,79 +1,79 @@
 error: invalid format string: field access isn't supported
-  --> $DIR/struct-field-as-captured-argument.rs:11:15
+  --> $DIR/struct-field-as-captured-argument.rs:11:23
    |
-LL |     format!("{foo.field}");
-   |               ^^^^^^^^^ not supported in format string
+LL |     let _ = format!("{foo.field}");
+   |                       ^^^^^^^^^ not supported in format string
    |
 help: consider using a positional formatting argument instead
    |
-LL |     format!("{0}", foo.field);
-   |               ~  +++++++++++
+LL |     let _ = format!("{0}", foo.field);
+   |                       ~  +++++++++++
 
 error: invalid format string: field access isn't supported
-  --> $DIR/struct-field-as-captured-argument.rs:12:15
+  --> $DIR/struct-field-as-captured-argument.rs:12:23
    |
-LL |     format!("{foo.field} {} {bar}", "aa");
-   |               ^^^^^^^^^ not supported in format string
+LL |     let _ = format!("{foo.field} {} {bar}", "aa");
+   |                       ^^^^^^^^^ not supported in format string
    |
 help: consider using a positional formatting argument instead
    |
-LL |     format!("{1} {} {bar}", "aa", foo.field);
-   |               ~                 +++++++++++
+LL |     let _ = format!("{1} {} {bar}", "aa", foo.field);
+   |                       ~                 +++++++++++
 
 error: invalid format string: field access isn't supported
-  --> $DIR/struct-field-as-captured-argument.rs:13:15
+  --> $DIR/struct-field-as-captured-argument.rs:13:23
    |
-LL |     format!("{foo.field} {} {1} {bar}", "aa", "bb");
-   |               ^^^^^^^^^ not supported in format string
+LL |     let _ = format!("{foo.field} {} {1} {bar}", "aa", "bb");
+   |                       ^^^^^^^^^ not supported in format string
    |
 help: consider using a positional formatting argument instead
    |
-LL |     format!("{2} {} {1} {bar}", "aa", "bb", foo.field);
-   |               ~                           +++++++++++
+LL |     let _ = format!("{2} {} {1} {bar}", "aa", "bb", foo.field);
+   |                       ~                           +++++++++++
 
 error: invalid format string: field access isn't supported
-  --> $DIR/struct-field-as-captured-argument.rs:14:15
+  --> $DIR/struct-field-as-captured-argument.rs:14:23
    |
-LL |     format!("{foo.field} {} {baz}", "aa", baz = 3);
-   |               ^^^^^^^^^ not supported in format string
+LL |     let _ = format!("{foo.field} {} {baz}", "aa", baz = 3);
+   |                       ^^^^^^^^^ not supported in format string
    |
 help: consider using a positional formatting argument instead
    |
-LL |     format!("{1} {} {baz}", "aa", foo.field, baz = 3);
-   |               ~                 +++++++++++
+LL |     let _ = format!("{1} {} {baz}", "aa", foo.field, baz = 3);
+   |                       ~                 +++++++++++
 
 error: invalid format string: field access isn't supported
-  --> $DIR/struct-field-as-captured-argument.rs:15:15
+  --> $DIR/struct-field-as-captured-argument.rs:15:23
    |
-LL |     format!("{foo.field:?} {} {baz}", "aa", baz = 3);
-   |               ^^^^^^^^^ not supported in format string
+LL |     let _ = format!("{foo.field:?} {} {baz}", "aa", baz = 3);
+   |                       ^^^^^^^^^ not supported in format string
    |
 help: consider using a positional formatting argument instead
    |
-LL |     format!("{1:?} {} {baz}", "aa", foo.field, baz = 3);
-   |               ~                   +++++++++++
+LL |     let _ = format!("{1:?} {} {baz}", "aa", foo.field, baz = 3);
+   |                       ~                   +++++++++++
 
 error: invalid format string: field access isn't supported
-  --> $DIR/struct-field-as-captured-argument.rs:16:15
+  --> $DIR/struct-field-as-captured-argument.rs:16:23
    |
-LL |     format!("{foo.field:#?} {} {baz}", "aa", baz = 3);
-   |               ^^^^^^^^^ not supported in format string
+LL |     let _ = format!("{foo.field:#?} {} {baz}", "aa", baz = 3);
+   |                       ^^^^^^^^^ not supported in format string
    |
 help: consider using a positional formatting argument instead
    |
-LL |     format!("{1:#?} {} {baz}", "aa", foo.field, baz = 3);
-   |               ~                    +++++++++++
+LL |     let _ = format!("{1:#?} {} {baz}", "aa", foo.field, baz = 3);
+   |                       ~                    +++++++++++
 
 error: invalid format string: field access isn't supported
-  --> $DIR/struct-field-as-captured-argument.rs:17:15
+  --> $DIR/struct-field-as-captured-argument.rs:17:23
    |
-LL |     format!("{foo.field:.3} {} {baz}", "aa", baz = 3);
-   |               ^^^^^^^^^ not supported in format string
+LL |     let _ = format!("{foo.field:.3} {} {baz}", "aa", baz = 3);
+   |                       ^^^^^^^^^ not supported in format string
    |
 help: consider using a positional formatting argument instead
    |
-LL |     format!("{1:.3} {} {baz}", "aa", foo.field, baz = 3);
-   |               ~                    +++++++++++
+LL |     let _ = format!("{1:.3} {} {baz}", "aa", foo.field, baz = 3);
+   |                       ~                    +++++++++++
 
 error: aborting due to 7 previous errors
 
diff --git a/tests/ui/issues/issue-20676.rs b/tests/ui/issues/issue-20676.rs
index b3319950b42..2059365c7d6 100644
--- a/tests/ui/issues/issue-20676.rs
+++ b/tests/ui/issues/issue-20676.rs
@@ -8,5 +8,5 @@ use std::fmt;
 
 fn main() {
     let a: &dyn fmt::Debug = &1;
-    format!("{:?}", a);
+    let _ = format!("{:?}", a);
 }
diff --git a/tests/ui/mir/alignment/misaligned-constant-gvn.rs b/tests/ui/mir/alignment/misaligned-constant-gvn.rs
new file mode 100644
index 00000000000..363d5c0ed34
--- /dev/null
+++ b/tests/ui/mir/alignment/misaligned-constant-gvn.rs
@@ -0,0 +1,8 @@
+//@ build-pass
+//@ compile-flags: -Zmir-opt-level=0 -Zmir-enable-passes=+GVN
+
+fn main() {
+    let variant: Option<u32> = None;
+    let transmuted: u64 = unsafe { std::mem::transmute(variant) };
+    println!("{transmuted}");
+}
diff --git a/tests/ui/mismatched_types/cast-rfc0401.rs b/tests/ui/mismatched_types/cast-rfc0401.rs
index 57222f45947..b2ff5b4a0c0 100644
--- a/tests/ui/mismatched_types/cast-rfc0401.rs
+++ b/tests/ui/mismatched_types/cast-rfc0401.rs
@@ -66,7 +66,7 @@ fn main()
 
     let cf: *const dyn Foo = &0;
     let _ = cf as *const [u16]; //~ ERROR is invalid
-    let _ = cf as *const dyn Bar; //~ ERROR is invalid
+    let _ = cf as *const dyn Bar; //~ ERROR casting `*const dyn Foo` as `*const dyn Bar` is invalid
 
     vec![0.0].iter().map(|s| s as f32).collect::<Vec<f32>>(); //~ ERROR is invalid
 }
diff --git a/tests/ui/suggestions/issue-114797-bad-parentheses-dyn-trait.fixed b/tests/ui/suggestions/issue-114797-bad-parentheses-dyn-trait.fixed
index e072c476c6b..4e562193f0d 100644
--- a/tests/ui/suggestions/issue-114797-bad-parentheses-dyn-trait.fixed
+++ b/tests/ui/suggestions/issue-114797-bad-parentheses-dyn-trait.fixed
@@ -3,9 +3,9 @@
 
 trait Trait {}
 
-fn assert_send(ptr: *mut dyn Trait) -> *mut (dyn Trait + Send) {
+fn assert_send() -> *mut (dyn Trait + Send) {
     //~^ ERROR incorrect parentheses around trait bounds
-    ptr as _
+    loop {}
 }
 
 fn foo2(_: &(dyn Trait + Send)) {}
diff --git a/tests/ui/suggestions/issue-114797-bad-parentheses-dyn-trait.rs b/tests/ui/suggestions/issue-114797-bad-parentheses-dyn-trait.rs
index 88995141426..4a00059400c 100644
--- a/tests/ui/suggestions/issue-114797-bad-parentheses-dyn-trait.rs
+++ b/tests/ui/suggestions/issue-114797-bad-parentheses-dyn-trait.rs
@@ -3,9 +3,9 @@
 
 trait Trait {}
 
-fn assert_send(ptr: *mut dyn Trait) -> *mut dyn (Trait + Send) {
+fn assert_send() -> *mut dyn (Trait + Send) {
     //~^ ERROR incorrect parentheses around trait bounds
-    ptr as _
+    loop {}
 }
 
 fn foo2(_: &dyn (Trait + Send)) {}
diff --git a/tests/ui/suggestions/issue-114797-bad-parentheses-dyn-trait.stderr b/tests/ui/suggestions/issue-114797-bad-parentheses-dyn-trait.stderr
index 2d1abe91a1e..c67557fa14f 100644
--- a/tests/ui/suggestions/issue-114797-bad-parentheses-dyn-trait.stderr
+++ b/tests/ui/suggestions/issue-114797-bad-parentheses-dyn-trait.stderr
@@ -1,13 +1,13 @@
 error: incorrect parentheses around trait bounds
-  --> $DIR/issue-114797-bad-parentheses-dyn-trait.rs:6:49
+  --> $DIR/issue-114797-bad-parentheses-dyn-trait.rs:6:30
    |
-LL | fn assert_send(ptr: *mut dyn Trait) -> *mut dyn (Trait + Send) {
-   |                                                 ^            ^
+LL | fn assert_send() -> *mut dyn (Trait + Send) {
+   |                              ^            ^
    |
 help: fix the parentheses
    |
-LL - fn assert_send(ptr: *mut dyn Trait) -> *mut dyn (Trait + Send) {
-LL + fn assert_send(ptr: *mut dyn Trait) -> *mut (dyn Trait + Send) {
+LL - fn assert_send() -> *mut dyn (Trait + Send) {
+LL + fn assert_send() -> *mut (dyn Trait + Send) {
    |
 
 error: incorrect parentheses around trait bounds
diff --git a/tests/ui/traits/upcast_soundness_bug.rs b/tests/ui/traits/upcast_soundness_bug.rs
index 95b48cdf379..5eaa58f7efe 100644
--- a/tests/ui/traits/upcast_soundness_bug.rs
+++ b/tests/ui/traits/upcast_soundness_bug.rs
@@ -1,7 +1,8 @@
 #![feature(trait_upcasting)]
-//@ known-bug: #120222
-//@ check-pass
-//! This will segfault at runtime.
+//@ check-fail
+//
+// issue: <https://github.com/rust-lang/rust/pull/120222>
+//! This would segfault at runtime.
 
 pub trait SupSupA {
     fn method(&self) {}
@@ -56,6 +57,7 @@ pub fn user2() -> &'static dyn Trait<u8, u16> {
 fn main() {
     let p: *const dyn Trait<u8, u8> = &();
     let p = p as *const dyn Trait<u8, u16>; // <- this is bad!
+    //~^ error: mismatched types
     let p = p as *const dyn Super<u16>; // <- this upcast accesses improper vtable entry
     // accessing from L__unnamed_2 the position for the 'Super<u16> vtable (pointer)',
     // thus reading 'null pointer for missing_method'
diff --git a/tests/ui/traits/upcast_soundness_bug.stderr b/tests/ui/traits/upcast_soundness_bug.stderr
new file mode 100644
index 00000000000..5864abcdb41
--- /dev/null
+++ b/tests/ui/traits/upcast_soundness_bug.stderr
@@ -0,0 +1,13 @@
+error[E0308]: mismatched types
+  --> $DIR/upcast_soundness_bug.rs:59:13
+   |
+LL |     let p = p as *const dyn Trait<u8, u16>; // <- this is bad!
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `u8`, found `u16`
+   |
+   = note: expected trait object `dyn Trait<u8, u8>`
+              found trait object `dyn Trait<u8, u16>`
+   = help: `dyn Trait<u8, u16>` implements `Trait` so you could box the found value and coerce it to the trait object `Box<dyn Trait>`, you will have to change the expected type as well
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0308`.