Skip to content

Commit 522d52c

Browse files
authored
Rollup merge of rust-lang#98811 - RalfJung:interpret-alloc-range, r=oli-obk
Interpret: AllocRange Debug impl, and use it more consistently The two commits are pretty independent but it did not seem worth having two PRs for them. r? ``@oli-obk``
2 parents 6a9db39 + 0832d1d commit 522d52c

File tree

9 files changed

+49
-63
lines changed

9 files changed

+49
-63
lines changed

compiler/rustc_const_eval/src/interpret/memory.rs

+17-31
Original file line numberDiff line numberDiff line change
@@ -276,7 +276,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
276276
kind: MemoryKind<M::MemoryKind>,
277277
) -> InterpResult<'tcx> {
278278
let (alloc_id, offset, tag) = self.ptr_get_alloc_id(ptr)?;
279-
trace!("deallocating: {}", alloc_id);
279+
trace!("deallocating: {alloc_id:?}");
280280

281281
if offset.bytes() != 0 {
282282
throw_ub_format!(
@@ -289,10 +289,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
289289
// Deallocating global memory -- always an error
290290
return Err(match self.tcx.get_global_alloc(alloc_id) {
291291
Some(GlobalAlloc::Function(..)) => {
292-
err_ub_format!("deallocating {}, which is a function", alloc_id)
292+
err_ub_format!("deallocating {alloc_id:?}, which is a function")
293293
}
294294
Some(GlobalAlloc::Static(..) | GlobalAlloc::Memory(..)) => {
295-
err_ub_format!("deallocating {}, which is static memory", alloc_id)
295+
err_ub_format!("deallocating {alloc_id:?}, which is static memory")
296296
}
297297
None => err_ub!(PointerUseAfterFree(alloc_id)),
298298
}
@@ -302,21 +302,17 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
302302
debug!(?alloc);
303303

304304
if alloc.mutability == Mutability::Not {
305-
throw_ub_format!("deallocating immutable allocation {}", alloc_id);
305+
throw_ub_format!("deallocating immutable allocation {alloc_id:?}");
306306
}
307307
if alloc_kind != kind {
308308
throw_ub_format!(
309-
"deallocating {}, which is {} memory, using {} deallocation operation",
310-
alloc_id,
311-
alloc_kind,
312-
kind
309+
"deallocating {alloc_id:?}, which is {alloc_kind} memory, using {kind} deallocation operation"
313310
);
314311
}
315312
if let Some((size, align)) = old_size_and_align {
316313
if size != alloc.size() || align != alloc.align {
317314
throw_ub_format!(
318-
"incorrect layout on deallocation: {} has size {} and alignment {}, but gave size {} and alignment {}",
319-
alloc_id,
315+
"incorrect layout on deallocation: {alloc_id:?} has size {} and alignment {}, but gave size {} and alignment {}",
320316
alloc.size().bytes(),
321317
alloc.align.bytes(),
322318
size.bytes(),
@@ -815,7 +811,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> std::fmt::Debug for DumpAllocs<'a,
815811
continue;
816812
}
817813

818-
write!(fmt, "{}", id)?;
814+
write!(fmt, "{id:?}")?;
819815
match self.ecx.memory.alloc_map.get(id) {
820816
Some(&(kind, ref alloc)) => {
821817
// normal alloc
@@ -859,25 +855,21 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> std::fmt::Debug for DumpAllocs<'a,
859855

860856
/// Reading and writing.
861857
impl<'tcx, 'a, Tag: Provenance, Extra> AllocRefMut<'a, 'tcx, Tag, Extra> {
858+
/// `range` is relative to this allocation reference, not the base of the allocation.
862859
pub fn write_scalar(
863860
&mut self,
864861
range: AllocRange,
865862
val: ScalarMaybeUninit<Tag>,
866863
) -> InterpResult<'tcx> {
867864
let range = self.range.subrange(range);
868-
debug!(
869-
"write_scalar in {} at {:#x}, size {}: {:?}",
870-
self.alloc_id,
871-
range.start.bytes(),
872-
range.size.bytes(),
873-
val
874-
);
865+
debug!("write_scalar at {:?}{range:?}: {val:?}", self.alloc_id);
875866
Ok(self
876867
.alloc
877868
.write_scalar(&self.tcx, range, val)
878869
.map_err(|e| e.to_interp_error(self.alloc_id))?)
879870
}
880871

872+
/// `offset` is relative to this allocation reference, not the base of the allocation.
881873
pub fn write_ptr_sized(
882874
&mut self,
883875
offset: Size,
@@ -896,6 +888,7 @@ impl<'tcx, 'a, Tag: Provenance, Extra> AllocRefMut<'a, 'tcx, Tag, Extra> {
896888
}
897889

898890
impl<'tcx, 'a, Tag: Provenance, Extra> AllocRef<'a, 'tcx, Tag, Extra> {
891+
/// `range` is relative to this allocation reference, not the base of the allocation.
899892
pub fn read_scalar(
900893
&self,
901894
range: AllocRange,
@@ -906,31 +899,24 @@ impl<'tcx, 'a, Tag: Provenance, Extra> AllocRef<'a, 'tcx, Tag, Extra> {
906899
.alloc
907900
.read_scalar(&self.tcx, range, read_provenance)
908901
.map_err(|e| e.to_interp_error(self.alloc_id))?;
909-
debug!(
910-
"read_scalar in {} at {:#x}, size {}: {:?}",
911-
self.alloc_id,
912-
range.start.bytes(),
913-
range.size.bytes(),
914-
res
915-
);
902+
debug!("read_scalar at {:?}{range:?}: {res:?}", self.alloc_id);
916903
Ok(res)
917904
}
918905

919-
pub fn read_integer(
920-
&self,
921-
offset: Size,
922-
size: Size,
923-
) -> InterpResult<'tcx, ScalarMaybeUninit<Tag>> {
924-
self.read_scalar(alloc_range(offset, size), /*read_provenance*/ false)
906+
/// `range` is relative to this allocation reference, not the base of the allocation.
907+
pub fn read_integer(&self, range: AllocRange) -> InterpResult<'tcx, ScalarMaybeUninit<Tag>> {
908+
self.read_scalar(range, /*read_provenance*/ false)
925909
}
926910

911+
/// `offset` is relative to this allocation reference, not the base of the allocation.
927912
pub fn read_pointer(&self, offset: Size) -> InterpResult<'tcx, ScalarMaybeUninit<Tag>> {
928913
self.read_scalar(
929914
alloc_range(offset, self.tcx.data_layout().pointer_size),
930915
/*read_provenance*/ true,
931916
)
932917
}
933918

919+
/// `range` is relative to this allocation reference, not the base of the allocation.
934920
pub fn check_bytes(
935921
&self,
936922
range: AllocRange,

compiler/rustc_const_eval/src/interpret/traits.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use std::convert::TryFrom;
22

3-
use rustc_middle::mir::interpret::{InterpResult, Pointer, PointerArithmetic};
3+
use rustc_middle::mir::interpret::{alloc_range, InterpResult, Pointer, PointerArithmetic};
44
use rustc_middle::ty::{
55
self, Ty, TyCtxt, COMMON_VTABLE_ENTRIES_ALIGN, COMMON_VTABLE_ENTRIES_DROPINPLACE,
66
COMMON_VTABLE_ENTRIES_SIZE,
@@ -102,18 +102,18 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
102102
)?
103103
.expect("cannot be a ZST");
104104
let size = vtable
105-
.read_integer(
105+
.read_integer(alloc_range(
106106
pointer_size * u64::try_from(COMMON_VTABLE_ENTRIES_SIZE).unwrap(),
107107
pointer_size,
108-
)?
108+
))?
109109
.check_init()?;
110110
let size = size.to_machine_usize(self)?;
111111
let size = Size::from_bytes(size);
112112
let align = vtable
113-
.read_integer(
113+
.read_integer(alloc_range(
114114
pointer_size * u64::try_from(COMMON_VTABLE_ENTRIES_ALIGN).unwrap(),
115115
pointer_size,
116-
)?
116+
))?
117117
.check_init()?;
118118
let align = align.to_machine_usize(self)?;
119119
let align = Align::from_bytes(align).map_err(|e| err_ub!(InvalidVtableAlignment(e)))?;

compiler/rustc_middle/src/mir/interpret/allocation.rs

+7-1
Original file line numberDiff line numberDiff line change
@@ -160,12 +160,18 @@ impl AllocError {
160160
}
161161

162162
/// The information that makes up a memory access: offset and size.
163-
#[derive(Copy, Clone, Debug)]
163+
#[derive(Copy, Clone)]
164164
pub struct AllocRange {
165165
pub start: Size,
166166
pub size: Size,
167167
}
168168

169+
impl fmt::Debug for AllocRange {
170+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
171+
write!(f, "[{:#x}..{:#x}]", self.start.bytes(), self.end().bytes())
172+
}
173+
}
174+
169175
/// Free-starting constructor for less syntactic overhead.
170176
#[inline(always)]
171177
pub fn alloc_range(start: Size, size: Size) -> AllocRange {

compiler/rustc_middle/src/mir/interpret/error.rs

+7-13
Original file line numberDiff line numberDiff line change
@@ -334,45 +334,39 @@ impl fmt::Display for UndefinedBehaviorInfo<'_> {
334334
p,
335335
),
336336
PointerUseAfterFree(a) => {
337-
write!(f, "pointer to {} was dereferenced after this allocation got freed", a)
337+
write!(f, "pointer to {a:?} was dereferenced after this allocation got freed")
338338
}
339339
PointerOutOfBounds { alloc_id, alloc_size, ptr_offset, ptr_size: Size::ZERO, msg } => {
340340
write!(
341341
f,
342-
"{}{alloc_id} has size {alloc_size}, so pointer at offset {ptr_offset} is out-of-bounds",
343-
msg,
344-
alloc_id = alloc_id,
342+
"{msg}{alloc_id:?} has size {alloc_size}, so pointer at offset {ptr_offset} is out-of-bounds",
345343
alloc_size = alloc_size.bytes(),
346-
ptr_offset = ptr_offset,
347344
)
348345
}
349346
PointerOutOfBounds { alloc_id, alloc_size, ptr_offset, ptr_size, msg } => write!(
350347
f,
351-
"{}{alloc_id} has size {alloc_size}, so pointer to {ptr_size} byte{ptr_size_p} starting at offset {ptr_offset} is out-of-bounds",
352-
msg,
353-
alloc_id = alloc_id,
348+
"{msg}{alloc_id:?} has size {alloc_size}, so pointer to {ptr_size} byte{ptr_size_p} starting at offset {ptr_offset} is out-of-bounds",
354349
alloc_size = alloc_size.bytes(),
355350
ptr_size = ptr_size.bytes(),
356351
ptr_size_p = pluralize!(ptr_size.bytes()),
357-
ptr_offset = ptr_offset,
358352
),
359353
DanglingIntPointer(0, CheckInAllocMsg::InboundsTest) => {
360354
write!(f, "null pointer is not a valid pointer for this operation")
361355
}
362356
DanglingIntPointer(0, msg) => {
363-
write!(f, "{}null pointer is not a valid pointer", msg)
357+
write!(f, "{msg}null pointer is not a valid pointer")
364358
}
365359
DanglingIntPointer(i, msg) => {
366-
write!(f, "{}0x{:x} is not a valid pointer", msg, i)
360+
write!(f, "{msg}{i:#x} is not a valid pointer")
367361
}
368362
AlignmentCheckFailed { required, has } => write!(
369363
f,
370364
"accessing memory with alignment {}, but alignment {} is required",
371365
has.bytes(),
372366
required.bytes()
373367
),
374-
WriteToReadOnly(a) => write!(f, "writing to {} which is read-only", a),
375-
DerefFunctionPointer(a) => write!(f, "accessing {} which contains a function", a),
368+
WriteToReadOnly(a) => write!(f, "writing to {a:?} which is read-only"),
369+
DerefFunctionPointer(a) => write!(f, "accessing {a:?} which contains a function"),
376370
ValidationFailure { path: None, msg } => {
377371
write!(f, "constructing invalid value: {}", msg)
378372
}

compiler/rustc_middle/src/mir/interpret/mod.rs

+4-8
Original file line numberDiff line numberDiff line change
@@ -190,11 +190,7 @@ impl fmt::Debug for AllocId {
190190
}
191191
}
192192

193-
impl fmt::Display for AllocId {
194-
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
195-
fmt::Debug::fmt(self, f)
196-
}
197-
}
193+
// No "Display" since AllocIds are not usually user-visible.
198194

199195
#[derive(TyDecodable, TyEncodable)]
200196
enum AllocDiscriminant {
@@ -470,7 +466,7 @@ impl<'tcx> TyCtxt<'tcx> {
470466
return alloc_id;
471467
}
472468
let id = alloc_map.reserve();
473-
debug!("creating alloc {:?} with id {}", alloc, id);
469+
debug!("creating alloc {alloc:?} with id {id:?}");
474470
alloc_map.alloc_map.insert(id, alloc.clone());
475471
alloc_map.dedup.insert(alloc, id);
476472
id
@@ -538,15 +534,15 @@ impl<'tcx> TyCtxt<'tcx> {
538534
pub fn global_alloc(self, id: AllocId) -> GlobalAlloc<'tcx> {
539535
match self.get_global_alloc(id) {
540536
Some(alloc) => alloc,
541-
None => bug!("could not find allocation for {}", id),
537+
None => bug!("could not find allocation for {id:?}"),
542538
}
543539
}
544540

545541
/// Freezes an `AllocId` created with `reserve` by pointing it at an `Allocation`. Trying to
546542
/// call this function twice, even with the same `Allocation` will ICE the compiler.
547543
pub fn set_alloc_id_memory(self, id: AllocId, mem: ConstAllocation<'tcx>) {
548544
if let Some(old) = self.alloc_map.lock().alloc_map.insert(id, GlobalAlloc::Memory(mem)) {
549-
bug!("tried to set allocation ID {}, but it was already existing as {:#?}", id, old);
545+
bug!("tried to set allocation ID {id:?}, but it was already existing as {old:#?}");
550546
}
551547
}
552548

compiler/rustc_middle/src/mir/interpret/pointer.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ impl Provenance for AllocId {
144144
}
145145
// Print offset only if it is non-zero.
146146
if ptr.offset.bytes() > 0 {
147-
write!(f, "+0x{:x}", ptr.offset.bytes())?;
147+
write!(f, "+{:#x}", ptr.offset.bytes())?;
148148
}
149149
Ok(())
150150
}
@@ -181,7 +181,7 @@ impl<Tag: Provenance> fmt::Debug for Pointer<Option<Tag>> {
181181
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
182182
match self.provenance {
183183
Some(tag) => Provenance::fmt(&Pointer::new(tag, self.offset), f),
184-
None => write!(f, "0x{:x}", self.offset.bytes()),
184+
None => write!(f, "{:#x}", self.offset.bytes()),
185185
}
186186
}
187187
}

compiler/rustc_middle/src/mir/interpret/value.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ impl<Tag: Provenance> fmt::LowerHex for Scalar<Tag> {
167167
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
168168
match self {
169169
Scalar::Ptr(ptr, _size) => write!(f, "pointer to {:?}", ptr),
170-
Scalar::Int(int) => write!(f, "0x{:x}", int),
170+
Scalar::Int(int) => write!(f, "{:#x}", int),
171171
}
172172
}
173173
}

compiler/rustc_middle/src/mir/pretty.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -716,12 +716,12 @@ pub fn write_allocations<'tcx>(
716716
}
717717
write!(w, "{}", display_allocation(tcx, alloc.inner()))
718718
};
719-
write!(w, "\n{}", id)?;
719+
write!(w, "\n{id:?}")?;
720720
match tcx.get_global_alloc(id) {
721721
// This can't really happen unless there are bugs, but it doesn't cost us anything to
722722
// gracefully handle it and allow buggy rustc to be debugged via allocation printing.
723723
None => write!(w, " (deallocated)")?,
724-
Some(GlobalAlloc::Function(inst)) => write!(w, " (fn: {})", inst)?,
724+
Some(GlobalAlloc::Function(inst)) => write!(w, " (fn: {inst})")?,
725725
Some(GlobalAlloc::Static(did)) if !tcx.is_foreign_item(did) => {
726726
match tcx.eval_static_initializer(did) {
727727
Ok(alloc) => {

compiler/rustc_middle/src/ty/consts/int.rs

+4
Original file line numberDiff line numberDiff line change
@@ -452,6 +452,10 @@ impl fmt::Debug for ScalarInt {
452452
impl fmt::LowerHex for ScalarInt {
453453
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
454454
self.check_data();
455+
if f.alternate() {
456+
// Like regular ints, alternate flag adds leading `0x`.
457+
write!(f, "0x")?;
458+
}
455459
// Format as hex number wide enough to fit any value of the given `size`.
456460
// So data=20, size=1 will be "0x14", but with size=4 it'll be "0x00000014".
457461
// Using a block `{self.data}` here to force a copy instead of using `self.data`

0 commit comments

Comments
 (0)