From e63a6257118effd270223ae38306013dfd477516 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 27 Aug 2022 14:11:19 -0400 Subject: [PATCH 1/5] =?UTF-8?q?interpret:=20rename=20relocation=20?= =?UTF-8?q?=E2=86=92=20provenance?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../rustc_codegen_cranelift/src/constant.rs | 2 +- compiler/rustc_codegen_gcc/src/consts.rs | 12 +- compiler/rustc_codegen_llvm/src/consts.rs | 22 +-- .../rustc_const_eval/src/interpret/intern.rs | 14 +- .../rustc_const_eval/src/interpret/machine.rs | 2 +- .../rustc_const_eval/src/interpret/memory.rs | 34 ++-- .../src/mir/interpret/allocation.rs | 181 +++++++++--------- .../rustc_middle/src/mir/interpret/mod.rs | 2 +- .../rustc_middle/src/mir/interpret/value.rs | 4 +- compiler/rustc_middle/src/mir/mod.rs | 8 +- compiler/rustc_middle/src/mir/pretty.rs | 30 +-- compiler/rustc_middle/src/ty/impls_ty.rs | 2 +- compiler/rustc_monomorphize/src/collector.rs | 6 +- compiler/rustc_typeck/src/check/mod.rs | 6 +- 14 files changed, 161 insertions(+), 164 deletions(-) diff --git a/compiler/rustc_codegen_cranelift/src/constant.rs b/compiler/rustc_codegen_cranelift/src/constant.rs index 7f7fd0e9c579d..4f1531139322b 100644 --- a/compiler/rustc_codegen_cranelift/src/constant.rs +++ b/compiler/rustc_codegen_cranelift/src/constant.rs @@ -430,7 +430,7 @@ fn define_all_allocs(tcx: TyCtxt<'_>, module: &mut dyn Module, cx: &mut Constant let bytes = alloc.inspect_with_uninit_and_ptr_outside_interpreter(0..alloc.len()).to_vec(); data_ctx.define(bytes.into_boxed_slice()); - for &(offset, alloc_id) in alloc.relocations().iter() { + for &(offset, alloc_id) in alloc.provenance().iter() { let addend = { let endianness = tcx.data_layout.endian; let offset = offset.bytes() as usize; diff --git a/compiler/rustc_codegen_gcc/src/consts.rs b/compiler/rustc_codegen_gcc/src/consts.rs index c0b8d21818f85..356c03ee3c189 100644 --- a/compiler/rustc_codegen_gcc/src/consts.rs +++ b/compiler/rustc_codegen_gcc/src/consts.rs @@ -127,7 +127,7 @@ impl<'gcc, 'tcx> StaticMethods for CodegenCx<'gcc, 'tcx> { // // We could remove this hack whenever we decide to drop macOS 10.10 support. if self.tcx.sess.target.options.is_like_osx { - // The `inspect` method is okay here because we checked relocations, and + // The `inspect` method is okay here because we checked for provenance, and // because we are doing this access to inspect the final interpreter state // (not as part of the interpreter execution). // @@ -296,17 +296,17 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { pub fn const_alloc_to_gcc<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, alloc: ConstAllocation<'tcx>) -> RValue<'gcc> { let alloc = alloc.inner(); - let mut llvals = Vec::with_capacity(alloc.relocations().len() + 1); + let mut llvals = Vec::with_capacity(alloc.provenance().len() + 1); let dl = cx.data_layout(); let pointer_size = dl.pointer_size.bytes() as usize; let mut next_offset = 0; - for &(offset, alloc_id) in alloc.relocations().iter() { + for &(offset, alloc_id) in alloc.provenance().iter() { let offset = offset.bytes(); assert_eq!(offset as usize as u64, offset); let offset = offset as usize; if offset > next_offset { - // This `inspect` is okay since we have checked that it is not within a relocation, it + // This `inspect` is okay since we have checked that it is not within a pointer with provenance, it // is within the bounds of the allocation, and it doesn't affect interpreter execution // (we inspect the result after interpreter execution). Any undef byte is replaced with // some arbitrary byte value. @@ -319,7 +319,7 @@ pub fn const_alloc_to_gcc<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, alloc: ConstAl read_target_uint( dl.endian, // This `inspect` is okay since it is within the bounds of the allocation, it doesn't // affect interpreter execution (we inspect the result after interpreter execution), - // and we properly interpret the relocation as a relocation pointer offset. + // and we properly interpret the provenance as a relocation pointer offset. alloc.inspect_with_uninit_and_ptr_outside_interpreter(offset..(offset + pointer_size)), ) .expect("const_alloc_to_llvm: could not read relocation pointer") @@ -336,7 +336,7 @@ pub fn const_alloc_to_gcc<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, alloc: ConstAl } if alloc.len() >= next_offset { let range = next_offset..alloc.len(); - // This `inspect` is okay since we have check that it is after all relocations, it is + // This `inspect` is okay since we have check that it is after all provenance, it is // within the bounds of the allocation, and it doesn't affect interpreter execution (we // inspect the result after interpreter execution). Any undef byte is replaced with some // arbitrary byte value. diff --git a/compiler/rustc_codegen_llvm/src/consts.rs b/compiler/rustc_codegen_llvm/src/consts.rs index f41ff325590af..d3e33da27993c 100644 --- a/compiler/rustc_codegen_llvm/src/consts.rs +++ b/compiler/rustc_codegen_llvm/src/consts.rs @@ -27,12 +27,12 @@ use tracing::debug; pub fn const_alloc_to_llvm<'ll>(cx: &CodegenCx<'ll, '_>, alloc: ConstAllocation<'_>) -> &'ll Value { let alloc = alloc.inner(); - let mut llvals = Vec::with_capacity(alloc.relocations().len() + 1); + let mut llvals = Vec::with_capacity(alloc.provenance().len() + 1); let dl = cx.data_layout(); let pointer_size = dl.pointer_size.bytes() as usize; - // Note: this function may call `inspect_with_uninit_and_ptr_outside_interpreter`, - // so `range` must be within the bounds of `alloc` and not contain or overlap a relocation. + // Note: this function may call `inspect_with_uninit_and_ptr_outside_interpreter`, so `range` + // must be within the bounds of `alloc` and not contain or overlap a pointer provenance. fn append_chunks_of_init_and_uninit_bytes<'ll, 'a, 'b>( llvals: &mut Vec<&'ll Value>, cx: &'a CodegenCx<'ll, 'b>, @@ -79,12 +79,12 @@ pub fn const_alloc_to_llvm<'ll>(cx: &CodegenCx<'ll, '_>, alloc: ConstAllocation< } let mut next_offset = 0; - for &(offset, alloc_id) in alloc.relocations().iter() { + for &(offset, alloc_id) in alloc.provenance().iter() { let offset = offset.bytes(); assert_eq!(offset as usize as u64, offset); let offset = offset as usize; if offset > next_offset { - // This `inspect` is okay since we have checked that it is not within a relocation, it + // This `inspect` is okay since we have checked that there is no provenance, it // is within the bounds of the allocation, and it doesn't affect interpreter execution // (we inspect the result after interpreter execution). append_chunks_of_init_and_uninit_bytes(&mut llvals, cx, alloc, next_offset..offset); @@ -93,7 +93,7 @@ pub fn const_alloc_to_llvm<'ll>(cx: &CodegenCx<'ll, '_>, alloc: ConstAllocation< dl.endian, // This `inspect` is okay since it is within the bounds of the allocation, it doesn't // affect interpreter execution (we inspect the result after interpreter execution), - // and we properly interpret the relocation as a relocation pointer offset. + // and we properly interpret the provenance as a relocation pointer offset. alloc.inspect_with_uninit_and_ptr_outside_interpreter(offset..(offset + pointer_size)), ) .expect("const_alloc_to_llvm: could not read relocation pointer") @@ -121,7 +121,7 @@ pub fn const_alloc_to_llvm<'ll>(cx: &CodegenCx<'ll, '_>, alloc: ConstAllocation< } if alloc.len() >= next_offset { let range = next_offset..alloc.len(); - // This `inspect` is okay since we have check that it is after all relocations, it is + // This `inspect` is okay since we have check that it is after all provenance, it is // within the bounds of the allocation, and it doesn't affect interpreter execution (we // inspect the result after interpreter execution). append_chunks_of_init_and_uninit_bytes(&mut llvals, cx, alloc, range); @@ -479,7 +479,7 @@ impl<'ll> StaticMethods for CodegenCx<'ll, '_> { // // We could remove this hack whenever we decide to drop macOS 10.10 support. if self.tcx.sess.target.is_like_osx { - // The `inspect` method is okay here because we checked relocations, and + // The `inspect` method is okay here because we checked for provenance, and // because we are doing this access to inspect the final interpreter state // (not as part of the interpreter execution). // @@ -487,7 +487,7 @@ impl<'ll> StaticMethods for CodegenCx<'ll, '_> { // happens to be zero. Instead, we should only check the value of defined bytes // and set all undefined bytes to zero if this allocation is headed for the // BSS. - let all_bytes_are_zero = alloc.relocations().is_empty() + let all_bytes_are_zero = alloc.provenance().is_empty() && alloc .inspect_with_uninit_and_ptr_outside_interpreter(0..alloc.len()) .iter() @@ -511,9 +511,9 @@ impl<'ll> StaticMethods for CodegenCx<'ll, '_> { section.as_str().as_ptr().cast(), section.as_str().len() as c_uint, ); - assert!(alloc.relocations().is_empty()); + assert!(alloc.provenance().is_empty()); - // The `inspect` method is okay here because we checked relocations, and + // The `inspect` method is okay here because we checked for provenance, and // because we are doing this access to inspect the final interpreter state (not // as part of the interpreter execution). let bytes = diff --git a/compiler/rustc_const_eval/src/interpret/intern.rs b/compiler/rustc_const_eval/src/interpret/intern.rs index 376b8872c90ac..66ab3f15716f2 100644 --- a/compiler/rustc_const_eval/src/interpret/intern.rs +++ b/compiler/rustc_const_eval/src/interpret/intern.rs @@ -134,7 +134,7 @@ fn intern_shallow<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx, const_eval: alloc.mutability = Mutability::Not; }; // link the alloc id to the actual allocation - leftover_allocations.extend(alloc.relocations().iter().map(|&(_, alloc_id)| alloc_id)); + leftover_allocations.extend(alloc.provenance().iter().map(|&(_, alloc_id)| alloc_id)); let alloc = tcx.intern_const_alloc(alloc); tcx.set_alloc_id_memory(alloc_id, alloc); None @@ -191,10 +191,10 @@ impl<'rt, 'mir, 'tcx: 'mir, M: CompileTimeMachine<'mir, 'tcx, const_eval::Memory return Ok(true); }; - // If there are no relocations in this allocation, it does not contain references + // If there is no provenance in this allocation, it does not contain references // that point to another allocation, and we can avoid the interning walk. if let Some(alloc) = self.ecx.get_ptr_alloc(mplace.ptr, size, align)? { - if !alloc.has_relocations() { + if !alloc.has_provenance() { return Ok(false); } } else { @@ -233,8 +233,8 @@ impl<'rt, 'mir, 'tcx: 'mir, M: CompileTimeMachine<'mir, 'tcx, const_eval::Memory } fn visit_value(&mut self, mplace: &MPlaceTy<'tcx>) -> InterpResult<'tcx> { - // Handle Reference types, as these are the only relocations supported by const eval. - // Raw pointers (and boxes) are handled by the `leftover_relocations` logic. + // Handle Reference types, as these are the only types with provenance supported by const eval. + // Raw pointers (and boxes) are handled by the `leftover_allocations` logic. let tcx = self.ecx.tcx; let ty = mplace.layout.ty; if let ty::Ref(_, referenced_ty, ref_mutability) = *ty.kind() { @@ -410,7 +410,7 @@ pub fn intern_const_alloc_recursive< // references and a `leftover_allocations` set (where we only have a todo-list here). // So we hand-roll the interning logic here again. match intern_kind { - // Statics may contain mutable allocations even behind relocations. + // Statics may point to mutable allocations. // Even for immutable statics it would be ok to have mutable allocations behind // raw pointers, e.g. for `static FOO: *const AtomicUsize = &AtomicUsize::new(42)`. InternKind::Static(_) => {} @@ -441,7 +441,7 @@ pub fn intern_const_alloc_recursive< } let alloc = tcx.intern_const_alloc(alloc); tcx.set_alloc_id_memory(alloc_id, alloc); - for &(_, alloc_id) in alloc.inner().relocations().iter() { + for &(_, alloc_id) in alloc.inner().provenance().iter() { if leftover_allocations.insert(alloc_id) { todo.push(alloc_id); } diff --git a/compiler/rustc_const_eval/src/interpret/machine.rs b/compiler/rustc_const_eval/src/interpret/machine.rs index 6bed8a7a00773..ae7c0347efc02 100644 --- a/compiler/rustc_const_eval/src/interpret/machine.rs +++ b/compiler/rustc_const_eval/src/interpret/machine.rs @@ -326,7 +326,7 @@ pub trait Machine<'mir, 'tcx>: Sized { /// cache the result. (This relies on `AllocMap::get_or` being able to add the /// owned allocation to the map even when the map is shared.) /// - /// This must only fail if `alloc` contains relocations. + /// This must only fail if `alloc` contains provenance. fn adjust_allocation<'b>( ecx: &InterpCx<'mir, 'tcx, Self>, id: AllocId, diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs index c4e9377029294..f84c6017dbf6d 100644 --- a/compiler/rustc_const_eval/src/interpret/memory.rs +++ b/compiler/rustc_const_eval/src/interpret/memory.rs @@ -214,7 +214,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { self.allocate_raw_ptr(alloc, kind).unwrap() } - /// This can fail only of `alloc` contains relocations. + /// This can fail only of `alloc` contains provenance. pub fn allocate_raw_ptr( &mut self, alloc: Allocation, @@ -794,10 +794,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { todo.extend(static_roots); while let Some(id) = todo.pop() { if reachable.insert(id) { - // This is a new allocation, add its relocations to `todo`. + // This is a new allocation, add the allocation it points to to `todo`. if let Some((_, alloc)) = self.memory.alloc_map.get(id) { todo.extend( - alloc.relocations().values().filter_map(|prov| prov.get_alloc_id()), + alloc.provenance().values().filter_map(|prov| prov.get_alloc_id()), ); } } @@ -833,7 +833,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> std::fmt::Debug for DumpAllocs<'a, allocs_to_print: &mut VecDeque, alloc: &Allocation, ) -> std::fmt::Result { - for alloc_id in alloc.relocations().values().filter_map(|prov| prov.get_alloc_id()) { + for alloc_id in alloc.provenance().values().filter_map(|prov| prov.get_alloc_id()) { allocs_to_print.push_back(alloc_id); } write!(fmt, "{}", display_allocation(tcx, alloc)) @@ -960,9 +960,9 @@ impl<'tcx, 'a, Prov: Provenance, Extra> AllocRef<'a, 'tcx, Prov, Extra> { .map_err(|e| e.to_interp_error(self.alloc_id))?) } - /// Returns whether the allocation has relocations for the entire range of the `AllocRef`. - pub(crate) fn has_relocations(&self) -> bool { - self.alloc.has_relocations(&self.tcx, self.range) + /// Returns whether the allocation has provenance anywhere in the range of the `AllocRef`. + pub(crate) fn has_provenance(&self) -> bool { + self.alloc.range_has_provenance(&self.tcx, self.range) } } @@ -1078,17 +1078,17 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { return Ok(()); }; - // This checks relocation edges on the src, which needs to happen before - // `prepare_relocation_copy`. + // This checks provenance edges on the src, which needs to happen before + // `prepare_provenance_copy`. let src_bytes = src_alloc .get_bytes_with_uninit_and_ptr(&tcx, src_range) .map_err(|e| e.to_interp_error(src_alloc_id))? .as_ptr(); // raw ptr, so we can also get a ptr to the destination allocation - // first copy the relocations to a temporary buffer, because - // `get_bytes_mut` will clear the relocations, which is correct, - // since we don't want to keep any relocations at the target. - let relocations = - src_alloc.prepare_relocation_copy(self, src_range, dest_offset, num_copies); + // first copy the provenance to a temporary buffer, because + // `get_bytes_mut` will clear the provenance, which is correct, + // since we don't want to keep any provenance at the target. + let provenance = + src_alloc.prepare_provenance_copy(self, src_range, dest_offset, num_copies); // Prepare a copy of the initialization mask. let compressed = src_alloc.compress_uninit_range(src_range); @@ -1117,7 +1117,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { dest_alloc .write_uninit(&tcx, dest_range) .map_err(|e| e.to_interp_error(dest_alloc_id))?; - // We can forget about the relocations, this is all not initialized anyway. + // We can forget about the provenance, this is all not initialized anyway. return Ok(()); } @@ -1161,8 +1161,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { alloc_range(dest_offset, size), // just a single copy (i.e., not full `dest_range`) num_copies, ); - // copy the relocations to the destination - dest_alloc.mark_relocation_range(relocations); + // copy the provenance to the destination + dest_alloc.mark_provenance_range(provenance); Ok(()) } diff --git a/compiler/rustc_middle/src/mir/interpret/allocation.rs b/compiler/rustc_middle/src/mir/interpret/allocation.rs index 3f618106525cf..cc39e434225f6 100644 --- a/compiler/rustc_middle/src/mir/interpret/allocation.rs +++ b/compiler/rustc_middle/src/mir/interpret/allocation.rs @@ -34,11 +34,11 @@ pub struct Allocation { /// The actual bytes of the allocation. /// Note that the bytes of a pointer represent the offset of the pointer. bytes: Box<[u8]>, - /// Maps from byte addresses to extra data for each pointer. + /// Maps from byte addresses to extra provenance data for each pointer. /// Only the first byte of a pointer is inserted into the map; i.e., /// every entry in this map applies to `pointer_size` consecutive bytes starting /// at the given offset. - relocations: Relocations, + provenance: ProvenanceMap, /// Denotes which part of this allocation is initialized. init_mask: InitMask, /// The alignment of the allocation to detect unaligned reads. @@ -84,7 +84,7 @@ impl hash::Hash for Allocation { } // Hash the other fields as usual. - self.relocations.hash(state); + self.provenance.hash(state); self.init_mask.hash(state); self.align.hash(state); self.mutability.hash(state); @@ -211,7 +211,7 @@ impl Allocation { let size = Size::from_bytes(bytes.len()); Self { bytes, - relocations: Relocations::new(), + provenance: ProvenanceMap::new(), init_mask: InitMask::new(size, true), align, mutability, @@ -246,7 +246,7 @@ impl Allocation { let bytes = unsafe { bytes.assume_init() }; Ok(Allocation { bytes, - relocations: Relocations::new(), + provenance: ProvenanceMap::new(), init_mask: InitMask::new(size, false), align, mutability: Mutability::Mut, @@ -266,22 +266,22 @@ impl Allocation { ) -> Result, Err> { // Compute new pointer provenance, which also adjusts the bytes. let mut bytes = self.bytes; - let mut new_relocations = Vec::with_capacity(self.relocations.0.len()); + let mut new_provenance = Vec::with_capacity(self.provenance.0.len()); let ptr_size = cx.data_layout().pointer_size.bytes_usize(); let endian = cx.data_layout().endian; - for &(offset, alloc_id) in self.relocations.iter() { + for &(offset, alloc_id) in self.provenance.iter() { let idx = offset.bytes_usize(); let ptr_bytes = &mut bytes[idx..idx + ptr_size]; let bits = read_target_uint(endian, ptr_bytes).unwrap(); let (ptr_prov, ptr_offset) = adjust_ptr(Pointer::new(alloc_id, Size::from_bytes(bits)))?.into_parts(); write_target_uint(endian, ptr_bytes, ptr_offset.bytes().into()).unwrap(); - new_relocations.push((offset, ptr_prov)); + new_provenance.push((offset, ptr_prov)); } // Create allocation. Ok(Allocation { bytes, - relocations: Relocations::from_presorted(new_relocations), + provenance: ProvenanceMap::from_presorted(new_provenance), init_mask: self.init_mask, align: self.align, mutability: self.mutability, @@ -300,8 +300,8 @@ impl Allocation { Size::from_bytes(self.len()) } - /// Looks at a slice which may describe uninitialized bytes or describe a relocation. This differs - /// from `get_bytes_with_uninit_and_ptr` in that it does no relocation checks (even on the + /// Looks at a slice which may contain uninitialized bytes or provenance. This differs + /// from `get_bytes_with_uninit_and_ptr` in that it does no provenance checks (even on the /// edges) at all. /// This must not be used for reads affecting the interpreter execution. pub fn inspect_with_uninit_and_ptr_outside_interpreter(&self, range: Range) -> &[u8] { @@ -313,23 +313,23 @@ impl Allocation { &self.init_mask } - /// Returns the relocation list. - pub fn relocations(&self) -> &Relocations { - &self.relocations + /// Returns the provenance map. + pub fn provenance(&self) -> &ProvenanceMap { + &self.provenance } } /// Byte accessors. impl Allocation { /// This is the entirely abstraction-violating way to just grab the raw bytes without - /// caring about relocations. It just deduplicates some code between `read_scalar` + /// caring about provenance. It just deduplicates some code between `read_scalar` /// and `get_bytes_internal`. fn get_bytes_even_more_internal(&self, range: AllocRange) -> &[u8] { &self.bytes[range.start.bytes_usize()..range.end().bytes_usize()] } /// The last argument controls whether we error out when there are uninitialized or pointer - /// bytes. However, we *always* error when there are relocations overlapping the edges of the + /// bytes. However, we *always* error when there is provenance overlapping the edges of the /// range. /// /// You should never call this, call `get_bytes` or `get_bytes_with_uninit_and_ptr` instead, @@ -347,10 +347,10 @@ impl Allocation { ) -> AllocResult<&[u8]> { if check_init_and_ptr { self.check_init(range)?; - self.check_relocations(cx, range)?; + self.check_provenance(cx, range)?; } else { - // We still don't want relocations on the *edges*. - self.check_relocation_edges(cx, range)?; + // We still don't want provenance on the *edges*. + self.check_provenance_edges(cx, range)?; } Ok(self.get_bytes_even_more_internal(range)) @@ -368,7 +368,7 @@ impl Allocation { } /// It is the caller's responsibility to handle uninitialized and pointer bytes. - /// However, this still checks that there are no relocations on the *edges*. + /// However, this still checks that there is no provenance on the *edges*. /// /// It is the caller's responsibility to check bounds and alignment beforehand. #[inline] @@ -380,7 +380,7 @@ impl Allocation { self.get_bytes_internal(cx, range, false) } - /// Just calling this already marks everything as defined and removes relocations, + /// Just calling this already marks everything as defined and removes provenance, /// so be sure to actually put data there! /// /// It is the caller's responsibility to check bounds and alignment beforehand. @@ -392,7 +392,7 @@ impl Allocation { range: AllocRange, ) -> AllocResult<&mut [u8]> { self.mark_init(range, true); - self.clear_relocations(cx, range)?; + self.clear_provenance(cx, range)?; Ok(&mut self.bytes[range.start.bytes_usize()..range.end().bytes_usize()]) } @@ -404,7 +404,7 @@ impl Allocation { range: AllocRange, ) -> AllocResult<*mut [u8]> { self.mark_init(range, true); - self.clear_relocations(cx, range)?; + self.clear_provenance(cx, range)?; assert!(range.end().bytes_usize() <= self.bytes.len()); // need to do our own bounds-check let begin_ptr = self.bytes.as_mut_ptr().wrapping_add(range.start.bytes_usize()); @@ -415,7 +415,7 @@ impl Allocation { /// Reading and writing. impl Allocation { - /// Validates that this memory range is initiailized and contains no relocations. + /// Validates that this memory range is initiailized and contains no provenance. pub fn check_bytes(&self, cx: &impl HasDataLayout, range: AllocRange) -> AllocResult { // This implicitly does all the checking we are asking for. self.get_bytes(cx, range)?; @@ -447,17 +447,17 @@ impl Allocation { return Err(AllocError::InvalidUninitBytes(None)); } - // If we are doing a pointer read, and there is a relocation exactly where we - // are reading, then we can put data and relocation back together and return that. - if read_provenance && let Some(&prov) = self.relocations.get(&range.start) { - // We already checked init and relocations, so we can use this function. + // If we are doing a pointer read, and there is provenance exactly where we + // are reading, then we can put data and provenance back together and return that. + if read_provenance && let Some(&prov) = self.provenance.get(&range.start) { + // We already checked init and provenance, so we can use this function. let bytes = self.get_bytes_even_more_internal(range); let bits = read_target_uint(cx.data_layout().endian, bytes).unwrap(); let ptr = Pointer::new(prov, Size::from_bytes(bits)); return Ok(Scalar::from_pointer(ptr, cx)); } - // If we are *not* reading a pointer, and we can just ignore relocations, + // If we are *not* reading a pointer, and we can just ignore provenance, // then do exactly that. if !read_provenance && Prov::OFFSET_IS_ADDR { // We just strip provenance. @@ -469,8 +469,8 @@ impl Allocation { // It's complicated. Better make sure there is no provenance anywhere. // FIXME: If !OFFSET_IS_ADDR, this is the best we can do. But if OFFSET_IS_ADDR, then // `read_pointer` is true and we ideally would distinguish the following two cases: - // - The entire `range` is covered by 2 relocations for the same provenance. - // Then we should return a pointer with that provenance. + // - The entire `range` is covered by the same provenance, stored in two separate entries of + // the provenance map. Then we should return a pointer with that provenance. // - The range has inhomogeneous provenance. Then we should return just the // underlying bits. let bytes = self.get_bytes(cx, range)?; @@ -508,9 +508,9 @@ impl Allocation { let dst = self.get_bytes_mut(cx, range)?; write_target_uint(endian, dst, bytes).unwrap(); - // See if we have to also write a relocation. + // See if we have to also store some provenance. if let Some(provenance) = provenance { - self.relocations.0.insert(range.start, provenance); + self.provenance.0.insert(range.start, provenance); } Ok(()) @@ -519,64 +519,64 @@ impl Allocation { /// Write "uninit" to the given memory range. pub fn write_uninit(&mut self, cx: &impl HasDataLayout, range: AllocRange) -> AllocResult { self.mark_init(range, false); - self.clear_relocations(cx, range)?; + self.clear_provenance(cx, range)?; return Ok(()); } } -/// Relocations. +/// Provenance. impl Allocation { - /// Returns all relocations overlapping with the given pointer-offset pair. - fn get_relocations(&self, cx: &impl HasDataLayout, range: AllocRange) -> &[(Size, Prov)] { + /// Returns all provenance overlapping with the given pointer-offset pair. + fn range_get_provenance(&self, cx: &impl HasDataLayout, range: AllocRange) -> &[(Size, Prov)] { // We have to go back `pointer_size - 1` bytes, as that one would still overlap with // the beginning of this range. let start = range.start.bytes().saturating_sub(cx.data_layout().pointer_size.bytes() - 1); - self.relocations.range(Size::from_bytes(start)..range.end()) + self.provenance.range(Size::from_bytes(start)..range.end()) } - /// Returns whether this allocation has relocations overlapping with the given range. + /// Returns whether this allocation has progrnance overlapping with the given range. /// - /// Note: this function exists to allow `get_relocations` to be private, in order to somewhat - /// limit access to relocations outside of the `Allocation` abstraction. + /// Note: this function exists to allow `range_get_provenance` to be private, in order to somewhat + /// limit access to provenance outside of the `Allocation` abstraction. /// - pub fn has_relocations(&self, cx: &impl HasDataLayout, range: AllocRange) -> bool { - !self.get_relocations(cx, range).is_empty() + pub fn range_has_provenance(&self, cx: &impl HasDataLayout, range: AllocRange) -> bool { + !self.range_get_provenance(cx, range).is_empty() } - /// Checks that there are no relocations overlapping with the given range. + /// Checks that there is no provenance overlapping with the given range. #[inline(always)] - fn check_relocations(&self, cx: &impl HasDataLayout, range: AllocRange) -> AllocResult { - if self.has_relocations(cx, range) { Err(AllocError::ReadPointerAsBytes) } else { Ok(()) } + fn check_provenance(&self, cx: &impl HasDataLayout, range: AllocRange) -> AllocResult { + if self.range_has_provenance(cx, range) { Err(AllocError::ReadPointerAsBytes) } else { Ok(()) } } - /// Removes all relocations inside the given range. - /// If there are relocations overlapping with the edges, they + /// Removes all provenance inside the given range. + /// If there is provenance overlapping with the edges, it /// are removed as well *and* the bytes they cover are marked as /// uninitialized. This is a somewhat odd "spooky action at a distance", /// but it allows strictly more code to run than if we would just error /// immediately in that case. - fn clear_relocations(&mut self, cx: &impl HasDataLayout, range: AllocRange) -> AllocResult + fn clear_provenance(&mut self, cx: &impl HasDataLayout, range: AllocRange) -> AllocResult where Prov: Provenance, { - // Find the start and end of the given range and its outermost relocations. + // Find the start and end of the given range and its outermost provenance. let (first, last) = { - // Find all relocations overlapping the given range. - let relocations = self.get_relocations(cx, range); - if relocations.is_empty() { + // Find all provenance overlapping the given range. + let provenance = self.range_get_provenance(cx, range); + if provenance.is_empty() { return Ok(()); } ( - relocations.first().unwrap().0, - relocations.last().unwrap().0 + cx.data_layout().pointer_size, + provenance.first().unwrap().0, + provenance.last().unwrap().0 + cx.data_layout().pointer_size, ) }; let start = range.start; let end = range.end(); - // We need to handle clearing the relocations from parts of a pointer. - // FIXME: Miri should preserve partial relocations; see + // We need to handle clearing the provenance from parts of a pointer. + // FIXME: Miri should preserve partial provenance; see // https://github.com/rust-lang/miri/issues/2181. if first < start { if Prov::ERR_ON_PARTIAL_PTR_OVERWRITE { @@ -599,41 +599,40 @@ impl Allocation { self.init_mask.set_range(end, last, false); } - // Forget all the relocations. - // Since relocations do not overlap, we know that removing until `last` (exclusive) is fine, - // i.e., this will not remove any other relocations just after the ones we care about. - self.relocations.0.remove_range(first..last); + // Forget all the provenance. + // Since provenance do not overlap, we know that removing until `last` (exclusive) is fine, + // i.e., this will not remove any other provenance just after the ones we care about. + self.provenance.0.remove_range(first..last); Ok(()) } - /// Errors if there are relocations overlapping with the edges of the - /// given memory range. + /// Errors if there is provenance overlapping with the edges of the given memory range. #[inline] - fn check_relocation_edges(&self, cx: &impl HasDataLayout, range: AllocRange) -> AllocResult { - self.check_relocations(cx, alloc_range(range.start, Size::ZERO))?; - self.check_relocations(cx, alloc_range(range.end(), Size::ZERO))?; + fn check_provenance_edges(&self, cx: &impl HasDataLayout, range: AllocRange) -> AllocResult { + self.check_provenance(cx, alloc_range(range.start, Size::ZERO))?; + self.check_provenance(cx, alloc_range(range.end(), Size::ZERO))?; Ok(()) } } -/// "Relocations" stores the provenance information of pointers stored in memory. +/// Stores the provenance information of pointers stored in memory. #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)] -pub struct Relocations(SortedMap); +pub struct ProvenanceMap(SortedMap); -impl Relocations { +impl ProvenanceMap { pub fn new() -> Self { - Relocations(SortedMap::new()) + ProvenanceMap(SortedMap::new()) } - // The caller must guarantee that the given relocations are already sorted + // The caller must guarantee that the given provenance list is already sorted // by address and contain no duplicates. pub fn from_presorted(r: Vec<(Size, Prov)>) -> Self { - Relocations(SortedMap::from_presorted_elements(r)) + ProvenanceMap(SortedMap::from_presorted_elements(r)) } } -impl Deref for Relocations { +impl Deref for ProvenanceMap { type Target = SortedMap; fn deref(&self) -> &Self::Target { @@ -641,36 +640,36 @@ impl Deref for Relocations { } } -/// A partial, owned list of relocations to transfer into another allocation. +/// A partial, owned list of provenance to transfer into another allocation. /// /// Offsets are already adjusted to the destination allocation. -pub struct AllocationRelocations { - dest_relocations: Vec<(Size, Prov)>, +pub struct AllocationProvenance { + dest_provenance: Vec<(Size, Prov)>, } impl Allocation { - pub fn prepare_relocation_copy( + pub fn prepare_provenance_copy( &self, cx: &impl HasDataLayout, src: AllocRange, dest: Size, count: u64, - ) -> AllocationRelocations { - let relocations = self.get_relocations(cx, src); - if relocations.is_empty() { - return AllocationRelocations { dest_relocations: Vec::new() }; + ) -> AllocationProvenance { + let provenance = self.range_get_provenance(cx, src); + if provenance.is_empty() { + return AllocationProvenance { dest_provenance: Vec::new() }; } let size = src.size; - let mut new_relocations = Vec::with_capacity(relocations.len() * (count as usize)); + let mut new_provenance = Vec::with_capacity(provenance.len() * (count as usize)); // If `count` is large, this is rather wasteful -- we are allocating a big array here, which // is mostly filled with redundant information since it's just N copies of the same `Prov`s - // at slightly adjusted offsets. The reason we do this is so that in `mark_relocation_range` + // at slightly adjusted offsets. The reason we do this is so that in `mark_provenance_range` // we can use `insert_presorted`. That wouldn't work with an `Iterator` that just produces - // the right sequence of relocations for all N copies. + // the right sequence of provenance for all N copies. for i in 0..count { - new_relocations.extend(relocations.iter().map(|&(offset, reloc)| { + new_provenance.extend(provenance.iter().map(|&(offset, reloc)| { // compute offset for current repetition let dest_offset = dest + size * i; // `Size` operations ( @@ -681,17 +680,17 @@ impl Allocation { })); } - AllocationRelocations { dest_relocations: new_relocations } + AllocationProvenance { dest_provenance: new_provenance } } - /// Applies a relocation copy. - /// The affected range, as defined in the parameters to `prepare_relocation_copy` is expected - /// to be clear of relocations. + /// Applies a provenance copy. + /// The affected range, as defined in the parameters to `prepare_provenance_copy` is expected + /// to be clear of provenance. /// /// This is dangerous to use as it can violate internal `Allocation` invariants! /// It only exists to support an efficient implementation of `mem_copy_repeatedly`. - pub fn mark_relocation_range(&mut self, relocations: AllocationRelocations) { - self.relocations.0.insert_presorted(relocations.dest_relocations); + pub fn mark_provenance_range(&mut self, provenance: AllocationProvenance) { + self.provenance.0.insert_presorted(provenance.dest_provenance); } } diff --git a/compiler/rustc_middle/src/mir/interpret/mod.rs b/compiler/rustc_middle/src/mir/interpret/mod.rs index 93fe7e63710b1..0fc1217d57196 100644 --- a/compiler/rustc_middle/src/mir/interpret/mod.rs +++ b/compiler/rustc_middle/src/mir/interpret/mod.rs @@ -128,7 +128,7 @@ pub use self::value::{get_slice_bytes, ConstAlloc, ConstValue, Scalar}; pub use self::allocation::{ alloc_range, AllocRange, Allocation, ConstAllocation, InitChunk, InitChunkIter, InitMask, - Relocations, + ProvenanceMap, }; pub use self::pointer::{Pointer, PointerArithmetic, Provenance}; diff --git a/compiler/rustc_middle/src/mir/interpret/value.rs b/compiler/rustc_middle/src/mir/interpret/value.rs index ba56c5267df0b..1ba16025e3218 100644 --- a/compiler/rustc_middle/src/mir/interpret/value.rs +++ b/compiler/rustc_middle/src/mir/interpret/value.rs @@ -130,9 +130,7 @@ pub enum Scalar { /// The raw bytes of a simple value. Int(ScalarInt), - /// A pointer into an `Allocation`. An `Allocation` in the `memory` module has a list of - /// relocations, but a `Scalar` is only large enough to contain one, so we just represent the - /// relocation and its associated offset together as a `Pointer` here. + /// A pointer. /// /// We also store the size of the pointer, such that a `Scalar` always knows how big it is. /// The size is always the pointer size of the current target, but this is not information diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 9da9b4e91f647..4e886ff159218 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -2692,8 +2692,8 @@ fn pretty_print_const_value<'tcx>( match inner.kind() { ty::Slice(t) => { if *t == u8_type { - // The `inspect` here is okay since we checked the bounds, and there are - // no relocations (we have an active slice reference here). We don't use + // The `inspect` here is okay since we checked the bounds, and `u8` carries + // no provenance (we have an active slice reference here). We don't use // this result to affect interpreter execution. let byte_str = data .inner() @@ -2703,8 +2703,8 @@ fn pretty_print_const_value<'tcx>( } } ty::Str => { - // The `inspect` here is okay since we checked the bounds, and there are no - // relocations (we have an active `str` reference here). We don't use this + // The `inspect` here is okay since we checked the bounds, and `str` carries + // no provenance (we have an active `str` reference here). We don't use this // result to affect interpreter execution. let slice = data .inner() diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index 0ce41337b910d..cd566681edf24 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -676,7 +676,7 @@ pub fn write_allocations<'tcx>( fn alloc_ids_from_alloc( alloc: ConstAllocation<'_>, ) -> impl DoubleEndedIterator + '_ { - alloc.inner().relocations().values().map(|id| *id) + alloc.inner().provenance().values().map(|id| *id) } fn alloc_ids_from_const_val(val: ConstValue<'_>) -> impl Iterator + '_ { @@ -778,7 +778,7 @@ pub fn write_allocations<'tcx>( /// If the allocation is small enough to fit into a single line, no start address is given. /// After the hex dump, an ascii dump follows, replacing all unprintable characters (control /// characters or characters whose value is larger than 127) with a `.` -/// This also prints relocations adequately. +/// This also prints provenance adequately. pub fn display_allocation<'a, 'tcx, Prov, Extra>( tcx: TyCtxt<'tcx>, alloc: &'a Allocation, @@ -873,34 +873,34 @@ fn write_allocation_bytes<'tcx, Prov: Provenance, Extra>( if i != line_start { write!(w, " ")?; } - if let Some(&prov) = alloc.relocations().get(&i) { - // Memory with a relocation must be defined + if let Some(&prov) = alloc.provenance().get(&i) { + // Memory with provenance must be defined assert!(alloc.init_mask().is_range_initialized(i, i + ptr_size).is_ok()); let j = i.bytes_usize(); let offset = alloc .inspect_with_uninit_and_ptr_outside_interpreter(j..j + ptr_size.bytes_usize()); let offset = read_target_uint(tcx.data_layout.endian, offset).unwrap(); let offset = Size::from_bytes(offset); - let relocation_width = |bytes| bytes * 3; + let provenance_width = |bytes| bytes * 3; let ptr = Pointer::new(prov, offset); let mut target = format!("{:?}", ptr); - if target.len() > relocation_width(ptr_size.bytes_usize() - 1) { + if target.len() > provenance_width(ptr_size.bytes_usize() - 1) { // This is too long, try to save some space. target = format!("{:#?}", ptr); } if ((i - line_start) + ptr_size).bytes_usize() > BYTES_PER_LINE { - // This branch handles the situation where a relocation starts in the current line + // This branch handles the situation where a provenance starts in the current line // but ends in the next one. let remainder = Size::from_bytes(BYTES_PER_LINE) - (i - line_start); let overflow = ptr_size - remainder; - let remainder_width = relocation_width(remainder.bytes_usize()) - 2; - let overflow_width = relocation_width(overflow.bytes_usize() - 1) + 1; + let remainder_width = provenance_width(remainder.bytes_usize()) - 2; + let overflow_width = provenance_width(overflow.bytes_usize() - 1) + 1; ascii.push('╾'); for _ in 0..remainder.bytes() - 1 { ascii.push('─'); } if overflow_width > remainder_width && overflow_width >= target.len() { - // The case where the relocation fits into the part in the next line + // The case where the provenance fits into the part in the next line write!(w, "╾{0:─^1$}", "", remainder_width)?; line_start = write_allocation_newline(w, line_start, &ascii, pos_width, prefix)?; @@ -921,11 +921,11 @@ fn write_allocation_bytes<'tcx, Prov: Provenance, Extra>( i += ptr_size; continue; } else { - // This branch handles a relocation that starts and ends in the current line. - let relocation_width = relocation_width(ptr_size.bytes_usize() - 1); - oversized_ptr(&mut target, relocation_width); + // This branch handles a provenance that starts and ends in the current line. + let provenance_width = provenance_width(ptr_size.bytes_usize() - 1); + oversized_ptr(&mut target, provenance_width); ascii.push('╾'); - write!(w, "╾{0:─^1$}╼", target, relocation_width)?; + write!(w, "╾{0:─^1$}╼", target, provenance_width)?; for _ in 0..ptr_size.bytes() - 2 { ascii.push('─'); } @@ -935,7 +935,7 @@ fn write_allocation_bytes<'tcx, Prov: Provenance, Extra>( } else if alloc.init_mask().is_range_initialized(i, i + Size::from_bytes(1)).is_ok() { let j = i.bytes_usize(); - // Checked definedness (and thus range) and relocations. This access also doesn't + // Checked definedness (and thus range) and provenance. This access also doesn't // influence interpreter execution but is only for debugging. let c = alloc.inspect_with_uninit_and_ptr_outside_interpreter(j..j + 1)[0]; write!(w, "{:02x}", c)?; diff --git a/compiler/rustc_middle/src/ty/impls_ty.rs b/compiler/rustc_middle/src/ty/impls_ty.rs index cd00b26b8def0..d1c0d62ac6e00 100644 --- a/compiler/rustc_middle/src/ty/impls_ty.rs +++ b/compiler/rustc_middle/src/ty/impls_ty.rs @@ -113,7 +113,7 @@ impl<'a> HashStable> for mir::interpret::AllocId { } // `Relocations` with default type parameters is a sorted map. -impl<'a, Prov> HashStable> for mir::interpret::Relocations +impl<'a, Prov> HashStable> for mir::interpret::ProvenanceMap where Prov: HashStable>, { diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index 82ef16a7f72fc..5f5540495e938 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -461,7 +461,7 @@ fn collect_items_rec<'tcx>( recursion_depth_reset = None; if let Ok(alloc) = tcx.eval_static_initializer(def_id) { - for &id in alloc.inner().relocations().values() { + for &id in alloc.inner().provenance().values() { collect_miri(tcx, id, &mut neighbors); } } @@ -1424,7 +1424,7 @@ fn collect_miri<'tcx>(tcx: TyCtxt<'tcx>, alloc_id: AllocId, output: &mut MonoIte } GlobalAlloc::Memory(alloc) => { trace!("collecting {:?} with {:#?}", alloc_id, alloc); - for &inner in alloc.inner().relocations().values() { + for &inner in alloc.inner().provenance().values() { rustc_data_structures::stack::ensure_sufficient_stack(|| { collect_miri(tcx, inner, output); }); @@ -1463,7 +1463,7 @@ fn collect_const_value<'tcx>( match value { ConstValue::Scalar(Scalar::Ptr(ptr, _size)) => collect_miri(tcx, ptr.provenance, output), ConstValue::Slice { data: alloc, start: _, end: _ } | ConstValue::ByRef { alloc, .. } => { - for &id in alloc.inner().relocations().values() { + for &id in alloc.inner().provenance().values() { collect_miri(tcx, id, output); } } diff --git a/compiler/rustc_typeck/src/check/mod.rs b/compiler/rustc_typeck/src/check/mod.rs index fb675212e3ffb..f8d839b648380 100644 --- a/compiler/rustc_typeck/src/check/mod.rs +++ b/compiler/rustc_typeck/src/check/mod.rs @@ -542,13 +542,13 @@ fn maybe_check_static_with_link_section(tcx: TyCtxt<'_>, id: LocalDefId) { // For the wasm32 target statics with `#[link_section]` are placed into custom // sections of the final output file, but this isn't link custom sections of // other executable formats. Namely we can only embed a list of bytes, - // nothing with pointers to anything else or relocations. If any relocation - // show up, reject them here. + // nothing with provenance (pointers to anything else). If any provenance + // show up, reject it here. // `#[link_section]` may contain arbitrary, or even undefined bytes, but it is // the consumer's responsibility to ensure all bytes that have been read // have defined values. if let Ok(alloc) = tcx.eval_static_initializer(id.to_def_id()) - && alloc.inner().relocations().len() != 0 + && alloc.inner().provenance().len() != 0 { let msg = "statics with a custom `#[link_section]` must be a \ simple list of bytes on the wasm target with no \ From 2e172473daefd24631faf3906bd411798d7d8a17 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 27 Aug 2022 14:54:02 -0400 Subject: [PATCH 2/5] interpret: make read-pointer-as-bytes *always* work in Miri and show some extra information when it happens in CTFE --- .../src/intrinsics/simd.rs | 5 +- .../rustc_const_eval/src/const_eval/error.rs | 13 ++ .../src/const_eval/eval_queries.rs | 8 +- .../src/interpret/intrinsics.rs | 21 ++- .../rustc_const_eval/src/interpret/memory.rs | 24 +-- .../rustc_const_eval/src/interpret/operand.rs | 2 +- .../rustc_const_eval/src/interpret/place.rs | 4 +- .../src/interpret/projection.rs | 4 +- .../src/interpret/validity.rs | 35 ++-- .../src/mir/interpret/allocation.rs | 156 ++++++++---------- .../rustc_middle/src/mir/interpret/error.rs | 13 +- .../rustc_middle/src/mir/interpret/pointer.rs | 7 + .../rustc_middle/src/mir/interpret/value.rs | 2 +- compiler/rustc_middle/src/mir/mod.rs | 2 +- compiler/rustc_middle/src/ty/print/pretty.rs | 2 +- 15 files changed, 153 insertions(+), 145 deletions(-) diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs index a32b413d45f93..1f358b1bbb96e 100644 --- a/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs +++ b/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs @@ -186,7 +186,10 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( let size = Size::from_bytes( 4 * ret_lane_count, /* size_of([u32; ret_lane_count]) */ ); - alloc.inner().get_bytes(fx, alloc_range(offset, size)).unwrap() + alloc + .inner() + .get_bytes_strip_provenance(fx, alloc_range(offset, size)) + .unwrap() } _ => unreachable!("{:?}", idx_const), }; diff --git a/compiler/rustc_const_eval/src/const_eval/error.rs b/compiler/rustc_const_eval/src/const_eval/error.rs index eb81f43c3fe8c..63a3fef2e6263 100644 --- a/compiler/rustc_const_eval/src/const_eval/error.rs +++ b/compiler/rustc_const_eval/src/const_eval/error.rs @@ -10,6 +10,7 @@ use rustc_span::{Span, Symbol}; use super::InterpCx; use crate::interpret::{ struct_error, ErrorHandled, FrameInfo, InterpError, InterpErrorInfo, Machine, MachineStopType, + UnsupportedOpInfo, }; /// The CTFE machine has some custom error kinds. @@ -153,6 +154,18 @@ impl<'tcx> ConstEvalErr<'tcx> { if let Some(span_msg) = span_msg { err.span_label(self.span, span_msg); } + // Add some more context for select error types. + match self.error { + InterpError::Unsupported( + UnsupportedOpInfo::ReadPointerAsBytes + | UnsupportedOpInfo::PartialPointerOverwrite(_) + | UnsupportedOpInfo::PartialPointerCopy(_), + ) => { + err.help("this code performed an operation that depends on the underlying bytes representing a pointer"); + err.help("the absolute address of a pointer is not known at compile-time, so such operations are not supported"); + } + _ => {} + } // Add spans for the stacktrace. Don't print a single-line backtrace though. if self.stacktrace.len() > 1 { // Helper closure to print duplicated lines. diff --git a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs index e13ad1c95bd04..6a737d120e262 100644 --- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs +++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs @@ -2,8 +2,8 @@ use super::{CompileTimeEvalContext, CompileTimeInterpreter, ConstEvalErr}; use crate::interpret::eval_nullary_intrinsic; use crate::interpret::{ intern_const_alloc_recursive, Allocation, ConstAlloc, ConstValue, CtfeValidationMode, GlobalId, - Immediate, InternKind, InterpCx, InterpResult, MPlaceTy, MemoryKind, OpTy, RefTracking, - StackPopCleanup, + Immediate, InternKind, InterpCx, InterpError, InterpResult, MPlaceTy, MemoryKind, OpTy, + RefTracking, StackPopCleanup, }; use rustc_hir::def::DefKind; @@ -385,7 +385,9 @@ pub fn eval_to_allocation_raw_provider<'tcx>( ecx.tcx, "it is undefined behavior to use this value", |diag| { - diag.note(NOTE_ON_UNDEFINED_BEHAVIOR_ERROR); + if matches!(err.error, InterpError::UndefinedBehavior(_)) { + diag.note(NOTE_ON_UNDEFINED_BEHAVIOR_ERROR); + } diag.note(&format!( "the raw bytes of the constant ({}", display_allocation( diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs index 6f3bd3bf4c52b..a8ec8447f64a4 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs @@ -687,10 +687,23 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let layout = self.layout_of(lhs.layout.ty.builtin_deref(true).unwrap().ty)?; assert!(!layout.is_unsized()); - let lhs = self.read_pointer(lhs)?; - let rhs = self.read_pointer(rhs)?; - let lhs_bytes = self.read_bytes_ptr(lhs, layout.size)?; - let rhs_bytes = self.read_bytes_ptr(rhs, layout.size)?; + let get_bytes = |this: &InterpCx<'mir, 'tcx, M>, + op: &OpTy<'tcx, >::Provenance>, + size| + -> InterpResult<'tcx, &[u8]> { + let ptr = this.read_pointer(op)?; + let Some(alloc_ref) = self.get_ptr_alloc(ptr, size, Align::ONE)? else { + // zero-sized access + return Ok(&[]); + }; + if alloc_ref.has_provenance() { + throw_ub_format!("`raw_eq` on bytes with provenance"); + } + alloc_ref.get_bytes_strip_provenance() + }; + + let lhs_bytes = get_bytes(self, lhs, layout.size)?; + let rhs_bytes = get_bytes(self, rhs, layout.size)?; Ok(Scalar::from_bool(lhs_bytes == rhs_bytes)) } } diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs index f84c6017dbf6d..69dbc9592fa87 100644 --- a/compiler/rustc_const_eval/src/interpret/memory.rs +++ b/compiler/rustc_const_eval/src/interpret/memory.rs @@ -953,10 +953,10 @@ impl<'tcx, 'a, Prov: Provenance, Extra> AllocRef<'a, 'tcx, Prov, Extra> { } /// `range` is relative to this allocation reference, not the base of the allocation. - pub fn check_bytes(&self, range: AllocRange) -> InterpResult<'tcx> { + pub fn get_bytes_strip_provenance<'b>(&'b self) -> InterpResult<'tcx, &'a [u8]> { Ok(self .alloc - .check_bytes(&self.tcx, self.range.subrange(range)) + .get_bytes_strip_provenance(&self.tcx, self.range) .map_err(|e| e.to_interp_error(self.alloc_id))?) } @@ -967,10 +967,11 @@ impl<'tcx, 'a, Prov: Provenance, Extra> AllocRef<'a, 'tcx, Prov, Extra> { } impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { - /// Reads the given number of bytes from memory. Returns them as a slice. + /// Reads the given number of bytes from memory, and strips their provenance if possible. + /// Returns them as a slice. /// /// Performs appropriate bounds checks. - pub fn read_bytes_ptr( + pub fn read_bytes_ptr_strip_provenance( &self, ptr: Pointer>, size: Size, @@ -983,7 +984,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // (We are staying inside the bounds here so all is good.) Ok(alloc_ref .alloc - .get_bytes(&alloc_ref.tcx, alloc_ref.range) + .get_bytes_strip_provenance(&alloc_ref.tcx, alloc_ref.range) .map_err(|e| e.to_interp_error(alloc_ref.alloc_id))?) } @@ -1078,12 +1079,15 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { return Ok(()); }; - // This checks provenance edges on the src, which needs to happen before + // Checks provenance edges on the src, which needs to happen before // `prepare_provenance_copy`. - let src_bytes = src_alloc - .get_bytes_with_uninit_and_ptr(&tcx, src_range) - .map_err(|e| e.to_interp_error(src_alloc_id))? - .as_ptr(); // raw ptr, so we can also get a ptr to the destination allocation + if src_alloc.range_has_provenance(&tcx, alloc_range(src_range.start, Size::ZERO)) { + throw_unsup!(PartialPointerCopy(Pointer::new(src_alloc_id, src_range.start))); + } + if src_alloc.range_has_provenance(&tcx, alloc_range(src_range.end(), Size::ZERO)) { + throw_unsup!(PartialPointerCopy(Pointer::new(src_alloc_id, src_range.end()))); + } + let src_bytes = src_alloc.get_bytes_unchecked(src_range).as_ptr(); // raw ptr, so we can also get a ptr to the destination allocation // first copy the provenance to a temporary buffer, because // `get_bytes_mut` will clear the provenance, which is correct, // since we don't want to keep any provenance at the target. diff --git a/compiler/rustc_const_eval/src/interpret/operand.rs b/compiler/rustc_const_eval/src/interpret/operand.rs index e80a82acd585b..6ec9b174f82ae 100644 --- a/compiler/rustc_const_eval/src/interpret/operand.rs +++ b/compiler/rustc_const_eval/src/interpret/operand.rs @@ -415,7 +415,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { /// Turn the wide MPlace into a string (must already be dereferenced!) pub fn read_str(&self, mplace: &MPlaceTy<'tcx, M::Provenance>) -> InterpResult<'tcx, &str> { let len = mplace.len(self)?; - let bytes = self.read_bytes_ptr(mplace.ptr, Size::from_bytes(len))?; + let bytes = self.read_bytes_ptr_strip_provenance(mplace.ptr, Size::from_bytes(len))?; let str = std::str::from_utf8(bytes).map_err(|err| err_ub!(InvalidStr(err)))?; Ok(str) } diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs index 7aa76fe1dae0a..d7841ba6670a1 100644 --- a/compiler/rustc_const_eval/src/interpret/place.rs +++ b/compiler/rustc_const_eval/src/interpret/place.rs @@ -2,8 +2,6 @@ //! into a place. //! All high-level functions to write to memory work on places as destinations. -use std::hash::Hash; - use rustc_ast::Mutability; use rustc_middle::mir; use rustc_middle::ty; @@ -290,7 +288,7 @@ impl<'tcx, Prov: Provenance> PlaceTy<'tcx, Prov> { // FIXME: Working around https://github.com/rust-lang/rust/issues/54385 impl<'mir, 'tcx: 'mir, Prov, M> InterpCx<'mir, 'tcx, M> where - Prov: Provenance + Eq + Hash + 'static, + Prov: Provenance + 'static, M: Machine<'mir, 'tcx, Provenance = Prov>, { /// Take a value, which represents a (thin or wide) reference, and make it a place. diff --git a/compiler/rustc_const_eval/src/interpret/projection.rs b/compiler/rustc_const_eval/src/interpret/projection.rs index 742339f2b0aff..a800553f34e24 100644 --- a/compiler/rustc_const_eval/src/interpret/projection.rs +++ b/compiler/rustc_const_eval/src/interpret/projection.rs @@ -7,8 +7,6 @@ //! but we still need to do bounds checking and adjust the layout. To not duplicate that with MPlaceTy, we actually //! implement the logic on OpTy, and MPlaceTy calls that. -use std::hash::Hash; - use rustc_middle::mir; use rustc_middle::ty; use rustc_middle::ty::layout::LayoutOf; @@ -22,7 +20,7 @@ use super::{ // FIXME: Working around https://github.com/rust-lang/rust/issues/54385 impl<'mir, 'tcx: 'mir, Prov, M> InterpCx<'mir, 'tcx, M> where - Prov: Provenance + Eq + Hash + 'static, + Prov: Provenance + 'static, M: Machine<'mir, 'tcx, Provenance = Prov>, { //# Field access diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs index e1555f6873777..ee55b4a0750f6 100644 --- a/compiler/rustc_const_eval/src/interpret/validity.rs +++ b/compiler/rustc_const_eval/src/interpret/validity.rs @@ -20,8 +20,8 @@ use rustc_target::abi::{Abi, Scalar as ScalarAbi, Size, VariantIdx, Variants, Wr use std::hash::Hash; use super::{ - alloc_range, CheckInAllocMsg, GlobalAlloc, ImmTy, Immediate, InterpCx, InterpResult, MPlaceTy, - Machine, MemPlaceMeta, OpTy, Scalar, ValueVisitor, + CheckInAllocMsg, GlobalAlloc, ImmTy, Immediate, InterpCx, InterpResult, MPlaceTy, Machine, + MemPlaceMeta, OpTy, Scalar, ValueVisitor, }; macro_rules! throw_validation_failure { @@ -312,7 +312,6 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, ' Ok(try_validation!( self.ecx.read_immediate(op), self.path, - err_unsup!(ReadPointerAsBytes) => { "(potentially part of) a pointer" } expected { "{expected}" }, err_ub!(InvalidUninitBytes(None)) => { "uninitialized memory" } expected { "{expected}" } )) } @@ -345,11 +344,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, ' // FIXME: check if the type/trait match what ty::Dynamic says? } ty::Slice(..) | ty::Str => { - let _len = try_validation!( - meta.unwrap_meta().to_machine_usize(self.ecx), - self.path, - err_unsup!(ReadPointerAsBytes) => { "non-integer slice length in wide pointer" }, - ); + let _len = meta.unwrap_meta().to_machine_usize(self.ecx)?; // We do not check that `len * elem_size <= isize::MAX`: // that is only required for references, and there it falls out of the // "dereferenceable" check performed by Stacked Borrows. @@ -669,8 +664,6 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M> { "{:x}", val } expected { "a valid enum tag" }, err_ub!(InvalidUninitBytes(None)) => { "uninitialized bytes" } expected { "a valid enum tag" }, - err_unsup!(ReadPointerAsBytes) => - { "a pointer" } expected { "a valid enum tag" }, ) .1) }) @@ -810,10 +803,9 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M> let mplace = op.assert_mem_place(); // strings are unsized and hence never immediate let len = mplace.len(self.ecx)?; try_validation!( - self.ecx.read_bytes_ptr(mplace.ptr, Size::from_bytes(len)), + self.ecx.read_bytes_ptr_strip_provenance(mplace.ptr, Size::from_bytes(len)), self.path, err_ub!(InvalidUninitBytes(..)) => { "uninitialized data in `str`" }, - err_unsup!(ReadPointerAsBytes) => { "a pointer in `str`" }, ); } ty::Array(tys, ..) | ty::Slice(tys) @@ -861,9 +853,9 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M> // We also accept uninit, for consistency with the slow path. let alloc = self.ecx.get_ptr_alloc(mplace.ptr, size, mplace.align)?.expect("we already excluded size 0"); - match alloc.check_bytes(alloc_range(Size::ZERO, size)) { + match alloc.get_bytes_strip_provenance() { // In the happy case, we needn't check anything else. - Ok(()) => {} + Ok(_) => {} // Some error happened, try to provide a more detailed description. Err(err) => { // For some errors we might be able to provide extra information. @@ -881,9 +873,6 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M> throw_validation_failure!(self.path, { "uninitialized bytes" }) } - err_unsup!(ReadPointerAsBytes) => { - throw_validation_failure!(self.path, { "a pointer" } expected { "plain (non-pointer) bytes" }) - } // Propagate upwards (that will also check for unexpected errors). _ => return Err(err), @@ -924,14 +913,14 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { Ok(()) => Ok(()), // Pass through validation failures. Err(err) if matches!(err.kind(), err_ub!(ValidationFailure { .. })) => Err(err), - // Also pass through InvalidProgram, those just indicate that we could not - // validate and each caller will know best what to do with them. - Err(err) if matches!(err.kind(), InterpError::InvalidProgram(_)) => Err(err), - // Avoid other errors as those do not show *where* in the value the issue lies. - Err(err) => { + // Complain about any other kind of UB error -- those are bad because we'd like to + // report them in a way that shows *where* in the value the issue lies. + Err(err) if matches!(err.kind(), InterpError::UndefinedBehavior(_)) => { err.print_backtrace(); - bug!("Unexpected error during validation: {}", err); + bug!("Unexpected Undefined Behavior error during validation: {}", err); } + // Pass through everything else. + Err(err) => Err(err), } } diff --git a/compiler/rustc_middle/src/mir/interpret/allocation.rs b/compiler/rustc_middle/src/mir/interpret/allocation.rs index cc39e434225f6..37ec04b07f847 100644 --- a/compiler/rustc_middle/src/mir/interpret/allocation.rs +++ b/compiler/rustc_middle/src/mir/interpret/allocation.rs @@ -130,6 +130,8 @@ pub enum AllocError { ReadPointerAsBytes, /// Partially overwriting a pointer. PartialPointerOverwrite(Size), + /// Partially copying a pointer. + PartialPointerCopy(Size), /// Using uninitialized data where it is not allowed. InvalidUninitBytes(Option), } @@ -152,6 +154,9 @@ impl AllocError { PartialPointerOverwrite(offset) => InterpError::Unsupported( UnsupportedOpInfo::PartialPointerOverwrite(Pointer::new(alloc_id, offset)), ), + PartialPointerCopy(offset) => InterpError::Unsupported( + UnsupportedOpInfo::PartialPointerCopy(Pointer::new(alloc_id, offset)), + ), InvalidUninitBytes(info) => InterpError::UndefinedBehavior( UndefinedBehaviorInfo::InvalidUninitBytes(info.map(|b| (alloc_id, b))), ), @@ -322,62 +327,35 @@ impl Allocation { /// Byte accessors. impl Allocation { /// This is the entirely abstraction-violating way to just grab the raw bytes without - /// caring about provenance. It just deduplicates some code between `read_scalar` - /// and `get_bytes_internal`. - fn get_bytes_even_more_internal(&self, range: AllocRange) -> &[u8] { - &self.bytes[range.start.bytes_usize()..range.end().bytes_usize()] - } - - /// The last argument controls whether we error out when there are uninitialized or pointer - /// bytes. However, we *always* error when there is provenance overlapping the edges of the - /// range. - /// - /// You should never call this, call `get_bytes` or `get_bytes_with_uninit_and_ptr` instead, + /// caring about provenance or initialization. /// /// This function also guarantees that the resulting pointer will remain stable /// even when new allocations are pushed to the `HashMap`. `mem_copy_repeatedly` relies /// on that. - /// - /// It is the caller's responsibility to check bounds and alignment beforehand. - fn get_bytes_internal( - &self, - cx: &impl HasDataLayout, - range: AllocRange, - check_init_and_ptr: bool, - ) -> AllocResult<&[u8]> { - if check_init_and_ptr { - self.check_init(range)?; - self.check_provenance(cx, range)?; - } else { - // We still don't want provenance on the *edges*. - self.check_provenance_edges(cx, range)?; - } - - Ok(self.get_bytes_even_more_internal(range)) + #[inline] + pub fn get_bytes_unchecked(&self, range: AllocRange) -> &[u8] { + &self.bytes[range.start.bytes_usize()..range.end().bytes_usize()] } - /// Checks that these bytes are initialized and not pointer bytes, and then return them - /// as a slice. + /// Checks that these bytes are initialized, and then strip provenance (if possible) and return + /// them. /// /// It is the caller's responsibility to check bounds and alignment beforehand. /// Most likely, you want to use the `PlaceTy` and `OperandTy`-based methods /// on `InterpCx` instead. #[inline] - pub fn get_bytes(&self, cx: &impl HasDataLayout, range: AllocRange) -> AllocResult<&[u8]> { - self.get_bytes_internal(cx, range, true) - } - - /// It is the caller's responsibility to handle uninitialized and pointer bytes. - /// However, this still checks that there is no provenance on the *edges*. - /// - /// It is the caller's responsibility to check bounds and alignment beforehand. - #[inline] - pub fn get_bytes_with_uninit_and_ptr( + pub fn get_bytes_strip_provenance( &self, cx: &impl HasDataLayout, range: AllocRange, ) -> AllocResult<&[u8]> { - self.get_bytes_internal(cx, range, false) + self.check_init(range)?; + if !Prov::OFFSET_IS_ADDR { + if self.range_has_provenance(cx, range) { + return Err(AllocError::ReadPointerAsBytes); + } + } + Ok(self.get_bytes_unchecked(range)) } /// Just calling this already marks everything as defined and removes provenance, @@ -415,13 +393,6 @@ impl Allocation { /// Reading and writing. impl Allocation { - /// Validates that this memory range is initiailized and contains no provenance. - pub fn check_bytes(&self, cx: &impl HasDataLayout, range: AllocRange) -> AllocResult { - // This implicitly does all the checking we are asking for. - self.get_bytes(cx, range)?; - Ok(()) - } - /// Reads a *non-ZST* scalar. /// /// If `read_provenance` is `true`, this will also read provenance; otherwise (if the machine @@ -438,43 +409,53 @@ impl Allocation { range: AllocRange, read_provenance: bool, ) -> AllocResult> { - if read_provenance { - assert_eq!(range.size, cx.data_layout().pointer_size); - } - // First and foremost, if anything is uninit, bail. if self.is_init(range).is_err() { return Err(AllocError::InvalidUninitBytes(None)); } - // If we are doing a pointer read, and there is provenance exactly where we - // are reading, then we can put data and provenance back together and return that. - if read_provenance && let Some(&prov) = self.provenance.get(&range.start) { - // We already checked init and provenance, so we can use this function. - let bytes = self.get_bytes_even_more_internal(range); - let bits = read_target_uint(cx.data_layout().endian, bytes).unwrap(); - let ptr = Pointer::new(prov, Size::from_bytes(bits)); - return Ok(Scalar::from_pointer(ptr, cx)); - } + // Get the integer part of the result. We HAVE TO check provenance before returning this! + let bytes = self.get_bytes_unchecked(range); + let bits = read_target_uint(cx.data_layout().endian, bytes).unwrap(); - // If we are *not* reading a pointer, and we can just ignore provenance, - // then do exactly that. - if !read_provenance && Prov::OFFSET_IS_ADDR { - // We just strip provenance. - let bytes = self.get_bytes_even_more_internal(range); - let bits = read_target_uint(cx.data_layout().endian, bytes).unwrap(); - return Ok(Scalar::from_uint(bits, range.size)); + if read_provenance { + assert_eq!(range.size, cx.data_layout().pointer_size); + + // When reading data with provenance, the easy case is finding provenance exactly where we + // are reading, then we can put data and provenance back together and return that. + if let Some(&prov) = self.provenance.get(&range.start) { + // Now we can return the bits, with their appropriate provenance. + let ptr = Pointer::new(prov, Size::from_bytes(bits)); + return Ok(Scalar::from_pointer(ptr, cx)); + } + + // If we can work on pointers byte-wise, join the byte-wise provenances. + if Prov::OFFSET_IS_ADDR { + let mut prov = self.offset_get_provenance(cx, range.start); + for offset in 1..range.size.bytes() { + let this_prov = + self.offset_get_provenance(cx, range.start + Size::from_bytes(offset)); + prov = Prov::join(prov, this_prov); + } + // Now use this provenance. + let ptr = Pointer::new(prov, Size::from_bytes(bits)); + return Ok(Scalar::from_maybe_pointer(ptr, cx)); + } + } else { + // We are *not* reading a pointer. + // If we can just ignore provenance, do exactly that. + if Prov::OFFSET_IS_ADDR { + // We just strip provenance. + return Ok(Scalar::from_uint(bits, range.size)); + } } - // It's complicated. Better make sure there is no provenance anywhere. - // FIXME: If !OFFSET_IS_ADDR, this is the best we can do. But if OFFSET_IS_ADDR, then - // `read_pointer` is true and we ideally would distinguish the following two cases: - // - The entire `range` is covered by the same provenance, stored in two separate entries of - // the provenance map. Then we should return a pointer with that provenance. - // - The range has inhomogeneous provenance. Then we should return just the - // underlying bits. - let bytes = self.get_bytes(cx, range)?; - let bits = read_target_uint(cx.data_layout().endian, bytes).unwrap(); + // Fallback path for when we cannot treat provenance bytewise or ignore it. + assert!(!Prov::OFFSET_IS_ADDR); + if self.range_has_provenance(cx, range) { + return Err(AllocError::ReadPointerAsBytes); + } + // There is no provenance, we can just return the bits. Ok(Scalar::from_uint(bits, range.size)) } @@ -534,6 +515,13 @@ impl Allocation { self.provenance.range(Size::from_bytes(start)..range.end()) } + /// Get the provenance of a single byte. + fn offset_get_provenance(&self, cx: &impl HasDataLayout, offset: Size) -> Option { + let prov = self.range_get_provenance(cx, alloc_range(offset, Size::from_bytes(1))); + assert!(prov.len() <= 1); + prov.first().map(|(_offset, prov)| *prov) + } + /// Returns whether this allocation has progrnance overlapping with the given range. /// /// Note: this function exists to allow `range_get_provenance` to be private, in order to somewhat @@ -543,12 +531,6 @@ impl Allocation { !self.range_get_provenance(cx, range).is_empty() } - /// Checks that there is no provenance overlapping with the given range. - #[inline(always)] - fn check_provenance(&self, cx: &impl HasDataLayout, range: AllocRange) -> AllocResult { - if self.range_has_provenance(cx, range) { Err(AllocError::ReadPointerAsBytes) } else { Ok(()) } - } - /// Removes all provenance inside the given range. /// If there is provenance overlapping with the edges, it /// are removed as well *and* the bytes they cover are marked as @@ -606,14 +588,6 @@ impl Allocation { Ok(()) } - - /// Errors if there is provenance overlapping with the edges of the given memory range. - #[inline] - fn check_provenance_edges(&self, cx: &impl HasDataLayout, range: AllocRange) -> AllocResult { - self.check_provenance(cx, alloc_range(range.start, Size::ZERO))?; - self.check_provenance(cx, alloc_range(range.end(), Size::ZERO))?; - Ok(()) - } } /// Stores the provenance information of pointers stored in memory. diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs index cecb55578d332..e4039cc7c685a 100644 --- a/compiler/rustc_middle/src/mir/interpret/error.rs +++ b/compiler/rustc_middle/src/mir/interpret/error.rs @@ -401,14 +401,18 @@ impl fmt::Display for UndefinedBehaviorInfo { pub enum UnsupportedOpInfo { /// Free-form case. Only for errors that are never caught! Unsupported(String), - /// Encountered a pointer where we needed raw bytes. - ReadPointerAsBytes, /// Overwriting parts of a pointer; the resulting state cannot be represented in our /// `Allocation` data structure. See . PartialPointerOverwrite(Pointer), + /// Attempting to `copy` parts of a pointer to somewhere else; the resulting state cannot be + /// represented in our `Allocation` data structure. See + /// . + PartialPointerCopy(Pointer), // // The variants below are only reachable from CTFE/const prop, miri will never emit them. // + /// Encountered a pointer where we needed raw bytes. + ReadPointerAsBytes, /// Accessing thread local statics ThreadLocalStatic(DefId), /// Accessing an unsupported extern static. @@ -420,10 +424,13 @@ impl fmt::Display for UnsupportedOpInfo { use UnsupportedOpInfo::*; match self { Unsupported(ref msg) => write!(f, "{msg}"), - ReadPointerAsBytes => write!(f, "unable to turn pointer into raw bytes"), PartialPointerOverwrite(ptr) => { write!(f, "unable to overwrite parts of a pointer in memory at {ptr:?}") } + PartialPointerCopy(ptr) => { + write!(f, "unable to copy parts of a pointer from memory at {ptr:?}") + } + ReadPointerAsBytes => write!(f, "unable to turn pointer into raw bytes"), ThreadLocalStatic(did) => write!(f, "cannot access thread local static ({did:?})"), ReadExternStatic(did) => write!(f, "cannot read from extern static ({did:?})"), } diff --git a/compiler/rustc_middle/src/mir/interpret/pointer.rs b/compiler/rustc_middle/src/mir/interpret/pointer.rs index 384954cbbd5f7..5fa802236edd3 100644 --- a/compiler/rustc_middle/src/mir/interpret/pointer.rs +++ b/compiler/rustc_middle/src/mir/interpret/pointer.rs @@ -125,6 +125,9 @@ pub trait Provenance: Copy + fmt::Debug { /// Otherwise this function is best-effort (but must agree with `Machine::ptr_get_alloc`). /// (Identifying the offset in that allocation, however, is harder -- use `Memory::ptr_get_alloc` for that.) fn get_alloc_id(self) -> Option; + + /// Defines the 'join' of provenance: what happens when doing a pointer load and different bytes have different provenance. + fn join(left: Option, right: Option) -> Option; } impl Provenance for AllocId { @@ -152,6 +155,10 @@ impl Provenance for AllocId { fn get_alloc_id(self) -> Option { Some(self) } + + fn join(_left: Option, _right: Option) -> Option { + panic!("merging provenance is not supported when `OFFSET_IS_ADDR` is false") + } } /// Represents a pointer in the Miri engine. diff --git a/compiler/rustc_middle/src/mir/interpret/value.rs b/compiler/rustc_middle/src/mir/interpret/value.rs index 1ba16025e3218..d4fad7f1ecdd9 100644 --- a/compiler/rustc_middle/src/mir/interpret/value.rs +++ b/compiler/rustc_middle/src/mir/interpret/value.rs @@ -507,7 +507,7 @@ pub fn get_slice_bytes<'tcx>(cx: &impl HasDataLayout, val: ConstValue<'tcx>) -> if let ConstValue::Slice { data, start, end } = val { let len = end - start; data.inner() - .get_bytes( + .get_bytes_strip_provenance( cx, AllocRange { start: Size::from_bytes(start), size: Size::from_bytes(len) }, ) diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 4e886ff159218..75327cff368d3 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -2719,7 +2719,7 @@ fn pretty_print_const_value<'tcx>( let n = n.kind().try_to_bits(tcx.data_layout.pointer_size).unwrap(); // cast is ok because we already checked for pointer size (32 or 64 bit) above let range = AllocRange { start: offset, size: Size::from_bytes(n) }; - let byte_str = alloc.inner().get_bytes(&tcx, range).unwrap(); + let byte_str = alloc.inner().get_bytes_strip_provenance(&tcx, range).unwrap(); fmt.write_str("*")?; pretty_print_byte_str(fmt, byte_str)?; return Ok(()); diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index cc55b7e8611af..2dfbcb7fa318f 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -1275,7 +1275,7 @@ pub trait PrettyPrinter<'tcx>: let range = AllocRange { start: offset, size: Size::from_bytes(len) }; if let Ok(byte_str) = - alloc.inner().get_bytes(&self.tcx(), range) + alloc.inner().get_bytes_strip_provenance(&self.tcx(), range) { p!(pretty_print_byte_str(byte_str)) } else { From cf2c65b251cb05a2dae55b4ab9a8ca65f44189cb Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 27 Aug 2022 17:46:14 -0400 Subject: [PATCH 3/5] adjust tests --- .../const-ptr/forbidden_slices.32bit.stderr | 10 +- .../const-ptr/forbidden_slices.64bit.stderr | 10 +- ...inter-values-in-various-types.64bit.stderr | 108 ++++++++++++++++++ .../const-eval/partial_ptr_overwrite.stderr | 4 + .../const-eval/ref_to_int_match.32bit.stderr | 4 + .../const-eval/ref_to_int_match.64bit.stderr | 4 + .../ui/consts/const-eval/ub-enum.32bit.stderr | 20 ++++ .../ui/consts/const-eval/ub-enum.64bit.stderr | 20 ++++ .../consts/const-eval/ub-ref-ptr.32bit.stderr | 12 ++ .../consts/const-eval/ub-ref-ptr.64bit.stderr | 12 ++ .../const-eval/ub-wide-ptr.32bit.stderr | 16 +++ .../const-eval/ub-wide-ptr.64bit.stderr | 16 +++ .../consts/extra-const-ub/detect-extra-ub.rs | 8 +- .../detect-extra-ub.with_flag.stderr | 56 ++++++++- src/test/ui/consts/issue-83182.32bit.stderr | 5 +- src/test/ui/consts/issue-83182.64bit.stderr | 5 +- src/test/ui/consts/issue-83182.rs | 1 - src/test/ui/consts/issue-miri-1910.rs | 1 + src/test/ui/consts/issue-miri-1910.stderr | 16 ++- .../ui/consts/miri_unleashed/ptr_arith.stderr | 3 + src/test/ui/consts/ptr_comparisons.stderr | 8 ++ 21 files changed, 311 insertions(+), 28 deletions(-) diff --git a/src/test/ui/const-ptr/forbidden_slices.32bit.stderr b/src/test/ui/const-ptr/forbidden_slices.32bit.stderr index f3bf9c496da7b..82a3c92e66fdf 100644 --- a/src/test/ui/const-ptr/forbidden_slices.32bit.stderr +++ b/src/test/ui/const-ptr/forbidden_slices.32bit.stderr @@ -55,9 +55,10 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/forbidden_slices.rs:27:1 | LL | pub static S5: &[u8] = unsafe { from_raw_parts((&D3) as *const _ as _, size_of::<&u32>()) }; - | ^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .: encountered a pointer, but expected plain (non-pointer) bytes + | ^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes | - = 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. + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported = note: the raw bytes of the constant (size: 8, align: 4) { ╾─ALLOC_ID─╼ 04 00 00 00 │ ╾──╼.... } @@ -170,9 +171,10 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/forbidden_slices.rs:57:1 | LL | pub static R5: &[u8] = unsafe { - | ^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .: encountered a pointer, but expected plain (non-pointer) bytes + | ^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes | - = 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. + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported = note: the raw bytes of the constant (size: 8, align: 4) { ╾ALLOC_ID─╼ 04 00 00 00 │ ╾──╼.... } diff --git a/src/test/ui/const-ptr/forbidden_slices.64bit.stderr b/src/test/ui/const-ptr/forbidden_slices.64bit.stderr index 5f2821a91937b..f88746af9769d 100644 --- a/src/test/ui/const-ptr/forbidden_slices.64bit.stderr +++ b/src/test/ui/const-ptr/forbidden_slices.64bit.stderr @@ -55,9 +55,10 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/forbidden_slices.rs:27:1 | LL | pub static S5: &[u8] = unsafe { from_raw_parts((&D3) as *const _ as _, size_of::<&u32>()) }; - | ^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .: encountered a pointer, but expected plain (non-pointer) bytes + | ^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes | - = 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. + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported = note: the raw bytes of the constant (size: 16, align: 8) { ╾───────ALLOC_ID───────╼ 08 00 00 00 00 00 00 00 │ ╾──────╼........ } @@ -170,9 +171,10 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/forbidden_slices.rs:57:1 | LL | pub static R5: &[u8] = unsafe { - | ^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .: encountered a pointer, but expected plain (non-pointer) bytes + | ^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes | - = 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. + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported = note: the raw bytes of the constant (size: 16, align: 8) { ╾──────ALLOC_ID───────╼ 08 00 00 00 00 00 00 00 │ ╾──────╼........ } diff --git a/src/test/ui/consts/const-eval/const-pointer-values-in-various-types.64bit.stderr b/src/test/ui/consts/const-eval/const-pointer-values-in-various-types.64bit.stderr index 82afa70309da0..12d5b7bd6bbc2 100644 --- a/src/test/ui/consts/const-eval/const-pointer-values-in-various-types.64bit.stderr +++ b/src/test/ui/consts/const-eval/const-pointer-values-in-various-types.64bit.stderr @@ -7,6 +7,8 @@ LL | const I32_REF_USIZE_UNION: usize = unsafe { Nonsense { int_32_ref: &3 } = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported error: any use of this value will cause an error --> $DIR/const-pointer-values-in-various-types.rs:30:43 @@ -16,6 +18,8 @@ LL | const I32_REF_U8_UNION: u8 = unsafe { Nonsense { int_32_ref: &3 }.uint_ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported error: any use of this value will cause an error --> $DIR/const-pointer-values-in-various-types.rs:34:45 @@ -25,6 +29,8 @@ LL | const I32_REF_U16_UNION: u16 = unsafe { Nonsense { int_32_ref: &3 }.uin | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported error: any use of this value will cause an error --> $DIR/const-pointer-values-in-various-types.rs:38:45 @@ -34,6 +40,8 @@ LL | const I32_REF_U32_UNION: u32 = unsafe { Nonsense { int_32_ref: &3 }.uin | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported error: any use of this value will cause an error --> $DIR/const-pointer-values-in-various-types.rs:42:45 @@ -43,6 +51,8 @@ LL | const I32_REF_U64_UNION: u64 = unsafe { Nonsense { int_32_ref: &3 }.uin | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported error[E0080]: evaluation of constant value failed --> $DIR/const-pointer-values-in-various-types.rs:46:47 @@ -58,6 +68,8 @@ LL | const I32_REF_I8_UNION: i8 = unsafe { Nonsense { int_32_ref: &3 }.int_8 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported error: any use of this value will cause an error --> $DIR/const-pointer-values-in-various-types.rs:54:45 @@ -67,6 +79,8 @@ LL | const I32_REF_I16_UNION: i16 = unsafe { Nonsense { int_32_ref: &3 }.int | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported error: any use of this value will cause an error --> $DIR/const-pointer-values-in-various-types.rs:58:45 @@ -76,6 +90,8 @@ LL | const I32_REF_I32_UNION: i32 = unsafe { Nonsense { int_32_ref: &3 }.int | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported error: any use of this value will cause an error --> $DIR/const-pointer-values-in-various-types.rs:62:45 @@ -85,6 +101,8 @@ LL | const I32_REF_I64_UNION: i64 = unsafe { Nonsense { int_32_ref: &3 }.int | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported error[E0080]: evaluation of constant value failed --> $DIR/const-pointer-values-in-various-types.rs:66:47 @@ -100,6 +118,8 @@ LL | const I32_REF_F32_UNION: f32 = unsafe { Nonsense { int_32_ref: &3 }.flo | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported error: any use of this value will cause an error --> $DIR/const-pointer-values-in-various-types.rs:74:45 @@ -109,6 +129,8 @@ LL | const I32_REF_F64_UNION: f64 = unsafe { Nonsense { int_32_ref: &3 }.flo | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported error: any use of this value will cause an error --> $DIR/const-pointer-values-in-various-types.rs:78:47 @@ -118,6 +140,8 @@ LL | const I32_REF_BOOL_UNION: bool = unsafe { Nonsense { int_32_ref: &3 }.t | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported error: any use of this value will cause an error --> $DIR/const-pointer-values-in-various-types.rs:82:47 @@ -127,6 +151,8 @@ LL | const I32_REF_CHAR_UNION: char = unsafe { Nonsense { int_32_ref: &3 }.c | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported error: any use of this value will cause an error --> $DIR/const-pointer-values-in-various-types.rs:86:39 @@ -136,6 +162,8 @@ LL | const STR_U8_UNION: u8 = unsafe { Nonsense { stringy: "3" }.uint_8 }; | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported error: any use of this value will cause an error --> $DIR/const-pointer-values-in-various-types.rs:90:41 @@ -145,6 +173,8 @@ LL | const STR_U16_UNION: u16 = unsafe { Nonsense { stringy: "3" }.uint_16 } | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported error: any use of this value will cause an error --> $DIR/const-pointer-values-in-various-types.rs:94:41 @@ -154,6 +184,8 @@ LL | const STR_U32_UNION: u32 = unsafe { Nonsense { stringy: "3" }.uint_32 } | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported error: any use of this value will cause an error --> $DIR/const-pointer-values-in-various-types.rs:98:41 @@ -163,6 +195,8 @@ LL | const STR_U64_UNION: u64 = unsafe { Nonsense { stringy: "3" }.uint_64 } | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported error: any use of this value will cause an error --> $DIR/const-pointer-values-in-various-types.rs:102:43 @@ -172,6 +206,8 @@ LL | const STR_U128_UNION: u128 = unsafe { Nonsense { stringy: "3" }.uint_12 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported error: any use of this value will cause an error --> $DIR/const-pointer-values-in-various-types.rs:106:39 @@ -181,6 +217,8 @@ LL | const STR_I8_UNION: i8 = unsafe { Nonsense { stringy: "3" }.int_8 }; | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported error: any use of this value will cause an error --> $DIR/const-pointer-values-in-various-types.rs:110:41 @@ -190,6 +228,8 @@ LL | const STR_I16_UNION: i16 = unsafe { Nonsense { stringy: "3" }.int_16 }; | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported error: any use of this value will cause an error --> $DIR/const-pointer-values-in-various-types.rs:114:41 @@ -199,6 +239,8 @@ LL | const STR_I32_UNION: i32 = unsafe { Nonsense { stringy: "3" }.int_32 }; | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported error: any use of this value will cause an error --> $DIR/const-pointer-values-in-various-types.rs:118:41 @@ -208,6 +250,8 @@ LL | const STR_I64_UNION: i64 = unsafe { Nonsense { stringy: "3" }.int_64 }; | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported error: any use of this value will cause an error --> $DIR/const-pointer-values-in-various-types.rs:122:43 @@ -217,6 +261,8 @@ LL | const STR_I128_UNION: i128 = unsafe { Nonsense { stringy: "3" }.int_128 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported error: any use of this value will cause an error --> $DIR/const-pointer-values-in-various-types.rs:126:41 @@ -226,6 +272,8 @@ LL | const STR_F32_UNION: f32 = unsafe { Nonsense { stringy: "3" }.float_32 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported error: any use of this value will cause an error --> $DIR/const-pointer-values-in-various-types.rs:130:41 @@ -235,6 +283,8 @@ LL | const STR_F64_UNION: f64 = unsafe { Nonsense { stringy: "3" }.float_64 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported error: any use of this value will cause an error --> $DIR/const-pointer-values-in-various-types.rs:134:43 @@ -244,6 +294,8 @@ LL | const STR_BOOL_UNION: bool = unsafe { Nonsense { stringy: "3" }.truthy_ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported error: any use of this value will cause an error --> $DIR/const-pointer-values-in-various-types.rs:138:43 @@ -253,6 +305,8 @@ LL | const STR_CHAR_UNION: char = unsafe { Nonsense { stringy: "3" }.charact | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported error: aborting due to 29 previous errors @@ -267,6 +321,8 @@ LL | const I32_REF_USIZE_UNION: usize = unsafe { Nonsense { int_32_ref: &3 } = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported Future breakage diagnostic: error: any use of this value will cause an error @@ -278,6 +334,8 @@ LL | const I32_REF_U8_UNION: u8 = unsafe { Nonsense { int_32_ref: &3 }.uint_ = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported Future breakage diagnostic: error: any use of this value will cause an error @@ -289,6 +347,8 @@ LL | const I32_REF_U16_UNION: u16 = unsafe { Nonsense { int_32_ref: &3 }.uin = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported Future breakage diagnostic: error: any use of this value will cause an error @@ -300,6 +360,8 @@ LL | const I32_REF_U32_UNION: u32 = unsafe { Nonsense { int_32_ref: &3 }.uin = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported Future breakage diagnostic: error: any use of this value will cause an error @@ -311,6 +373,8 @@ LL | const I32_REF_U64_UNION: u64 = unsafe { Nonsense { int_32_ref: &3 }.uin = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported Future breakage diagnostic: error: any use of this value will cause an error @@ -322,6 +386,8 @@ LL | const I32_REF_I8_UNION: i8 = unsafe { Nonsense { int_32_ref: &3 }.int_8 = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported Future breakage diagnostic: error: any use of this value will cause an error @@ -333,6 +399,8 @@ LL | const I32_REF_I16_UNION: i16 = unsafe { Nonsense { int_32_ref: &3 }.int = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported Future breakage diagnostic: error: any use of this value will cause an error @@ -344,6 +412,8 @@ LL | const I32_REF_I32_UNION: i32 = unsafe { Nonsense { int_32_ref: &3 }.int = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported Future breakage diagnostic: error: any use of this value will cause an error @@ -355,6 +425,8 @@ LL | const I32_REF_I64_UNION: i64 = unsafe { Nonsense { int_32_ref: &3 }.int = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported Future breakage diagnostic: error: any use of this value will cause an error @@ -366,6 +438,8 @@ LL | const I32_REF_F32_UNION: f32 = unsafe { Nonsense { int_32_ref: &3 }.flo = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported Future breakage diagnostic: error: any use of this value will cause an error @@ -377,6 +451,8 @@ LL | const I32_REF_F64_UNION: f64 = unsafe { Nonsense { int_32_ref: &3 }.flo = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported Future breakage diagnostic: error: any use of this value will cause an error @@ -388,6 +464,8 @@ LL | const I32_REF_BOOL_UNION: bool = unsafe { Nonsense { int_32_ref: &3 }.t = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported Future breakage diagnostic: error: any use of this value will cause an error @@ -399,6 +477,8 @@ LL | const I32_REF_CHAR_UNION: char = unsafe { Nonsense { int_32_ref: &3 }.c = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported Future breakage diagnostic: error: any use of this value will cause an error @@ -410,6 +490,8 @@ LL | const STR_U8_UNION: u8 = unsafe { Nonsense { stringy: "3" }.uint_8 }; = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported Future breakage diagnostic: error: any use of this value will cause an error @@ -421,6 +503,8 @@ LL | const STR_U16_UNION: u16 = unsafe { Nonsense { stringy: "3" }.uint_16 } = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported Future breakage diagnostic: error: any use of this value will cause an error @@ -432,6 +516,8 @@ LL | const STR_U32_UNION: u32 = unsafe { Nonsense { stringy: "3" }.uint_32 } = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported Future breakage diagnostic: error: any use of this value will cause an error @@ -443,6 +529,8 @@ LL | const STR_U64_UNION: u64 = unsafe { Nonsense { stringy: "3" }.uint_64 } = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported Future breakage diagnostic: error: any use of this value will cause an error @@ -454,6 +542,8 @@ LL | const STR_U128_UNION: u128 = unsafe { Nonsense { stringy: "3" }.uint_12 = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported Future breakage diagnostic: error: any use of this value will cause an error @@ -465,6 +555,8 @@ LL | const STR_I8_UNION: i8 = unsafe { Nonsense { stringy: "3" }.int_8 }; = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported Future breakage diagnostic: error: any use of this value will cause an error @@ -476,6 +568,8 @@ LL | const STR_I16_UNION: i16 = unsafe { Nonsense { stringy: "3" }.int_16 }; = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported Future breakage diagnostic: error: any use of this value will cause an error @@ -487,6 +581,8 @@ LL | const STR_I32_UNION: i32 = unsafe { Nonsense { stringy: "3" }.int_32 }; = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported Future breakage diagnostic: error: any use of this value will cause an error @@ -498,6 +594,8 @@ LL | const STR_I64_UNION: i64 = unsafe { Nonsense { stringy: "3" }.int_64 }; = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported Future breakage diagnostic: error: any use of this value will cause an error @@ -509,6 +607,8 @@ LL | const STR_I128_UNION: i128 = unsafe { Nonsense { stringy: "3" }.int_128 = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported Future breakage diagnostic: error: any use of this value will cause an error @@ -520,6 +620,8 @@ LL | const STR_F32_UNION: f32 = unsafe { Nonsense { stringy: "3" }.float_32 = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported Future breakage diagnostic: error: any use of this value will cause an error @@ -531,6 +633,8 @@ LL | const STR_F64_UNION: f64 = unsafe { Nonsense { stringy: "3" }.float_64 = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported Future breakage diagnostic: error: any use of this value will cause an error @@ -542,6 +646,8 @@ LL | const STR_BOOL_UNION: bool = unsafe { Nonsense { stringy: "3" }.truthy_ = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported Future breakage diagnostic: error: any use of this value will cause an error @@ -553,4 +659,6 @@ LL | const STR_CHAR_UNION: char = unsafe { Nonsense { stringy: "3" }.charact = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported diff --git a/src/test/ui/consts/const-eval/partial_ptr_overwrite.stderr b/src/test/ui/consts/const-eval/partial_ptr_overwrite.stderr index b007dda246de3..75e50a27b3a83 100644 --- a/src/test/ui/consts/const-eval/partial_ptr_overwrite.stderr +++ b/src/test/ui/consts/const-eval/partial_ptr_overwrite.stderr @@ -10,6 +10,8 @@ LL | *(ptr as *mut u8) = 123; = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported error: aborting due to previous error @@ -26,4 +28,6 @@ LL | *(ptr as *mut u8) = 123; = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported diff --git a/src/test/ui/consts/const-eval/ref_to_int_match.32bit.stderr b/src/test/ui/consts/const-eval/ref_to_int_match.32bit.stderr index 0e37435881009..30935e41549bf 100644 --- a/src/test/ui/consts/const-eval/ref_to_int_match.32bit.stderr +++ b/src/test/ui/consts/const-eval/ref_to_int_match.32bit.stderr @@ -7,6 +7,8 @@ LL | const BAR: Int = unsafe { Foo { r: &42 }.f }; = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported error: could not evaluate constant pattern --> $DIR/ref_to_int_match.rs:7:14 @@ -32,4 +34,6 @@ LL | const BAR: Int = unsafe { Foo { r: &42 }.f }; = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported diff --git a/src/test/ui/consts/const-eval/ref_to_int_match.64bit.stderr b/src/test/ui/consts/const-eval/ref_to_int_match.64bit.stderr index 0e37435881009..30935e41549bf 100644 --- a/src/test/ui/consts/const-eval/ref_to_int_match.64bit.stderr +++ b/src/test/ui/consts/const-eval/ref_to_int_match.64bit.stderr @@ -7,6 +7,8 @@ LL | const BAR: Int = unsafe { Foo { r: &42 }.f }; = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported error: could not evaluate constant pattern --> $DIR/ref_to_int_match.rs:7:14 @@ -32,4 +34,6 @@ LL | const BAR: Int = unsafe { Foo { r: &42 }.f }; = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported diff --git a/src/test/ui/consts/const-eval/ub-enum.32bit.stderr b/src/test/ui/consts/const-eval/ub-enum.32bit.stderr index 1e80dd7c765da..752fd01f33805 100644 --- a/src/test/ui/consts/const-eval/ub-enum.32bit.stderr +++ b/src/test/ui/consts/const-eval/ub-enum.32bit.stderr @@ -18,6 +18,8 @@ LL | const BAD_ENUM_PTR: Enum = unsafe { mem::transmute(&1) }; = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported error: any use of this value will cause an error --> $DIR/ub-enum.rs:30:1 @@ -27,6 +29,8 @@ LL | const BAD_ENUM_WRAPPED: Wrap = unsafe { mem::transmute(&1) }; | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported error[E0080]: it is undefined behavior to use this value --> $DIR/ub-enum.rs:43:1 @@ -47,6 +51,8 @@ LL | const BAD_ENUM2_PTR: Enum2 = unsafe { mem::transmute(&0) }; | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported error: any use of this value will cause an error --> $DIR/ub-enum.rs:49:1 @@ -56,6 +62,8 @@ LL | const BAD_ENUM2_WRAPPED: Wrap = unsafe { mem::transmute(&0) }; | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported error[E0080]: evaluation of constant value failed --> $DIR/ub-enum.rs:59:42 @@ -71,6 +79,8 @@ LL | const BAD_ENUM2_OPTION_PTR: Option = unsafe { mem::transmute(&0) }; | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported error[E0080]: it is undefined behavior to use this value --> $DIR/ub-enum.rs:82:1 @@ -130,6 +140,8 @@ LL | const BAD_ENUM_PTR: Enum = unsafe { mem::transmute(&1) }; = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported Future breakage diagnostic: error: any use of this value will cause an error @@ -141,6 +153,8 @@ LL | const BAD_ENUM_WRAPPED: Wrap = unsafe { mem::transmute(&1) }; = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported Future breakage diagnostic: error: any use of this value will cause an error @@ -152,6 +166,8 @@ LL | const BAD_ENUM2_PTR: Enum2 = unsafe { mem::transmute(&0) }; = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported Future breakage diagnostic: error: any use of this value will cause an error @@ -163,6 +179,8 @@ LL | const BAD_ENUM2_WRAPPED: Wrap = unsafe { mem::transmute(&0) }; = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported Future breakage diagnostic: error: any use of this value will cause an error @@ -174,4 +192,6 @@ LL | const BAD_ENUM2_OPTION_PTR: Option = unsafe { mem::transmute(&0) }; = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported diff --git a/src/test/ui/consts/const-eval/ub-enum.64bit.stderr b/src/test/ui/consts/const-eval/ub-enum.64bit.stderr index a6208f30c22a0..3f1546a2786ca 100644 --- a/src/test/ui/consts/const-eval/ub-enum.64bit.stderr +++ b/src/test/ui/consts/const-eval/ub-enum.64bit.stderr @@ -18,6 +18,8 @@ LL | const BAD_ENUM_PTR: Enum = unsafe { mem::transmute(&1) }; = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported error: any use of this value will cause an error --> $DIR/ub-enum.rs:30:1 @@ -27,6 +29,8 @@ LL | const BAD_ENUM_WRAPPED: Wrap = unsafe { mem::transmute(&1) }; | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported error[E0080]: it is undefined behavior to use this value --> $DIR/ub-enum.rs:43:1 @@ -47,6 +51,8 @@ LL | const BAD_ENUM2_PTR: Enum2 = unsafe { mem::transmute(&0) }; | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported error: any use of this value will cause an error --> $DIR/ub-enum.rs:49:1 @@ -56,6 +62,8 @@ LL | const BAD_ENUM2_WRAPPED: Wrap = unsafe { mem::transmute(&0) }; | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported error[E0080]: evaluation of constant value failed --> $DIR/ub-enum.rs:59:42 @@ -71,6 +79,8 @@ LL | const BAD_ENUM2_OPTION_PTR: Option = unsafe { mem::transmute(&0) }; | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported error[E0080]: it is undefined behavior to use this value --> $DIR/ub-enum.rs:82:1 @@ -130,6 +140,8 @@ LL | const BAD_ENUM_PTR: Enum = unsafe { mem::transmute(&1) }; = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported Future breakage diagnostic: error: any use of this value will cause an error @@ -141,6 +153,8 @@ LL | const BAD_ENUM_WRAPPED: Wrap = unsafe { mem::transmute(&1) }; = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported Future breakage diagnostic: error: any use of this value will cause an error @@ -152,6 +166,8 @@ LL | const BAD_ENUM2_PTR: Enum2 = unsafe { mem::transmute(&0) }; = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported Future breakage diagnostic: error: any use of this value will cause an error @@ -163,6 +179,8 @@ LL | const BAD_ENUM2_WRAPPED: Wrap = unsafe { mem::transmute(&0) }; = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported Future breakage diagnostic: error: any use of this value will cause an error @@ -174,4 +192,6 @@ LL | const BAD_ENUM2_OPTION_PTR: Option = unsafe { mem::transmute(&0) }; = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported diff --git a/src/test/ui/consts/const-eval/ub-ref-ptr.32bit.stderr b/src/test/ui/consts/const-eval/ub-ref-ptr.32bit.stderr index 25560d8003d43..3e93219c86dc1 100644 --- a/src/test/ui/consts/const-eval/ub-ref-ptr.32bit.stderr +++ b/src/test/ui/consts/const-eval/ub-ref-ptr.32bit.stderr @@ -51,6 +51,8 @@ LL | const REF_AS_USIZE: usize = unsafe { mem::transmute(&0) }; = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported error: any use of this value will cause an error --> $DIR/ub-ref-ptr.rs:35:39 @@ -60,6 +62,8 @@ LL | const REF_AS_USIZE_SLICE: &[usize] = &[unsafe { mem::transmute(&0) }]; | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported error: any use of this value will cause an error --> $DIR/ub-ref-ptr.rs:35:38 @@ -78,6 +82,8 @@ LL | const REF_AS_USIZE_BOX_SLICE: Box<[usize]> = unsafe { mem::transmute::<&[us | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported error: any use of this value will cause an error --> $DIR/ub-ref-ptr.rs:41:85 @@ -168,6 +174,8 @@ LL | const REF_AS_USIZE: usize = unsafe { mem::transmute(&0) }; = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported Future breakage diagnostic: error: any use of this value will cause an error @@ -179,6 +187,8 @@ LL | const REF_AS_USIZE_SLICE: &[usize] = &[unsafe { mem::transmute(&0) }]; = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported Future breakage diagnostic: error: any use of this value will cause an error @@ -201,6 +211,8 @@ LL | const REF_AS_USIZE_BOX_SLICE: Box<[usize]> = unsafe { mem::transmute::<&[us = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported Future breakage diagnostic: error: any use of this value will cause an error diff --git a/src/test/ui/consts/const-eval/ub-ref-ptr.64bit.stderr b/src/test/ui/consts/const-eval/ub-ref-ptr.64bit.stderr index 8c86ddbfa5f9b..bc2aa12a2f31e 100644 --- a/src/test/ui/consts/const-eval/ub-ref-ptr.64bit.stderr +++ b/src/test/ui/consts/const-eval/ub-ref-ptr.64bit.stderr @@ -51,6 +51,8 @@ LL | const REF_AS_USIZE: usize = unsafe { mem::transmute(&0) }; = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported error: any use of this value will cause an error --> $DIR/ub-ref-ptr.rs:35:39 @@ -60,6 +62,8 @@ LL | const REF_AS_USIZE_SLICE: &[usize] = &[unsafe { mem::transmute(&0) }]; | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported error: any use of this value will cause an error --> $DIR/ub-ref-ptr.rs:35:38 @@ -78,6 +82,8 @@ LL | const REF_AS_USIZE_BOX_SLICE: Box<[usize]> = unsafe { mem::transmute::<&[us | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported error: any use of this value will cause an error --> $DIR/ub-ref-ptr.rs:41:85 @@ -168,6 +174,8 @@ LL | const REF_AS_USIZE: usize = unsafe { mem::transmute(&0) }; = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported Future breakage diagnostic: error: any use of this value will cause an error @@ -179,6 +187,8 @@ LL | const REF_AS_USIZE_SLICE: &[usize] = &[unsafe { mem::transmute(&0) }]; = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported Future breakage diagnostic: error: any use of this value will cause an error @@ -201,6 +211,8 @@ LL | const REF_AS_USIZE_BOX_SLICE: Box<[usize]> = unsafe { mem::transmute::<&[us = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported Future breakage diagnostic: error: any use of this value will cause an error diff --git a/src/test/ui/consts/const-eval/ub-wide-ptr.32bit.stderr b/src/test/ui/consts/const-eval/ub-wide-ptr.32bit.stderr index 09a877400d0a3..4cd974e7bf977 100644 --- a/src/test/ui/consts/const-eval/ub-wide-ptr.32bit.stderr +++ b/src/test/ui/consts/const-eval/ub-wide-ptr.32bit.stderr @@ -29,6 +29,8 @@ LL | const STR_LENGTH_PTR: &str = unsafe { mem::transmute((&42u8, &3)) }; = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported error: any use of this value will cause an error --> $DIR/ub-wide-ptr.rs:46:1 @@ -38,6 +40,8 @@ LL | const MY_STR_LENGTH_PTR: &MyStr = unsafe { mem::transmute((&42u8, &3)) }; | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:49:1 @@ -108,6 +112,8 @@ LL | const SLICE_LENGTH_PTR: &[u8] = unsafe { mem::transmute((&42u8, &3)) }; | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:80:1 @@ -128,6 +134,8 @@ LL | const SLICE_LENGTH_PTR_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, &3) | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:88:1 @@ -315,6 +323,8 @@ LL | const STR_LENGTH_PTR: &str = unsafe { mem::transmute((&42u8, &3)) }; = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported Future breakage diagnostic: error: any use of this value will cause an error @@ -326,6 +336,8 @@ LL | const MY_STR_LENGTH_PTR: &MyStr = unsafe { mem::transmute((&42u8, &3)) }; = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported Future breakage diagnostic: error: any use of this value will cause an error @@ -337,6 +349,8 @@ LL | const SLICE_LENGTH_PTR: &[u8] = unsafe { mem::transmute((&42u8, &3)) }; = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported Future breakage diagnostic: error: any use of this value will cause an error @@ -348,6 +362,8 @@ LL | const SLICE_LENGTH_PTR_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, &3) = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported Future breakage diagnostic: error: any use of this value will cause an error diff --git a/src/test/ui/consts/const-eval/ub-wide-ptr.64bit.stderr b/src/test/ui/consts/const-eval/ub-wide-ptr.64bit.stderr index 79fa7a83e8445..1d84b7bce1410 100644 --- a/src/test/ui/consts/const-eval/ub-wide-ptr.64bit.stderr +++ b/src/test/ui/consts/const-eval/ub-wide-ptr.64bit.stderr @@ -29,6 +29,8 @@ LL | const STR_LENGTH_PTR: &str = unsafe { mem::transmute((&42u8, &3)) }; = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported error: any use of this value will cause an error --> $DIR/ub-wide-ptr.rs:46:1 @@ -38,6 +40,8 @@ LL | const MY_STR_LENGTH_PTR: &MyStr = unsafe { mem::transmute((&42u8, &3)) }; | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:49:1 @@ -108,6 +112,8 @@ LL | const SLICE_LENGTH_PTR: &[u8] = unsafe { mem::transmute((&42u8, &3)) }; | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:80:1 @@ -128,6 +134,8 @@ LL | const SLICE_LENGTH_PTR_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, &3) | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:88:1 @@ -315,6 +323,8 @@ LL | const STR_LENGTH_PTR: &str = unsafe { mem::transmute((&42u8, &3)) }; = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported Future breakage diagnostic: error: any use of this value will cause an error @@ -326,6 +336,8 @@ LL | const MY_STR_LENGTH_PTR: &MyStr = unsafe { mem::transmute((&42u8, &3)) }; = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported Future breakage diagnostic: error: any use of this value will cause an error @@ -337,6 +349,8 @@ LL | const SLICE_LENGTH_PTR: &[u8] = unsafe { mem::transmute((&42u8, &3)) }; = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported Future breakage diagnostic: error: any use of this value will cause an error @@ -348,6 +362,8 @@ LL | const SLICE_LENGTH_PTR_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, &3) = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported Future breakage diagnostic: error: any use of this value will cause an error diff --git a/src/test/ui/consts/extra-const-ub/detect-extra-ub.rs b/src/test/ui/consts/extra-const-ub/detect-extra-ub.rs index 97c9e1505197f..86fbadb946d53 100644 --- a/src/test/ui/consts/extra-const-ub/detect-extra-ub.rs +++ b/src/test/ui/consts/extra-const-ub/detect-extra-ub.rs @@ -13,15 +13,15 @@ const INVALID_BOOL: () = unsafe { const INVALID_PTR_IN_INT: () = unsafe { let _x: usize = transmute(&3u8); - //[with_flag]~^ ERROR: evaluation of constant value failed - //[with_flag]~| invalid value + //[with_flag]~^ ERROR: any use of this value will cause an error + //[with_flag]~| previously accepted }; const INVALID_SLICE_TO_USIZE_TRANSMUTE: () = unsafe { let x: &[u8] = &[0; 32]; let _x: (usize, usize) = transmute(x); - //[with_flag]~^ ERROR: evaluation of constant value failed - //[with_flag]~| invalid value + //[with_flag]~^ ERROR: any use of this value will cause an error + //[with_flag]~| previously accepted }; const UNALIGNED_PTR: () = unsafe { diff --git a/src/test/ui/consts/extra-const-ub/detect-extra-ub.with_flag.stderr b/src/test/ui/consts/extra-const-ub/detect-extra-ub.with_flag.stderr index b940a77f8a509..793725d3b80fc 100644 --- a/src/test/ui/consts/extra-const-ub/detect-extra-ub.with_flag.stderr +++ b/src/test/ui/consts/extra-const-ub/detect-extra-ub.with_flag.stderr @@ -4,17 +4,33 @@ error[E0080]: evaluation of constant value failed LL | let _x: bool = transmute(3u8); | ^^^^^^^^^^^^^^ constructing invalid value: encountered 0x03, but expected a boolean -error[E0080]: evaluation of constant value failed +error: any use of this value will cause an error --> $DIR/detect-extra-ub.rs:15:21 | +LL | const INVALID_PTR_IN_INT: () = unsafe { + | ---------------------------- LL | let _x: usize = transmute(&3u8); - | ^^^^^^^^^^^^^^^ constructing invalid value: encountered (potentially part of) a pointer, but expected an integer + | ^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes + | + = note: `#[deny(const_err)]` on by default + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #71800 + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported -error[E0080]: evaluation of constant value failed +error: any use of this value will cause an error --> $DIR/detect-extra-ub.rs:22:30 | +LL | const INVALID_SLICE_TO_USIZE_TRANSMUTE: () = unsafe { + | ------------------------------------------ +LL | let x: &[u8] = &[0; 32]; LL | let _x: (usize, usize) = transmute(x); - | ^^^^^^^^^^^^ constructing invalid value at .0: encountered (potentially part of) a pointer, but expected an integer + | ^^^^^^^^^^^^ unable to turn pointer into raw bytes + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #71800 + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported error[E0080]: evaluation of constant value failed --> $DIR/detect-extra-ub.rs:28:20 @@ -49,7 +65,6 @@ LL | const UNALIGNED_READ: () = { LL | INNER; | ^^^^^ referenced constant has errors | - = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 @@ -57,6 +72,37 @@ error: aborting due to 6 previous errors For more information about this error, try `rustc --explain E0080`. Future incompatibility report: Future breakage diagnostic: +error: any use of this value will cause an error + --> $DIR/detect-extra-ub.rs:15:21 + | +LL | const INVALID_PTR_IN_INT: () = unsafe { + | ---------------------------- +LL | let _x: usize = transmute(&3u8); + | ^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes + | + = note: `#[deny(const_err)]` on by default + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #71800 + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported + +Future breakage diagnostic: +error: any use of this value will cause an error + --> $DIR/detect-extra-ub.rs:22:30 + | +LL | const INVALID_SLICE_TO_USIZE_TRANSMUTE: () = unsafe { + | ------------------------------------------ +LL | let x: &[u8] = &[0; 32]; +LL | let _x: (usize, usize) = transmute(x); + | ^^^^^^^^^^^^ unable to turn pointer into raw bytes + | + = note: `#[deny(const_err)]` on by default + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #71800 + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported + +Future breakage diagnostic: error: any use of this value will cause an error --> $DIR/detect-extra-ub.rs:34:5 | diff --git a/src/test/ui/consts/issue-83182.32bit.stderr b/src/test/ui/consts/issue-83182.32bit.stderr index c810c8a7848c7..2776e2b6fa21f 100644 --- a/src/test/ui/consts/issue-83182.32bit.stderr +++ b/src/test/ui/consts/issue-83182.32bit.stderr @@ -2,9 +2,10 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/issue-83182.rs:5:1 | LL | const MYSTR_NO_INIT: &MyStr = unsafe { mem::transmute::<&[_], _>(&[&()]) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at ..0: encountered a pointer in `str` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes | - = 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. + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported = note: the raw bytes of the constant (size: 8, align: 4) { ╾─alloc4──╼ 01 00 00 00 │ ╾──╼.... } diff --git a/src/test/ui/consts/issue-83182.64bit.stderr b/src/test/ui/consts/issue-83182.64bit.stderr index 5fc2c934474dc..9e884ce12890b 100644 --- a/src/test/ui/consts/issue-83182.64bit.stderr +++ b/src/test/ui/consts/issue-83182.64bit.stderr @@ -2,9 +2,10 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/issue-83182.rs:5:1 | LL | const MYSTR_NO_INIT: &MyStr = unsafe { mem::transmute::<&[_], _>(&[&()]) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at ..0: encountered a pointer in `str` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes | - = 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. + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported = note: the raw bytes of the constant (size: 16, align: 8) { ╾───────alloc4────────╼ 01 00 00 00 00 00 00 00 │ ╾──────╼........ } diff --git a/src/test/ui/consts/issue-83182.rs b/src/test/ui/consts/issue-83182.rs index 292765843048c..2536d2f08f288 100644 --- a/src/test/ui/consts/issue-83182.rs +++ b/src/test/ui/consts/issue-83182.rs @@ -4,5 +4,4 @@ use std::mem; struct MyStr(str); const MYSTR_NO_INIT: &MyStr = unsafe { mem::transmute::<&[_], _>(&[&()]) }; //~^ ERROR: it is undefined behavior to use this value -//~| constructing invalid value at ..0: encountered a pointer in `str` fn main() {} diff --git a/src/test/ui/consts/issue-miri-1910.rs b/src/test/ui/consts/issue-miri-1910.rs index 2b23626e3d709..29e0ea9502640 100644 --- a/src/test/ui/consts/issue-miri-1910.rs +++ b/src/test/ui/consts/issue-miri-1910.rs @@ -1,4 +1,5 @@ // error-pattern unable to turn pointer into raw bytes +// normalize-stderr-test: "alloc[0-9]+\+0x[a-z0-9]+" -> "ALLOC" #![feature(const_ptr_read)] const C: () = unsafe { diff --git a/src/test/ui/consts/issue-miri-1910.stderr b/src/test/ui/consts/issue-miri-1910.stderr index afcf11bd5f247..0f0539e09799e 100644 --- a/src/test/ui/consts/issue-miri-1910.stderr +++ b/src/test/ui/consts/issue-miri-1910.stderr @@ -4,12 +4,12 @@ error: any use of this value will cause an error LL | copy_nonoverlapping(src, tmp.as_mut_ptr(), 1); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | | - | unable to turn pointer into raw bytes + | unable to copy parts of a pointer from memory at ALLOC | inside `std::ptr::read::` at $SRC_DIR/core/src/ptr/mod.rs:LL:COL | inside `ptr::const_ptr::::read` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL - | inside `C` at $DIR/issue-miri-1910.rs:7:5 + | inside `C` at $DIR/issue-miri-1910.rs:8:5 | - ::: $DIR/issue-miri-1910.rs:4:1 + ::: $DIR/issue-miri-1910.rs:5:1 | LL | const C: () = unsafe { | ----------- @@ -17,6 +17,8 @@ LL | const C: () = unsafe { = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported error: aborting due to previous error @@ -27,12 +29,12 @@ error: any use of this value will cause an error LL | copy_nonoverlapping(src, tmp.as_mut_ptr(), 1); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | | - | unable to turn pointer into raw bytes + | unable to copy parts of a pointer from memory at ALLOC | inside `std::ptr::read::` at $SRC_DIR/core/src/ptr/mod.rs:LL:COL | inside `ptr::const_ptr::::read` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL - | inside `C` at $DIR/issue-miri-1910.rs:7:5 + | inside `C` at $DIR/issue-miri-1910.rs:8:5 | - ::: $DIR/issue-miri-1910.rs:4:1 + ::: $DIR/issue-miri-1910.rs:5:1 | LL | const C: () = unsafe { | ----------- @@ -40,4 +42,6 @@ LL | const C: () = unsafe { = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported diff --git a/src/test/ui/consts/miri_unleashed/ptr_arith.stderr b/src/test/ui/consts/miri_unleashed/ptr_arith.stderr index 00cff23fb3fbe..f67ac4802ee4d 100644 --- a/src/test/ui/consts/miri_unleashed/ptr_arith.stderr +++ b/src/test/ui/consts/miri_unleashed/ptr_arith.stderr @@ -9,6 +9,9 @@ error[E0080]: could not evaluate static initializer | LL | let _v = x + 0; | ^ unable to turn pointer into raw bytes + | + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported warning: skipping const checks | diff --git a/src/test/ui/consts/ptr_comparisons.stderr b/src/test/ui/consts/ptr_comparisons.stderr index 67b9fec4a0e11..1d47f243f01cd 100644 --- a/src/test/ui/consts/ptr_comparisons.stderr +++ b/src/test/ui/consts/ptr_comparisons.stderr @@ -27,6 +27,8 @@ LL | const _: usize = unsafe { std::mem::transmute::<*const usize, usize>(FOO) + = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported error: any use of this value will cause an error --> $DIR/ptr_comparisons.rs:70:27 @@ -36,6 +38,8 @@ LL | const _: usize = unsafe { *std::mem::transmute::<&&usize, &usize>(&FOO) + 4 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported error: aborting due to 4 previous errors @@ -50,6 +54,8 @@ LL | const _: usize = unsafe { std::mem::transmute::<*const usize, usize>(FOO) + = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported Future breakage diagnostic: error: any use of this value will cause an error @@ -61,4 +67,6 @@ LL | const _: usize = unsafe { *std::mem::transmute::<&&usize, &usize>(&FOO) + 4 = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported From 1a1220c5e4e0afa97a053536254dddf6a68551f7 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 28 Aug 2022 11:48:55 -0400 Subject: [PATCH 4/5] validation should only catch UB errors --- .../src/interpret/validity.rs | 37 ++++++++++--------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs index ee55b4a0750f6..c130252e2490f 100644 --- a/compiler/rustc_const_eval/src/interpret/validity.rs +++ b/compiler/rustc_const_eval/src/interpret/validity.rs @@ -19,6 +19,8 @@ use rustc_target::abi::{Abi, Scalar as ScalarAbi, Size, VariantIdx, Variants, Wr use std::hash::Hash; +// for the validation errors +use super::UndefinedBehaviorInfo::*; use super::{ CheckInAllocMsg, GlobalAlloc, ImmTy, Immediate, InterpCx, InterpResult, MPlaceTy, Machine, MemPlaceMeta, OpTy, Scalar, ValueVisitor, @@ -59,6 +61,7 @@ macro_rules! throw_validation_failure { /// }); /// ``` /// +/// The patterns must be of type `UndefinedBehaviorInfo`. /// An additional expected parameter can also be added to the failure message: /// /// ``` @@ -86,7 +89,7 @@ macro_rules! try_validation { // allocation here as this can only slow down builds that fail anyway. Err(e) => match e.kind() { $( - $($p)|+ => + InterpError::UndefinedBehavior($($p)|+) => throw_validation_failure!( $where, { $( $what_fmt ),+ } $( expected { $( $expected_fmt ),+ } )? @@ -312,7 +315,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, ' Ok(try_validation!( self.ecx.read_immediate(op), self.path, - err_ub!(InvalidUninitBytes(None)) => { "uninitialized memory" } expected { "{expected}" } + InvalidUninitBytes(None) => { "uninitialized memory" } expected { "{expected}" } )) } @@ -337,8 +340,8 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, ' let (_ty, _trait) = try_validation!( self.ecx.get_ptr_vtable(vtable), self.path, - err_ub!(DanglingIntPointer(..)) | - err_ub!(InvalidVTablePointer(..)) => + DanglingIntPointer(..) | + InvalidVTablePointer(..) => { "{vtable}" } expected { "a vtable pointer" }, ); // FIXME: check if the type/trait match what ty::Dynamic says? @@ -374,7 +377,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, ' let size_and_align = try_validation!( self.ecx.size_and_align_of_mplace(&place), self.path, - err_ub!(InvalidMeta(msg)) => { "invalid {} metadata: {}", kind, msg }, + InvalidMeta(msg) => { "invalid {} metadata: {}", kind, msg }, ); let (size, align) = size_and_align // for the purpose of validity, consider foreign types to have @@ -390,21 +393,21 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, ' CheckInAllocMsg::InboundsTest, // will anyway be replaced by validity message ), self.path, - err_ub!(AlignmentCheckFailed { required, has }) => + AlignmentCheckFailed { required, has } => { "an unaligned {kind} (required {} byte alignment but found {})", required.bytes(), has.bytes() }, - err_ub!(DanglingIntPointer(0, _)) => + DanglingIntPointer(0, _) => { "a null {kind}" }, - err_ub!(DanglingIntPointer(i, _)) => + DanglingIntPointer(i, _) => { "a dangling {kind} (address {i:#x} is unallocated)" }, - err_ub!(PointerOutOfBounds { .. }) => + PointerOutOfBounds { .. } => { "a dangling {kind} (going beyond the bounds of its allocation)" }, // This cannot happen during const-eval (because interning already detects // dangling pointers), but it can happen in Miri. - err_ub!(PointerUseAfterFree(..)) => + PointerUseAfterFree(..) => { "a dangling {kind} (use-after-free)" }, ); // Do not allow pointers to uninhabited types. @@ -475,7 +478,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, ' try_validation!( value.to_bool(), self.path, - err_ub!(InvalidBool(..)) => + InvalidBool(..) => { "{:x}", value } expected { "a boolean" }, ); Ok(true) @@ -485,7 +488,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, ' try_validation!( value.to_char(), self.path, - err_ub!(InvalidChar(..)) => + InvalidChar(..) => { "{:x}", value } expected { "a valid unicode scalar value (in `0..=0x10FFFF` but not in `0xD800..=0xDFFF`)" }, ); Ok(true) @@ -544,8 +547,8 @@ 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(..)) | - err_ub!(InvalidFunctionPointer(..)) => + DanglingIntPointer(..) | + InvalidFunctionPointer(..) => { "{ptr}" } expected { "a function pointer" }, ); // FIXME: Check if the signature matches @@ -660,9 +663,9 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M> Ok(try_validation!( this.ecx.read_discriminant(op), this.path, - err_ub!(InvalidTag(val)) => + InvalidTag(val) => { "{:x}", val } expected { "a valid enum tag" }, - err_ub!(InvalidUninitBytes(None)) => + InvalidUninitBytes(None) => { "uninitialized bytes" } expected { "a valid enum tag" }, ) .1) @@ -805,7 +808,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M> try_validation!( self.ecx.read_bytes_ptr_strip_provenance(mplace.ptr, Size::from_bytes(len)), self.path, - err_ub!(InvalidUninitBytes(..)) => { "uninitialized data in `str`" }, + InvalidUninitBytes(..) => { "uninitialized data in `str`" }, ); } ty::Array(tys, ..) | ty::Slice(tys) From c46e803aaf5a0bfc5dfcd1570349eee71ce81634 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 28 Aug 2022 13:01:56 -0400 Subject: [PATCH 5/5] improve OFFSET_IS_ADDR docs --- compiler/rustc_middle/src/mir/interpret/pointer.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_middle/src/mir/interpret/pointer.rs b/compiler/rustc_middle/src/mir/interpret/pointer.rs index 5fa802236edd3..95e52e391d8f8 100644 --- a/compiler/rustc_middle/src/mir/interpret/pointer.rs +++ b/compiler/rustc_middle/src/mir/interpret/pointer.rs @@ -107,8 +107,12 @@ impl PointerArithmetic for T {} /// pointer), but `derive` adds some unnecessary bounds. pub trait Provenance: Copy + fmt::Debug { /// Says whether the `offset` field of `Pointer`s with this provenance is the actual physical address. - /// If `true, ptr-to-int casts work by simply discarding the provenance. - /// If `false`, ptr-to-int casts are not supported. The offset *must* be relative in that case. + /// - If `false`, the offset *must* be relative. This means the bytes representing a pointer are + /// different from what the Abstract Machine prescribes, so the interpreter must prevent any + /// operation that would inspect the underlying bytes of a pointer, such as ptr-to-int + /// transmutation. A `ReadPointerAsBytes` error will be raised in such situations. + /// - If `true`, the interpreter will permit operations to inspect the underlying bytes of a + /// pointer, and implement ptr-to-int transmutation by stripping provenance. const OFFSET_IS_ADDR: bool; /// We also use this trait to control whether to abort execution when a pointer is being partially overwritten