]> git.lizzy.rs Git - rust.git/commitdiff
make use of symbolic vtables in interpreter
authorRalf Jung <post@ralfj.de>
Sun, 17 Jul 2022 20:02:49 +0000 (16:02 -0400)
committerRalf Jung <post@ralfj.de>
Wed, 20 Jul 2022 21:12:04 +0000 (17:12 -0400)
23 files changed:
compiler/rustc_const_eval/src/interpret/cast.rs
compiler/rustc_const_eval/src/interpret/eval_context.rs
compiler/rustc_const_eval/src/interpret/memory.rs
compiler/rustc_const_eval/src/interpret/place.rs
compiler/rustc_const_eval/src/interpret/terminator.rs
compiler/rustc_const_eval/src/interpret/traits.rs
compiler/rustc_const_eval/src/interpret/validity.rs
compiler/rustc_const_eval/src/interpret/visitor.rs
compiler/rustc_middle/src/mir/interpret/error.rs
src/test/ui/consts/const-eval/const_transmute.rs [deleted file]
src/test/ui/consts/const-eval/ub-incorrect-vtable.32bit.stderr
src/test/ui/consts/const-eval/ub-incorrect-vtable.64bit.stderr
src/test/ui/consts/const-eval/ub-incorrect-vtable.rs
src/test/ui/consts/const-eval/ub-ref-ptr.32bit.stderr
src/test/ui/consts/const-eval/ub-ref-ptr.64bit.stderr
src/test/ui/consts/const-eval/ub-upvars.32bit.stderr
src/test/ui/consts/const-eval/ub-upvars.64bit.stderr
src/test/ui/consts/const-eval/ub-wide-ptr.32bit.stderr
src/test/ui/consts/const-eval/ub-wide-ptr.64bit.stderr
src/test/ui/consts/const-eval/ub-wide-ptr.rs
src/test/ui/consts/issue-79690.64bit.stderr
src/test/ui/consts/miri_unleashed/mutable_references_err.32bit.stderr
src/test/ui/consts/miri_unleashed/mutable_references_err.64bit.stderr

index 2e6cbb131ef3c1689411e4fe31053a561c5abab4..473ba848a58300112f540faffdedf2bc8fcc8f48 100644 (file)
@@ -299,29 +299,35 @@ fn unsize_into_ptr(
             }
             (&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)
index 45928d7b02e36d6d5dc517cd93e959c53995381b..fdf243c4108d31bb4afa0329428a27444bff8e37 100644 (file)
@@ -631,7 +631,7 @@ pub(super) fn size_and_align_of(
             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 => {
index 0287c180e94b603d3622cbd5c3e69f44d6c8e3cd..5e49e6a4f084514749e59bac370f314e171e942a 100644 (file)
@@ -16,7 +16,7 @@
 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 @@ fn get_global_alloc(
                 // 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 @@ pub fn get_alloc_info(&self, id: AllocId) -> (Size, Align, AllocKind) {
         // 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 @@ pub fn get_alloc_info(&self, id: AllocId) -> (Size, Align, AllocKind) {
             }
             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 @@ pub fn get_ptr_fn(
         &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 @@ pub fn get_ptr_fn(
             .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(())
index 4a45d979a79a2d207320580e0786797e0fe49940..c7d8a744f7c09878c158e254a9a25d777ee25582 100644 (file)
@@ -885,28 +885,19 @@ pub fn raw_const_to_mplace(
     }
 
     /// 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)
     }
 }
index 279ecef08c6502192f06478d57f62eab911ff074..2ae0e1a6f5ac78aa5d76f351868db028995512b8 100644 (file)
@@ -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 @@ pub(crate) fn eval_fn_call(
                     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 @@ pub(crate) fn eval_fn_call(
                 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 @@ fn drop_in_place(
 
         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),
         };
index e4052b61782746961a82f33b0ce680fb2e21e31f..bddca2a20edecd55fd218190f372162f14bfe4cf 100644 (file)
@@ -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 @@ pub fn get_vtable(
         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))
     }
 }
index 569af01c4853ad2413dc655e17e5d4c80ad2239e..190eb732f9ad32e6c32c550eda3eea3a7b0777e8 100644 (file)
@@ -313,50 +313,15 @@ fn check_wide_ptr_meta(
         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 @@ fn try_visit_primitive(
                     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 {
index 24228feb73e7db7d384be3fabf79d190e91093d0..aee1f93b1a39cc65e2eef83fde163d0650ac3827 100644 (file)
@@ -425,7 +425,7 @@ fn walk_value(&mut self, v: &Self::V) -> InterpResult<'tcx>
                         // 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()));
index 68559ae2249fb2c2e36713ff5ec5c7171e66a171..81d9db98478f928d91e27dcd1cec51786fde139a 100644 (file)
@@ -1,7 +1,7 @@
 use super::{AllocId, AllocRange, ConstAlloc, Pointer, Scalar};
 
 use crate::mir::interpret::ConstValue;
-use crate::ty::{layout, query::TyCtxtAt, tls, FnSig, Ty, ValTree};
+use crate::ty::{layout, query::TyCtxtAt, tls, Ty, ValTree};
 
 use rustc_data_structures::sync::Lock;
 use rustc_errors::{pluralize, struct_span_err, DiagnosticBuilder, ErrorGuaranteed};
@@ -219,7 +219,7 @@ pub struct ScalarSizeMismatch {
 }
 
 /// Error information for when the program caused Undefined Behavior.
-pub enum UndefinedBehaviorInfo<'tcx> {
+pub enum UndefinedBehaviorInfo {
     /// Free-form case. Only for errors that are never caught!
     Ub(String),
     /// Unreachable code was executed.
@@ -241,12 +241,6 @@ pub enum UndefinedBehaviorInfo<'tcx> {
     PointerArithOverflow,
     /// Invalid metadata in a wide pointer (using `str` to avoid allocations).
     InvalidMeta(&'static str),
-    /// Invalid drop function in vtable.
-    InvalidVtableDropFn(FnSig<'tcx>),
-    /// Invalid size in a vtable: too large.
-    InvalidVtableSize,
-    /// Invalid alignment in a vtable: too large, or not a power of 2.
-    InvalidVtableAlignment(String),
     /// Reading a C string that does not end within its allocation.
     UnterminatedCString(Pointer),
     /// Dereferencing a dangling pointer after it got freed.
@@ -290,6 +284,8 @@ pub enum UndefinedBehaviorInfo<'tcx> {
     InvalidTag(Scalar),
     /// Using a pointer-not-to-a-function as function pointer.
     InvalidFunctionPointer(Pointer),
+    /// Using a pointer-not-to-a-vtable as vtable pointer.
+    InvalidVtablePointer(Pointer),
     /// Using a string that is not valid UTF-8,
     InvalidStr(std::str::Utf8Error),
     /// Using uninitialized data where it is not allowed.
@@ -302,7 +298,7 @@ pub enum UndefinedBehaviorInfo<'tcx> {
     UninhabitedEnumVariantWritten,
 }
 
-impl fmt::Display for UndefinedBehaviorInfo<'_> {
+impl fmt::Display for UndefinedBehaviorInfo {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         use UndefinedBehaviorInfo::*;
         match self {
@@ -317,14 +313,6 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
             RemainderOverflow => write!(f, "overflow in signed remainder (dividing MIN by -1)"),
             PointerArithOverflow => write!(f, "overflowing in-bounds pointer arithmetic"),
             InvalidMeta(msg) => write!(f, "invalid metadata in wide pointer: {msg}"),
-            InvalidVtableDropFn(sig) => write!(
-                f,
-                "invalid drop function signature: got {sig}, expected exactly one argument which must be a pointer type",
-            ),
-            InvalidVtableSize => {
-                write!(f, "invalid vtable: size is bigger than largest supported object")
-            }
-            InvalidVtableAlignment(msg) => write!(f, "invalid vtable: alignment {msg}"),
             UnterminatedCString(p) => write!(
                 f,
                 "reading a null-terminated string starting at {p:?} with no null found before end of allocation",
@@ -378,6 +366,9 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
             InvalidFunctionPointer(p) => {
                 write!(f, "using {p:?} as function pointer but it does not point to a function")
             }
+            InvalidVtablePointer(p) => {
+                write!(f, "using {p:?} as vtable pointer but it does not point to a vtable")
+            }
             InvalidStr(err) => write!(f, "this string is not valid UTF-8: {err}"),
             InvalidUninitBytes(Some((alloc, info))) => write!(
                 f,
@@ -497,7 +488,7 @@ pub fn downcast_ref<T: Any>(&self) -> Option<&T> {
 
 pub enum InterpError<'tcx> {
     /// The program caused undefined behavior.
-    UndefinedBehavior(UndefinedBehaviorInfo<'tcx>),
+    UndefinedBehavior(UndefinedBehaviorInfo),
     /// The program did something the interpreter does not support (some of these *might* be UB
     /// but the interpreter is not sure).
     Unsupported(UnsupportedOpInfo),
diff --git a/src/test/ui/consts/const-eval/const_transmute.rs b/src/test/ui/consts/const-eval/const_transmute.rs
deleted file mode 100644 (file)
index 90a454c..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-// run-pass
-
-#![allow(dead_code)]
-
-#[repr(C)]
-union Transmute<T: Copy, U: Copy> {
-    t: T,
-    u: U,
-}
-
-trait Bar {
-    fn bar(&self) -> u32;
-}
-
-struct Foo {
-    foo: u32,
-    bar: bool,
-}
-
-impl Bar for Foo {
-    fn bar(&self) -> u32 {
-        self.foo
-    }
-}
-
-impl Drop for Foo {
-    fn drop(&mut self) {
-        assert!(!self.bar);
-        self.bar = true;
-        println!("dropping Foo");
-    }
-}
-
-#[derive(Copy, Clone)]
-struct Fat<'a>(&'a Foo, &'static VTable);
-
-struct VTable {
-    drop: Option<for<'a> fn(&'a mut Foo)>,
-    size: usize,
-    align: usize,
-    bar: for<'a> fn(&'a Foo) -> u32,
-}
-
-const FOO: &dyn Bar = &Foo { foo: 128, bar: false };
-const G: Fat = unsafe { Transmute { t: FOO }.u };
-const F: Option<for<'a> fn(&'a mut Foo)> = G.1.drop;
-const H: for<'a> fn(&'a Foo) -> u32 = G.1.bar;
-
-fn main() {
-    let mut foo = Foo { foo: 99, bar: false };
-    (F.unwrap())(&mut foo);
-    std::mem::forget(foo); // already ran the drop impl
-    assert_eq!(H(&Foo { foo: 42, bar: false }), 42);
-}
index c6422447a4b79b88519efce3a0883a7aec7b7cb2..965256de21a0f4159ef66dd00635e42630d74fea 100644 (file)
@@ -2,19 +2,19 @@ error[E0080]: evaluation of constant value failed
   --> $DIR/ub-incorrect-vtable.rs:19:14
    |
 LL |     unsafe { std::mem::transmute((&92u8, &[0usize, 1usize, 1000usize])) };
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid vtable: alignment `1000` is not a power of 2
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using allocN as vtable pointer but it does not point to a vtable
 
 error[E0080]: evaluation of constant value failed
   --> $DIR/ub-incorrect-vtable.rs:24:14
    |
 LL |     unsafe { std::mem::transmute((&92u8, &[1usize, usize::MAX, 1usize])) };
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid vtable: size is bigger than largest supported object
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using allocN as vtable pointer but it does not point to a vtable
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-incorrect-vtable.rs:34:1
+  --> $DIR/ub-incorrect-vtable.rs:33:1
    |
 LL | const INVALID_VTABLE_ALIGNMENT_UB: W<&dyn Trait> =
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered invalid vtable: alignment `1000` is not a power of 2
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered allocN, but expected a vtable pointer
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 4) {
@@ -22,16 +22,38 @@ LL | const INVALID_VTABLE_ALIGNMENT_UB: W<&dyn Trait> =
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-incorrect-vtable.rs:39:1
+  --> $DIR/ub-incorrect-vtable.rs:38:1
    |
 LL | const INVALID_VTABLE_SIZE_UB: W<&dyn Trait> =
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered invalid vtable: size is bigger than largest supported object
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered allocN, but expected a vtable pointer
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 4) {
                ╾─allocN─╼ ╾─allocN─╼                         │ ╾──╼╾──╼
            }
 
-error: aborting due to 4 previous errors
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/ub-incorrect-vtable.rs:44:1
+   |
+LL | const INVALID_VTABLE_UB: W<&dyn Trait> =
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered allocN, but expected a vtable pointer
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
+   = note: the raw bytes of the constant (size: 8, align: 4) {
+               ╾─allocN─╼ ╾─allocN─╼                         │ ╾──╼╾──╼
+           }
+
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/ub-incorrect-vtable.rs:91:1
+   |
+LL | const G: Wide = unsafe { Transmute { t: FOO }.u };
+   | ^^^^^^^^^^^^^ constructing invalid value at .1: encountered a dangling reference (going beyond the bounds of its allocation)
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
+   = note: the raw bytes of the constant (size: 8, align: 4) {
+               ╾─allocN─╼ ╾─allocN─╼                         │ ╾──╼╾──╼
+           }
+
+error: aborting due to 6 previous errors
 
 For more information about this error, try `rustc --explain E0080`.
index e594ad71b5b48c8b7f20118a7cd8d80d2c8caf8e..bd542a7a5f2933351c4c45ee9f6dca7550402ff9 100644 (file)
@@ -2,19 +2,19 @@ error[E0080]: evaluation of constant value failed
   --> $DIR/ub-incorrect-vtable.rs:19:14
    |
 LL |     unsafe { std::mem::transmute((&92u8, &[0usize, 1usize, 1000usize])) };
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid vtable: alignment `1000` is not a power of 2
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using allocN as vtable pointer but it does not point to a vtable
 
 error[E0080]: evaluation of constant value failed
   --> $DIR/ub-incorrect-vtable.rs:24:14
    |
 LL |     unsafe { std::mem::transmute((&92u8, &[1usize, usize::MAX, 1usize])) };
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid vtable: size is bigger than largest supported object
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using allocN as vtable pointer but it does not point to a vtable
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-incorrect-vtable.rs:34:1
+  --> $DIR/ub-incorrect-vtable.rs:33:1
    |
 LL | const INVALID_VTABLE_ALIGNMENT_UB: W<&dyn Trait> =
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered invalid vtable: alignment `1000` is not a power of 2
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered allocN, but expected a vtable pointer
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 16, align: 8) {
@@ -22,16 +22,38 @@ LL | const INVALID_VTABLE_ALIGNMENT_UB: W<&dyn Trait> =
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-incorrect-vtable.rs:39:1
+  --> $DIR/ub-incorrect-vtable.rs:38:1
    |
 LL | const INVALID_VTABLE_SIZE_UB: W<&dyn Trait> =
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered invalid vtable: size is bigger than largest supported object
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered allocN, but expected a vtable pointer
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 16, align: 8) {
                ╾───────allocN───────╼ ╾───────allocN───────╼ │ ╾──────╼╾──────╼
            }
 
-error: aborting due to 4 previous errors
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/ub-incorrect-vtable.rs:44:1
+   |
+LL | const INVALID_VTABLE_UB: W<&dyn Trait> =
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered allocN, but expected a vtable pointer
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
+   = note: the raw bytes of the constant (size: 16, align: 8) {
+               ╾───────allocN───────╼ ╾───────allocN───────╼ │ ╾──────╼╾──────╼
+           }
+
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/ub-incorrect-vtable.rs:91:1
+   |
+LL | const G: Wide = unsafe { Transmute { t: FOO }.u };
+   | ^^^^^^^^^^^^^ constructing invalid value at .1: encountered a dangling reference (going beyond the bounds of its allocation)
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
+   = note: the raw bytes of the constant (size: 16, align: 8) {
+               ╾───────allocN───────╼ ╾───────allocN───────╼ │ ╾──────╼╾──────╼
+           }
+
+error: aborting due to 6 previous errors
 
 For more information about this error, try `rustc --explain E0080`.
index 4ec853576c91bd4b7a202f230c370f9db0662e9d..4bb30b75bc8eb657fb6b0f21e093dbda598ed750 100644 (file)
@@ -18,27 +18,79 @@ trait Trait {}
 const INVALID_VTABLE_ALIGNMENT: &dyn Trait =
     unsafe { std::mem::transmute((&92u8, &[0usize, 1usize, 1000usize])) };
 //~^ ERROR evaluation of constant value failed
-//~| invalid vtable: alignment `1000` is not a power of 2
+//~| does not point to a vtable
 
 const INVALID_VTABLE_SIZE: &dyn Trait =
     unsafe { std::mem::transmute((&92u8, &[1usize, usize::MAX, 1usize])) };
 //~^ ERROR evaluation of constant value failed
-//~| invalid vtable: size is bigger than largest supported object
+//~| does not point to a vtable
 
 #[repr(transparent)]
 struct W<T>(T);
 
-// The drop fn is checked before size/align are, so get ourselves a "sufficiently valid" drop fn
 fn drop_me(_: *mut usize) {}
 
 const INVALID_VTABLE_ALIGNMENT_UB: W<&dyn Trait> =
     unsafe { std::mem::transmute((&92u8, &(drop_me as fn(*mut usize), 1usize, 1000usize))) };
 //~^^ ERROR it is undefined behavior to use this value
-//~| invalid vtable: alignment `1000` is not a power of 2
+//~| expected a vtable pointer
 
 const INVALID_VTABLE_SIZE_UB: W<&dyn Trait> =
     unsafe { std::mem::transmute((&92u8, &(drop_me as fn(*mut usize), usize::MAX, 1usize))) };
 //~^^ ERROR it is undefined behavior to use this value
-//~| invalid vtable: size is bigger than largest supported object
+//~| expected a vtable pointer
+
+// Even if the vtable has a fn ptr and a reasonable size+align, it still does not work.
+const INVALID_VTABLE_UB: W<&dyn Trait> =
+    unsafe { std::mem::transmute((&92u8, &(drop_me as fn(*mut usize), 1usize, 1usize))) };
+//~^^ ERROR it is undefined behavior to use this value
+//~| expected a vtable pointer
+
+// Trying to access the data in a vtable does not work, either.
+
+#[derive(Copy, Clone)]
+struct Wide<'a>(&'a Foo, &'static VTable);
+
+struct VTable {
+    drop: Option<for<'a> fn(&'a mut Foo)>,
+    size: usize,
+    align: usize,
+    bar: for<'a> fn(&'a Foo) -> u32,
+}
+
+trait Bar {
+    fn bar(&self) -> u32;
+}
+
+struct Foo {
+    foo: u32,
+    bar: bool,
+}
+
+impl Bar for Foo {
+    fn bar(&self) -> u32 {
+        self.foo
+    }
+}
+
+impl Drop for Foo {
+    fn drop(&mut self) {
+        assert!(!self.bar);
+        self.bar = true;
+        println!("dropping Foo");
+    }
+}
+
+#[repr(C)]
+union Transmute<T: Copy, U: Copy> {
+    t: T,
+    u: U,
+}
+
+const FOO: &dyn Bar = &Foo { foo: 128, bar: false };
+const G: Wide = unsafe { Transmute { t: FOO }.u };
+//~^ ERROR it is undefined behavior to use this value
+//~| encountered a dangling reference
+// (it is dangling because vtables do not contain memory that can be dereferenced)
 
 fn main() {}
index 2cae35bc4d0ed2a4e88132fe4d3ab9d9408fd402..ae114233c0f72a5fb4c7f5a19760dc4270edc07b 100644 (file)
@@ -125,7 +125,7 @@ error[E0080]: it is undefined behavior to use this value
   --> $DIR/ub-ref-ptr.rs:56:1
    |
 LL | const NULL_FN_PTR: fn() = unsafe { mem::transmute(0usize) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a null function pointer
+   | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered null pointer, but expected a function pointer
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 4, align: 4) {
@@ -147,7 +147,7 @@ error[E0080]: it is undefined behavior to use this value
   --> $DIR/ub-ref-ptr.rs:60:1
    |
 LL | const DANGLING_FN_PTR: fn() = unsafe { mem::transmute(13usize) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0x0000000d, but expected a function pointer
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0xd[noalloc], but expected a function pointer
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 4, align: 4) {
@@ -158,7 +158,7 @@ error[E0080]: it is undefined behavior to use this value
   --> $DIR/ub-ref-ptr.rs:62:1
    |
 LL | const DATA_FN_PTR: fn() = unsafe { mem::transmute(&13) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered pointer to alloc41, but expected a function pointer
+   | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered alloc41, but expected a function pointer
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 4, align: 4) {
index e2cd0e64db80695f5b46bc773316a4871281bd2a..1b93a869c0dd90d64e8cf8d14960789395e3565e 100644 (file)
@@ -125,7 +125,7 @@ error[E0080]: it is undefined behavior to use this value
   --> $DIR/ub-ref-ptr.rs:56:1
    |
 LL | const NULL_FN_PTR: fn() = unsafe { mem::transmute(0usize) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a null function pointer
+   | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered null pointer, but expected a function pointer
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 8) {
@@ -147,7 +147,7 @@ error[E0080]: it is undefined behavior to use this value
   --> $DIR/ub-ref-ptr.rs:60:1
    |
 LL | const DANGLING_FN_PTR: fn() = unsafe { mem::transmute(13usize) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0x000000000000000d, but expected a function pointer
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0xd[noalloc], but expected a function pointer
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 8) {
@@ -158,7 +158,7 @@ error[E0080]: it is undefined behavior to use this value
   --> $DIR/ub-ref-ptr.rs:62:1
    |
 LL | const DATA_FN_PTR: fn() = unsafe { mem::transmute(&13) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered pointer to alloc41, but expected a function pointer
+   | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered alloc41, but expected a function pointer
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 8) {
index 43f73f6ec7f2792a00bfe5fc06f74dbfda847947..f7898e55ee2c53b894dbc44b164499b0ce6a8ffc 100644 (file)
@@ -6,7 +6,7 @@ LL | const BAD_UPVAR: &dyn FnOnce() = &{
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 4) {
-               ╾─alloc3──╼ ╾─alloc6──╼                         │ ╾──╼╾──╼
+               ╾─alloc3──╼ ╾─alloc4──╼                         │ ╾──╼╾──╼
            }
 
 error: aborting due to previous error
index 64185a063629733372ce4b842bbe1a9322ea7f37..60432380e134701aa483008725815e35a1302148 100644 (file)
@@ -6,7 +6,7 @@ LL | const BAD_UPVAR: &dyn FnOnce() = &{
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 16, align: 8) {
-               ╾───────alloc3────────╼ ╾───────alloc6────────╼ │ ╾──────╼╾──────╼
+               ╾───────alloc3────────╼ ╾───────alloc4────────╼ │ ╾──────╼╾──────╼
            }
 
 error: aborting due to previous error
index 2fd98ea322b023fc96b9baa3bd620170cb925dda..ee27651dca03f78f591517290c9642b15f5bf441 100644 (file)
@@ -209,7 +209,7 @@ error[E0080]: it is undefined behavior to use this value
   --> $DIR/ub-wide-ptr.rs:117:1
    |
 LL | const TRAIT_OBJ_SHORT_VTABLE_1: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &3u8))) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered too small vtable
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered allocN, but expected a vtable pointer
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 4) {
@@ -220,7 +220,7 @@ error[E0080]: it is undefined behavior to use this value
   --> $DIR/ub-wide-ptr.rs:120:1
    |
 LL | const TRAIT_OBJ_SHORT_VTABLE_2: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &3u64))) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered too small vtable
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered allocN, but expected a vtable pointer
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 4) {
@@ -231,51 +231,36 @@ error[E0080]: it is undefined behavior to use this value
   --> $DIR/ub-wide-ptr.rs:123:1
    |
 LL | const TRAIT_OBJ_INT_VTABLE: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, 4usize))) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered dangling vtable pointer in wide pointer
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered 0x4[noalloc], but expected a vtable pointer
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 4) {
                ╾allocN─╼ 04 00 00 00                         │ ╾──╼....
            }
 
-error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:125:1
+error[E0080]: evaluation of constant value failed
+  --> $DIR/ub-wide-ptr.rs:125:57
    |
 LL | const TRAIT_OBJ_UNALIGNED_VTABLE: &dyn Trait = unsafe { mem::transmute((&92u8, &[0u8; 128])) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered unaligned vtable pointer in wide pointer
-   |
-   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
-   = note: the raw bytes of the constant (size: 8, align: 4) {
-               ╾allocN─╼ ╾allocN─╼                         │ ╾──╼╾──╼
-           }
+   |                                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using allocN as vtable pointer but it does not point to a vtable
 
-error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:127:1
+error[E0080]: evaluation of constant value failed
+  --> $DIR/ub-wide-ptr.rs:128:57
    |
 LL | const TRAIT_OBJ_BAD_DROP_FN_NULL: &dyn Trait = unsafe { mem::transmute((&92u8, &[0usize; 8])) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered invalid drop function pointer in vtable (not pointing to a function)
-   |
-   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
-   = note: the raw bytes of the constant (size: 8, align: 4) {
-               ╾allocN─╼ ╾allocN─╼                         │ ╾──╼╾──╼
-           }
+   |                                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using allocN as vtable pointer but it does not point to a vtable
 
-error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:129:1
+error[E0080]: evaluation of constant value failed
+  --> $DIR/ub-wide-ptr.rs:131:56
    |
 LL | const TRAIT_OBJ_BAD_DROP_FN_INT: &dyn Trait = unsafe { mem::transmute((&92u8, &[1usize; 8])) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered invalid drop function pointer in vtable (not pointing to a function)
-   |
-   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
-   = note: the raw bytes of the constant (size: 8, align: 4) {
-               ╾allocN─╼ ╾allocN─╼                         │ ╾──╼╾──╼
-           }
+   |                                                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using allocN as vtable pointer but it does not point to a vtable
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:131:1
+  --> $DIR/ub-wide-ptr.rs:134:1
    |
 LL | const TRAIT_OBJ_BAD_DROP_FN_NOT_FN_PTR: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &[&42u8; 8]))) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered invalid drop function pointer in vtable (not pointing to a function)
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered allocN, but expected a vtable pointer
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 4) {
@@ -283,7 +268,7 @@ LL | const TRAIT_OBJ_BAD_DROP_FN_NOT_FN_PTR: W<&dyn Trait> = unsafe { mem::trans
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:135:1
+  --> $DIR/ub-wide-ptr.rs:138:1
    |
 LL | const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = unsafe { mem::transmute::<_, &bool>(&3u8) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>.<dyn-downcast>: encountered 0x03, but expected a boolean
@@ -294,10 +279,10 @@ LL | const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = unsafe { mem::transmute::<_,
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:139:1
+  --> $DIR/ub-wide-ptr.rs:142:1
    |
 LL | const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { mem::transmute((&92u8, 0usize)) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered dangling vtable pointer in wide pointer
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered null pointer, but expected a vtable pointer
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 4) {
@@ -305,10 +290,10 @@ LL | const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { mem::transmute
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:141:1
+  --> $DIR/ub-wide-ptr.rs:144:1
    |
 LL | const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { mem::transmute((&92u8, &3u64)) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered too small vtable
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered allocN, but expected a vtable pointer
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 4) {
@@ -316,16 +301,16 @@ LL | const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { mem::transm
            }
 
 error[E0080]: could not evaluate static initializer
-  --> $DIR/ub-wide-ptr.rs:147:5
+  --> $DIR/ub-wide-ptr.rs:150:5
    |
 LL |     mem::transmute::<_, &dyn Trait>((&92u8, 0usize))
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: null pointer is a dangling pointer (it has no provenance)
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer use: null pointer is a dangling pointer (it has no provenance)
 
 error[E0080]: could not evaluate static initializer
-  --> $DIR/ub-wide-ptr.rs:151:5
+  --> $DIR/ub-wide-ptr.rs:154:5
    |
 LL |     mem::transmute::<_, &dyn Trait>((&92u8, &3u64))
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: allocN has size N, so pointer to 12 bytes starting at offset N is out-of-bounds
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using allocN as vtable pointer but it does not point to a vtable
 
 error: aborting due to 32 previous errors
 
index bae249076598ef4bc1f302f7ca191fafc853a11d..84c323e87b6c88f9128d115caa7885a227d647be 100644 (file)
@@ -209,7 +209,7 @@ error[E0080]: it is undefined behavior to use this value
   --> $DIR/ub-wide-ptr.rs:117:1
    |
 LL | const TRAIT_OBJ_SHORT_VTABLE_1: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &3u8))) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered too small vtable
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered allocN, but expected a vtable pointer
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 16, align: 8) {
@@ -220,7 +220,7 @@ error[E0080]: it is undefined behavior to use this value
   --> $DIR/ub-wide-ptr.rs:120:1
    |
 LL | const TRAIT_OBJ_SHORT_VTABLE_2: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &3u64))) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered too small vtable
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered allocN, but expected a vtable pointer
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 16, align: 8) {
@@ -231,51 +231,36 @@ error[E0080]: it is undefined behavior to use this value
   --> $DIR/ub-wide-ptr.rs:123:1
    |
 LL | const TRAIT_OBJ_INT_VTABLE: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, 4usize))) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered dangling vtable pointer in wide pointer
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered 0x4[noalloc], but expected a vtable pointer
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 16, align: 8) {
                ╾──────allocN───────╼ 04 00 00 00 00 00 00 00 │ ╾──────╼........
            }
 
-error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:125:1
+error[E0080]: evaluation of constant value failed
+  --> $DIR/ub-wide-ptr.rs:125:57
    |
 LL | const TRAIT_OBJ_UNALIGNED_VTABLE: &dyn Trait = unsafe { mem::transmute((&92u8, &[0u8; 128])) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered unaligned vtable pointer in wide pointer
-   |
-   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
-   = note: the raw bytes of the constant (size: 16, align: 8) {
-               ╾──────allocN───────╼ ╾──────allocN───────╼ │ ╾──────╼╾──────╼
-           }
+   |                                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using allocN as vtable pointer but it does not point to a vtable
 
-error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:127:1
+error[E0080]: evaluation of constant value failed
+  --> $DIR/ub-wide-ptr.rs:128:57
    |
 LL | const TRAIT_OBJ_BAD_DROP_FN_NULL: &dyn Trait = unsafe { mem::transmute((&92u8, &[0usize; 8])) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered invalid drop function pointer in vtable (not pointing to a function)
-   |
-   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
-   = note: the raw bytes of the constant (size: 16, align: 8) {
-               ╾──────allocN───────╼ ╾──────allocN───────╼ │ ╾──────╼╾──────╼
-           }
+   |                                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using allocN as vtable pointer but it does not point to a vtable
 
-error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:129:1
+error[E0080]: evaluation of constant value failed
+  --> $DIR/ub-wide-ptr.rs:131:56
    |
 LL | const TRAIT_OBJ_BAD_DROP_FN_INT: &dyn Trait = unsafe { mem::transmute((&92u8, &[1usize; 8])) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered invalid drop function pointer in vtable (not pointing to a function)
-   |
-   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
-   = note: the raw bytes of the constant (size: 16, align: 8) {
-               ╾──────allocN───────╼ ╾──────allocN───────╼ │ ╾──────╼╾──────╼
-           }
+   |                                                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using allocN as vtable pointer but it does not point to a vtable
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:131:1
+  --> $DIR/ub-wide-ptr.rs:134:1
    |
 LL | const TRAIT_OBJ_BAD_DROP_FN_NOT_FN_PTR: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &[&42u8; 8]))) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered invalid drop function pointer in vtable (not pointing to a function)
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered allocN, but expected a vtable pointer
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 16, align: 8) {
@@ -283,7 +268,7 @@ LL | const TRAIT_OBJ_BAD_DROP_FN_NOT_FN_PTR: W<&dyn Trait> = unsafe { mem::trans
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:135:1
+  --> $DIR/ub-wide-ptr.rs:138:1
    |
 LL | const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = unsafe { mem::transmute::<_, &bool>(&3u8) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>.<dyn-downcast>: encountered 0x03, but expected a boolean
@@ -294,10 +279,10 @@ LL | const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = unsafe { mem::transmute::<_,
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:139:1
+  --> $DIR/ub-wide-ptr.rs:142:1
    |
 LL | const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { mem::transmute((&92u8, 0usize)) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered dangling vtable pointer in wide pointer
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered null pointer, but expected a vtable pointer
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 16, align: 8) {
@@ -305,10 +290,10 @@ LL | const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { mem::transmute
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:141:1
+  --> $DIR/ub-wide-ptr.rs:144:1
    |
 LL | const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { mem::transmute((&92u8, &3u64)) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered too small vtable
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered allocN, but expected a vtable pointer
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 16, align: 8) {
@@ -316,16 +301,16 @@ LL | const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { mem::transm
            }
 
 error[E0080]: could not evaluate static initializer
-  --> $DIR/ub-wide-ptr.rs:147:5
+  --> $DIR/ub-wide-ptr.rs:150:5
    |
 LL |     mem::transmute::<_, &dyn Trait>((&92u8, 0usize))
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: null pointer is a dangling pointer (it has no provenance)
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer use: null pointer is a dangling pointer (it has no provenance)
 
 error[E0080]: could not evaluate static initializer
-  --> $DIR/ub-wide-ptr.rs:151:5
+  --> $DIR/ub-wide-ptr.rs:154:5
    |
 LL |     mem::transmute::<_, &dyn Trait>((&92u8, &3u64))
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: allocN has size N, so pointer to 24 bytes starting at offset N is out-of-bounds
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using allocN as vtable pointer but it does not point to a vtable
 
 error: aborting due to 32 previous errors
 
index f2e5738f88c9f7ffbd75280bf1046a290be0cdfc..9e3d349cd7eb040b064067d53544c5fb0cf1df27 100644 (file)
@@ -123,11 +123,14 @@ impl Trait for bool {}
 const TRAIT_OBJ_INT_VTABLE: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, 4usize))) };
 //~^ ERROR it is undefined behavior to use this value
 const TRAIT_OBJ_UNALIGNED_VTABLE: &dyn Trait = unsafe { mem::transmute((&92u8, &[0u8; 128])) };
-//~^ ERROR it is undefined behavior to use this value
+//~^ ERROR evaluation of constant value failed
+//~| does not point to a vtable
 const TRAIT_OBJ_BAD_DROP_FN_NULL: &dyn Trait = unsafe { mem::transmute((&92u8, &[0usize; 8])) };
-//~^ ERROR it is undefined behavior to use this value
+//~^ ERROR evaluation of constant value failed
+//~| does not point to a vtable
 const TRAIT_OBJ_BAD_DROP_FN_INT: &dyn Trait = unsafe { mem::transmute((&92u8, &[1usize; 8])) };
-//~^ ERROR it is undefined behavior to use this value
+//~^ ERROR evaluation of constant value failed
+//~| does not point to a vtable
 const TRAIT_OBJ_BAD_DROP_FN_NOT_FN_PTR: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &[&42u8; 8]))) };
 //~^ ERROR it is undefined behavior to use this value
 
index c7aba555370885a60024628fcb644178b4d83362..b8798a9755fe2b1b0055568a83e52f838857d37e 100644 (file)
@@ -2,11 +2,11 @@ error[E0080]: it is undefined behavior to use this value
   --> $DIR/issue-79690.rs:30:1
    |
 LL | const G: Fat = unsafe { Transmute { t: FOO }.u };
-   | ^^^^^^^^^^^^ constructing invalid value at .1.<deref>.size.foo: encountered (potentially part of) a pointer, but expected plain (non-pointer) bytes
+   | ^^^^^^^^^^^^ constructing invalid value at .1: encountered a dangling reference (going beyond the bounds of its allocation)
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 16, align: 8) {
-               ╾───────alloc3────────╼ ╾───────alloc6────────╼ │ ╾──────╼╾──────╼
+               ╾───────alloc3────────╼ ╾───────alloc4────────╼ │ ╾──────╼╾──────╼
            }
 
 error: aborting due to previous error
index bb8636f1225ad6e6ddaae1eeb4fd8911ca2f7170..7ea35f70d108eb35b8eee6f3909987557b8f721b 100644 (file)
@@ -17,7 +17,7 @@ LL | const SNEAKY: &dyn Sync = &Synced { x: UnsafeCell::new(42) };
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 4) {
-               ╾─alloc7──╼ ╾─alloc9──╼                         │ ╾──╼╾──╼
+               ╾─alloc7──╼ ╾─alloc8──╼                         │ ╾──╼╾──╼
            }
 
 error[E0080]: it is undefined behavior to use this value
@@ -28,7 +28,7 @@ LL | const BLUNT: &mut i32 = &mut 42;
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 4, align: 4) {
-               ╾─alloc11─╼                                     │ ╾──╼
+               ╾─alloc10─╼                                     │ ╾──╼
            }
 
 warning: skipping const checks
index f1652da922a57456c7a1f14ee78ad09a804a424c..5ad39893089090c4f4b1f1d6c5226fa1bd00db51 100644 (file)
@@ -17,7 +17,7 @@ LL | const SNEAKY: &dyn Sync = &Synced { x: UnsafeCell::new(42) };
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 16, align: 8) {
-               ╾───────alloc7────────╼ ╾───────alloc9────────╼ │ ╾──────╼╾──────╼
+               ╾───────alloc7────────╼ ╾───────alloc8────────╼ │ ╾──────╼╾──────╼
            }
 
 error[E0080]: it is undefined behavior to use this value
@@ -28,7 +28,7 @@ LL | const BLUNT: &mut i32 = &mut 42;
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 8) {
-               ╾───────alloc11───────╼                         │ ╾──────╼
+               ╾───────alloc10───────╼                         │ ╾──────╼
            }
 
 warning: skipping const checks