about summary refs log tree commit diff
path: root/library/core/src
diff options
context:
space:
mode:
author许杰友 Jieyou Xu (Joe) <39484203+jieyouxu@users.noreply.github.com>2025-03-16 13:19:51 +0800
committerGitHub <noreply@github.com>2025-03-16 13:19:51 +0800
commita23a93cb4e848c75d6cf2ddb9ca418a0e501af90 (patch)
treef03275adb8cf505e3e2710b3c205fa7260382723 /library/core/src
parent66678e68227913a42438afc7320a2849dffd4d51 (diff)
parent697737a8b18b685270f197ccdd1211e8a010b98b (diff)
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
```
Diffstat (limited to 'library/core/src')
-rw-r--r--library/core/src/fmt/mod.rs9
-rw-r--r--library/core/src/ptr/metadata.rs2
-rw-r--r--library/core/src/unit.rs16
3 files changed, 26 insertions, 1 deletions
diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs
index a0f5b00cd2d..b13c7ee5aa2 100644
--- a/library/core/src/fmt/mod.rs
+++ b/library/core/src/fmt/mod.rs
@@ -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()
+        }
     }
 }
 
diff --git a/library/core/src/ptr/metadata.rs b/library/core/src/ptr/metadata.rs
index 48707506389..9c5da306e27 100644
--- a/library/core/src/ptr/metadata.rs
+++ b/library/core/src/ptr/metadata.rs
@@ -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;
 }
 
diff --git a/library/core/src/unit.rs b/library/core/src/unit.rs
index d656005f3d4..d54816c444b 100644
--- a/library/core/src/unit.rs
+++ b/library/core/src/unit.rs
@@ -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
+    }
+}