From 71763208216e44901c4865119458edc8e6e466c1 Mon Sep 17 00:00:00 2001 From: Martin Nordholts Date: Sat, 4 Jan 2025 09:36:07 +0100 Subject: [PATCH 1/4] tests: Use `as *const _` instead of `.as_ptr()` in ptr fmt test Because `.as_ptr()` changes the type of the pointer (e.g. `&[u8]` becomes `*const u8` instead of `*const [u8]`), and it can't be expected that different types will be formatted the same way. --- library/coretests/tests/fmt/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/coretests/tests/fmt/mod.rs b/library/coretests/tests/fmt/mod.rs index 025c69c4f6236..381615ed39706 100644 --- a/library/coretests/tests/fmt/mod.rs +++ b/library/coretests/tests/fmt/mod.rs @@ -15,8 +15,8 @@ fn test_format_flags() { fn test_pointer_formats_data_pointer() { let b: &[u8] = b""; let s: &str = ""; - assert_eq!(format!("{s:p}"), format!("{:p}", s.as_ptr())); - assert_eq!(format!("{b:p}"), format!("{:p}", b.as_ptr())); + assert_eq!(format!("{s:p}"), format!("{:p}", s as *const _)); + assert_eq!(format!("{b:p}"), format!("{:p}", b as *const _)); } #[test] From 9479b6f0ead1787a895f82473eeb57dd74fded5a Mon Sep 17 00:00:00 2001 From: Martin Nordholts Date: Fri, 3 Jan 2025 17:51:32 +0100 Subject: [PATCH 2/4] tests: Add regression test for `Debug` impl of raw pointers --- library/Cargo.lock | 26 +++++++++++++++++++++++++ library/coretests/Cargo.toml | 1 + library/coretests/tests/fmt/mod.rs | 31 ++++++++++++++++++++++++++++++ 3 files changed, 58 insertions(+) diff --git a/library/Cargo.lock b/library/Cargo.lock index 0be2f9a154939..061c8db4e0225 100644 --- a/library/Cargo.lock +++ b/library/Cargo.lock @@ -79,6 +79,7 @@ version = "0.0.0" dependencies = [ "rand", "rand_xorshift", + "regex", ] [[package]] @@ -297,6 +298,31 @@ dependencies = [ "rand_core", ] +[[package]] +name = "regex" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" +dependencies = [ + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" +dependencies = [ + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" + [[package]] name = "rustc-demangle" version = "0.1.24" diff --git a/library/coretests/Cargo.toml b/library/coretests/Cargo.toml index e44f01d347b3d..88a7e159c956b 100644 --- a/library/coretests/Cargo.toml +++ b/library/coretests/Cargo.toml @@ -25,3 +25,4 @@ test = true [dev-dependencies] rand = { version = "0.9.0", default-features = false } rand_xorshift = { version = "0.4.0", default-features = false } +regex = { version = "1.11.1", default-features = false } diff --git a/library/coretests/tests/fmt/mod.rs b/library/coretests/tests/fmt/mod.rs index 381615ed39706..13f7bca646fa8 100644 --- a/library/coretests/tests/fmt/mod.rs +++ b/library/coretests/tests/fmt/mod.rs @@ -19,6 +19,37 @@ fn test_pointer_formats_data_pointer() { assert_eq!(format!("{b:p}"), format!("{:p}", b as *const _)); } +#[test] +fn test_fmt_debug_of_raw_pointers() { + use core::fmt::Debug; + + fn check_fmt(t: T, expected: &str) { + use std::sync::LazyLock; + + use regex::Regex; + + static ADDR_REGEX: LazyLock = + LazyLock::new(|| Regex::new(r"0x[0-9a-fA-F]+").unwrap()); + + let formatted = format!("{:?}", t); + let normalized = ADDR_REGEX.replace_all(&formatted, "$$HEX"); + + assert_eq!(normalized, expected); + } + + let plain = &mut 100; + check_fmt(plain as *mut i32, "$HEX"); + check_fmt(plain as *const i32, "$HEX"); + + let slice = &mut [200, 300, 400][..]; + check_fmt(slice as *mut [i32], "$HEX"); + check_fmt(slice as *const [i32], "$HEX"); + + let vtable = &mut 500 as &mut dyn Debug; + check_fmt(vtable as *mut dyn Debug, "$HEX"); + check_fmt(vtable as *const dyn Debug, "$HEX"); +} + #[test] fn test_estimated_capacity() { assert_eq!(format_args!("").estimated_capacity(), 0); From d16da3b8b2be9f1da5a2e9d2b31c499a21d2d7a1 Mon Sep 17 00:00:00 2001 From: Martin Nordholts Date: Fri, 14 Feb 2025 06:42:49 +0100 Subject: [PATCH 3/4] core: Document why Pointee::Metadata can't have 'static bound Co-authored-by: Lukas <26522220+lukas-code@users.noreply.github.com> --- library/core/src/ptr/metadata.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/library/core/src/ptr/metadata.rs b/library/core/src/ptr/metadata.rs index 9eee29d485f41..e986b16d116c8 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` + // so a `'static` bound must not be added. type Metadata: fmt::Debug + Copy + Send + Sync + Ord + Hash + Unpin + Freeze; } From 697737a8b18b685270f197ccdd1211e8a010b98b Mon Sep 17 00:00:00 2001 From: Martin Nordholts Date: Fri, 3 Jan 2025 18:02:33 +0100 Subject: [PATCH 4/4] core: Make `Debug` impl of raw pointers print metadata if present Make Rust pointers less magic by including metadata information in their `Debug` output. This does not break Rust stability guarantees because `Debug` output is explicitly exempted from stability: https://doc.rust-lang.org/std/fmt/trait.Debug.html#stability Co-authored-by: Lukas <26522220+lukas-code@users.noreply.github.com> Co-authored-by: Josh Stone --- library/core/src/fmt/mod.rs | 9 ++++++++- library/core/src/unit.rs | 16 ++++++++++++++++ library/coretests/tests/fmt/mod.rs | 8 ++++---- 3 files changed, 28 insertions(+), 5 deletions(-) diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs index a1bf3a4d7a706..4cfcb412bfd29 100644 --- a/library/core/src/fmt/mod.rs +++ b/library/core/src/fmt/mod.rs @@ -2776,7 +2776,14 @@ impl Display for char { #[stable(feature = "rust1", since = "1.0.0")] impl Pointer for *const T { fn fmt(&self, f: &mut Formatter<'_>) -> Result { - pointer_fmt_inner(self.expose_provenance(), f) + if <::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/unit.rs b/library/core/src/unit.rs index d656005f3d42d..d54816c444bc4 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 IsUnit for T { + default fn is_unit() -> bool { + false + } +} + +impl IsUnit for () { + fn is_unit() -> bool { + true + } +} diff --git a/library/coretests/tests/fmt/mod.rs b/library/coretests/tests/fmt/mod.rs index 13f7bca646fa8..cb185dae9de35 100644 --- a/library/coretests/tests/fmt/mod.rs +++ b/library/coretests/tests/fmt/mod.rs @@ -42,12 +42,12 @@ fn test_fmt_debug_of_raw_pointers() { check_fmt(plain as *const i32, "$HEX"); let slice = &mut [200, 300, 400][..]; - check_fmt(slice as *mut [i32], "$HEX"); - check_fmt(slice as *const [i32], "$HEX"); + check_fmt(slice as *mut [i32], "Pointer { addr: $HEX, metadata: 3 }"); + check_fmt(slice as *const [i32], "Pointer { addr: $HEX, metadata: 3 }"); let vtable = &mut 500 as &mut dyn Debug; - check_fmt(vtable as *mut dyn Debug, "$HEX"); - check_fmt(vtable as *const dyn Debug, "$HEX"); + check_fmt(vtable as *mut dyn Debug, "Pointer { addr: $HEX, metadata: DynMetadata($HEX) }"); + check_fmt(vtable as *const dyn Debug, "Pointer { addr: $HEX, metadata: DynMetadata($HEX) }"); } #[test]