about summary refs log tree commit diff
diff options
context:
space:
mode:
authorDylan DPC <99973273+Dylan-DPC@users.noreply.github.com>2022-06-02 15:26:57 +0200
committerGitHub <noreply@github.com>2022-06-02 15:26:57 +0200
commit0b2d48e5af11ca20878ccb463fceba2c180a6a4a (patch)
tree2e9d036e397cf106d5dd888b09044a0f50304ae1
parent9598b4b594c97dff66feb93522e22db500deea07 (diff)
parentac5c15d6beec450db1d8116cf76c4c6b6e3b351f (diff)
downloadrust-0b2d48e5af11ca20878ccb463fceba2c180a6a4a.tar.gz
rust-0b2d48e5af11ca20878ccb463fceba2c180a6a4a.zip
Rollup merge of #97420 - WaffleLapkin:no_oxford_casts_qqq, r=Mark-Simulacrum
Be a little nicer with casts when formatting `fn` pointers

This removes a `fn(...) -> ...` -> `usize` -> `*const ()` -> `usize` cast. cc #95489.
-rw-r--r--library/core/src/fmt/mod.rs54
-rw-r--r--library/core/src/ptr/mod.rs14
2 files changed, 32 insertions, 36 deletions
diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs
index dde9bc383d2..63655ae8a24 100644
--- a/library/core/src/fmt/mod.rs
+++ b/library/core/src/fmt/mod.rs
@@ -2233,35 +2233,41 @@ 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 {
-        /// Since the formatting will be identical for all pointer types, use a non-monomorphized
-        /// implementation for the actual formatting to reduce the amount of codegen work needed
-        fn inner(ptr: *const (), f: &mut Formatter<'_>) -> Result {
-            let old_width = f.width;
-            let old_flags = f.flags;
-
-            // The alternate flag is already treated by LowerHex as being special-
-            // it denotes whether to prefix with 0x. We use it to work out whether
-            // or not to zero extend, and then unconditionally set it to get the
-            // prefix.
-            if f.alternate() {
-                f.flags |= 1 << (FlagV1::SignAwareZeroPad as u32);
-
-                if f.width.is_none() {
-                    f.width = Some((usize::BITS / 4) as usize + 2);
-                }
-            }
-            f.flags |= 1 << (FlagV1::Alternate as u32);
+        // Cast is needed here because `.addr()` requires `T: Sized`.
+        pointer_fmt_inner((*self as *const ()).addr(), f)
+    }
+}
 
-            let ret = LowerHex::fmt(&(ptr.addr()), f);
+/// Since the formatting will be identical for all pointer types, use a non-monomorphized
+/// implementation for the actual formatting to reduce the amount of codegen work needed.
+///
+/// This uses `ptr_addr: usize` and not `ptr: *const ()` to be able to use this for
+/// `fn(...) -> ...` without using [problematic] "Oxford Casts".
+///
+/// [problematic]: https://github.com/rust-lang/rust/issues/95489
+pub(crate) fn pointer_fmt_inner(ptr_addr: usize, f: &mut Formatter<'_>) -> Result {
+    let old_width = f.width;
+    let old_flags = f.flags;
 
-            f.width = old_width;
-            f.flags = old_flags;
+    // The alternate flag is already treated by LowerHex as being special-
+    // it denotes whether to prefix with 0x. We use it to work out whether
+    // or not to zero extend, and then unconditionally set it to get the
+    // prefix.
+    if f.alternate() {
+        f.flags |= 1 << (FlagV1::SignAwareZeroPad as u32);
 
-            ret
+        if f.width.is_none() {
+            f.width = Some((usize::BITS / 4) as usize + 2);
         }
-
-        inner(*self as *const (), f)
     }
+    f.flags |= 1 << (FlagV1::Alternate as u32);
+
+    let ret = LowerHex::fmt(&ptr_addr, f);
+
+    f.width = old_width;
+    f.flags = old_flags;
+
+    ret
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs
index 6b1e63e0cfa..5b04ae7b07e 100644
--- a/library/core/src/ptr/mod.rs
+++ b/library/core/src/ptr/mod.rs
@@ -1878,24 +1878,14 @@ macro_rules! fnptr_impls_safety_abi {
         #[stable(feature = "fnptr_impls", since = "1.4.0")]
         impl<Ret, $($Arg),*> fmt::Pointer for $FnTy {
             fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-                // HACK: The intermediate cast as usize is required for AVR
-                // so that the address space of the source function pointer
-                // is preserved in the final function pointer.
-                //
-                // https://github.com/avr-rust/rust/issues/143
-                fmt::Pointer::fmt(&(*self as usize as *const ()), f)
+                fmt::pointer_fmt_inner(*self as usize, f)
             }
         }
 
         #[stable(feature = "fnptr_impls", since = "1.4.0")]
         impl<Ret, $($Arg),*> fmt::Debug for $FnTy {
             fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-                // HACK: The intermediate cast as usize is required for AVR
-                // so that the address space of the source function pointer
-                // is preserved in the final function pointer.
-                //
-                // https://github.com/avr-rust/rust/issues/143
-                fmt::Pointer::fmt(&(*self as usize as *const ()), f)
+                fmt::pointer_fmt_inner(*self as usize, f)
             }
         }
     }