mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-26 08:44:35 +00:00
Deduplicate some logic between dyn* and dyn
This commit is contained in:
parent
ad6dd60396
commit
472059d854
@ -571,26 +571,9 @@ 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)
|
|
||||||
) =>
|
|
||||||
{
|
|
||||||
let receiver = self.deref_operand(&receiver)?;
|
|
||||||
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)?;
|
|
||||||
if dyn_trait != data.principal() {
|
|
||||||
throw_ub_format!(
|
|
||||||
"`dyn*` call on a pointer whose vtable does not match its type"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
ty::Dynamic(_, _, ty::DynStar) => {
|
ty::Dynamic(_, _, ty::DynStar) => {
|
||||||
// Not clear how to handle this, so far we assume the receiver is always a pointer.
|
// Not clear how to handle this, so far we assume the receiver is always a pointer.
|
||||||
span_bug!(
|
span_bug!(
|
||||||
@ -598,37 +581,45 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||||||
"by-value calls on a `dyn*`... are those a thing?"
|
"by-value calls on a `dyn*`... are those a thing?"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
_ => {
|
_ => bug!(),
|
||||||
let receiver_place = match recv_ty.kind() {
|
};
|
||||||
ty::Ref(..) | ty::RawPtr(..) => self.deref_operand(&receiver)?,
|
let (vptr, dyn_ty, adjusted_receiver) = if let ty::Dynamic(data, _, ty::DynStar) =
|
||||||
ty::Dynamic(_, _, ty::Dyn) => receiver.assert_mem_place(), // unsized (`dyn`) cannot be immediate
|
receiver_place.layout.ty.kind()
|
||||||
_ => bug!(),
|
{
|
||||||
};
|
let (recv, vptr) = self.unpack_dyn_star(&receiver_place.into())?;
|
||||||
// Doesn't have to be a `dyn Trait`, but the unsized tail must be `dyn Trait`.
|
let (dyn_ty, dyn_trait) = self.get_ptr_vtable(vptr)?;
|
||||||
// (For that reason we also cannot use `unpack_dyn_trait`.)
|
if dyn_trait != data.principal() {
|
||||||
let receiver_tail = self.tcx.struct_tail_erasing_lifetimes(
|
throw_ub_format!(
|
||||||
receiver_place.layout.ty,
|
"`dyn*` call on a pointer whose vtable does not match its type"
|
||||||
self.param_env,
|
|
||||||
);
|
);
|
||||||
let ty::Dynamic(data, _, ty::Dyn) = receiver_tail.kind() else {
|
}
|
||||||
|
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)
|
||||||
|
} else {
|
||||||
|
// 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`.)
|
||||||
|
let receiver_tail = self
|
||||||
|
.tcx
|
||||||
|
.struct_tail_erasing_lifetimes(receiver_place.layout.ty, self.param_env);
|
||||||
|
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)
|
||||||
};
|
};
|
||||||
assert!(receiver_place.layout.is_unsized());
|
assert!(receiver_place.layout.is_unsized());
|
||||||
|
|
||||||
// Get the required information from the vtable.
|
// Get the required information from the vtable.
|
||||||
let vptr = receiver_place.meta.unwrap_meta().to_pointer(self)?;
|
let vptr = receiver_place.meta.unwrap_meta().to_pointer(self)?;
|
||||||
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!(
|
||||||
"`dyn` call on a pointer whose vtable does not match its type"
|
"`dyn` call on a pointer whose vtable does not match its type"
|
||||||
);
|
);
|
||||||
}
|
|
||||||
|
|
||||||
// It might be surprising that we use a pointer as the receiver even if this
|
|
||||||
// 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.
|
|
||||||
(vptr, dyn_ty, receiver_place.ptr)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// It might be surprising that we use a pointer as the receiver even if this
|
||||||
|
// 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.
|
||||||
|
(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
|
||||||
|
Loading…
Reference in New Issue
Block a user