-
Notifications
You must be signed in to change notification settings - Fork 12.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Debug-format fat pointers with their metadata for better insight #93544
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,6 +6,7 @@ use crate::cell::{Cell, Ref, RefCell, RefMut, UnsafeCell}; | |
use crate::char::EscapeDebugExtArgs; | ||
use crate::marker::PhantomData; | ||
use crate::mem; | ||
use crate::ptr::{self, DynMetadata}; | ||
use crate::num::fmt as numfmt; | ||
use crate::ops::Deref; | ||
use crate::result; | ||
|
@@ -2281,16 +2282,51 @@ impl<T: ?Sized> Pointer for &mut T { | |
|
||
// Implementation of Display/Debug for various core types | ||
|
||
/// A local trait for pointer Debug impl so that we can have | ||
/// min_specialization-compliant specializations for two types of fat ptrs. | ||
trait PtrMetadataFmt { | ||
fn fmt_ptr(&self, ptr: *const (), f: &mut Formatter<'_>) -> Result; | ||
} | ||
|
||
// Regular pointer / default impl | ||
impl<T> PtrMetadataFmt for T { | ||
#[inline] | ||
default fn fmt_ptr(&self, ptr: *const (), f: &mut Formatter<'_>) -> Result { | ||
Pointer::fmt(&ptr, f) | ||
} | ||
} | ||
|
||
// Pointer + length | ||
impl PtrMetadataFmt for usize { | ||
#[inline] | ||
fn fmt_ptr(&self, ptr: *const (), f: &mut Formatter<'_>) -> Result { | ||
write!(f, "({:p}, {})", ptr, *self) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. (bikeshedding) I wonder how silly something like There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure I understand, what's the |
||
} | ||
} | ||
|
||
// Pointer + vtable | ||
impl<Dyn: ?Sized> PtrMetadataFmt for DynMetadata<Dyn> { | ||
#[inline] | ||
fn fmt_ptr(&self, ptr: *const (), f: &mut Formatter<'_>) -> Result { | ||
f.debug_tuple("") | ||
.field(&ptr) | ||
.field(self) | ||
.finish() | ||
} | ||
} | ||
|
||
#[stable(feature = "rust1", since = "1.0.0")] | ||
impl<T: ?Sized> Debug for *const T { | ||
fn fmt(&self, f: &mut Formatter<'_>) -> Result { | ||
Pointer::fmt(self, f) | ||
let meta = ptr::metadata(*self); | ||
meta.fmt_ptr(*self as *const (), f) | ||
} | ||
} | ||
#[stable(feature = "rust1", since = "1.0.0")] | ||
impl<T: ?Sized> Debug for *mut T { | ||
fn fmt(&self, f: &mut Formatter<'_>) -> Result { | ||
Pointer::fmt(self, f) | ||
let ptr: *const T = *self; | ||
Debug::fmt(&ptr, f) | ||
} | ||
} | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You should be able to improve this in one of two ways:
()
case from the default:()
is "guaranteed simple" (but maybe specializing on the original pointee beingSized
would be stronger)unreachable!()
in there)Pointee::Metadata
(just like it requiresCopy
,Eq
, etc. today)pub trait
in a privatemod
, not nameable outsidecore
- for now, anyway)PtrMetadataFmt
for now, even if we may want to change it in the future (see below)Pointee
would be claiming it's always implemented for valid metadata typesfmt::Debug
bound and not let the user see the data pointer or choose how it is printed?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know exactly what you mean, in fact, I've been meaning to propose in #81513 that
Pointee::Metadata
should maybe be its own trait (and yeah initially sealed by all means), which could enable attaching arbitrary things to it that might be needed in the future, be it debug printing or something else.I initially did try the
fmt::Debug
bound approach but I think there was issues with it, altough I don't remember off the top of my head at the moment...There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, because
Debug
onPointee::Metadata
gets me the ability to debug-print the metadata, but in this case I need to format the whole pointer+metadata combo somehow, ideally preserving the simple "just hex number" format for simple pointers...Edit: But I could use a custom sealed trait, sure, I'll try that later and wil update...