about summary refs log tree commit diff
path: root/compiler/rustc_const_eval/src
diff options
context:
space:
mode:
authorOli Scherer <git-spam-no-reply9815368754983@oli-obk.de>2023-02-20 14:07:19 +0000
committerOli Scherer <git-spam-no-reply9815368754983@oli-obk.de>2023-02-20 14:11:38 +0000
commit472059d854c8c901321a8aa4d12e861bb064e437 (patch)
tree26d3081b1597092d6c58b0ec2728e725fbfb6cc5 /compiler/rustc_const_eval/src
parentad6dd60396d2a4e493e65ee5ba66562168d28cec (diff)
downloadrust-472059d854c8c901321a8aa4d12e861bb064e437.tar.gz
rust-472059d854c8c901321a8aa4d12e861bb064e437.zip
Deduplicate some logic between dyn* and dyn
Diffstat (limited to 'compiler/rustc_const_eval/src')
-rw-r--r--compiler/rustc_const_eval/src/interpret/terminator.rs83
1 files changed, 37 insertions, 46 deletions
diff --git a/compiler/rustc_const_eval/src/interpret/terminator.rs b/compiler/rustc_const_eval/src/interpret/terminator.rs
index 96b0aee7ffb..94ac3b6ebad 100644
--- a/compiler/rustc_const_eval/src/interpret/terminator.rs
+++ b/compiler/rustc_const_eval/src/interpret/terminator.rs
@@ -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.
                 let recv_ty = receiver.layout.ty;
-                let (vptr, dyn_ty, adjusted_receiver) = match recv_ty.kind() {
-                    ty::Ref(..) | ty::RawPtr(..)
-                        if matches!(
-                            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)
-                    }
+                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
                     ty::Dynamic(_, _, ty::DynStar) => {
                         // Not clear how to handle this, so far we assume the receiver is always a pointer.
                         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?"
                         );
                     }
-                    _ => {
-                        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`.
-                        // (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,
+                    _ => bug!(),
+                };
+                let (vptr, dyn_ty, adjusted_receiver) = if let ty::Dynamic(data, _, ty::DynStar) =
+                    receiver_place.layout.ty.kind()
+                {
+                    let (recv, vptr) = self.unpack_dyn_star(&receiver_place.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 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)
                         };
-                        assert!(receiver_place.layout.is_unsized());
-
-                        // Get the required information from the vtable.
-                        let vptr = receiver_place.meta.unwrap_meta().to_pointer(self)?;
-                        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"
-                            );
-                        }
+                    assert!(receiver_place.layout.is_unsized());
 
-                        // 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)
+                    // Get the required information from the vtable.
+                    let vptr = receiver_place.meta.unwrap_meta().to_pointer(self)?;
+                    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"
+                        );
                     }
+
+                    // 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