Skip to content

Commit 472059d

Browse files
committed
Deduplicate some logic between dyn* and dyn
1 parent ad6dd60 commit 472059d

File tree

1 file changed

+37
-46
lines changed

1 file changed

+37
-46
lines changed

compiler/rustc_const_eval/src/interpret/terminator.rs

+37-46
Original file line numberDiff line numberDiff line change
@@ -571,64 +571,55 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
571571

572572
// Obtain the underlying trait we are working on, and the adjusted receiver argument.
573573
let recv_ty = receiver.layout.ty;
574-
let (vptr, dyn_ty, adjusted_receiver) = match recv_ty.kind() {
575-
ty::Ref(..) | ty::RawPtr(..)
576-
if matches!(
577-
recv_ty.builtin_deref(true).unwrap().ty.kind(),
578-
ty::Dynamic(_, _, ty::DynStar)
579-
) =>
580-
{
581-
let receiver = self.deref_operand(&receiver)?;
582-
let ty::Dynamic(data, ..) = receiver.layout.ty.kind() else { bug!() };
583-
let (recv, vptr) = self.unpack_dyn_star(&receiver.into())?;
584-
let (dyn_ty, dyn_trait) = self.get_ptr_vtable(vptr)?;
585-
if dyn_trait != data.principal() {
586-
throw_ub_format!(
587-
"`dyn*` call on a pointer whose vtable does not match its type"
588-
);
589-
}
590-
let recv = recv.assert_mem_place(); // we passed an MPlaceTy to `unpack_dyn_star` so we definitely still have one
591-
592-
(vptr, dyn_ty, recv.ptr)
593-
}
574+
let receiver_place = match recv_ty.kind() {
575+
ty::Ref(..) | ty::RawPtr(..) => self.deref_operand(&receiver)?,
576+
ty::Dynamic(_, _, ty::Dyn) => receiver.assert_mem_place(), // unsized (`dyn`) cannot be immediate
594577
ty::Dynamic(_, _, ty::DynStar) => {
595578
// Not clear how to handle this, so far we assume the receiver is always a pointer.
596579
span_bug!(
597580
self.cur_span(),
598581
"by-value calls on a `dyn*`... are those a thing?"
599582
);
600583
}
601-
_ => {
602-
let receiver_place = match recv_ty.kind() {
603-
ty::Ref(..) | ty::RawPtr(..) => self.deref_operand(&receiver)?,
604-
ty::Dynamic(_, _, ty::Dyn) => receiver.assert_mem_place(), // unsized (`dyn`) cannot be immediate
605-
_ => bug!(),
606-
};
607-
// Doesn't have to be a `dyn Trait`, but the unsized tail must be `dyn Trait`.
608-
// (For that reason we also cannot use `unpack_dyn_trait`.)
609-
let receiver_tail = self.tcx.struct_tail_erasing_lifetimes(
610-
receiver_place.layout.ty,
611-
self.param_env,
584+
_ => bug!(),
585+
};
586+
let (vptr, dyn_ty, adjusted_receiver) = if let ty::Dynamic(data, _, ty::DynStar) =
587+
receiver_place.layout.ty.kind()
588+
{
589+
let (recv, vptr) = self.unpack_dyn_star(&receiver_place.into())?;
590+
let (dyn_ty, dyn_trait) = self.get_ptr_vtable(vptr)?;
591+
if dyn_trait != data.principal() {
592+
throw_ub_format!(
593+
"`dyn*` call on a pointer whose vtable does not match its type"
612594
);
613-
let ty::Dynamic(data, _, ty::Dyn) = receiver_tail.kind() else {
595+
}
596+
let recv = recv.assert_mem_place(); // we passed an MPlaceTy to `unpack_dyn_star` so we definitely still have one
597+
598+
(vptr, dyn_ty, recv.ptr)
599+
} else {
600+
// Doesn't have to be a `dyn Trait`, but the unsized tail must be `dyn Trait`.
601+
// (For that reason we also cannot use `unpack_dyn_trait`.)
602+
let receiver_tail = self
603+
.tcx
604+
.struct_tail_erasing_lifetimes(receiver_place.layout.ty, self.param_env);
605+
let ty::Dynamic(data, _, ty::Dyn) = receiver_tail.kind() else {
614606
span_bug!(self.cur_span(), "dynamic call on non-`dyn` type {}", receiver_tail)
615607
};
616-
assert!(receiver_place.layout.is_unsized());
617-
618-
// Get the required information from the vtable.
619-
let vptr = receiver_place.meta.unwrap_meta().to_pointer(self)?;
620-
let (dyn_ty, dyn_trait) = self.get_ptr_vtable(vptr)?;
621-
if dyn_trait != data.principal() {
622-
throw_ub_format!(
623-
"`dyn` call on a pointer whose vtable does not match its type"
624-
);
625-
}
608+
assert!(receiver_place.layout.is_unsized());
626609

627-
// It might be surprising that we use a pointer as the receiver even if this
628-
// is a by-val case; this works because by-val passing of an unsized `dyn
629-
// Trait` to a function is actually desugared to a pointer.
630-
(vptr, dyn_ty, receiver_place.ptr)
610+
// Get the required information from the vtable.
611+
let vptr = receiver_place.meta.unwrap_meta().to_pointer(self)?;
612+
let (dyn_ty, dyn_trait) = self.get_ptr_vtable(vptr)?;
613+
if dyn_trait != data.principal() {
614+
throw_ub_format!(
615+
"`dyn` call on a pointer whose vtable does not match its type"
616+
);
631617
}
618+
619+
// It might be surprising that we use a pointer as the receiver even if this
620+
// is a by-val case; this works because by-val passing of an unsized `dyn
621+
// Trait` to a function is actually desugared to a pointer.
622+
(vptr, dyn_ty, receiver_place.ptr)
632623
};
633624

634625
// Now determine the actual method to call. We can do that in two different ways and

0 commit comments

Comments
 (0)