Deduplicate some logic between dyn* and dyn

This commit is contained in:
Oli Scherer 2023-02-20 14:07:19 +00:00
parent ad6dd60396
commit 472059d854

View File

@ -571,16 +571,22 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
// Obtain the underlying trait we are working on, and the adjusted receiver argument. // Obtain the underlying trait we are working on, and the adjusted receiver argument.
let recv_ty = receiver.layout.ty; let recv_ty = receiver.layout.ty;
let (vptr, dyn_ty, adjusted_receiver) = match recv_ty.kind() { let receiver_place = match recv_ty.kind() {
ty::Ref(..) | ty::RawPtr(..) ty::Ref(..) | ty::RawPtr(..) => self.deref_operand(&receiver)?,
if matches!( ty::Dynamic(_, _, ty::Dyn) => receiver.assert_mem_place(), // unsized (`dyn`) cannot be immediate
recv_ty.builtin_deref(true).unwrap().ty.kind(), ty::Dynamic(_, _, ty::DynStar) => {
ty::Dynamic(_, _, ty::DynStar) // Not clear how to handle this, so far we assume the receiver is always a pointer.
) => span_bug!(
self.cur_span(),
"by-value calls on a `dyn*`... are those a thing?"
);
}
_ => bug!(),
};
let (vptr, dyn_ty, adjusted_receiver) = if let ty::Dynamic(data, _, ty::DynStar) =
receiver_place.layout.ty.kind()
{ {
let receiver = self.deref_operand(&receiver)?; let (recv, vptr) = self.unpack_dyn_star(&receiver_place.into())?;
let ty::Dynamic(data, ..) = receiver.layout.ty.kind() else { bug!() };
let (recv, vptr) = self.unpack_dyn_star(&receiver.into())?;
let (dyn_ty, dyn_trait) = self.get_ptr_vtable(vptr)?; let (dyn_ty, dyn_trait) = self.get_ptr_vtable(vptr)?;
if dyn_trait != data.principal() { if dyn_trait != data.principal() {
throw_ub_format!( throw_ub_format!(
@ -590,26 +596,12 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
let recv = recv.assert_mem_place(); // we passed an MPlaceTy to `unpack_dyn_star` so we definitely still have one let recv = recv.assert_mem_place(); // we passed an MPlaceTy to `unpack_dyn_star` so we definitely still have one
(vptr, dyn_ty, recv.ptr) (vptr, dyn_ty, recv.ptr)
} } else {
ty::Dynamic(_, _, ty::DynStar) => {
// Not clear how to handle this, so far we assume the receiver is always a pointer.
span_bug!(
self.cur_span(),
"by-value calls on a `dyn*`... are those a thing?"
);
}
_ => {
let receiver_place = match recv_ty.kind() {
ty::Ref(..) | ty::RawPtr(..) => self.deref_operand(&receiver)?,
ty::Dynamic(_, _, ty::Dyn) => receiver.assert_mem_place(), // unsized (`dyn`) cannot be immediate
_ => bug!(),
};
// Doesn't have to be a `dyn Trait`, but the unsized tail must be `dyn Trait`. // Doesn't have to be a `dyn Trait`, but the unsized tail must be `dyn Trait`.
// (For that reason we also cannot use `unpack_dyn_trait`.) // (For that reason we also cannot use `unpack_dyn_trait`.)
let receiver_tail = self.tcx.struct_tail_erasing_lifetimes( let receiver_tail = self
receiver_place.layout.ty, .tcx
self.param_env, .struct_tail_erasing_lifetimes(receiver_place.layout.ty, self.param_env);
);
let ty::Dynamic(data, _, ty::Dyn) = receiver_tail.kind() else { let ty::Dynamic(data, _, ty::Dyn) = receiver_tail.kind() else {
span_bug!(self.cur_span(), "dynamic call on non-`dyn` type {}", receiver_tail) span_bug!(self.cur_span(), "dynamic call on non-`dyn` type {}", receiver_tail)
}; };
@ -628,7 +620,6 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
// is a by-val case; this works because by-val passing of an unsized `dyn // is a by-val case; this works because by-val passing of an unsized `dyn
// Trait` to a function is actually desugared to a pointer. // Trait` to a function is actually desugared to a pointer.
(vptr, dyn_ty, receiver_place.ptr) (vptr, dyn_ty, receiver_place.ptr)
}
}; };
// Now determine the actual method to call. We can do that in two different ways and // Now determine the actual method to call. We can do that in two different ways and