diff options
| author | Ralf Jung <post@ralfj.de> | 2022-07-17 16:02:49 -0400 |
|---|---|---|
| committer | Ralf Jung <post@ralfj.de> | 2022-07-20 17:12:04 -0400 |
| commit | fe00573324854e5681546b660bbbaf4e1ec38eb2 (patch) | |
| tree | 226774fcd3c885bc7cdafde8a5aa0425c762b651 /compiler/rustc_const_eval/src/interpret | |
| parent | a10d8e458118b3feac96fe5e56c25e70cee99b88 (diff) | |
| download | rust-fe00573324854e5681546b660bbbaf4e1ec38eb2.tar.gz rust-fe00573324854e5681546b660bbbaf4e1ec38eb2.zip | |
make use of symbolic vtables in interpreter
Diffstat (limited to 'compiler/rustc_const_eval/src/interpret')
| -rw-r--r-- | compiler/rustc_const_eval/src/interpret/cast.rs | 34 | ||||
| -rw-r--r-- | compiler/rustc_const_eval/src/interpret/eval_context.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_const_eval/src/interpret/memory.rs | 33 | ||||
| -rw-r--r-- | compiler/rustc_const_eval/src/interpret/place.rs | 15 | ||||
| -rw-r--r-- | compiler/rustc_const_eval/src/interpret/terminator.rs | 16 | ||||
| -rw-r--r-- | compiler/rustc_const_eval/src/interpret/traits.rs | 133 | ||||
| -rw-r--r-- | compiler/rustc_const_eval/src/interpret/validity.rs | 51 | ||||
| -rw-r--r-- | compiler/rustc_const_eval/src/interpret/visitor.rs | 2 |
8 files changed, 93 insertions, 193 deletions
diff --git a/compiler/rustc_const_eval/src/interpret/cast.rs b/compiler/rustc_const_eval/src/interpret/cast.rs index 2e6cbb131ef..473ba848a58 100644 --- a/compiler/rustc_const_eval/src/interpret/cast.rs +++ b/compiler/rustc_const_eval/src/interpret/cast.rs @@ -299,29 +299,35 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } (&ty::Dynamic(ref data_a, ..), &ty::Dynamic(ref data_b, ..)) => { let val = self.read_immediate(src)?; + let (old_data, old_vptr) = val.to_scalar_pair()?; + let old_vptr = self.scalar_to_ptr(old_vptr)?; if data_a.principal_def_id() == data_b.principal_def_id() { return self.write_immediate(*val, dest); } // trait upcasting coercion - let vptr_entry_idx = self.tcx.vtable_trait_upcasting_coercion_new_vptr_slot(( + let Some(vptr_entry_idx) = self.tcx.vtable_trait_upcasting_coercion_new_vptr_slot(( src_pointee_ty, dest_pointee_ty, - )); - - if let Some(entry_idx) = vptr_entry_idx { - let entry_idx = u64::try_from(entry_idx).unwrap(); - let (old_data, old_vptr) = val.to_scalar_pair()?; - let old_vptr = self.scalar_to_ptr(old_vptr)?; - let new_vptr = self - .read_new_vtable_after_trait_upcasting_from_vtable(old_vptr, entry_idx)?; - self.write_immediate(Immediate::new_dyn_trait(old_data, new_vptr, self), dest) - } else { - self.write_immediate(*val, dest) - } + )) else { + return self.write_immediate(*val, dest); + }; + + let (ty, _) = self.get_ptr_vtable(old_vptr)?; + let Some(ty::VtblEntry::TraitVPtr(new_trait)) = self.get_vtable_entries(old_vptr)?.get(vptr_entry_idx) else { + throw_ub_format!( + "upcasting to index {vptr_entry_idx} of vtable {old_vptr} but \ + that vtable is too small or does not have an upcast-vtable at that index" + ) + }; + let new_trait = new_trait.map_bound(|trait_ref| { + ty::ExistentialTraitRef::erase_self_ty(*self.tcx, trait_ref) + }); + let new_vptr = self.get_vtable_ptr(ty, Some(new_trait))?; + self.write_immediate(Immediate::new_dyn_trait(old_data, new_vptr, self), dest) } (_, &ty::Dynamic(ref data, _)) => { // Initial cast from sized to dyn trait - let vtable = self.get_vtable(src_pointee_ty, data.principal())?; + let vtable = self.get_vtable_ptr(src_pointee_ty, data.principal())?; let ptr = self.read_immediate(src)?.to_scalar()?; let val = Immediate::new_dyn_trait(ptr, vtable, &*self.tcx); self.write_immediate(val, dest) diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs index 45928d7b02e..fdf243c4108 100644 --- a/compiler/rustc_const_eval/src/interpret/eval_context.rs +++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs @@ -631,7 +631,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { ty::Dynamic(..) => { let vtable = self.scalar_to_ptr(metadata.unwrap_meta())?; // Read size and align from vtable (already checks size). - Ok(Some(self.read_size_and_align_from_vtable(vtable)?)) + Ok(Some(self.get_vtable_size_and_align(vtable)?)) } ty::Slice(_) | ty::Str => { diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs index 0287c180e94..5e49e6a4f08 100644 --- a/compiler/rustc_const_eval/src/interpret/memory.rs +++ b/compiler/rustc_const_eval/src/interpret/memory.rs @@ -16,7 +16,7 @@ use std::ptr; use rustc_ast::Mutability; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_middle::mir::display_allocation; -use rustc_middle::ty::{Instance, ParamEnv, TyCtxt}; +use rustc_middle::ty::{self, Instance, ParamEnv, Ty, TyCtxt}; use rustc_target::abi::{Align, HasDataLayout, Size}; use super::{ @@ -500,6 +500,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // contains a reference to memory that was created during its evaluation (i.e., not // to another static), those inner references only exist in "resolved" form. if self.tcx.is_foreign_item(def_id) { + // This is unreachable in Miri, but can happen in CTFE where we actually *do* support + // referencing arbitrary (declared) extern statics. throw_unsup!(ReadExternStatic(def_id)); } @@ -670,11 +672,13 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // Can't do this in the match argument, we may get cycle errors since the lock would // be held throughout the match. match self.tcx.try_get_global_alloc(id) { - Some(GlobalAlloc::Static(did)) => { - assert!(!self.tcx.is_thread_local_static(did)); + Some(GlobalAlloc::Static(def_id)) => { + assert!(self.tcx.is_static(def_id)); + assert!(!self.tcx.is_thread_local_static(def_id)); // Use size and align of the type. - let ty = self.tcx.type_of(did); + let ty = self.tcx.type_of(def_id); let layout = self.tcx.layout_of(ParamEnv::empty().and(ty)).unwrap(); + assert!(!layout.is_unsized()); (layout.size, layout.align.abi, AllocKind::LiveData) } Some(GlobalAlloc::Memory(alloc)) => { @@ -685,8 +689,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } Some(GlobalAlloc::Function(_)) => bug!("We already checked function pointers above"), Some(GlobalAlloc::Vtable(..)) => { - // No data to be accessed here. - return (Size::ZERO, Align::ONE, AllocKind::Vtable); + // No data to be accessed here. But vtables are pointer-aligned. + return (Size::ZERO, self.tcx.data_layout.pointer_align.abi, AllocKind::Vtable); } // The rest must be dead. None => { @@ -726,7 +730,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { &self, ptr: Pointer<Option<M::Provenance>>, ) -> InterpResult<'tcx, FnVal<'tcx, M::ExtraFnVal>> { - trace!("get_fn({:?})", ptr); + trace!("get_ptr_fn({:?})", ptr); let (alloc_id, offset, _prov) = self.ptr_get_alloc_id(ptr)?; if offset.bytes() != 0 { throw_ub!(InvalidFunctionPointer(Pointer::new(alloc_id, offset))) @@ -735,6 +739,21 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { .ok_or_else(|| err_ub!(InvalidFunctionPointer(Pointer::new(alloc_id, offset))).into()) } + pub fn get_ptr_vtable( + &self, + ptr: Pointer<Option<M::Provenance>>, + ) -> InterpResult<'tcx, (Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>)> { + trace!("get_ptr_vtable({:?})", ptr); + let (alloc_id, offset, _tag) = self.ptr_get_alloc_id(ptr)?; + if offset.bytes() != 0 { + throw_ub!(InvalidVtablePointer(Pointer::new(alloc_id, offset))) + } + match self.tcx.try_get_global_alloc(alloc_id) { + Some(GlobalAlloc::Vtable(ty, trait_ref)) => Ok((ty, trait_ref)), + _ => throw_ub!(InvalidVtablePointer(Pointer::new(alloc_id, offset))), + } + } + pub fn alloc_mark_immutable(&mut self, id: AllocId) -> InterpResult<'tcx> { self.get_alloc_raw_mut(id)?.0.mutability = Mutability::Not; Ok(()) diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs index 4a45d979a79..c7d8a744f7c 100644 --- a/compiler/rustc_const_eval/src/interpret/place.rs +++ b/compiler/rustc_const_eval/src/interpret/place.rs @@ -885,28 +885,19 @@ where } /// Turn a place with a `dyn Trait` type into a place with the actual dynamic type. - /// Also return some more information so drop doesn't have to run the same code twice. pub(super) fn unpack_dyn_trait( &self, mplace: &MPlaceTy<'tcx, M::Provenance>, - ) -> InterpResult<'tcx, (ty::Instance<'tcx>, MPlaceTy<'tcx, M::Provenance>)> { + ) -> InterpResult<'tcx, MPlaceTy<'tcx, M::Provenance>> { let vtable = self.scalar_to_ptr(mplace.vtable())?; // also sanity checks the type - let (instance, ty) = self.read_drop_type_from_vtable(vtable)?; + let (ty, _) = self.get_ptr_vtable(vtable)?; let layout = self.layout_of(ty)?; - // More sanity checks - if cfg!(debug_assertions) { - let (size, align) = self.read_size_and_align_from_vtable(vtable)?; - assert_eq!(size, layout.size); - // only ABI alignment is preserved - assert_eq!(align, layout.align.abi); - } - let mplace = MPlaceTy { mplace: MemPlace { meta: MemPlaceMeta::None, ..**mplace }, layout, align: layout.align.abi, }; - Ok((instance, mplace)) + Ok(mplace) } } diff --git a/compiler/rustc_const_eval/src/interpret/terminator.rs b/compiler/rustc_const_eval/src/interpret/terminator.rs index 279ecef08c6..2ae0e1a6f5a 100644 --- a/compiler/rustc_const_eval/src/interpret/terminator.rs +++ b/compiler/rustc_const_eval/src/interpret/terminator.rs @@ -1,5 +1,4 @@ use std::borrow::Cow; -use std::convert::TryFrom; use rustc_middle::ty::layout::{FnAbiOf, LayoutOf}; use rustc_middle::ty::Instance; @@ -563,7 +562,12 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { ty::Dynamic(..) )); let vtable = self.scalar_to_ptr(receiver_place.meta.unwrap_meta())?; - let fn_val = self.get_vtable_slot(vtable, u64::try_from(idx).unwrap())?; + let Some(ty::VtblEntry::Method(fn_inst)) = self.get_vtable_entries(vtable)?.get(idx).copied() else { + throw_ub_format!( + "calling index {idx} of vtable {vtable} but \ + that vtable is too small or does not have a method at that index" + ) + }; // `*mut receiver_place.layout.ty` is almost the layout that we // want for args[0]: We have to project to field 0 because we want @@ -579,7 +583,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { trace!("Patched receiver operand to {:#?}", args[0]); // recurse with concrete function self.eval_fn_call( - fn_val, + FnVal::Instance(fn_inst), (caller_abi, caller_fn_abi), &args, with_caller_location, @@ -606,8 +610,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let (instance, place) = match place.layout.ty.kind() { ty::Dynamic(..) => { - // Dropping a trait object. - self.unpack_dyn_trait(&place)? + // Dropping a trait object. Need to find actual drop fn. + let place = self.unpack_dyn_trait(&place)?; + let instance = ty::Instance::resolve_drop_in_place(*self.tcx, place.layout.ty); + (instance, place) } _ => (instance, place), }; diff --git a/compiler/rustc_const_eval/src/interpret/traits.rs b/compiler/rustc_const_eval/src/interpret/traits.rs index e4052b61782..bddca2a20ed 100644 --- a/compiler/rustc_const_eval/src/interpret/traits.rs +++ b/compiler/rustc_const_eval/src/interpret/traits.rs @@ -1,14 +1,10 @@ -use std::convert::TryFrom; - -use rustc_middle::mir::interpret::{alloc_range, InterpResult, Pointer, PointerArithmetic}; -use rustc_middle::ty::{ - self, Ty, TyCtxt, COMMON_VTABLE_ENTRIES_ALIGN, COMMON_VTABLE_ENTRIES_DROPINPLACE, - COMMON_VTABLE_ENTRIES_SIZE, -}; +use rustc_middle::mir::interpret::{InterpResult, Pointer}; +use rustc_middle::ty::layout::LayoutOf; +use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_target::abi::{Align, Size}; use super::util::ensure_monomorphic_enough; -use super::{FnVal, InterpCx, Machine}; +use super::{InterpCx, Machine}; impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { /// Creates a dynamic vtable for the given type and vtable origin. This is used only for @@ -17,8 +13,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { /// The `trait_ref` encodes the erased self type. Hence, if we are /// making an object `Foo<Trait>` from a value of type `Foo<T>`, then /// `trait_ref` would map `T: Trait`. - pub fn get_vtable( - &mut self, + pub fn get_vtable_ptr( + &self, ty: Ty<'tcx>, poly_trait_ref: Option<ty::PolyExistentialTraitRef<'tcx>>, ) -> InterpResult<'tcx, Pointer<Option<M::Provenance>>> { @@ -30,114 +26,33 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { ensure_monomorphic_enough(*self.tcx, ty)?; ensure_monomorphic_enough(*self.tcx, poly_trait_ref)?; - let vtable_allocation = self.tcx.vtable_allocation((ty, poly_trait_ref)); - - let vtable_ptr = self.global_base_pointer(Pointer::from(vtable_allocation))?; - + let vtable_symbolic_allocation = self.tcx.create_vtable_alloc(ty, poly_trait_ref); + let vtable_ptr = self.global_base_pointer(Pointer::from(vtable_symbolic_allocation))?; Ok(vtable_ptr.into()) } - /// Resolves the function at the specified slot in the provided - /// vtable. Currently an index of '3' (`TyCtxt::COMMON_VTABLE_ENTRIES.len()`) - /// corresponds to the first method declared in the trait of the provided vtable. - pub fn get_vtable_slot( + /// Returns a high-level representation of the entires of the given vtable. + pub fn get_vtable_entries( &self, vtable: Pointer<Option<M::Provenance>>, - idx: u64, - ) -> InterpResult<'tcx, FnVal<'tcx, M::ExtraFnVal>> { - let ptr_size = self.pointer_size(); - let vtable_slot = vtable.offset(ptr_size * idx, self)?; - let vtable_slot = self - .get_ptr_alloc(vtable_slot, ptr_size, self.tcx.data_layout.pointer_align.abi)? - .expect("cannot be a ZST"); - let fn_ptr = self.scalar_to_ptr(vtable_slot.read_pointer(Size::ZERO)?.check_init()?)?; - self.get_ptr_fn(fn_ptr) + ) -> InterpResult<'tcx, &'tcx [ty::VtblEntry<'tcx>]> { + let (ty, poly_trait_ref) = self.get_ptr_vtable(vtable)?; + Ok(if let Some(poly_trait_ref) = poly_trait_ref { + let trait_ref = poly_trait_ref.with_self_ty(*self.tcx, ty); + let trait_ref = self.tcx.erase_regions(trait_ref); + self.tcx.vtable_entries(trait_ref) + } else { + TyCtxt::COMMON_VTABLE_ENTRIES + }) } - /// Returns the drop fn instance as well as the actual dynamic type. - pub fn read_drop_type_from_vtable( - &self, - vtable: Pointer<Option<M::Provenance>>, - ) -> InterpResult<'tcx, (ty::Instance<'tcx>, Ty<'tcx>)> { - let pointer_size = self.pointer_size(); - // We don't care about the pointee type; we just want a pointer. - let vtable = self - .get_ptr_alloc( - vtable, - pointer_size * u64::try_from(TyCtxt::COMMON_VTABLE_ENTRIES.len()).unwrap(), - self.tcx.data_layout.pointer_align.abi, - )? - .expect("cannot be a ZST"); - let drop_fn = vtable - .read_pointer(pointer_size * u64::try_from(COMMON_VTABLE_ENTRIES_DROPINPLACE).unwrap())? - .check_init()?; - // We *need* an instance here, no other kind of function value, to be able - // to determine the type. - let drop_instance = self.get_ptr_fn(self.scalar_to_ptr(drop_fn)?)?.as_instance()?; - trace!("Found drop fn: {:?}", drop_instance); - let fn_sig = drop_instance.ty(*self.tcx, self.param_env).fn_sig(*self.tcx); - let fn_sig = self.tcx.normalize_erasing_late_bound_regions(self.param_env, fn_sig); - // The drop function takes `*mut T` where `T` is the type being dropped, so get that. - let args = fn_sig.inputs(); - if args.len() != 1 { - throw_ub!(InvalidVtableDropFn(fn_sig)); - } - let ty = - args[0].builtin_deref(true).ok_or_else(|| err_ub!(InvalidVtableDropFn(fn_sig)))?.ty; - Ok((drop_instance, ty)) - } - - pub fn read_size_and_align_from_vtable( + pub fn get_vtable_size_and_align( &self, vtable: Pointer<Option<M::Provenance>>, ) -> InterpResult<'tcx, (Size, Align)> { - let pointer_size = self.pointer_size(); - // We check for `size = 3 * ptr_size`, which covers the drop fn (unused here), - // the size, and the align (which we read below). - let vtable = self - .get_ptr_alloc( - vtable, - pointer_size * u64::try_from(TyCtxt::COMMON_VTABLE_ENTRIES.len()).unwrap(), - self.tcx.data_layout.pointer_align.abi, - )? - .expect("cannot be a ZST"); - let size = vtable - .read_integer(alloc_range( - pointer_size * u64::try_from(COMMON_VTABLE_ENTRIES_SIZE).unwrap(), - pointer_size, - ))? - .check_init()?; - let size = size.to_machine_usize(self)?; - let size = Size::from_bytes(size); - let align = vtable - .read_integer(alloc_range( - pointer_size * u64::try_from(COMMON_VTABLE_ENTRIES_ALIGN).unwrap(), - pointer_size, - ))? - .check_init()?; - let align = align.to_machine_usize(self)?; - let align = Align::from_bytes(align).map_err(|e| err_ub!(InvalidVtableAlignment(e)))?; - - if size > self.max_size_of_val() { - throw_ub!(InvalidVtableSize); - } - Ok((size, align)) - } - - pub fn read_new_vtable_after_trait_upcasting_from_vtable( - &self, - vtable: Pointer<Option<M::Provenance>>, - idx: u64, - ) -> InterpResult<'tcx, Pointer<Option<M::Provenance>>> { - let pointer_size = self.pointer_size(); - - let vtable_slot = vtable.offset(pointer_size * idx, self)?; - let new_vtable = self - .get_ptr_alloc(vtable_slot, pointer_size, self.tcx.data_layout.pointer_align.abi)? - .expect("cannot be a ZST"); - - let new_vtable = self.scalar_to_ptr(new_vtable.read_pointer(Size::ZERO)?.check_init()?)?; - - Ok(new_vtable) + let (ty, _trait_ref) = self.get_ptr_vtable(vtable)?; + let layout = self.layout_of(ty)?; + assert!(!layout.is_unsized(), "there are no vtables for unsized types"); + Ok((layout.size, layout.align.abi)) } } diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs index 569af01c485..190eb732f9a 100644 --- a/compiler/rustc_const_eval/src/interpret/validity.rs +++ b/compiler/rustc_const_eval/src/interpret/validity.rs @@ -313,50 +313,15 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, ' match tail.kind() { ty::Dynamic(..) => { let vtable = self.ecx.scalar_to_ptr(meta.unwrap_meta())?; - // Direct call to `check_ptr_access_align` checks alignment even on CTFE machines. - try_validation!( - self.ecx.check_ptr_access_align( - vtable, - 3 * self.ecx.tcx.data_layout.pointer_size, // drop, size, align - self.ecx.tcx.data_layout.pointer_align.abi, - CheckInAllocMsg::InboundsTest, // will anyway be replaced by validity message - ), - self.path, - err_ub!(DanglingIntPointer(..)) | - err_ub!(PointerUseAfterFree(..)) => - { "dangling vtable pointer in wide pointer" }, - err_ub!(AlignmentCheckFailed { .. }) => - { "unaligned vtable pointer in wide pointer" }, - err_ub!(PointerOutOfBounds { .. }) => - { "too small vtable" }, - ); - try_validation!( - self.ecx.read_drop_type_from_vtable(vtable), + // Make sure it is a genuine vtable pointer. + let (_ty, _trait) = try_validation!( + self.ecx.get_ptr_vtable(vtable), self.path, err_ub!(DanglingIntPointer(..)) | - err_ub!(InvalidFunctionPointer(..)) => - { "invalid drop function pointer in vtable (not pointing to a function)" }, - err_ub!(InvalidVtableDropFn(..)) => - { "invalid drop function pointer in vtable (function has incompatible signature)" }, - // Stacked Borrows errors can happen here, see https://github.com/rust-lang/miri/issues/2123. - // (We assume there are no other MachineStop errors possible here.) - InterpError::MachineStop(_) => - { "vtable pointer does not have permission to read drop function pointer" }, - ); - try_validation!( - self.ecx.read_size_and_align_from_vtable(vtable), - self.path, - err_ub!(InvalidVtableSize) => - { "invalid vtable: size is bigger than largest supported object" }, - err_ub!(InvalidVtableAlignment(msg)) => - { "invalid vtable: alignment {}", msg }, - err_unsup!(ReadPointerAsBytes) => { "invalid size or align in vtable" }, - // Stacked Borrows errors can happen here, see https://github.com/rust-lang/miri/issues/2123. - // (We assume there are no other MachineStop errors possible here.) - InterpError::MachineStop(_) => - { "vtable pointer does not have permission to read size and alignment" }, + err_ub!(InvalidVtablePointer(..)) => + { "{vtable}" } expected { "a vtable pointer" }, ); - // FIXME: More checks for the vtable. + // FIXME: check if the type/trait match what ty::Dynamic says? } ty::Slice(..) | ty::Str => { let _len = try_validation!( @@ -607,11 +572,9 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, ' let _fn = try_validation!( self.ecx.get_ptr_fn(ptr), self.path, - err_ub!(DanglingIntPointer(0, _)) => - { "a null function pointer" }, err_ub!(DanglingIntPointer(..)) | err_ub!(InvalidFunctionPointer(..)) => - { "{:x}", value } expected { "a function pointer" }, + { "{ptr}" } expected { "a function pointer" }, ); // FIXME: Check if the signature matches } else { diff --git a/compiler/rustc_const_eval/src/interpret/visitor.rs b/compiler/rustc_const_eval/src/interpret/visitor.rs index 24228feb73e..aee1f93b1a3 100644 --- a/compiler/rustc_const_eval/src/interpret/visitor.rs +++ b/compiler/rustc_const_eval/src/interpret/visitor.rs @@ -425,7 +425,7 @@ macro_rules! make_value_visitor { // unsized values are never immediate, so we can assert_mem_place let op = v.to_op_for_read(self.ecx())?; let dest = op.assert_mem_place(); - let inner_mplace = self.ecx().unpack_dyn_trait(&dest)?.1; + let inner_mplace = self.ecx().unpack_dyn_trait(&dest)?; trace!("walk_value: dyn object layout: {:#?}", inner_mplace.layout); // recurse with the inner type return self.visit_field(&v, 0, &$value_trait::from_op(&inner_mplace.into())); |
