Rollup merge of #135080 - Enselic:debug-ptr-metadata, r=thomcc

core: Make `Debug` impl of raw pointers print metadata if present

Make Rust pointers appear less magic by including metadata information in their `Debug` output.

This does not break Rust stability guarantees because `Debug` impl are explicitly exempted from stability:
https://doc.rust-lang.org/std/fmt/trait.Debug.html#stability

> ## Stability
>
> Derived `Debug` formats are not stable, and so may change with future Rust versions. Additionally, `Debug` implementations of types provided by the standard library (`std`, `core`, `alloc`, etc.) are not stable, and may also change with future Rust versions.

Note that a regression test is added as a separate commit to make it clear what impact the last commit has on the output.

Closes #128684 because the output of that code now becomes:

```
thread 'main' panicked at src/main.rs:5:5:
assertion `left == right` failed
  left: Pointer { addr: 0x7ffd45c6fc6b, metadata: 5 }
 right: Pointer { addr: 0x7ffd45c6fc6b, metadata: 3 }
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
```
This commit is contained in:
许杰友 Jieyou Xu (Joe)
2025-03-16 13:19:51 +08:00
committed by GitHub
6 changed files with 86 additions and 3 deletions

View File

@@ -2771,7 +2771,14 @@ impl Display for char {
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized> Pointer for *const T {
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
pointer_fmt_inner(self.expose_provenance(), f)
if <<T as core::ptr::Pointee>::Metadata as core::unit::IsUnit>::is_unit() {
pointer_fmt_inner(self.expose_provenance(), f)
} else {
f.debug_struct("Pointer")
.field_with("addr", |f| pointer_fmt_inner(self.expose_provenance(), f))
.field("metadata", &core::ptr::metadata(*self))
.finish()
}
}
}

View File

@@ -61,6 +61,8 @@ pub trait Pointee {
// NOTE: Keep trait bounds in `static_assert_expected_bounds_for_metadata`
// in `library/core/src/ptr/metadata.rs`
// in sync with those here:
// NOTE: The metadata of `dyn Trait + 'a` is `DynMetadata<dyn Trait + 'a>`
// so a `'static` bound must not be added.
type Metadata: fmt::Debug + Copy + Send + Sync + Ord + Hash + Unpin + Freeze;
}

View File

@@ -17,3 +17,19 @@ impl FromIterator<()> for () {
iter.into_iter().for_each(|()| {})
}
}
pub(crate) trait IsUnit {
fn is_unit() -> bool;
}
impl<T: ?Sized> IsUnit for T {
default fn is_unit() -> bool {
false
}
}
impl IsUnit for () {
fn is_unit() -> bool {
true
}
}