This commit is contained in:
Michael Goulet 2025-08-23 17:13:03 +00:00
parent c957c4e704
commit e0fb6ebf7b

View file

@ -1456,78 +1456,79 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
}
CastKind::PtrToPtr => {
let ty_from = op.ty(self.body, tcx);
let cast_ty_from = CastTy::from_ty(ty_from);
let cast_ty_to = CastTy::from_ty(*ty);
let Some(CastTy::Ptr(src)) = CastTy::from_ty(ty_from) else {
unreachable!();
};
let Some(CastTy::Ptr(dst)) = CastTy::from_ty(*ty) else {
unreachable!();
};
match (cast_ty_from, cast_ty_to) {
(Some(CastTy::Ptr(src)), Some(CastTy::Ptr(dst))) => {
if self
.infcx
.type_is_sized_modulo_regions(self.infcx.param_env, dst.ty)
{
// Wide to thin ptr cast. This may even occur in an env with
// impossible predicates, such as `where dyn Trait: Sized`.
// In this case, we don't want to fall into the case below,
// since the types may not actually be equatable, but it's
// fine to perform this operation in an impossible env.
} else if let ty::Dynamic(src_tty, _src_lt, ty::Dyn) =
*self.struct_tail(src.ty, location).kind()
&& let ty::Dynamic(dst_tty, dst_lt, ty::Dyn) =
*self.struct_tail(dst.ty, location).kind()
&& src_tty.principal().is_some()
&& dst_tty.principal().is_some()
{
// This checks (lifetime part of) vtable validity for pointer casts,
// which is irrelevant when there are aren't principal traits on
// both sides (aka only auto traits).
//
// Note that other checks (such as denying `dyn Send` -> `dyn
// Debug`) are in `rustc_hir_typeck`.
if self.infcx.type_is_sized_modulo_regions(self.infcx.param_env, dst.ty) {
// Wide to thin ptr cast. This may even occur in an env with
// impossible predicates, such as `where dyn Trait: Sized`.
// In this case, we don't want to fall into the case below,
// since the types may not actually be equatable, but it's
// fine to perform this operation in an impossible env.
let trait_ref = ty::TraitRef::new(
tcx,
tcx.require_lang_item(LangItem::Sized, self.last_span),
[dst.ty],
);
self.prove_trait_ref(
trait_ref,
location.to_locations(),
ConstraintCategory::Cast {
is_implicit_coercion: true,
unsize_to: None,
},
);
} else if let ty::Dynamic(src_tty, _src_lt, ty::Dyn) =
*self.struct_tail(src.ty, location).kind()
&& let ty::Dynamic(dst_tty, dst_lt, ty::Dyn) =
*self.struct_tail(dst.ty, location).kind()
&& src_tty.principal().is_some()
&& dst_tty.principal().is_some()
{
// This checks (lifetime part of) vtable validity for pointer casts,
// which is irrelevant when there are aren't principal traits on
// both sides (aka only auto traits).
//
// Note that other checks (such as denying `dyn Send` -> `dyn
// Debug`) are in `rustc_hir_typeck`.
// Remove auto traits.
// Auto trait checks are handled in `rustc_hir_typeck` as FCW.
let src_obj = Ty::new_dynamic(
tcx,
tcx.mk_poly_existential_predicates(
&src_tty.without_auto_traits().collect::<Vec<_>>(),
),
// FIXME: Once we disallow casting `*const dyn Trait + 'short`
// to `*const dyn Trait + 'long`, then this can just be `src_lt`.
dst_lt,
ty::Dyn,
);
let dst_obj = Ty::new_dynamic(
tcx,
tcx.mk_poly_existential_predicates(
&dst_tty.without_auto_traits().collect::<Vec<_>>(),
),
dst_lt,
ty::Dyn,
);
// Remove auto traits.
// Auto trait checks are handled in `rustc_hir_typeck` as FCW.
let src_obj = Ty::new_dynamic(
tcx,
tcx.mk_poly_existential_predicates(
&src_tty.without_auto_traits().collect::<Vec<_>>(),
),
// FIXME: Once we disallow casting `*const dyn Trait + 'short`
// to `*const dyn Trait + 'long`, then this can just be `src_lt`.
dst_lt,
ty::Dyn,
);
let dst_obj = Ty::new_dynamic(
tcx,
tcx.mk_poly_existential_predicates(
&dst_tty.without_auto_traits().collect::<Vec<_>>(),
),
dst_lt,
ty::Dyn,
);
debug!(?src_tty, ?dst_tty, ?src_obj, ?dst_obj);
debug!(?src_tty, ?dst_tty, ?src_obj, ?dst_obj);
self.sub_types(
src_obj,
dst_obj,
location.to_locations(),
ConstraintCategory::Cast {
is_implicit_coercion: false,
unsize_to: None,
},
)
.unwrap();
}
}
_ => {
span_mirbug!(
self,
rvalue,
"Invalid PtrToPtr cast {:?} -> {:?}",
ty_from,
ty
)
}
self.sub_types(
src_obj,
dst_obj,
location.to_locations(),
ConstraintCategory::Cast {
is_implicit_coercion: false,
unsize_to: None,
},
)
.unwrap();
}
}
CastKind::Transmute => {