Skip to content

Commit 30e5888

Browse files
vojtechkralm-ou-se
andcommitted
fmt: Debug-format fat pointers with their metadata for better insight
Use ptr::metadata() fn to improve debug prints of fat pointers. Co-authored-by: Mara Bos <m-ou.se@m-ou.se>
1 parent 498eeb7 commit 30e5888

File tree

2 files changed

+74
-4
lines changed

2 files changed

+74
-4
lines changed

library/core/src/fmt/mod.rs

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use crate::cell::{Cell, Ref, RefCell, RefMut, UnsafeCell};
66
use crate::char::EscapeDebugExtArgs;
77
use crate::marker::PhantomData;
88
use crate::mem;
9+
use crate::ptr::{self, DynMetadata};
910
use crate::num::fmt as numfmt;
1011
use crate::ops::Deref;
1112
use crate::result;
@@ -2281,16 +2282,51 @@ impl<T: ?Sized> Pointer for &mut T {
22812282

22822283
// Implementation of Display/Debug for various core types
22832284

2285+
/// A local trait for pointer Debug impl so that we can have
2286+
/// min_specialization-compliant specializations for two types of fat ptrs.
2287+
trait PtrMetadataFmt {
2288+
fn fmt_ptr(&self, ptr: *const (), f: &mut Formatter<'_>) -> Result;
2289+
}
2290+
2291+
// Regular pointer / default impl
2292+
impl<T> PtrMetadataFmt for T {
2293+
#[inline]
2294+
default fn fmt_ptr(&self, ptr: *const (), f: &mut Formatter<'_>) -> Result {
2295+
Pointer::fmt(&ptr, f)
2296+
}
2297+
}
2298+
2299+
// Pointer + length
2300+
impl PtrMetadataFmt for usize {
2301+
#[inline]
2302+
fn fmt_ptr(&self, ptr: *const (), f: &mut Formatter<'_>) -> Result {
2303+
write!(f, "({:p}, {})", ptr, *self)
2304+
}
2305+
}
2306+
2307+
// Pointer + vtable
2308+
impl<Dyn: ?Sized> PtrMetadataFmt for DynMetadata<Dyn> {
2309+
#[inline]
2310+
fn fmt_ptr(&self, ptr: *const (), f: &mut Formatter<'_>) -> Result {
2311+
f.debug_tuple("")
2312+
.field(&ptr)
2313+
.field(self)
2314+
.finish()
2315+
}
2316+
}
2317+
22842318
#[stable(feature = "rust1", since = "1.0.0")]
22852319
impl<T: ?Sized> Debug for *const T {
22862320
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
2287-
Pointer::fmt(self, f)
2321+
let meta = ptr::metadata(*self);
2322+
meta.fmt_ptr(*self as *const (), f)
22882323
}
22892324
}
22902325
#[stable(feature = "rust1", since = "1.0.0")]
22912326
impl<T: ?Sized> Debug for *mut T {
22922327
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
2293-
Pointer::fmt(self, f)
2328+
let ptr: *const T = *self;
2329+
Debug::fmt(&ptr, f)
22942330
}
22952331
}
22962332

library/core/tests/fmt/mod.rs

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@ mod builders;
22
mod float;
33
mod num;
44

5+
use core::any::Any;
6+
use core::fmt;
7+
use core::ptr;
8+
59
#[test]
610
fn test_format_flags() {
711
// No residual flags left by pointer formatting
@@ -19,6 +23,36 @@ fn test_pointer_formats_data_pointer() {
1923
assert_eq!(format!("{:p}", b), format!("{:p}", b.as_ptr()));
2024
}
2125

26+
#[test]
27+
fn test_pointer_formats_debug_thin() {
28+
let thinptr = &42 as *const i32;
29+
assert_eq!(format!("{:?}", thinptr as *const ()), format!("{:p}", thinptr));
30+
}
31+
32+
#[test]
33+
fn test_pointer_formats_debug_slice() {
34+
let b: &[u8] = b"hello";
35+
let s: &str = "hello";
36+
let b_ptr = &*b as *const _;
37+
let s_ptr = &*s as *const _;
38+
assert_eq!(format!("{:?}", b_ptr), format!("({:?}, 5)", b.as_ptr()));
39+
assert_eq!(format!("{:?}", s_ptr), format!("({:?}, 5)", s.as_ptr()));
40+
41+
// :p should format as a thin pointer / without metadata
42+
assert_eq!(format!("{:p}", b_ptr), format!("{:p}", b.as_ptr()));
43+
assert_eq!(format!("{:p}", s_ptr), format!("{:p}", s.as_ptr()));
44+
}
45+
46+
#[test]
47+
fn test_pointer_formats_debug_trait_object() {
48+
let mut any: Box<dyn Any> = Box::new(42);
49+
let dyn_ptr = &mut *any as *mut dyn Any;
50+
assert_eq!(format!("{:?}", dyn_ptr), format!("({:?}, {:?})", dyn_ptr as *const (), ptr::metadata(dyn_ptr)));
51+
52+
// :p should format as a thin pointer / without metadata
53+
assert_eq!(format!("{:p}", dyn_ptr), format!("{:p}", dyn_ptr as *const ()));
54+
}
55+
2256
#[test]
2357
fn test_estimated_capacity() {
2458
assert_eq!(format_args!("").estimated_capacity(), 0);
@@ -33,8 +67,8 @@ fn test_estimated_capacity() {
3367
fn pad_integral_resets() {
3468
struct Bar;
3569

36-
impl core::fmt::Display for Bar {
37-
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
70+
impl fmt::Display for Bar {
71+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3872
"1".fmt(f)?;
3973
f.pad_integral(true, "", "5")?;
4074
"1".fmt(f)

0 commit comments

Comments
 (0)