|
1 | 1 | use std::borrow::Cow;
|
2 | 2 |
|
3 | 3 | use either::Either;
|
| 4 | +use rustc_middle::ty::TyCtxt; |
4 | 5 | use tracing::trace;
|
5 | 6 |
|
6 | 7 | use rustc_middle::span_bug;
|
@@ -827,49 +828,47 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
827 | 828 | };
|
828 | 829 |
|
829 | 830 | // Obtain the underlying trait we are working on, and the adjusted receiver argument.
|
830 |
| - let (vptr, dyn_ty, adjusted_receiver) = if let ty::Dynamic(data, _, ty::DynStar) = |
831 |
| - receiver_place.layout.ty.kind() |
832 |
| - { |
833 |
| - let (recv, vptr) = self.unpack_dyn_star(&receiver_place, data)?; |
834 |
| - let (dyn_ty, _dyn_trait) = self.get_ptr_vtable(vptr)?; |
| 831 | + let (dyn_trait, dyn_ty, adjusted_receiver) = |
| 832 | + if let ty::Dynamic(data, _, ty::DynStar) = receiver_place.layout.ty.kind() { |
| 833 | + let recv = self.unpack_dyn_star(&receiver_place, data)?; |
| 834 | + |
| 835 | + (data.principal(), recv.layout.ty, recv.ptr()) |
| 836 | + } else { |
| 837 | + // Doesn't have to be a `dyn Trait`, but the unsized tail must be `dyn Trait`. |
| 838 | + // (For that reason we also cannot use `unpack_dyn_trait`.) |
| 839 | + let receiver_tail = self.tcx.struct_tail_erasing_lifetimes( |
| 840 | + receiver_place.layout.ty, |
| 841 | + self.param_env, |
| 842 | + ); |
| 843 | + let ty::Dynamic(receiver_trait, _, ty::Dyn) = receiver_tail.kind() else { |
| 844 | + span_bug!( |
| 845 | + self.cur_span(), |
| 846 | + "dynamic call on non-`dyn` type {}", |
| 847 | + receiver_tail |
| 848 | + ) |
| 849 | + }; |
| 850 | + assert!(receiver_place.layout.is_unsized()); |
835 | 851 |
|
836 |
| - (vptr, dyn_ty, recv.ptr()) |
837 |
| - } else { |
838 |
| - // Doesn't have to be a `dyn Trait`, but the unsized tail must be `dyn Trait`. |
839 |
| - // (For that reason we also cannot use `unpack_dyn_trait`.) |
840 |
| - let receiver_tail = self |
841 |
| - .tcx |
842 |
| - .struct_tail_erasing_lifetimes(receiver_place.layout.ty, self.param_env); |
843 |
| - let ty::Dynamic(data, _, ty::Dyn) = receiver_tail.kind() else { |
844 |
| - span_bug!( |
845 |
| - self.cur_span(), |
846 |
| - "dynamic call on non-`dyn` type {}", |
847 |
| - receiver_tail |
848 |
| - ) |
849 |
| - }; |
850 |
| - assert!(receiver_place.layout.is_unsized()); |
851 |
| - |
852 |
| - // Get the required information from the vtable. |
853 |
| - let vptr = receiver_place.meta().unwrap_meta().to_pointer(self)?; |
854 |
| - let (dyn_ty, dyn_trait) = self.get_ptr_vtable(vptr)?; |
855 |
| - if dyn_trait != data.principal() { |
856 |
| - throw_ub!(InvalidVTableTrait { |
857 |
| - expected_trait: data, |
858 |
| - vtable_trait: dyn_trait, |
859 |
| - }); |
860 |
| - } |
| 852 | + // Get the required information from the vtable. |
| 853 | + let vptr = receiver_place.meta().unwrap_meta().to_pointer(self)?; |
| 854 | + let dyn_ty = self.get_ptr_vtable_ty(vptr, Some(receiver_trait))?; |
861 | 855 |
|
862 |
| - // It might be surprising that we use a pointer as the receiver even if this |
863 |
| - // is a by-val case; this works because by-val passing of an unsized `dyn |
864 |
| - // Trait` to a function is actually desugared to a pointer. |
865 |
| - (vptr, dyn_ty, receiver_place.ptr()) |
866 |
| - }; |
| 856 | + // It might be surprising that we use a pointer as the receiver even if this |
| 857 | + // is a by-val case; this works because by-val passing of an unsized `dyn |
| 858 | + // Trait` to a function is actually desugared to a pointer. |
| 859 | + (receiver_trait.principal(), dyn_ty, receiver_place.ptr()) |
| 860 | + }; |
867 | 861 |
|
868 | 862 | // Now determine the actual method to call. We can do that in two different ways and
|
869 | 863 | // compare them to ensure everything fits.
|
870 |
| - let Some(ty::VtblEntry::Method(fn_inst)) = |
871 |
| - self.get_vtable_entries(vptr)?.get(idx).copied() |
872 |
| - else { |
| 864 | + let vtable_entries = if let Some(dyn_trait) = dyn_trait { |
| 865 | + let trait_ref = dyn_trait.with_self_ty(*self.tcx, dyn_ty); |
| 866 | + let trait_ref = self.tcx.erase_regions(trait_ref); |
| 867 | + self.tcx.vtable_entries(trait_ref) |
| 868 | + } else { |
| 869 | + TyCtxt::COMMON_VTABLE_ENTRIES |
| 870 | + }; |
| 871 | + let Some(ty::VtblEntry::Method(fn_inst)) = vtable_entries.get(idx).copied() else { |
873 | 872 | // FIXME(fee1-dead) these could be variants of the UB info enum instead of this
|
874 | 873 | throw_ub_custom!(fluent::const_eval_dyn_call_not_a_method);
|
875 | 874 | };
|
@@ -974,11 +973,11 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
974 | 973 | let place = match place.layout.ty.kind() {
|
975 | 974 | ty::Dynamic(data, _, ty::Dyn) => {
|
976 | 975 | // Dropping a trait object. Need to find actual drop fn.
|
977 |
| - self.unpack_dyn_trait(&place, data)?.0 |
| 976 | + self.unpack_dyn_trait(&place, data)? |
978 | 977 | }
|
979 | 978 | ty::Dynamic(data, _, ty::DynStar) => {
|
980 | 979 | // Dropping a `dyn*`. Need to find actual drop fn.
|
981 |
| - self.unpack_dyn_star(&place, data)?.0 |
| 980 | + self.unpack_dyn_star(&place, data)? |
982 | 981 | }
|
983 | 982 | _ => {
|
984 | 983 | debug_assert_eq!(
|
|
0 commit comments