about summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_ast/Cargo.toml3
-rw-r--r--compiler/rustc_attr/src/builtin.rs2
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs8
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/region_errors.rs3
-rw-r--r--compiler/rustc_borrowck/src/type_check/mod.rs71
-rw-r--r--compiler/rustc_codegen_cranelift/src/base.rs15
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/rvalue.rs14
-rw-r--r--compiler/rustc_const_eval/src/check_consts/check.rs13
-rw-r--r--compiler/rustc_const_eval/src/interpret/cast.rs11
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs34
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs3
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/mod.rs6
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/lib.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/cast.rs144
-rw-r--r--compiler/rustc_hir_typeck/src/coercion.rs5
-rw-r--r--compiler/rustc_hir_typeck/src/expr.rs1
-rw-r--r--compiler/rustc_hir_typeck/src/expr_use_visitor.rs7
-rw-r--r--compiler/rustc_hir_typeck/src/method/probe.rs4
-rw-r--r--compiler/rustc_hir_typeck/src/method/suggest.rs11
-rw-r--r--compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs4
-rw-r--r--compiler/rustc_metadata/src/rmeta/encoder.rs4
-rw-r--r--compiler/rustc_middle/src/mir/query.rs4
-rw-r--r--compiler/rustc_middle/src/mir/statement.rs3
-rw-r--r--compiler/rustc_middle/src/mir/syntax.rs17
-rw-r--r--compiler/rustc_middle/src/query/erase.rs6
-rw-r--r--compiler/rustc_middle/src/query/mod.rs14
-rw-r--r--compiler/rustc_middle/src/thir.rs6
-rw-r--r--compiler/rustc_middle/src/thir/visit.rs7
-rw-r--r--compiler/rustc_middle/src/ty/adjustment.rs6
-rw-r--r--compiler/rustc_middle/src/ty/cast.rs6
-rw-r--r--compiler/rustc_middle/src/ty/trait_def.rs20
-rw-r--r--compiler/rustc_mir_build/src/build/expr/as_place.rs14
-rw-r--r--compiler/rustc_mir_build/src/build/expr/as_rvalue.rs6
-rw-r--r--compiler/rustc_mir_build/src/build/matches/test.rs10
-rw-r--r--compiler/rustc_mir_build/src/thir/cx/expr.rs40
-rw-r--r--compiler/rustc_mir_build/src/thir/print.rs13
-rw-r--r--compiler/rustc_mir_transform/src/cleanup_post_borrowck.rs1
-rw-r--r--compiler/rustc_mir_transform/src/dataflow_const_prop.rs2
-rw-r--r--compiler/rustc_mir_transform/src/gvn.rs10
-rw-r--r--compiler/rustc_mir_transform/src/mentioned_items.rs10
-rw-r--r--compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs9
-rw-r--r--compiler/rustc_mir_transform/src/validate.rs18
-rw-r--r--compiler/rustc_monomorphize/src/collector.rs12
-rw-r--r--compiler/rustc_resolve/src/late/diagnostics.rs6
-rw-r--r--compiler/rustc_smir/src/rustc_smir/convert/mir.rs5
-rw-r--r--compiler/rustc_smir/src/rustc_smir/convert/ty.rs1
-rw-r--r--compiler/stable_mir/src/mir/body.rs1
49 files changed, 381 insertions, 235 deletions
diff --git a/compiler/rustc_ast/Cargo.toml b/compiler/rustc_ast/Cargo.toml
index d33f9666b48..34c612dac69 100644
--- a/compiler/rustc_ast/Cargo.toml
+++ b/compiler/rustc_ast/Cargo.toml
@@ -4,10 +4,9 @@ version = "0.0.0"
 edition = "2021"
 
 [dependencies]
-# FIXME: bumping memchr to 2.7.1 causes linker errors in MSVC thin-lto
 # tidy-alphabetical-start
 bitflags = "2.4.1"
-memchr = "=2.5.0"
+memchr = "2.7.4"
 rustc_ast_ir = { path = "../rustc_ast_ir" }
 rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_index = { path = "../rustc_index" }
diff --git a/compiler/rustc_attr/src/builtin.rs b/compiler/rustc_attr/src/builtin.rs
index dcc4cf2478f..762ebc47ca9 100644
--- a/compiler/rustc_attr/src/builtin.rs
+++ b/compiler/rustc_attr/src/builtin.rs
@@ -153,7 +153,7 @@ pub enum StabilityLevel {
 }
 
 /// Rust release in which a feature is stabilized.
-#[derive(Encodable, Decodable, PartialEq, Copy, Clone, Debug, Eq, Hash)]
+#[derive(Encodable, Decodable, PartialEq, Copy, Clone, Debug, Eq, PartialOrd, Ord, Hash)]
 #[derive(HashStable_Generic)]
 pub enum StableSince {
     Version(RustcVersion),
diff --git a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
index 7077d78f459..31a5d451ff6 100644
--- a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
@@ -333,7 +333,11 @@ impl<'tcx> BorrowExplanation<'tcx> {
                     }
                 }
 
-                if let ConstraintCategory::Cast { unsize_to: Some(unsize_ty) } = category {
+                if let ConstraintCategory::Cast {
+                    is_implicit_coercion: true,
+                    unsize_to: Some(unsize_ty),
+                } = category
+                {
                     self.add_object_lifetime_default_note(tcx, err, unsize_ty);
                 }
                 self.add_lifetime_bound_suggestion_to_diagnostic(err, &category, span, region_name);
@@ -740,7 +744,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> {
                         // If we see an unsized cast, then if it is our data we should check
                         // whether it is being cast to a trait object.
                         Rvalue::Cast(
-                            CastKind::PointerCoercion(PointerCoercion::Unsize),
+                            CastKind::PointerCoercion(PointerCoercion::Unsize, _),
                             operand,
                             ty,
                         ) => {
diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
index ca0a3c66130..39175b406a4 100644
--- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
@@ -47,7 +47,8 @@ impl<'tcx> ConstraintDescription for ConstraintCategory<'tcx> {
             ConstraintCategory::Yield => "yielding this value ",
             ConstraintCategory::UseAsConst => "using this value as a constant ",
             ConstraintCategory::UseAsStatic => "using this value as a static ",
-            ConstraintCategory::Cast { .. } => "cast ",
+            ConstraintCategory::Cast { is_implicit_coercion: false, .. } => "cast ",
+            ConstraintCategory::Cast { is_implicit_coercion: true, .. } => "coercion ",
             ConstraintCategory::CallArgument(_) => "argument ",
             ConstraintCategory::TypeAnnotation => "type annotation ",
             ConstraintCategory::ClosureBounds => "closure body ",
diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index 4056b423548..16e51e82f85 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -1975,8 +1975,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
             Rvalue::Cast(cast_kind, op, ty) => {
                 self.check_operand(op, location);
 
-                match cast_kind {
-                    CastKind::PointerCoercion(PointerCoercion::ReifyFnPointer) => {
+                match *cast_kind {
+                    CastKind::PointerCoercion(PointerCoercion::ReifyFnPointer, coercion_source) => {
+                        let is_implicit_coercion = coercion_source == CoercionSource::Implicit;
                         let src_sig = op.ty(body, tcx).fn_sig(tcx);
 
                         // HACK: This shouldn't be necessary... We can remove this when we actually
@@ -2007,7 +2008,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                             self.prove_predicate(
                                 ty::ClauseKind::WellFormed(src_ty.into()),
                                 location.to_locations(),
-                                ConstraintCategory::Cast { unsize_to: None },
+                                ConstraintCategory::Cast { is_implicit_coercion, unsize_to: None },
                             );
 
                             let src_ty = self.normalize(src_ty, location);
@@ -2015,7 +2016,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                                 src_ty,
                                 *ty,
                                 location.to_locations(),
-                                ConstraintCategory::Cast { unsize_to: None },
+                                ConstraintCategory::Cast { is_implicit_coercion, unsize_to: None },
                             ) {
                                 span_mirbug!(
                                     self,
@@ -2036,7 +2037,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                         self.prove_predicate(
                             ty::ClauseKind::WellFormed(src_ty.into()),
                             location.to_locations(),
-                            ConstraintCategory::Cast { unsize_to: None },
+                            ConstraintCategory::Cast { is_implicit_coercion, unsize_to: None },
                         );
 
                         // The type that we see in the fcx is like
@@ -2049,7 +2050,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                             src_ty,
                             *ty,
                             location.to_locations(),
-                            ConstraintCategory::Cast { unsize_to: None },
+                            ConstraintCategory::Cast { is_implicit_coercion, unsize_to: None },
                         ) {
                             span_mirbug!(
                                 self,
@@ -2062,19 +2063,23 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                         }
                     }
 
-                    CastKind::PointerCoercion(PointerCoercion::ClosureFnPointer(safety)) => {
+                    CastKind::PointerCoercion(
+                        PointerCoercion::ClosureFnPointer(safety),
+                        coercion_source,
+                    ) => {
                         let sig = match op.ty(body, tcx).kind() {
                             ty::Closure(_, args) => args.as_closure().sig(),
                             _ => bug!(),
                         };
                         let ty_fn_ptr_from =
-                            Ty::new_fn_ptr(tcx, tcx.signature_unclosure(sig, *safety));
+                            Ty::new_fn_ptr(tcx, tcx.signature_unclosure(sig, safety));
 
+                        let is_implicit_coercion = coercion_source == CoercionSource::Implicit;
                         if let Err(terr) = self.sub_types(
                             ty_fn_ptr_from,
                             *ty,
                             location.to_locations(),
-                            ConstraintCategory::Cast { unsize_to: None },
+                            ConstraintCategory::Cast { is_implicit_coercion, unsize_to: None },
                         ) {
                             span_mirbug!(
                                 self,
@@ -2087,7 +2092,10 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                         }
                     }
 
-                    CastKind::PointerCoercion(PointerCoercion::UnsafeFnPointer) => {
+                    CastKind::PointerCoercion(
+                        PointerCoercion::UnsafeFnPointer,
+                        coercion_source,
+                    ) => {
                         let fn_sig = op.ty(body, tcx).fn_sig(tcx);
 
                         // The type that we see in the fcx is like
@@ -2099,11 +2107,12 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
 
                         let ty_fn_ptr_from = tcx.safe_to_unsafe_fn_ty(fn_sig);
 
+                        let is_implicit_coercion = coercion_source == CoercionSource::Implicit;
                         if let Err(terr) = self.sub_types(
                             ty_fn_ptr_from,
                             *ty,
                             location.to_locations(),
-                            ConstraintCategory::Cast { unsize_to: None },
+                            ConstraintCategory::Cast { is_implicit_coercion, unsize_to: None },
                         ) {
                             span_mirbug!(
                                 self,
@@ -2116,7 +2125,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                         }
                     }
 
-                    CastKind::PointerCoercion(PointerCoercion::Unsize) => {
+                    CastKind::PointerCoercion(PointerCoercion::Unsize, coercion_source) => {
                         let &ty = ty;
                         let trait_ref = ty::TraitRef::new(
                             tcx,
@@ -2124,22 +2133,21 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                             [op.ty(body, tcx), ty],
                         );
 
+                        let is_implicit_coercion = coercion_source == CoercionSource::Implicit;
+                        let unsize_to = tcx.fold_regions(ty, |r, _| {
+                            if let ty::ReVar(_) = r.kind() { tcx.lifetimes.re_erased } else { r }
+                        });
                         self.prove_trait_ref(
                             trait_ref,
                             location.to_locations(),
                             ConstraintCategory::Cast {
-                                unsize_to: Some(tcx.fold_regions(ty, |r, _| {
-                                    if let ty::ReVar(_) = r.kind() {
-                                        tcx.lifetimes.re_erased
-                                    } else {
-                                        r
-                                    }
-                                })),
+                                is_implicit_coercion,
+                                unsize_to: Some(unsize_to),
                             },
                         );
                     }
 
-                    CastKind::DynStar => {
+                    CastKind::PointerCoercion(PointerCoercion::DynStar, coercion_source) => {
                         // get the constraints from the target type (`dyn* Clone`)
                         //
                         // apply them to prove that the source type `Foo` implements `Clone` etc
@@ -2150,12 +2158,13 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
 
                         let self_ty = op.ty(body, tcx);
 
+                        let is_implicit_coercion = coercion_source == CoercionSource::Implicit;
                         self.prove_predicates(
                             existential_predicates
                                 .iter()
                                 .map(|predicate| predicate.with_self_ty(tcx, self_ty)),
                             location.to_locations(),
-                            ConstraintCategory::Cast { unsize_to: None },
+                            ConstraintCategory::Cast { is_implicit_coercion, unsize_to: None },
                         );
 
                         let outlives_predicate = tcx.mk_predicate(Binder::dummy(
@@ -2166,11 +2175,14 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                         self.prove_predicate(
                             outlives_predicate,
                             location.to_locations(),
-                            ConstraintCategory::Cast { unsize_to: None },
+                            ConstraintCategory::Cast { is_implicit_coercion, unsize_to: None },
                         );
                     }
 
-                    CastKind::PointerCoercion(PointerCoercion::MutToConstPointer) => {
+                    CastKind::PointerCoercion(
+                        PointerCoercion::MutToConstPointer,
+                        coercion_source,
+                    ) => {
                         let ty::RawPtr(ty_from, hir::Mutability::Mut) = op.ty(body, tcx).kind()
                         else {
                             span_mirbug!(self, rvalue, "unexpected base type for cast {:?}", ty,);
@@ -2180,11 +2192,12 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                             span_mirbug!(self, rvalue, "unexpected target type for cast {:?}", ty,);
                             return;
                         };
+                        let is_implicit_coercion = coercion_source == CoercionSource::Implicit;
                         if let Err(terr) = self.sub_types(
                             *ty_from,
                             *ty_to,
                             location.to_locations(),
-                            ConstraintCategory::Cast { unsize_to: None },
+                            ConstraintCategory::Cast { is_implicit_coercion, unsize_to: None },
                         ) {
                             span_mirbug!(
                                 self,
@@ -2197,7 +2210,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                         }
                     }
 
-                    CastKind::PointerCoercion(PointerCoercion::ArrayToPointer) => {
+                    CastKind::PointerCoercion(PointerCoercion::ArrayToPointer, coercion_source) => {
                         let ty_from = op.ty(body, tcx);
 
                         let opt_ty_elem_mut = match ty_from.kind() {
@@ -2242,11 +2255,12 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                             return;
                         }
 
+                        let is_implicit_coercion = coercion_source == CoercionSource::Implicit;
                         if let Err(terr) = self.sub_types(
                             *ty_elem,
                             *ty_to,
                             location.to_locations(),
-                            ConstraintCategory::Cast { unsize_to: None },
+                            ConstraintCategory::Cast { is_implicit_coercion, unsize_to: None },
                         ) {
                             span_mirbug!(
                                 self,
@@ -2427,7 +2441,10 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                                         src_obj,
                                         dst_obj,
                                         location.to_locations(),
-                                        ConstraintCategory::Cast { unsize_to: None },
+                                        ConstraintCategory::Cast {
+                                            is_implicit_coercion: false,
+                                            unsize_to: None,
+                                        },
                                     )
                                     .unwrap();
                                 }
diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs
index dc342e151f3..1ce0aacab49 100644
--- a/compiler/rustc_codegen_cranelift/src/base.rs
+++ b/compiler/rustc_codegen_cranelift/src/base.rs
@@ -652,7 +652,7 @@ fn codegen_stmt<'tcx>(
                     lval.write_cvalue(fx, res);
                 }
                 Rvalue::Cast(
-                    CastKind::PointerCoercion(PointerCoercion::ReifyFnPointer),
+                    CastKind::PointerCoercion(PointerCoercion::ReifyFnPointer, _),
                     ref operand,
                     to_ty,
                 ) => {
@@ -677,7 +677,7 @@ fn codegen_stmt<'tcx>(
                     }
                 }
                 Rvalue::Cast(
-                    CastKind::PointerCoercion(PointerCoercion::UnsafeFnPointer),
+                    CastKind::PointerCoercion(PointerCoercion::UnsafeFnPointer, _),
                     ref operand,
                     to_ty,
                 ) => {
@@ -688,6 +688,7 @@ fn codegen_stmt<'tcx>(
                 Rvalue::Cast(
                     CastKind::PointerCoercion(
                         PointerCoercion::MutToConstPointer | PointerCoercion::ArrayToPointer,
+                        _,
                     ),
                     ..,
                 ) => {
@@ -741,7 +742,7 @@ fn codegen_stmt<'tcx>(
                     }
                 }
                 Rvalue::Cast(
-                    CastKind::PointerCoercion(PointerCoercion::ClosureFnPointer(_)),
+                    CastKind::PointerCoercion(PointerCoercion::ClosureFnPointer(_), _),
                     ref operand,
                     _to_ty,
                 ) => {
@@ -763,14 +764,18 @@ fn codegen_stmt<'tcx>(
                     }
                 }
                 Rvalue::Cast(
-                    CastKind::PointerCoercion(PointerCoercion::Unsize),
+                    CastKind::PointerCoercion(PointerCoercion::Unsize, _),
                     ref operand,
                     _to_ty,
                 ) => {
                     let operand = codegen_operand(fx, operand);
                     crate::unsize::coerce_unsized_into(fx, operand, lval);
                 }
-                Rvalue::Cast(CastKind::DynStar, ref operand, _) => {
+                Rvalue::Cast(
+                    CastKind::PointerCoercion(PointerCoercion::DynStar, _),
+                    ref operand,
+                    _,
+                ) => {
                     let operand = codegen_operand(fx, operand);
                     crate::unsize::coerce_dyn_star(fx, operand, lval);
                 }
diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
index ad0e03fc263..f9c0f3ce941 100644
--- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
@@ -34,7 +34,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
             }
 
             mir::Rvalue::Cast(
-                mir::CastKind::PointerCoercion(PointerCoercion::Unsize),
+                mir::CastKind::PointerCoercion(PointerCoercion::Unsize, _),
                 ref source,
                 _,
             ) => {
@@ -465,7 +465,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                         let lladdr = bx.ptrtoint(llptr, llcast_ty);
                         OperandValue::Immediate(lladdr)
                     }
-                    mir::CastKind::PointerCoercion(PointerCoercion::ReifyFnPointer) => {
+                    mir::CastKind::PointerCoercion(PointerCoercion::ReifyFnPointer, _) => {
                         match *operand.layout.ty.kind() {
                             ty::FnDef(def_id, args) => {
                                 let instance = ty::Instance::resolve_for_fn_ptr(
@@ -481,7 +481,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                             _ => bug!("{} cannot be reified to a fn ptr", operand.layout.ty),
                         }
                     }
-                    mir::CastKind::PointerCoercion(PointerCoercion::ClosureFnPointer(_)) => {
+                    mir::CastKind::PointerCoercion(PointerCoercion::ClosureFnPointer(_), _) => {
                         match *operand.layout.ty.kind() {
                             ty::Closure(def_id, args) => {
                                 let instance = Instance::resolve_closure(
@@ -496,11 +496,11 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                             _ => bug!("{} cannot be cast to a fn ptr", operand.layout.ty),
                         }
                     }
-                    mir::CastKind::PointerCoercion(PointerCoercion::UnsafeFnPointer) => {
+                    mir::CastKind::PointerCoercion(PointerCoercion::UnsafeFnPointer, _) => {
                         // This is a no-op at the LLVM level.
                         operand.val
                     }
-                    mir::CastKind::PointerCoercion(PointerCoercion::Unsize) => {
+                    mir::CastKind::PointerCoercion(PointerCoercion::Unsize, _) => {
                         assert!(bx.cx().is_backend_scalar_pair(cast));
                         let (lldata, llextra) = operand.val.pointer_parts();
                         let (lldata, llextra) =
@@ -508,7 +508,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                         OperandValue::Pair(lldata, llextra)
                     }
                     mir::CastKind::PointerCoercion(
-                        PointerCoercion::MutToConstPointer | PointerCoercion::ArrayToPointer,
+                        PointerCoercion::MutToConstPointer | PointerCoercion::ArrayToPointer, _
                     ) => {
                         bug!("{kind:?} is for borrowck, and should never appear in codegen");
                     }
@@ -526,7 +526,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                             bug!("unexpected non-pair operand");
                         }
                     }
-                    mir::CastKind::DynStar => {
+                    mir::CastKind::PointerCoercion(PointerCoercion::DynStar, _) => {
                         let (lldata, llextra) = operand.val.pointer_parts();
                         let (lldata, llextra) =
                             base::cast_to_dyn_star(bx, lldata, operand.layout, cast.ty, llextra);
diff --git a/compiler/rustc_const_eval/src/check_consts/check.rs b/compiler/rustc_const_eval/src/check_consts/check.rs
index 2c33ff9d219..e1b60597997 100644
--- a/compiler/rustc_const_eval/src/check_consts/check.rs
+++ b/compiler/rustc_const_eval/src/check_consts/check.rs
@@ -440,6 +440,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
                     | PointerCoercion::UnsafeFnPointer
                     | PointerCoercion::ClosureFnPointer(_)
                     | PointerCoercion::ReifyFnPointer,
+                    _,
                 ),
                 _,
                 _,
@@ -447,8 +448,12 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
                 // These are all okay; they only change the type, not the data.
             }
 
-            Rvalue::Cast(CastKind::PointerCoercion(PointerCoercion::Unsize), _, _) => {
-                // Unsizing is implemented for CTFE.
+            Rvalue::Cast(
+                CastKind::PointerCoercion(PointerCoercion::Unsize | PointerCoercion::DynStar, _),
+                _,
+                _,
+            ) => {
+                // Unsizing and `dyn*` coercions are implemented for CTFE.
             }
 
             Rvalue::Cast(CastKind::PointerExposeProvenance, _, _) => {
@@ -458,10 +463,6 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
                 // Since no pointer can ever get exposed (rejected above), this is easy to support.
             }
 
-            Rvalue::Cast(CastKind::DynStar, _, _) => {
-                // `dyn*` coercion is implemented for CTFE.
-            }
-
             Rvalue::Cast(_, _, _) => {}
 
             Rvalue::NullaryOp(
diff --git a/compiler/rustc_const_eval/src/interpret/cast.rs b/compiler/rustc_const_eval/src/interpret/cast.rs
index 70d074cfdc5..85e7d91c2ad 100644
--- a/compiler/rustc_const_eval/src/interpret/cast.rs
+++ b/compiler/rustc_const_eval/src/interpret/cast.rs
@@ -32,7 +32,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
             if cast_ty == dest.layout.ty { dest.layout } else { self.layout_of(cast_ty)? };
         // FIXME: In which cases should we trigger UB when the source is uninit?
         match cast_kind {
-            CastKind::PointerCoercion(PointerCoercion::Unsize) => {
+            CastKind::PointerCoercion(PointerCoercion::Unsize, _) => {
                 self.unsize_into(src, cast_layout, dest)?;
             }
 
@@ -68,11 +68,12 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
 
             CastKind::PointerCoercion(
                 PointerCoercion::MutToConstPointer | PointerCoercion::ArrayToPointer,
+                _,
             ) => {
                 bug!("{cast_kind:?} casts are for borrowck only, not runtime MIR");
             }
 
-            CastKind::PointerCoercion(PointerCoercion::ReifyFnPointer) => {
+            CastKind::PointerCoercion(PointerCoercion::ReifyFnPointer, _) => {
                 // All reifications must be monomorphic, bail out otherwise.
                 ensure_monomorphic_enough(*self.tcx, src.layout.ty)?;
 
@@ -94,7 +95,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
                 }
             }
 
-            CastKind::PointerCoercion(PointerCoercion::UnsafeFnPointer) => {
+            CastKind::PointerCoercion(PointerCoercion::UnsafeFnPointer, _) => {
                 let src = self.read_immediate(src)?;
                 match cast_ty.kind() {
                     ty::FnPtr(..) => {
@@ -105,7 +106,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
                 }
             }
 
-            CastKind::PointerCoercion(PointerCoercion::ClosureFnPointer(_)) => {
+            CastKind::PointerCoercion(PointerCoercion::ClosureFnPointer(_), _) => {
                 // All reifications must be monomorphic, bail out otherwise.
                 ensure_monomorphic_enough(*self.tcx, src.layout.ty)?;
 
@@ -125,7 +126,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
                 }
             }
 
-            CastKind::DynStar => {
+            CastKind::PointerCoercion(PointerCoercion::DynStar, _) => {
                 if let ty::Dynamic(data, _, ty::DynStar) = cast_ty.kind() {
                     // Initial cast from sized to dyn trait
                     let vtable = self.get_vtable_ptr(src.layout.ty, data)?;
diff --git a/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs b/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs
index c07d8009aa5..dfb3c088afb 100644
--- a/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs
@@ -22,36 +22,38 @@ use crate::errors;
 pub(crate) fn crate_inherent_impls(
     tcx: TyCtxt<'_>,
     (): (),
-) -> Result<&'_ CrateInherentImpls, ErrorGuaranteed> {
+) -> (&'_ CrateInherentImpls, Result<(), ErrorGuaranteed>) {
     let mut collect = InherentCollect { tcx, impls_map: Default::default() };
+
     let mut res = Ok(());
     for id in tcx.hir().items() {
         res = res.and(collect.check_item(id));
     }
-    res?;
-    Ok(tcx.arena.alloc(collect.impls_map))
+
+    (tcx.arena.alloc(collect.impls_map), res)
 }
 
-pub(crate) fn crate_incoherent_impls(
+pub(crate) fn crate_inherent_impls_validity_check(
     tcx: TyCtxt<'_>,
-    simp: SimplifiedType,
-) -> Result<&[DefId], ErrorGuaranteed> {
-    let crate_map = tcx.crate_inherent_impls(())?;
-    Ok(tcx.arena.alloc_from_iter(
+    (): (),
+) -> Result<(), ErrorGuaranteed> {
+    tcx.crate_inherent_impls(()).1
+}
+
+pub(crate) fn crate_incoherent_impls(tcx: TyCtxt<'_>, simp: SimplifiedType) -> &[DefId] {
+    let (crate_map, _) = tcx.crate_inherent_impls(());
+    tcx.arena.alloc_from_iter(
         crate_map.incoherent_impls.get(&simp).unwrap_or(&Vec::new()).iter().map(|d| d.to_def_id()),
-    ))
+    )
 }
 
 /// On-demand query: yields a vector of the inherent impls for a specific type.
-pub(crate) fn inherent_impls(
-    tcx: TyCtxt<'_>,
-    ty_def_id: LocalDefId,
-) -> Result<&[DefId], ErrorGuaranteed> {
-    let crate_map = tcx.crate_inherent_impls(())?;
-    Ok(match crate_map.inherent_impls.get(&ty_def_id) {
+pub(crate) fn inherent_impls(tcx: TyCtxt<'_>, ty_def_id: LocalDefId) -> &[DefId] {
+    let (crate_map, _) = tcx.crate_inherent_impls(());
+    match crate_map.inherent_impls.get(&ty_def_id) {
         Some(v) => &v[..],
         None => &[],
-    })
+    }
 }
 
 struct InherentCollect<'tcx> {
diff --git a/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs b/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs
index 43b9093ecac..b8066b4b47d 100644
--- a/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs
@@ -177,8 +177,7 @@ impl<'tcx> InherentOverlapChecker<'tcx> {
             return Ok(());
         }
 
-        let impls = self.tcx.inherent_impls(id.owner_id)?;
-
+        let impls = self.tcx.inherent_impls(id.owner_id);
         let overlap_mode = OverlapMode::get(self.tcx, id.owner_id.to_def_id());
 
         let impls_items = impls
diff --git a/compiler/rustc_hir_analysis/src/coherence/mod.rs b/compiler/rustc_hir_analysis/src/coherence/mod.rs
index 185f3176f07..b25406583f6 100644
--- a/compiler/rustc_hir_analysis/src/coherence/mod.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/mod.rs
@@ -124,7 +124,10 @@ fn enforce_empty_impls_for_marker_traits(
 
 pub(crate) fn provide(providers: &mut Providers) {
     use self::builtin::coerce_unsized_info;
-    use self::inherent_impls::{crate_incoherent_impls, crate_inherent_impls, inherent_impls};
+    use self::inherent_impls::{
+        crate_incoherent_impls, crate_inherent_impls, crate_inherent_impls_validity_check,
+        inherent_impls,
+    };
     use self::inherent_impls_overlap::crate_inherent_impls_overlap_check;
     use self::orphan::orphan_check_impl;
 
@@ -133,6 +136,7 @@ pub(crate) fn provide(providers: &mut Providers) {
         crate_inherent_impls,
         crate_incoherent_impls,
         inherent_impls,
+        crate_inherent_impls_validity_check,
         crate_inherent_impls_overlap_check,
         coerce_unsized_info,
         orphan_check_impl,
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs
index 5e3203e8473..5775a8867b1 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs
@@ -1028,7 +1028,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                 ..
             }) = node
             && let Some(ty_def_id) = qself_ty.ty_def_id()
-            && let Ok([inherent_impl]) = tcx.inherent_impls(ty_def_id)
+            && let [inherent_impl] = tcx.inherent_impls(ty_def_id)
             && let name = format!("{ident2}_{ident3}")
             && let Some(ty::AssocItem { kind: ty::AssocKind::Fn, .. }) = tcx
                 .associated_items(inherent_impl)
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
index e95b5142559..d7d4a98e63f 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
@@ -1272,7 +1272,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
         }
 
         let candidates: Vec<_> = tcx
-            .inherent_impls(adt_did)?
+            .inherent_impls(adt_did)
             .iter()
             .filter_map(|&impl_| {
                 let (item, scope) =
diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs
index 1dc85c4903e..92d85d48a42 100644
--- a/compiler/rustc_hir_analysis/src/lib.rs
+++ b/compiler/rustc_hir_analysis/src/lib.rs
@@ -170,7 +170,7 @@ pub fn check_crate(tcx: TyCtxt<'_>) {
             let _ = tcx.ensure().coherent_trait(trait_def_id);
         }
         // these queries are executed for side-effects (error reporting):
-        let _ = tcx.ensure().crate_inherent_impls(());
+        let _ = tcx.ensure().crate_inherent_impls_validity_check(());
         let _ = tcx.ensure().crate_inherent_impls_overlap_check(());
     });
 
diff --git a/compiler/rustc_hir_typeck/src/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs
index aab0c4c116a..fcd2940b83a 100644
--- a/compiler/rustc_hir_typeck/src/cast.rs
+++ b/compiler/rustc_hir_typeck/src/cast.rs
@@ -32,13 +32,14 @@ use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::codes::*;
 use rustc_errors::{Applicability, Diag, ErrorGuaranteed};
 use rustc_hir::{self as hir, ExprKind};
+use rustc_infer::infer::DefineOpaqueTypes;
 use rustc_macros::{TypeFoldable, TypeVisitable};
-use rustc_middle::bug;
 use rustc_middle::mir::Mutability;
 use rustc_middle::ty::adjustment::AllowTwoPhase;
 use rustc_middle::ty::cast::{CastKind, CastTy};
 use rustc_middle::ty::error::TypeError;
 use rustc_middle::ty::{self, Ty, TyCtxt, TypeAndMut, TypeVisitableExt, VariantDef};
+use rustc_middle::{bug, span_bug};
 use rustc_session::lint;
 use rustc_span::def_id::LOCAL_CRATE;
 use rustc_span::symbol::sym;
@@ -152,12 +153,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 }
 
 #[derive(Copy, Clone, Debug)]
-pub enum CastError {
+enum CastError<'tcx> {
     ErrorGuaranteed(ErrorGuaranteed),
 
     CastToBool,
     CastToChar,
-    DifferingKinds,
+    DifferingKinds {
+        src_kind: PointerKind<'tcx>,
+        dst_kind: PointerKind<'tcx>,
+    },
     /// Cast of thin to fat raw ptr (e.g., `*const () as *const [u8]`).
     SizedUnsizedCast,
     IllegalCast,
@@ -177,7 +181,7 @@ pub enum CastError {
     ForeignNonExhaustiveAdt,
 }
 
-impl From<ErrorGuaranteed> for CastError {
+impl From<ErrorGuaranteed> for CastError<'_> {
     fn from(err: ErrorGuaranteed) -> Self {
         CastError::ErrorGuaranteed(err)
     }
@@ -251,7 +255,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
         }
     }
 
-    fn report_cast_error(&self, fcx: &FnCtxt<'a, 'tcx>, e: CastError) {
+    fn report_cast_error(&self, fcx: &FnCtxt<'a, 'tcx>, e: CastError<'tcx>) {
         match e {
             CastError::ErrorGuaranteed(_) => {
                 // an error has already been reported
@@ -303,10 +307,52 @@ impl<'a, 'tcx> CastCheck<'tcx> {
             CastError::IllegalCast => {
                 make_invalid_casting_error(self.span, self.expr_ty, self.cast_ty, fcx).emit();
             }
-            CastError::DifferingKinds => {
-                make_invalid_casting_error(self.span, self.expr_ty, self.cast_ty, fcx)
-                    .with_note("vtable kinds may not match")
-                    .emit();
+            CastError::DifferingKinds { src_kind, dst_kind } => {
+                let mut err =
+                    make_invalid_casting_error(self.span, self.expr_ty, self.cast_ty, fcx);
+
+                match (src_kind, dst_kind) {
+                    (PointerKind::VTable(_), PointerKind::VTable(_)) => {
+                        err.note("the trait objects may have different vtables");
+                    }
+                    (
+                        PointerKind::OfParam(_) | PointerKind::OfAlias(_),
+                        PointerKind::OfParam(_)
+                        | PointerKind::OfAlias(_)
+                        | PointerKind::VTable(_)
+                        | PointerKind::Length,
+                    )
+                    | (
+                        PointerKind::VTable(_) | PointerKind::Length,
+                        PointerKind::OfParam(_) | PointerKind::OfAlias(_),
+                    ) => {
+                        err.note("the pointers may have different metadata");
+                    }
+                    (PointerKind::VTable(_), PointerKind::Length)
+                    | (PointerKind::Length, PointerKind::VTable(_)) => {
+                        err.note("the pointers have different metadata");
+                    }
+                    (
+                        PointerKind::Thin,
+                        PointerKind::Thin
+                        | PointerKind::VTable(_)
+                        | PointerKind::Length
+                        | PointerKind::OfParam(_)
+                        | PointerKind::OfAlias(_),
+                    )
+                    | (
+                        PointerKind::VTable(_)
+                        | PointerKind::Length
+                        | PointerKind::OfParam(_)
+                        | PointerKind::OfAlias(_),
+                        PointerKind::Thin,
+                    )
+                    | (PointerKind::Length, PointerKind::Length) => {
+                        span_bug!(self.span, "unexpected cast error: {e:?}")
+                    }
+                }
+
+                err.emit();
             }
             CastError::CastToBool => {
                 let expr_ty = fcx.resolve_vars_if_possible(self.expr_ty);
@@ -670,10 +716,20 @@ impl<'a, 'tcx> CastCheck<'tcx> {
     /// Checks a cast, and report an error if one exists. In some cases, this
     /// can return Ok and create type errors in the fcx rather than returning
     /// directly. coercion-cast is handled in check instead of here.
-    fn do_check(&self, fcx: &FnCtxt<'a, 'tcx>) -> Result<CastKind, CastError> {
+    fn do_check(&self, fcx: &FnCtxt<'a, 'tcx>) -> Result<CastKind, CastError<'tcx>> {
         use rustc_middle::ty::cast::CastTy::*;
         use rustc_middle::ty::cast::IntTy::*;
 
+        if self.cast_ty.is_dyn_star() {
+            if fcx.tcx.features().dyn_star {
+                span_bug!(self.span, "should be handled by `coerce`");
+            } else {
+                // Report "casting is invalid" rather than "non-primitive cast"
+                // if the feature is not enabled.
+                return Err(CastError::IllegalCast);
+            }
+        }
+
         let (t_from, t_cast) = match (CastTy::from_ty(self.expr_ty), CastTy::from_ty(self.cast_ty))
         {
             (Some(t_from), Some(t_cast)) => (t_from, t_cast),
@@ -780,16 +836,6 @@ impl<'a, 'tcx> CastCheck<'tcx> {
             (Int(Char) | Int(Bool), Int(_)) => Ok(CastKind::PrimIntCast),
 
             (Int(_) | Float, Int(_) | Float) => Ok(CastKind::NumericCast),
-
-            (_, DynStar) => {
-                if fcx.tcx.features().dyn_star {
-                    bug!("should be handled by `coerce`")
-                } else {
-                    Err(CastError::IllegalCast)
-                }
-            }
-
-            (DynStar, _) => Err(CastError::IllegalCast),
         }
     }
 
@@ -798,27 +844,34 @@ impl<'a, 'tcx> CastCheck<'tcx> {
         fcx: &FnCtxt<'a, 'tcx>,
         m_src: ty::TypeAndMut<'tcx>,
         m_dst: ty::TypeAndMut<'tcx>,
-    ) -> Result<CastKind, CastError> {
+    ) -> Result<CastKind, CastError<'tcx>> {
         debug!("check_ptr_ptr_cast m_src={m_src:?} m_dst={m_dst:?}");
-        // ptr-ptr cast. vtables must match.
+        // ptr-ptr cast. metadata must match.
 
         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)?);
 
-        match (src_kind, dst_kind) {
-            // We can't cast if target pointer kind is unknown
-            (_, None) => Err(CastError::UnknownCastPtrKind),
-            // Cast to thin pointer is OK
-            (_, Some(PointerKind::Thin)) => Ok(CastKind::PtrPtrCast),
+        // We can't cast if target pointer kind is unknown
+        let Some(dst_kind) = dst_kind else {
+            return Err(CastError::UnknownCastPtrKind);
+        };
+
+        // Cast to thin pointer is OK
+        if dst_kind == PointerKind::Thin {
+            return Ok(CastKind::PtrPtrCast);
+        }
 
-            // We can't cast to fat pointer if source pointer kind is unknown
-            (None, _) => Err(CastError::UnknownExprPtrKind),
+        // We can't cast to fat pointer if source pointer kind is unknown
+        let Some(src_kind) = src_kind else {
+            return Err(CastError::UnknownCastPtrKind);
+        };
 
+        match (src_kind, dst_kind) {
             // thin -> fat? report invalid cast (don't complain about vtable kinds)
-            (Some(PointerKind::Thin), _) => Err(CastError::SizedUnsizedCast),
+            (PointerKind::Thin, _) => Err(CastError::SizedUnsizedCast),
 
             // trait object -> trait object? need to do additional checks
-            (Some(PointerKind::VTable(src_tty)), Some(PointerKind::VTable(dst_tty))) => {
+            (PointerKind::VTable(src_tty), 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
@@ -834,7 +887,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
                         // 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);
+                            return Err(CastError::DifferingKinds { src_kind, dst_kind });
                         }
 
                         // We need to reconstruct trait object types.
@@ -860,7 +913,16 @@ impl<'a, 'tcx> CastCheck<'tcx> {
                         ));
 
                         // `dyn Src = dyn Dst`, this checks for matching traits/generics
-                        fcx.demand_eqtype(self.span, src_obj, dst_obj);
+                        // This is `demand_eqtype`, but inlined to give a better error.
+                        let cause = fcx.misc(self.span);
+                        if fcx
+                            .at(&cause, fcx.param_env)
+                            .eq(DefineOpaqueTypes::Yes, src_obj, dst_obj)
+                            .map(|infer_ok| fcx.register_infer_ok_obligations(infer_ok))
+                            .is_err()
+                        {
+                            return Err(CastError::DifferingKinds { src_kind, dst_kind });
+                        }
 
                         // Check that `SrcAuto` (+auto traits implied by `Src`) is a superset of `DstAuto`.
                         // Emit an FCW otherwise.
@@ -905,17 +967,17 @@ impl<'a, 'tcx> CastCheck<'tcx> {
 
                     // dyn Trait -> dyn Auto? should be ok, but we used to not allow it.
                     // FIXME: allow this
-                    (Some(_), None) => Err(CastError::DifferingKinds),
+                    (Some(_), None) => Err(CastError::DifferingKinds { src_kind, dst_kind }),
 
                     // dyn Auto -> dyn Trait? not ok.
-                    (None, Some(_)) => Err(CastError::DifferingKinds),
+                    (None, Some(_)) => Err(CastError::DifferingKinds { src_kind, dst_kind }),
                 }
             }
 
             // fat -> fat? metadata kinds must match
-            (Some(src_kind), Some(dst_kind)) if src_kind == dst_kind => Ok(CastKind::PtrPtrCast),
+            (src_kind, dst_kind) if src_kind == dst_kind => Ok(CastKind::PtrPtrCast),
 
-            (_, _) => Err(CastError::DifferingKinds),
+            (_, _) => Err(CastError::DifferingKinds { src_kind, dst_kind }),
         }
     }
 
@@ -923,7 +985,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
         &self,
         fcx: &FnCtxt<'a, 'tcx>,
         m_cast: ty::TypeAndMut<'tcx>,
-    ) -> Result<CastKind, CastError> {
+    ) -> Result<CastKind, CastError<'tcx>> {
         // fptr-ptr cast. must be to thin ptr
 
         match fcx.pointer_kind(m_cast.ty, self.span)? {
@@ -937,7 +999,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
         &self,
         fcx: &FnCtxt<'a, 'tcx>,
         m_expr: ty::TypeAndMut<'tcx>,
-    ) -> Result<CastKind, CastError> {
+    ) -> Result<CastKind, CastError<'tcx>> {
         // ptr-addr cast. must be from thin ptr
 
         match fcx.pointer_kind(m_expr.ty, self.span)? {
@@ -952,7 +1014,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
         fcx: &FnCtxt<'a, 'tcx>,
         m_expr: ty::TypeAndMut<'tcx>,
         m_cast: ty::TypeAndMut<'tcx>,
-    ) -> Result<CastKind, CastError> {
+    ) -> Result<CastKind, CastError<'tcx>> {
         // array-ptr-cast: allow mut-to-mut, mut-to-const, const-to-const
         if m_expr.mutbl >= m_cast.mutbl {
             if let ty::Array(ety, _) = m_expr.ty.kind() {
@@ -987,7 +1049,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
         &self,
         fcx: &FnCtxt<'a, 'tcx>,
         m_cast: TypeAndMut<'tcx>,
-    ) -> Result<CastKind, CastError> {
+    ) -> Result<CastKind, CastError<'tcx>> {
         // ptr-addr cast. pointer must be thin.
         match fcx.pointer_kind(m_cast.ty, self.span)? {
             None => Err(CastError::UnknownCastPtrKind),
diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs
index 7be91d78e19..b08c5bc6d9a 100644
--- a/compiler/rustc_hir_typeck/src/coercion.rs
+++ b/compiler/rustc_hir_typeck/src/coercion.rs
@@ -769,7 +769,10 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
         ));
 
         Ok(InferOk {
-            value: (vec![Adjustment { kind: Adjust::DynStar, target: b }], b),
+            value: (
+                vec![Adjustment { kind: Adjust::Pointer(PointerCoercion::DynStar), target: b }],
+                b,
+            ),
             obligations,
         })
     }
diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs
index 015a7283250..b34ed4640db 100644
--- a/compiler/rustc_hir_typeck/src/expr.rs
+++ b/compiler/rustc_hir_typeck/src/expr.rs
@@ -2126,7 +2126,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 .tcx
                 .inherent_impls(def_id)
                 .into_iter()
-                .flatten()
                 .flat_map(|i| self.tcx.associated_items(i).in_definition_order())
                 // Only assoc fn with no receivers.
                 .filter(|item| {
diff --git a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
index 29feed56290..bb5f3511373 100644
--- a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
+++ b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
@@ -759,9 +759,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
         for adjustment in adjustments {
             debug!("walk_adjustment expr={:?} adj={:?}", expr, adjustment);
             match adjustment.kind {
-                adjustment::Adjust::NeverToAny
-                | adjustment::Adjust::Pointer(_)
-                | adjustment::Adjust::DynStar => {
+                adjustment::Adjust::NeverToAny | adjustment::Adjust::Pointer(_) => {
                     // Creating a closure/fn-pointer or unsizing consumes
                     // the input and stores it into the resulting rvalue.
                     self.consume_or_copy(&place_with_id, place_with_id.hir_id);
@@ -1296,8 +1294,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
             adjustment::Adjust::NeverToAny
             | adjustment::Adjust::Pointer(_)
             | adjustment::Adjust::Borrow(_)
-            | adjustment::Adjust::ReborrowPin(..)
-            | adjustment::Adjust::DynStar => {
+            | adjustment::Adjust::ReborrowPin(..) => {
                 // Result is an rvalue.
                 Ok(self.cat_rvalue(expr.hir_id, target))
             }
diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs
index 3828b40b885..1a8afcf003d 100644
--- a/compiler/rustc_hir_typeck/src/method/probe.rs
+++ b/compiler/rustc_hir_typeck/src/method/probe.rs
@@ -728,13 +728,13 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
         let Some(simp) = simplify_type(self.tcx, self_ty, TreatParams::InstantiateWithInfer) else {
             bug!("unexpected incoherent type: {:?}", self_ty)
         };
-        for &impl_def_id in self.tcx.incoherent_impls(simp).into_iter().flatten() {
+        for &impl_def_id in self.tcx.incoherent_impls(simp).into_iter() {
             self.assemble_inherent_impl_probe(impl_def_id);
         }
     }
 
     fn assemble_inherent_impl_candidates_for_type(&mut self, def_id: DefId) {
-        let impl_def_ids = self.tcx.at(self.span).inherent_impls(def_id).into_iter().flatten();
+        let impl_def_ids = self.tcx.at(self.span).inherent_impls(def_id).into_iter();
         for &impl_def_id in impl_def_ids {
             self.assemble_inherent_impl_probe(impl_def_id);
         }
diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs
index feb47209f5e..e03be4f43f7 100644
--- a/compiler/rustc_hir_typeck/src/method/suggest.rs
+++ b/compiler/rustc_hir_typeck/src/method/suggest.rs
@@ -680,7 +680,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         self.tcx
                             .inherent_impls(adt_def.did())
                             .into_iter()
-                            .flatten()
                             .any(|def_id| self.associated_value(*def_id, item_name).is_some())
                     } else {
                         false
@@ -1438,7 +1437,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         .tcx
                         .inherent_impls(adt.did())
                         .into_iter()
-                        .flatten()
                         .copied()
                         .filter(|def_id| {
                             if let Some(assoc) = self.associated_value(*def_id, item_name) {
@@ -1900,7 +1898,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         call_args: Option<Vec<Ty<'tcx>>>,
     ) -> Option<Symbol> {
         if let ty::Adt(adt, adt_args) = rcvr_ty.kind() {
-            for inherent_impl_did in self.tcx.inherent_impls(adt.did()).into_iter().flatten() {
+            for inherent_impl_did in self.tcx.inherent_impls(adt.did()).into_iter() {
                 for inherent_method in
                     self.tcx.associated_items(inherent_impl_did).in_definition_order()
                 {
@@ -2114,9 +2112,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let ty::Adt(adt_def, _) = rcvr_ty.kind() else {
             return;
         };
-        // FIXME(oli-obk): try out bubbling this error up one level and cancelling the other error in that case.
-        let Ok(impls) = self.tcx.inherent_impls(adt_def.did()) else { return };
-        let mut items = impls
+        let mut items = self
+            .tcx
+            .inherent_impls(adt_def.did())
             .iter()
             .flat_map(|i| self.tcx.associated_items(i).in_definition_order())
             // Only assoc fn with no receivers and only if
@@ -2495,7 +2493,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 .and_then(|simp| {
                     tcx.incoherent_impls(simp)
                         .into_iter()
-                        .flatten()
                         .find_map(|&id| self.associated_value(id, item_name))
                 })
                 .is_some()
diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
index 53d2089296d..69707fdbe8f 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
@@ -347,7 +347,7 @@ provide! { tcx, def_id, other, cdata,
         tcx.arena.alloc_from_iter(cdata.get_associated_item_or_field_def_ids(def_id.index))
     }
     associated_item => { cdata.get_associated_item(def_id.index, tcx.sess) }
-    inherent_impls => { Ok(cdata.get_inherent_implementations_for_type(tcx, def_id.index)) }
+    inherent_impls => { cdata.get_inherent_implementations_for_type(tcx, def_id.index) }
     item_attrs => { tcx.arena.alloc_from_iter(cdata.get_item_attrs(def_id.index, tcx.sess)) }
     is_mir_available => { cdata.is_item_mir_available(def_id.index) }
     is_ctfe_mir_available => { cdata.is_ctfe_mir_available(def_id.index) }
@@ -393,7 +393,7 @@ provide! { tcx, def_id, other, cdata,
     traits => { tcx.arena.alloc_from_iter(cdata.get_traits()) }
     trait_impls_in_crate => { tcx.arena.alloc_from_iter(cdata.get_trait_impls()) }
     implementations_of_trait => { cdata.get_implementations_of_trait(tcx, other) }
-    crate_incoherent_impls => { Ok(cdata.get_incoherent_impls(tcx, other)) }
+    crate_incoherent_impls => { cdata.get_incoherent_impls(tcx, other) }
 
     dep_kind => { cdata.dep_kind }
     module_children => {
diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs
index 891f1793441..5f756672b04 100644
--- a/compiler/rustc_metadata/src/rmeta/encoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/encoder.rs
@@ -1540,7 +1540,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
             }
         }
 
-        for (def_id, impls) in &tcx.crate_inherent_impls(()).unwrap().inherent_impls {
+        for (def_id, impls) in &tcx.crate_inherent_impls(()).0.inherent_impls {
             record_defaulted_array!(self.tables.inherent_impls[def_id.to_def_id()] <- impls.iter().map(|def_id| {
                 assert!(def_id.is_local());
                 def_id.index
@@ -2089,7 +2089,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
 
         let all_impls: Vec<_> = tcx
             .crate_inherent_impls(())
-            .unwrap()
+            .0
             .incoherent_impls
             .iter()
             .map(|(&simp, impls)| IncoherentImpls {
diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs
index 1002f64f849..70331214ac5 100644
--- a/compiler/rustc_middle/src/mir/query.rs
+++ b/compiler/rustc_middle/src/mir/query.rs
@@ -234,7 +234,9 @@ pub enum ConstraintCategory<'tcx> {
     UseAsStatic,
     TypeAnnotation,
     Cast {
-        /// Whether this is an unsizing cast and if yes, this contains the target type.
+        /// Whether this cast is a coercion that was automatically inserted by the compiler.
+        is_implicit_coercion: bool,
+        /// Whether this is an unsizing coercion and if yes, this contains the target type.
         /// Region variables are erased to ReErased.
         #[derive_where(skip)]
         unsize_to: Option<Ty<'tcx>>,
diff --git a/compiler/rustc_middle/src/mir/statement.rs b/compiler/rustc_middle/src/mir/statement.rs
index bc7dfa6205e..88ed90c3114 100644
--- a/compiler/rustc_middle/src/mir/statement.rs
+++ b/compiler/rustc_middle/src/mir/statement.rs
@@ -432,9 +432,8 @@ impl<'tcx> Rvalue<'tcx> {
                 | CastKind::IntToFloat
                 | CastKind::FnPtrToPtr
                 | CastKind::PtrToPtr
-                | CastKind::PointerCoercion(_)
+                | CastKind::PointerCoercion(_, _)
                 | CastKind::PointerWithExposedProvenance
-                | CastKind::DynStar
                 | CastKind::Transmute,
                 _,
                 _,
diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs
index 231eb198983..ae75f2d4187 100644
--- a/compiler/rustc_middle/src/mir/syntax.rs
+++ b/compiler/rustc_middle/src/mir/syntax.rs
@@ -579,7 +579,8 @@ pub struct CopyNonOverlapping<'tcx> {
     pub count: Operand<'tcx>,
 }
 
-/// Represents how a `TerminatorKind::Call` was constructed, used for diagnostics
+/// Represents how a [`TerminatorKind::Call`] was constructed.
+/// Used only for diagnostics.
 #[derive(Clone, Copy, TyEncodable, TyDecodable, Debug, PartialEq, Hash, HashStable)]
 #[derive(TypeFoldable, TypeVisitable)]
 pub enum CallSource {
@@ -1403,9 +1404,7 @@ pub enum CastKind {
     /// * [`PointerCoercion::MutToConstPointer`]
     ///
     /// Both are runtime nops, so should be [`CastKind::PtrToPtr`] instead in runtime MIR.
-    PointerCoercion(PointerCoercion),
-    /// Cast into a dyn* object.
-    DynStar,
+    PointerCoercion(PointerCoercion, CoercionSource),
     IntToInt,
     FloatToInt,
     FloatToFloat,
@@ -1421,6 +1420,16 @@ pub enum CastKind {
     Transmute,
 }
 
+/// Represents how a [`CastKind::PointerCoercion`] was constructed.
+/// Used only for diagnostics.
+#[derive(Clone, Copy, Debug, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable)]
+pub enum CoercionSource {
+    /// The coercion was manually written by the user with an `as` cast.
+    AsCast,
+    /// The coercion was automatically inserted by the compiler.
+    Implicit,
+}
+
 #[derive(Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable)]
 #[derive(TypeFoldable, TypeVisitable)]
 pub enum AggregateKind<'tcx> {
diff --git a/compiler/rustc_middle/src/query/erase.rs b/compiler/rustc_middle/src/query/erase.rs
index bd20e6aa005..48bf4ffced0 100644
--- a/compiler/rustc_middle/src/query/erase.rs
+++ b/compiler/rustc_middle/src/query/erase.rs
@@ -1,6 +1,8 @@
 use std::intrinsics::transmute_unchecked;
 use std::mem::MaybeUninit;
 
+use rustc_span::ErrorGuaranteed;
+
 use crate::query::CyclePlaceholder;
 use crate::ty::adjustment::CoerceUnsizedInfo;
 use crate::ty::{self, Ty};
@@ -216,6 +218,10 @@ impl<T0, T1> EraseType for (&'_ T0, &'_ [T1]) {
     type Result = [u8; size_of::<(&'static (), &'static [()])>()];
 }
 
+impl<T0> EraseType for (&'_ T0, Result<(), ErrorGuaranteed>) {
+    type Result = [u8; size_of::<(&'static (), Result<(), ErrorGuaranteed>)>()];
+}
+
 macro_rules! trivial {
     ($($ty:ty),+ $(,)?) => {
         $(
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index 00036097ef5..9609ef46d5c 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -881,13 +881,13 @@ rustc_queries! {
     /// Maps a `DefId` of a type to a list of its inherent impls.
     /// Contains implementations of methods that are inherent to a type.
     /// Methods in these implementations don't need to be exported.
-    query inherent_impls(key: DefId) -> Result<&'tcx [DefId], ErrorGuaranteed> {
+    query inherent_impls(key: DefId) -> &'tcx [DefId] {
         desc { |tcx| "collecting inherent impls for `{}`", tcx.def_path_str(key) }
         cache_on_disk_if { key.is_local() }
         separate_provide_extern
     }
 
-    query incoherent_impls(key: SimplifiedType) -> Result<&'tcx [DefId], ErrorGuaranteed> {
+    query incoherent_impls(key: SimplifiedType) -> &'tcx [DefId] {
         desc { |tcx| "collecting all inherent impls for `{:?}`", key }
     }
 
@@ -1017,8 +1017,14 @@ rustc_queries! {
 
     /// Gets a complete map from all types to their inherent impls.
     /// Not meant to be used directly outside of coherence.
-    query crate_inherent_impls(k: ()) -> Result<&'tcx CrateInherentImpls, ErrorGuaranteed> {
+    query crate_inherent_impls(k: ()) -> (&'tcx CrateInherentImpls, Result<(), ErrorGuaranteed>) {
         desc { "finding all inherent impls defined in crate" }
+    }
+
+    /// Checks all types in the crate for overlap in their inherent impls. Reports errors.
+    /// Not meant to be used directly outside of coherence.
+    query crate_inherent_impls_validity_check(_: ()) -> Result<(), ErrorGuaranteed> {
+        desc { "check for inherent impls that should not be defined in crate" }
         ensure_forwards_result_if_red
     }
 
@@ -1715,7 +1721,7 @@ rustc_queries! {
     ///
     /// Do not call this directly, but instead use the `incoherent_impls` query.
     /// This query is only used to get the data necessary for that query.
-    query crate_incoherent_impls(key: (CrateNum, SimplifiedType)) -> Result<&'tcx [DefId], ErrorGuaranteed> {
+    query crate_incoherent_impls(key: (CrateNum, SimplifiedType)) -> &'tcx [DefId] {
         desc { |tcx| "collecting all impls for a type in a crate" }
         separate_provide_extern
     }
diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs
index 32234d6b55d..e614d41899a 100644
--- a/compiler/rustc_middle/src/thir.rs
+++ b/compiler/rustc_middle/src/thir.rs
@@ -338,6 +338,8 @@ pub enum ExprKind<'tcx> {
     PointerCoercion {
         cast: PointerCoercion,
         source: ExprId,
+        /// Whether this coercion is written with an `as` cast in the source code.
+        is_from_as_cast: bool,
     },
     /// A `loop` expression.
     Loop {
@@ -453,12 +455,14 @@ pub enum ExprKind<'tcx> {
         source: ExprId,
         /// Type that the user gave to this expression
         user_ty: UserTy<'tcx>,
+        user_ty_span: Span,
     },
-    /// A type ascription on a value, e.g. `42: i32`.
+    /// A type ascription on a value, e.g. `type_ascribe!(42, i32)` or `42 as i32`.
     ValueTypeAscription {
         source: ExprId,
         /// Type that the user gave to this expression
         user_ty: UserTy<'tcx>,
+        user_ty_span: Span,
     },
     /// A closure definition.
     Closure(Box<ClosureExpr<'tcx>>),
diff --git a/compiler/rustc_middle/src/thir/visit.rs b/compiler/rustc_middle/src/thir/visit.rs
index e246ecebbec..58e2ebaeaf8 100644
--- a/compiler/rustc_middle/src/thir/visit.rs
+++ b/compiler/rustc_middle/src/thir/visit.rs
@@ -68,7 +68,9 @@ pub fn walk_expr<'thir, 'tcx: 'thir, V: Visitor<'thir, 'tcx>>(
         Cast { source } => visitor.visit_expr(&visitor.thir()[source]),
         Use { source } => visitor.visit_expr(&visitor.thir()[source]),
         NeverToAny { source } => visitor.visit_expr(&visitor.thir()[source]),
-        PointerCoercion { source, cast: _ } => visitor.visit_expr(&visitor.thir()[source]),
+        PointerCoercion { source, cast: _, is_from_as_cast: _ } => {
+            visitor.visit_expr(&visitor.thir()[source])
+        }
         Let { expr, ref pat } => {
             visitor.visit_expr(&visitor.thir()[expr]);
             visitor.visit_pat(pat);
@@ -129,7 +131,8 @@ pub fn walk_expr<'thir, 'tcx: 'thir, V: Visitor<'thir, 'tcx>>(
                 visitor.visit_expr(&visitor.thir()[base.base]);
             }
         }
-        PlaceTypeAscription { source, user_ty: _ } | ValueTypeAscription { source, user_ty: _ } => {
+        PlaceTypeAscription { source, user_ty: _, user_ty_span: _ }
+        | ValueTypeAscription { source, user_ty: _, user_ty_span: _ } => {
             visitor.visit_expr(&visitor.thir()[source])
         }
         Closure(box ClosureExpr {
diff --git a/compiler/rustc_middle/src/ty/adjustment.rs b/compiler/rustc_middle/src/ty/adjustment.rs
index 5a32078760e..41a20e89cbf 100644
--- a/compiler/rustc_middle/src/ty/adjustment.rs
+++ b/compiler/rustc_middle/src/ty/adjustment.rs
@@ -35,6 +35,9 @@ pub enum PointerCoercion {
     /// type. Codegen backends and miri figure out what has to be done
     /// based on the precise source/target type at hand.
     Unsize,
+
+    /// Go from a pointer-like type to a `dyn*` object.
+    DynStar,
 }
 
 /// Represents coercing a value to a different type of value.
@@ -102,9 +105,6 @@ pub enum Adjust<'tcx> {
 
     Pointer(PointerCoercion),
 
-    /// Cast into a dyn* object.
-    DynStar,
-
     /// Take a pinned reference and reborrow as a `Pin<&mut T>` or `Pin<&T>`.
     ReborrowPin(ty::Region<'tcx>, hir::Mutability),
 }
diff --git a/compiler/rustc_middle/src/ty/cast.rs b/compiler/rustc_middle/src/ty/cast.rs
index 46f37659536..b1316ceef5a 100644
--- a/compiler/rustc_middle/src/ty/cast.rs
+++ b/compiler/rustc_middle/src/ty/cast.rs
@@ -34,15 +34,12 @@ pub enum CastTy<'tcx> {
     FnPtr,
     /// Raw pointers.
     Ptr(ty::TypeAndMut<'tcx>),
-    /// Casting into a `dyn*` value.
-    DynStar,
 }
 
 /// Cast Kind. See [RFC 401](https://rust-lang.github.io/rfcs/0401-coercions.html)
 /// (or rustc_hir_analysis/check/cast.rs).
 #[derive(Copy, Clone, Debug, TyEncodable, TyDecodable, HashStable)]
 pub enum CastKind {
-    CoercionCast,
     PtrPtrCast,
     PtrAddrCast,
     AddrPtrCast,
@@ -53,7 +50,6 @@ pub enum CastKind {
     ArrayPtrCast,
     FnPtrPtrCast,
     FnPtrAddrCast,
-    DynStarCast,
 }
 
 impl<'tcx> CastTy<'tcx> {
@@ -71,7 +67,6 @@ impl<'tcx> CastTy<'tcx> {
             ty::Adt(d, _) if d.is_enum() && d.is_payloadfree() => Some(CastTy::Int(IntTy::CEnum)),
             ty::RawPtr(ty, mutbl) => Some(CastTy::Ptr(ty::TypeAndMut { ty, mutbl })),
             ty::FnPtr(..) => Some(CastTy::FnPtr),
-            ty::Dynamic(_, _, ty::DynStar) => Some(CastTy::DynStar),
             _ => None,
         }
     }
@@ -86,7 +81,6 @@ pub fn mir_cast_kind<'tcx>(from_ty: Ty<'tcx>, cast_ty: Ty<'tcx>) -> mir::CastKin
             mir::CastKind::PointerExposeProvenance
         }
         (Some(CastTy::Int(_)), Some(CastTy::Ptr(_))) => mir::CastKind::PointerWithExposedProvenance,
-        (_, Some(CastTy::DynStar)) => mir::CastKind::DynStar,
         (Some(CastTy::Int(_)), Some(CastTy::Int(_))) => mir::CastKind::IntToInt,
         (Some(CastTy::FnPtr), Some(CastTy::Ptr(_))) => mir::CastKind::FnPtrToPtr,
 
diff --git a/compiler/rustc_middle/src/ty/trait_def.rs b/compiler/rustc_middle/src/ty/trait_def.rs
index 82690f70e5f..188107e5d54 100644
--- a/compiler/rustc_middle/src/ty/trait_def.rs
+++ b/compiler/rustc_middle/src/ty/trait_def.rs
@@ -253,30 +253,16 @@ pub(super) fn trait_impls_of_provider(tcx: TyCtxt<'_>, trait_id: DefId) -> Trait
 }
 
 /// Query provider for `incoherent_impls`.
-pub(super) fn incoherent_impls_provider(
-    tcx: TyCtxt<'_>,
-    simp: SimplifiedType,
-) -> Result<&[DefId], ErrorGuaranteed> {
+pub(super) fn incoherent_impls_provider(tcx: TyCtxt<'_>, simp: SimplifiedType) -> &[DefId] {
     let mut impls = Vec::new();
-
-    let mut res = Ok(());
     for cnum in iter::once(LOCAL_CRATE).chain(tcx.crates(()).iter().copied()) {
-        let incoherent_impls = match tcx.crate_incoherent_impls((cnum, simp)) {
-            Ok(impls) => impls,
-            Err(e) => {
-                res = Err(e);
-                continue;
-            }
-        };
-        for &impl_def_id in incoherent_impls {
+        for &impl_def_id in tcx.crate_incoherent_impls((cnum, simp)) {
             impls.push(impl_def_id)
         }
     }
-
     debug!(?impls);
-    res?;
 
-    Ok(tcx.arena.alloc_slice(&impls))
+    tcx.arena.alloc_slice(&impls)
 }
 
 pub(super) fn traits_provider(tcx: TyCtxt<'_>, _: LocalCrate) -> &[DefId] {
diff --git a/compiler/rustc_mir_build/src/build/expr/as_place.rs b/compiler/rustc_mir_build/src/build/expr/as_place.rs
index 2084bcae7b7..c7298e3ddfa 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_place.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_place.rs
@@ -470,21 +470,22 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 block.and(place_builder)
             }
 
-            ExprKind::PlaceTypeAscription { source, ref user_ty } => {
+            ExprKind::PlaceTypeAscription { source, ref user_ty, user_ty_span } => {
                 let place_builder = unpack!(
                     block = this.expr_as_place(block, source, mutability, fake_borrow_temps,)
                 );
                 if let Some(user_ty) = user_ty {
+                    let ty_source_info = this.source_info(user_ty_span);
                     let annotation_index =
                         this.canonical_user_type_annotations.push(CanonicalUserTypeAnnotation {
-                            span: source_info.span,
+                            span: user_ty_span,
                             user_ty: user_ty.clone(),
                             inferred_ty: expr.ty,
                         });
 
                     let place = place_builder.to_place(this);
                     this.cfg.push(block, Statement {
-                        source_info,
+                        source_info: ty_source_info,
                         kind: StatementKind::AscribeUserType(
                             Box::new((place, UserTypeProjection {
                                 base: annotation_index,
@@ -496,20 +497,21 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 }
                 block.and(place_builder)
             }
-            ExprKind::ValueTypeAscription { source, ref user_ty } => {
+            ExprKind::ValueTypeAscription { source, ref user_ty, user_ty_span } => {
                 let source_expr = &this.thir[source];
                 let temp = unpack!(
                     block = this.as_temp(block, source_expr.temp_lifetime, source, mutability)
                 );
                 if let Some(user_ty) = user_ty {
+                    let ty_source_info = this.source_info(user_ty_span);
                     let annotation_index =
                         this.canonical_user_type_annotations.push(CanonicalUserTypeAnnotation {
-                            span: source_info.span,
+                            span: user_ty_span,
                             user_ty: user_ty.clone(),
                             inferred_ty: expr.ty,
                         });
                     this.cfg.push(block, Statement {
-                        source_info,
+                        source_info: ty_source_info,
                         kind: StatementKind::AscribeUserType(
                             Box::new((Place::from(temp), UserTypeProjection {
                                 base: annotation_index,
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 ffedee8a1e8..fd949a53384 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
@@ -292,7 +292,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 let cast_kind = mir_cast_kind(ty, expr.ty);
                 block.and(Rvalue::Cast(cast_kind, source, expr.ty))
             }
-            ExprKind::PointerCoercion { cast, source } => {
+            ExprKind::PointerCoercion { cast, source, is_from_as_cast } => {
                 let source = unpack!(
                     block = this.as_operand(
                         block,
@@ -302,7 +302,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                         NeedsTemporary::No
                     )
                 );
-                block.and(Rvalue::Cast(CastKind::PointerCoercion(cast), source, expr.ty))
+                let origin =
+                    if is_from_as_cast { CoercionSource::AsCast } else { CoercionSource::Implicit };
+                block.and(Rvalue::Cast(CastKind::PointerCoercion(cast, origin), source, expr.ty))
             }
             ExprKind::Array { ref fields } => {
                 // (*) We would (maybe) be closer to codegen if we
diff --git a/compiler/rustc_mir_build/src/build/matches/test.rs b/compiler/rustc_mir_build/src/build/matches/test.rs
index 63873aad02a..020c202f965 100644
--- a/compiler/rustc_mir_build/src/build/matches/test.rs
+++ b/compiler/rustc_mir_build/src/build/matches/test.rs
@@ -407,7 +407,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                         source_info,
                         temp,
                         Rvalue::Cast(
-                            CastKind::PointerCoercion(PointerCoercion::Unsize),
+                            CastKind::PointerCoercion(
+                                PointerCoercion::Unsize,
+                                CoercionSource::Implicit,
+                            ),
                             Operand::Copy(val),
                             ty,
                         ),
@@ -421,7 +424,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                         source_info,
                         slice,
                         Rvalue::Cast(
-                            CastKind::PointerCoercion(PointerCoercion::Unsize),
+                            CastKind::PointerCoercion(
+                                PointerCoercion::Unsize,
+                                CoercionSource::Implicit,
+                            ),
                             expect,
                             ty,
                         ),
diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs
index 55236933922..fbd45f59a4f 100644
--- a/compiler/rustc_mir_build/src/thir/cx/expr.rs
+++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs
@@ -104,16 +104,29 @@ impl<'tcx> Cx<'tcx> {
         };
 
         let kind = match adjustment.kind {
-            Adjust::Pointer(PointerCoercion::Unsize) => {
-                adjust_span(&mut expr);
+            Adjust::Pointer(cast) => {
+                if cast == PointerCoercion::Unsize {
+                    adjust_span(&mut expr);
+                }
+
+                let is_from_as_cast = if let hir::Node::Expr(hir::Expr {
+                    kind: hir::ExprKind::Cast(..),
+                    span: cast_span,
+                    ..
+                }) = self.tcx.parent_hir_node(hir_expr.hir_id)
+                {
+                    // Use the whole span of the `x as T` expression for the coercion.
+                    span = *cast_span;
+                    true
+                } else {
+                    false
+                };
                 ExprKind::PointerCoercion {
-                    cast: PointerCoercion::Unsize,
+                    cast,
                     source: self.thir.exprs.push(expr),
+                    is_from_as_cast,
                 }
             }
-            Adjust::Pointer(cast) => {
-                ExprKind::PointerCoercion { cast, source: self.thir.exprs.push(expr) }
-            }
             Adjust::NeverToAny if adjustment.target.is_never() => return expr,
             Adjust::NeverToAny => ExprKind::NeverToAny { source: self.thir.exprs.push(expr) },
             Adjust::Deref(None) => {
@@ -146,7 +159,6 @@ impl<'tcx> Cx<'tcx> {
             Adjust::Borrow(AutoBorrow::RawPtr(mutability)) => {
                 ExprKind::RawBorrow { mutability, arg: self.thir.exprs.push(expr) }
             }
-            Adjust::DynStar => ExprKind::Cast { source: self.thir.exprs.push(expr) },
             Adjust::ReborrowPin(region, mutbl) => {
                 debug!("apply ReborrowPin adjustment");
                 // Rewrite `$expr` as `Pin { __pointer: &(mut)? *($expr).__pointer }`
@@ -236,6 +248,7 @@ impl<'tcx> Cx<'tcx> {
             ExprKind::PointerCoercion {
                 source: self.mirror_expr(source),
                 cast: PointerCoercion::ArrayToPointer,
+                is_from_as_cast: true,
             }
         } else if let hir::ExprKind::Path(ref qpath) = source.kind
             && let res = self.typeck_results().qpath_res(qpath, source.hir_id)
@@ -841,6 +854,7 @@ impl<'tcx> Cx<'tcx> {
                     ExprKind::ValueTypeAscription {
                         source: cast_expr,
                         user_ty: Some(Box::new(*user_ty)),
+                        user_ty_span: cast_ty.span,
                     }
                 } else {
                     cast
@@ -852,9 +866,17 @@ impl<'tcx> Cx<'tcx> {
                 debug!("make_mirror_unadjusted: (type) user_ty={:?}", user_ty);
                 let mirrored = self.mirror_expr(source);
                 if source.is_syntactic_place_expr() {
-                    ExprKind::PlaceTypeAscription { source: mirrored, user_ty }
+                    ExprKind::PlaceTypeAscription {
+                        source: mirrored,
+                        user_ty,
+                        user_ty_span: ty.span,
+                    }
                 } else {
-                    ExprKind::ValueTypeAscription { source: mirrored, user_ty }
+                    ExprKind::ValueTypeAscription {
+                        source: mirrored,
+                        user_ty,
+                        user_ty_span: ty.span,
+                    }
                 }
             }
             hir::ExprKind::DropTemps(source) => ExprKind::Use { source: self.mirror_expr(source) },
diff --git a/compiler/rustc_mir_build/src/thir/print.rs b/compiler/rustc_mir_build/src/thir/print.rs
index ce7774f5948..61317925d09 100644
--- a/compiler/rustc_mir_build/src/thir/print.rs
+++ b/compiler/rustc_mir_build/src/thir/print.rs
@@ -292,9 +292,14 @@ impl<'a, 'tcx> ThirPrinter<'a, 'tcx> {
                 self.print_expr(*source, depth_lvl + 2);
                 print_indented!(self, "}", depth_lvl);
             }
-            PointerCoercion { cast, source } => {
+            PointerCoercion { cast, is_from_as_cast, source } => {
                 print_indented!(self, "Pointer {", depth_lvl);
                 print_indented!(self, format!("cast: {:?}", cast), depth_lvl + 1);
+                print_indented!(
+                    self,
+                    format!("is_from_as_cast: {:?}", is_from_as_cast),
+                    depth_lvl + 1
+                );
                 print_indented!(self, "source:", depth_lvl + 1);
                 self.print_expr(*source, depth_lvl + 2);
                 print_indented!(self, "}", depth_lvl);
@@ -454,16 +459,18 @@ impl<'a, 'tcx> ThirPrinter<'a, 'tcx> {
                 self.print_adt_expr(&**adt_expr, depth_lvl + 1);
                 print_indented!(self, "}", depth_lvl);
             }
-            PlaceTypeAscription { source, user_ty } => {
+            PlaceTypeAscription { source, user_ty, user_ty_span } => {
                 print_indented!(self, "PlaceTypeAscription {", depth_lvl);
                 print_indented!(self, format!("user_ty: {:?}", user_ty), depth_lvl + 1);
+                print_indented!(self, format!("user_ty_span: {:?}", user_ty_span), depth_lvl + 1);
                 print_indented!(self, "source:", depth_lvl + 1);
                 self.print_expr(*source, depth_lvl + 2);
                 print_indented!(self, "}", depth_lvl);
             }
-            ValueTypeAscription { source, user_ty } => {
+            ValueTypeAscription { source, user_ty, user_ty_span } => {
                 print_indented!(self, "ValueTypeAscription {", depth_lvl);
                 print_indented!(self, format!("user_ty: {:?}", user_ty), depth_lvl + 1);
+                print_indented!(self, format!("user_ty_span: {:?}", user_ty_span), depth_lvl + 1);
                 print_indented!(self, "source:", depth_lvl + 1);
                 self.print_expr(*source, depth_lvl + 2);
                 print_indented!(self, "}", depth_lvl);
diff --git a/compiler/rustc_mir_transform/src/cleanup_post_borrowck.rs b/compiler/rustc_mir_transform/src/cleanup_post_borrowck.rs
index 5395e1b0e94..6a22a58470c 100644
--- a/compiler/rustc_mir_transform/src/cleanup_post_borrowck.rs
+++ b/compiler/rustc_mir_transform/src/cleanup_post_borrowck.rs
@@ -42,6 +42,7 @@ impl<'tcx> crate::MirPass<'tcx> for CleanupPostBorrowck {
                             ref mut cast_kind @ CastKind::PointerCoercion(
                                 PointerCoercion::ArrayToPointer
                                 | PointerCoercion::MutToConstPointer,
+                                _,
                             ),
                             ..,
                         ),
diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs
index 2026b789315..88dc8e74a8c 100644
--- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs
+++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs
@@ -189,7 +189,7 @@ impl<'tcx> ValueAnalysis<'tcx> for ConstAnalysis<'_, 'tcx> {
                 }
             }
             Rvalue::Cast(
-                CastKind::PointerCoercion(ty::adjustment::PointerCoercion::Unsize),
+                CastKind::PointerCoercion(ty::adjustment::PointerCoercion::Unsize, _),
                 operand,
                 _,
             ) => {
diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs
index 4d44669fa3e..f735d08fca5 100644
--- a/compiler/rustc_mir_transform/src/gvn.rs
+++ b/compiler/rustc_mir_transform/src/gvn.rs
@@ -576,7 +576,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
                     }
                     value.offset(Size::ZERO, to, &self.ecx).ok()?
                 }
-                CastKind::PointerCoercion(ty::adjustment::PointerCoercion::Unsize) => {
+                CastKind::PointerCoercion(ty::adjustment::PointerCoercion::Unsize, _) => {
                     let src = self.evaluated[value].as_ref()?;
                     let to = self.ecx.layout_of(to).ok()?;
                     let dest = self.ecx.allocate(to, MemoryKind::Stack).ok()?;
@@ -593,7 +593,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
                     let ret = self.ecx.ptr_to_ptr(&src, to).ok()?;
                     ret.into()
                 }
-                CastKind::PointerCoercion(ty::adjustment::PointerCoercion::UnsafeFnPointer) => {
+                CastKind::PointerCoercion(ty::adjustment::PointerCoercion::UnsafeFnPointer, _) => {
                     let src = self.evaluated[value].as_ref()?;
                     let src = self.ecx.read_immediate(src).ok()?;
                     let to = self.ecx.layout_of(to).ok()?;
@@ -1138,7 +1138,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
             (
                 UnOp::PtrMetadata,
                 Value::Cast {
-                    kind: CastKind::PointerCoercion(ty::adjustment::PointerCoercion::Unsize),
+                    kind: CastKind::PointerCoercion(ty::adjustment::PointerCoercion::Unsize, _),
                     from,
                     to,
                     ..
@@ -1342,7 +1342,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
             return Some(value);
         }
 
-        if let CastKind::PointerCoercion(ReifyFnPointer | ClosureFnPointer(_)) = kind {
+        if let CastKind::PointerCoercion(ReifyFnPointer | ClosureFnPointer(_), _) = kind {
             // Each reification of a generic fn may get a different pointer.
             // Do not try to merge them.
             return self.new_opaque();
@@ -1429,7 +1429,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
 
         // We have an unsizing cast, which assigns the length to fat pointer metadata.
         if let Value::Cast { kind, from, to, .. } = self.get(inner)
-            && let CastKind::PointerCoercion(ty::adjustment::PointerCoercion::Unsize) = kind
+            && let CastKind::PointerCoercion(ty::adjustment::PointerCoercion::Unsize, _) = kind
             && let Some(from) = from.builtin_deref(true)
             && let ty::Array(_, len) = from.kind()
             && let Some(to) = to.builtin_deref(true)
diff --git a/compiler/rustc_mir_transform/src/mentioned_items.rs b/compiler/rustc_mir_transform/src/mentioned_items.rs
index f24de609e6b..cf5c5f85a9f 100644
--- a/compiler/rustc_mir_transform/src/mentioned_items.rs
+++ b/compiler/rustc_mir_transform/src/mentioned_items.rs
@@ -70,11 +70,11 @@ impl<'tcx> Visitor<'tcx> for MentionedItemsVisitor<'_, 'tcx> {
         match *rvalue {
             // We need to detect unsizing casts that required vtables.
             mir::Rvalue::Cast(
-                mir::CastKind::PointerCoercion(PointerCoercion::Unsize),
+                mir::CastKind::PointerCoercion(PointerCoercion::Unsize, _)
+                | mir::CastKind::PointerCoercion(PointerCoercion::DynStar, _),
                 ref operand,
                 target_ty,
-            )
-            | mir::Rvalue::Cast(mir::CastKind::DynStar, ref operand, target_ty) => {
+            ) => {
                 // This isn't monomorphized yet so we can't tell what the actual types are -- just
                 // add everything that may involve a vtable.
                 let source_ty = operand.ty(self.body, self.tcx);
@@ -96,7 +96,7 @@ impl<'tcx> Visitor<'tcx> for MentionedItemsVisitor<'_, 'tcx> {
             }
             // Similarly, record closures that are turned into function pointers.
             mir::Rvalue::Cast(
-                mir::CastKind::PointerCoercion(PointerCoercion::ClosureFnPointer(_)),
+                mir::CastKind::PointerCoercion(PointerCoercion::ClosureFnPointer(_), _),
                 ref operand,
                 _,
             ) => {
@@ -106,7 +106,7 @@ impl<'tcx> Visitor<'tcx> for MentionedItemsVisitor<'_, 'tcx> {
             }
             // And finally, function pointer reification casts.
             mir::Rvalue::Cast(
-                mir::CastKind::PointerCoercion(PointerCoercion::ReifyFnPointer),
+                mir::CastKind::PointerCoercion(PointerCoercion::ReifyFnPointer, _),
                 ref operand,
                 _,
             ) => {
diff --git a/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs b/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs
index c206252c15a..71723f040b3 100644
--- a/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs
+++ b/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs
@@ -7,9 +7,10 @@ use rustc_hir::def_id::DefId;
 use rustc_hir::lang_items::LangItem;
 use rustc_index::{Idx, IndexVec};
 use rustc_middle::mir::{
-    BasicBlock, BasicBlockData, Body, CallSource, CastKind, Const, ConstOperand, ConstValue, Local,
-    LocalDecl, MirSource, Operand, Place, PlaceElem, RETURN_PLACE, Rvalue, SourceInfo, Statement,
-    StatementKind, Terminator, TerminatorKind, UnwindAction, UnwindTerminateReason,
+    BasicBlock, BasicBlockData, Body, CallSource, CastKind, CoercionSource, Const, ConstOperand,
+    ConstValue, Local, LocalDecl, MirSource, Operand, Place, PlaceElem, RETURN_PLACE, Rvalue,
+    SourceInfo, Statement, StatementKind, Terminator, TerminatorKind, UnwindAction,
+    UnwindTerminateReason,
 };
 use rustc_middle::ty::adjustment::PointerCoercion;
 use rustc_middle::ty::util::{AsyncDropGlueMorphology, Discr};
@@ -329,7 +330,7 @@ impl<'tcx> AsyncDestructorCtorShimBuilder<'tcx> {
     fn put_array_as_slice(&mut self, elem_ty: Ty<'tcx>) {
         let slice_ptr_ty = Ty::new_mut_ptr(self.tcx, Ty::new_slice(self.tcx, elem_ty));
         self.put_temp_rvalue(Rvalue::Cast(
-            CastKind::PointerCoercion(PointerCoercion::Unsize),
+            CastKind::PointerCoercion(PointerCoercion::Unsize, CoercionSource::Implicit),
             Operand::Copy(Self::SELF_PTR.into()),
             slice_ptr_ty,
         ))
diff --git a/compiler/rustc_mir_transform/src/validate.rs b/compiler/rustc_mir_transform/src/validate.rs
index 914dddc1a56..eda0b8c75f3 100644
--- a/compiler/rustc_mir_transform/src/validate.rs
+++ b/compiler/rustc_mir_transform/src/validate.rs
@@ -1128,12 +1128,9 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
             Rvalue::Cast(kind, operand, target_type) => {
                 let op_ty = operand.ty(self.body, self.tcx);
                 match kind {
-                    CastKind::DynStar => {
-                        // FIXME(dyn-star): make sure nothing needs to be done here.
-                    }
                     // FIXME: Add Checks for these
                     CastKind::PointerWithExposedProvenance | CastKind::PointerExposeProvenance => {}
-                    CastKind::PointerCoercion(PointerCoercion::ReifyFnPointer) => {
+                    CastKind::PointerCoercion(PointerCoercion::ReifyFnPointer, _) => {
                         // FIXME: check signature compatibility.
                         check_kinds!(
                             op_ty,
@@ -1146,7 +1143,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
                             ty::FnPtr(..)
                         );
                     }
-                    CastKind::PointerCoercion(PointerCoercion::UnsafeFnPointer) => {
+                    CastKind::PointerCoercion(PointerCoercion::UnsafeFnPointer, _) => {
                         // FIXME: check safety and signature compatibility.
                         check_kinds!(
                             op_ty,
@@ -1159,7 +1156,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
                             ty::FnPtr(..)
                         );
                     }
-                    CastKind::PointerCoercion(PointerCoercion::ClosureFnPointer(..)) => {
+                    CastKind::PointerCoercion(PointerCoercion::ClosureFnPointer(..), _) => {
                         // FIXME: check safety, captures, and signature compatibility.
                         check_kinds!(
                             op_ty,
@@ -1172,7 +1169,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
                             ty::FnPtr(..)
                         );
                     }
-                    CastKind::PointerCoercion(PointerCoercion::MutToConstPointer) => {
+                    CastKind::PointerCoercion(PointerCoercion::MutToConstPointer, _) => {
                         // FIXME: check same pointee?
                         check_kinds!(
                             op_ty,
@@ -1188,7 +1185,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
                             self.fail(location, format!("After borrowck, MIR disallows {kind:?}"));
                         }
                     }
-                    CastKind::PointerCoercion(PointerCoercion::ArrayToPointer) => {
+                    CastKind::PointerCoercion(PointerCoercion::ArrayToPointer, _) => {
                         // FIXME: Check pointee types
                         check_kinds!(
                             op_ty,
@@ -1204,10 +1201,13 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
                             self.fail(location, format!("After borrowck, MIR disallows {kind:?}"));
                         }
                     }
-                    CastKind::PointerCoercion(PointerCoercion::Unsize) => {
+                    CastKind::PointerCoercion(PointerCoercion::Unsize, _) => {
                         // This is used for all `CoerceUnsized` types,
                         // not just pointers/references, so is hard to check.
                     }
+                    CastKind::PointerCoercion(PointerCoercion::DynStar, _) => {
+                        // FIXME(dyn-star): make sure nothing needs to be done here.
+                    }
                     CastKind::IntToInt | CastKind::IntToFloat => {
                         let input_valid = op_ty.is_integral() || op_ty.is_char() || op_ty.is_bool();
                         let target_valid = target_type.is_numeric() || target_type.is_char();
diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs
index 8d137b8d8f9..276098a8400 100644
--- a/compiler/rustc_monomorphize/src/collector.rs
+++ b/compiler/rustc_monomorphize/src/collector.rs
@@ -665,11 +665,11 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> {
             // have to instantiate all methods of the trait being cast to, so we
             // can build the appropriate vtable.
             mir::Rvalue::Cast(
-                mir::CastKind::PointerCoercion(PointerCoercion::Unsize),
+                mir::CastKind::PointerCoercion(PointerCoercion::Unsize, _)
+                | mir::CastKind::PointerCoercion(PointerCoercion::DynStar, _),
                 ref operand,
                 target_ty,
-            )
-            | mir::Rvalue::Cast(mir::CastKind::DynStar, ref operand, target_ty) => {
+            ) => {
                 let source_ty = operand.ty(self.body, self.tcx);
                 // *Before* monomorphizing, record that we already handled this mention.
                 self.used_mentioned_items
@@ -694,7 +694,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> {
                 }
             }
             mir::Rvalue::Cast(
-                mir::CastKind::PointerCoercion(PointerCoercion::ReifyFnPointer),
+                mir::CastKind::PointerCoercion(PointerCoercion::ReifyFnPointer, _),
                 ref operand,
                 _,
             ) => {
@@ -705,7 +705,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> {
                 visit_fn_use(self.tcx, fn_ty, false, span, self.used_items);
             }
             mir::Rvalue::Cast(
-                mir::CastKind::PointerCoercion(PointerCoercion::ClosureFnPointer(_)),
+                mir::CastKind::PointerCoercion(PointerCoercion::ClosureFnPointer(_), _),
                 ref operand,
                 _,
             ) => {
@@ -1183,7 +1183,7 @@ fn collect_alloc<'tcx>(tcx: TyCtxt<'tcx>, alloc_id: AllocId, output: &mut MonoIt
 }
 
 fn assoc_fn_of_type<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, fn_ident: Ident) -> Option<DefId> {
-    for impl_def_id in tcx.inherent_impls(def_id).ok()? {
+    for impl_def_id in tcx.inherent_impls(def_id) {
         if let Some(new) = tcx.associated_items(impl_def_id).find_by_name_and_kind(
             tcx,
             fn_ident,
diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs
index 7ea057c7b4b..35d166e8b4a 100644
--- a/compiler/rustc_resolve/src/late/diagnostics.rs
+++ b/compiler/rustc_resolve/src/late/diagnostics.rs
@@ -1825,10 +1825,12 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
             // Doing analysis on local `DefId`s would cause infinite recursion.
             return;
         }
-        let Ok(impls) = self.r.tcx.inherent_impls(def_id) else { return };
         // Look at all the associated functions without receivers in the type's
         // inherent impls to look for builders that return `Self`
-        let mut items = impls
+        let mut items = self
+            .r
+            .tcx
+            .inherent_impls(def_id)
             .iter()
             .flat_map(|i| self.r.tcx.associated_items(i).in_definition_order())
             // Only assoc fn with no receivers.
diff --git a/compiler/rustc_smir/src/rustc_smir/convert/mir.rs b/compiler/rustc_smir/src/rustc_smir/convert/mir.rs
index f4c7fd7c900..0dbbc338e73 100644
--- a/compiler/rustc_smir/src/rustc_smir/convert/mir.rs
+++ b/compiler/rustc_smir/src/rustc_smir/convert/mir.rs
@@ -282,11 +282,12 @@ impl<'tcx> Stable<'tcx> for mir::CastKind {
     type T = stable_mir::mir::CastKind;
     fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
         use rustc_middle::mir::CastKind::*;
+        use rustc_middle::ty::adjustment::PointerCoercion;
         match self {
             PointerExposeProvenance => stable_mir::mir::CastKind::PointerExposeAddress,
             PointerWithExposedProvenance => stable_mir::mir::CastKind::PointerWithExposedProvenance,
-            PointerCoercion(c) => stable_mir::mir::CastKind::PointerCoercion(c.stable(tables)),
-            DynStar => stable_mir::mir::CastKind::DynStar,
+            PointerCoercion(PointerCoercion::DynStar, _) => stable_mir::mir::CastKind::DynStar,
+            PointerCoercion(c, _) => stable_mir::mir::CastKind::PointerCoercion(c.stable(tables)),
             IntToInt => stable_mir::mir::CastKind::IntToInt,
             FloatToInt => stable_mir::mir::CastKind::FloatToInt,
             FloatToFloat => stable_mir::mir::CastKind::FloatToFloat,
diff --git a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs
index e54ab1f7e24..ac9a0235762 100644
--- a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs
+++ b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs
@@ -119,6 +119,7 @@ impl<'tcx> Stable<'tcx> for ty::adjustment::PointerCoercion {
             }
             PointerCoercion::ArrayToPointer => stable_mir::mir::PointerCoercion::ArrayToPointer,
             PointerCoercion::Unsize => stable_mir::mir::PointerCoercion::Unsize,
+            PointerCoercion::DynStar => unreachable!("represented as `CastKind::DynStar` in smir"),
         }
     }
 }
diff --git a/compiler/stable_mir/src/mir/body.rs b/compiler/stable_mir/src/mir/body.rs
index 7c09fe1a085..ab9fc218d19 100644
--- a/compiler/stable_mir/src/mir/body.rs
+++ b/compiler/stable_mir/src/mir/body.rs
@@ -960,6 +960,7 @@ pub enum CastKind {
     PointerExposeAddress,
     PointerWithExposedProvenance,
     PointerCoercion(PointerCoercion),
+    // FIXME(smir-rename): change this to PointerCoercion(DynStar)
     DynStar,
     IntToInt,
     FloatToInt,