about summary refs log tree commit diff
diff options
context:
space:
mode:
authorTrevor Gross <tmgross@umich.edu>2025-03-19 00:19:04 +0000
committerTrevor Gross <t.gross35@gmail.com>2025-04-23 15:27:05 -0400
commit975617e8d4105f30d741ac7a3f5478d3b7b7917c (patch)
treeb26c7776296e0fe5af2ed1cab2535ce48b3fc8f3
parent99202af0758bbeb9909acf848de3cd968a41148f (diff)
downloadrust-975617e8d4105f30d741ac7a3f5478d3b7b7917c.tar.gz
rust-975617e8d4105f30d741ac7a3f5478d3b7b7917c.zip
Warn on `unsafe_op_in_unsafe_fn` by default
Edition 2024 requires that we avoid this. There is a lot of code that
will need to be adjusted, so start the process here with a warning that
will show up in CI.
-rw-r--r--library/compiler-builtins/builtins-test-intrinsics/src/main.rs20
-rw-r--r--library/compiler-builtins/compiler-builtins/src/arm.rs181
-rw-r--r--library/compiler-builtins/compiler-builtins/src/lib.rs3
-rw-r--r--library/compiler-builtins/compiler-builtins/src/macros.rs15
-rw-r--r--library/compiler-builtins/compiler-builtins/src/mem/mod.rs2
-rw-r--r--library/compiler-builtins/compiler-builtins/src/x86_64.rs2
6 files changed, 172 insertions, 51 deletions
diff --git a/library/compiler-builtins/builtins-test-intrinsics/src/main.rs b/library/compiler-builtins/builtins-test-intrinsics/src/main.rs
index c4c026368e0..18f943eff35 100644
--- a/library/compiler-builtins/builtins-test-intrinsics/src/main.rs
+++ b/library/compiler-builtins/builtins-test-intrinsics/src/main.rs
@@ -649,14 +649,14 @@ fn something_with_a_dtor(f: &dyn Fn()) {
     f();
 }
 
-#[no_mangle]
+#[unsafe(no_mangle)]
 #[cfg(not(thumb))]
 fn main(_argc: core::ffi::c_int, _argv: *const *const u8) -> core::ffi::c_int {
     run();
     0
 }
 
-#[no_mangle]
+#[unsafe(no_mangle)]
 #[cfg(thumb)]
 pub fn _start() -> ! {
     run();
@@ -669,30 +669,30 @@ pub fn _start() -> ! {
 extern "C" {}
 
 // ARM targets need these symbols
-#[no_mangle]
+#[unsafe(no_mangle)]
 pub fn __aeabi_unwind_cpp_pr0() {}
 
-#[no_mangle]
+#[unsafe(no_mangle)]
 pub fn __aeabi_unwind_cpp_pr1() {}
 
 #[cfg(not(any(windows, target_os = "cygwin")))]
 #[allow(non_snake_case)]
-#[no_mangle]
+#[unsafe(no_mangle)]
 pub fn _Unwind_Resume() {}
 
 #[cfg(not(any(windows, target_os = "cygwin")))]
 #[lang = "eh_personality"]
-#[no_mangle]
+#[unsafe(no_mangle)]
 pub extern "C" fn eh_personality() {}
 
 #[cfg(any(all(windows, target_env = "gnu"), target_os = "cygwin"))]
 mod mingw_unwinding {
-    #[no_mangle]
+    #[unsafe(no_mangle)]
     pub fn rust_eh_personality() {}
-    #[no_mangle]
+    #[unsafe(no_mangle)]
     pub fn rust_eh_unwind_resume() {}
-    #[no_mangle]
+    #[unsafe(no_mangle)]
     pub fn rust_eh_register_frames() {}
-    #[no_mangle]
+    #[unsafe(no_mangle)]
     pub fn rust_eh_unregister_frames() {}
 }
diff --git a/library/compiler-builtins/compiler-builtins/src/arm.rs b/library/compiler-builtins/compiler-builtins/src/arm.rs
index 7859b51207c..a9107e3cdfd 100644
--- a/library/compiler-builtins/compiler-builtins/src/arm.rs
+++ b/library/compiler-builtins/compiler-builtins/src/arm.rs
@@ -76,90 +76,205 @@ intrinsics! {
         );
     }
 
-    // FIXME: The `*4` and `*8` variants should be defined as aliases.
+    // FIXME(arm): The `*4` and `*8` variants should be defined as aliases.
 
+    /// `memcpy` provided with the `aapcs` ABI.
+    ///
+    /// # Safety
+    ///
+    /// Usual `memcpy` requirements apply.
     #[cfg(not(target_vendor = "apple"))]
-    pub unsafe extern "aapcs" fn __aeabi_memcpy(dest: *mut u8, src: *const u8, n: usize) {
-        crate::mem::memcpy(dest, src, n);
+    pub unsafe extern "aapcs" fn __aeabi_memcpy(dst: *mut u8, src: *const u8, n: usize) {
+        // SAFETY: memcpy preconditions apply.
+        unsafe { crate::mem::memcpy(dst, src, n) };
     }
 
+    /// `memcpy` for 4-byte alignment.
+    ///
+    /// # Safety
+    ///
+    /// Usual `memcpy` requirements apply. Additionally, `dest` and `src` must be aligned to
+    /// four bytes.
     #[cfg(not(target_vendor = "apple"))]
-    pub unsafe extern "aapcs" fn __aeabi_memcpy4(dest: *mut u8, src: *const u8, n: usize) {
+    pub unsafe extern "aapcs" fn __aeabi_memcpy4(dst: *mut u8, src: *const u8, n: usize) {
         // We are guaranteed 4-alignment, so accessing at u32 is okay.
-        let mut dest = dest as *mut u32;
-        let mut src = src as *mut u32;
+        let mut dst = dst.cast::<u32>();
+        let mut src = src.cast::<u32>();
+        debug_assert!(dst.is_aligned());
+        debug_assert!(src.is_aligned());
         let mut n = n;
 
         while n >= 4 {
-            *dest = *src;
-            dest = dest.offset(1);
-            src = src.offset(1);
+            // SAFETY: `dst` and `src` are both valid for at least 4 bytes, from
+            // `memcpy` preconditions and the loop guard.
+            unsafe { *dst = *src };
+
+            // FIXME(addr): if we can make this end-of-address-space safe without losing
+            // performance, we may want to consider that.
+            // SAFETY: memcpy is not expected to work at the end of the address space
+            unsafe {
+                dst = dst.offset(1);
+                src = src.offset(1);
+            }
+
             n -= 4;
         }
 
-        __aeabi_memcpy(dest as *mut u8, src as *const u8, n);
+        // SAFETY: `dst` and `src` will still be valid for `n` bytes
+        unsafe { __aeabi_memcpy(dst.cast::<u8>(), src.cast::<u8>(), n) };
     }
 
+    /// `memcpy` for 8-byte alignment.
+    ///
+    /// # Safety
+    ///
+    /// Usual `memcpy` requirements apply. Additionally, `dest` and `src` must be aligned to
+    /// eight bytes.
     #[cfg(not(target_vendor = "apple"))]
-    pub unsafe extern "aapcs" fn __aeabi_memcpy8(dest: *mut u8, src: *const u8, n: usize) {
-        __aeabi_memcpy4(dest, src, n);
+    pub unsafe extern "aapcs" fn __aeabi_memcpy8(dst: *mut u8, src: *const u8, n: usize) {
+        debug_assert!(dst.addr() & 7 == 0);
+        debug_assert!(src.addr() & 7 == 0);
+
+        // SAFETY: memcpy preconditions apply, less strict alignment.
+        unsafe { __aeabi_memcpy4(dst, src, n) };
     }
 
+    /// `memmove` provided with the `aapcs` ABI.
+    ///
+    /// # Safety
+    ///
+    /// Usual `memmove` requirements apply.
     #[cfg(not(target_vendor = "apple"))]
-    pub unsafe extern "aapcs" fn __aeabi_memmove(dest: *mut u8, src: *const u8, n: usize) {
-        crate::mem::memmove(dest, src, n);
+    pub unsafe extern "aapcs" fn __aeabi_memmove(dst: *mut u8, src: *const u8, n: usize) {
+        // SAFETY: memmove preconditions apply.
+        unsafe { crate::mem::memmove(dst, src, n) };
     }
 
+    /// `memmove` for 4-byte alignment.
+    ///
+    /// # Safety
+    ///
+    /// Usual `memmove` requirements apply. Additionally, `dest` and `src` must be aligned to
+    /// four bytes.
     #[cfg(not(any(target_vendor = "apple", target_env = "msvc")))]
-    pub unsafe extern "aapcs" fn __aeabi_memmove4(dest: *mut u8, src: *const u8, n: usize) {
-        __aeabi_memmove(dest, src, n);
+    pub unsafe extern "aapcs" fn __aeabi_memmove4(dst: *mut u8, src: *const u8, n: usize) {
+        debug_assert!(dst.addr() & 3 == 0);
+        debug_assert!(src.addr() & 3 == 0);
+
+        // SAFETY: same preconditions, less strict aligment.
+        unsafe { __aeabi_memmove(dst, src, n) };
     }
 
+    /// `memmove` for 8-byte alignment.
+    ///
+    /// # Safety
+    ///
+    /// Usual `memmove` requirements apply. Additionally, `dst` and `src` must be aligned to
+    /// eight bytes.
     #[cfg(not(any(target_vendor = "apple", target_env = "msvc")))]
-    pub unsafe extern "aapcs" fn __aeabi_memmove8(dest: *mut u8, src: *const u8, n: usize) {
-        __aeabi_memmove(dest, src, n);
+    pub unsafe extern "aapcs" fn __aeabi_memmove8(dst: *mut u8, src: *const u8, n: usize) {
+        debug_assert!(dst.addr() & 7 == 0);
+        debug_assert!(src.addr() & 7 == 0);
+
+        // SAFETY: memmove preconditions apply, less strict alignment.
+        unsafe { __aeabi_memmove(dst, src, n) };
     }
 
+    /// `memset` provided with the `aapcs` ABI.
+    ///
+    /// # Safety
+    ///
+    /// Usual `memset` requirements apply.
     #[cfg(not(target_vendor = "apple"))]
-    pub unsafe extern "aapcs" fn __aeabi_memset(dest: *mut u8, n: usize, c: i32) {
+    pub unsafe extern "aapcs" fn __aeabi_memset(dst: *mut u8, n: usize, c: i32) {
         // Note the different argument order
-        crate::mem::memset(dest, c, n);
+        // SAFETY: memset preconditions apply.
+        unsafe { crate::mem::memset(dst, c, n) };
     }
 
+    /// `memset` for 4-byte alignment.
+    ///
+    /// # Safety
+    ///
+    /// Usual `memset` requirements apply. Additionally, `dest` and `src` must be aligned to
+    /// four bytes.
     #[cfg(not(target_vendor = "apple"))]
-    pub unsafe extern "aapcs" fn __aeabi_memset4(dest: *mut u8, n: usize, c: i32) {
-        let mut dest = dest as *mut u32;
+    pub unsafe extern "aapcs" fn __aeabi_memset4(dst: *mut u8, n: usize, c: i32) {
+        let mut dst = dst.cast::<u32>();
+        debug_assert!(dst.is_aligned());
         let mut n = n;
 
         let byte = (c as u32) & 0xff;
         let c = (byte << 24) | (byte << 16) | (byte << 8) | byte;
 
         while n >= 4 {
-            *dest = c;
-            dest = dest.offset(1);
+            // SAFETY: `dst` is valid for at least 4 bytes, from `memset` preconditions and
+            // the loop guard.
+            unsafe { *dst = c };
+
+            // FIXME(addr): if we can make this end-of-address-space safe without losing
+            // performance, we may want to consider that.
+            // SAFETY: memcpy is not expected to work at the end of the address space
+            unsafe {
+                dst = dst.offset(1);
+            }
             n -= 4;
         }
 
-        __aeabi_memset(dest as *mut u8, n, byte as i32);
+        // SAFETY: `dst` will still be valid for `n` bytes
+        unsafe { __aeabi_memset(dst.cast::<u8>(), n, byte as i32) };
     }
 
+    /// `memset` for 8-byte alignment.
+    ///
+    /// # Safety
+    ///
+    /// Usual `memset` requirements apply. Additionally, `dst` and `src` must be aligned to
+    /// eight bytes.
     #[cfg(not(target_vendor = "apple"))]
-    pub unsafe extern "aapcs" fn __aeabi_memset8(dest: *mut u8, n: usize, c: i32) {
-        __aeabi_memset4(dest, n, c);
+    pub unsafe extern "aapcs" fn __aeabi_memset8(dst: *mut u8, n: usize, c: i32) {
+        debug_assert!(dst.addr() & 7 == 0);
+
+        // SAFETY: memset preconditions apply, less strict alignment.
+        unsafe { __aeabi_memset4(dst, n, c) };
     }
 
+    /// `memclr` provided with the `aapcs` ABI.
+    ///
+    /// # Safety
+    ///
+    /// Usual `memclr` requirements apply.
     #[cfg(not(target_vendor = "apple"))]
-    pub unsafe extern "aapcs" fn __aeabi_memclr(dest: *mut u8, n: usize) {
-        __aeabi_memset(dest, n, 0);
+    pub unsafe extern "aapcs" fn __aeabi_memclr(dst: *mut u8, n: usize) {
+        // SAFETY: memclr preconditions apply, less strict alignment.
+        unsafe { __aeabi_memset(dst, n, 0) };
     }
 
+    /// `memclr` for 4-byte alignment.
+    ///
+    /// # Safety
+    ///
+    /// Usual `memclr` requirements apply. Additionally, `dest` and `src` must be aligned to
+    /// four bytes.
     #[cfg(not(any(target_vendor = "apple", target_env = "msvc")))]
-    pub unsafe extern "aapcs" fn __aeabi_memclr4(dest: *mut u8, n: usize) {
-        __aeabi_memset4(dest, n, 0);
+    pub unsafe extern "aapcs" fn __aeabi_memclr4(dst: *mut u8, n: usize) {
+        debug_assert!(dst.addr() & 3 == 0);
+
+        // SAFETY: memclr preconditions apply, less strict alignment.
+        unsafe { __aeabi_memset4(dst, n, 0) };
     }
 
+    /// `memclr` for 8-byte alignment.
+    ///
+    /// # Safety
+    ///
+    /// Usual `memclr` requirements apply. Additionally, `dst` and `src` must be aligned to
+    /// eight bytes.
     #[cfg(not(any(target_vendor = "apple", target_env = "msvc")))]
-    pub unsafe extern "aapcs" fn __aeabi_memclr8(dest: *mut u8, n: usize) {
-        __aeabi_memset4(dest, n, 0);
+    pub unsafe extern "aapcs" fn __aeabi_memclr8(dst: *mut u8, n: usize) {
+        debug_assert!(dst.addr() & 7 == 0);
+
+        // SAFETY: memclr preconditions apply, less strict alignment.
+        unsafe { __aeabi_memset4(dst, n, 0) };
     }
 }
diff --git a/library/compiler-builtins/compiler-builtins/src/lib.rs b/library/compiler-builtins/compiler-builtins/src/lib.rs
index 7523a00cf9b..6a6b28067e8 100644
--- a/library/compiler-builtins/compiler-builtins/src/lib.rs
+++ b/library/compiler-builtins/compiler-builtins/src/lib.rs
@@ -22,6 +22,9 @@
 #![allow(clippy::manual_swap)]
 // Support compiling on both stage0 and stage1 which may differ in supported stable features.
 #![allow(stable_features)]
+// By default, disallow this as it is forbidden in edition 2024. There is a lot of unsafe code to
+// be migrated, however, so exceptions exist.
+#![warn(unsafe_op_in_unsafe_fn)]
 
 // We disable #[no_mangle] for tests so that we can verify the test results
 // against the native compiler-rt implementations of the builtins.
diff --git a/library/compiler-builtins/compiler-builtins/src/macros.rs b/library/compiler-builtins/compiler-builtins/src/macros.rs
index 4fa53656e5c..dbf71553440 100644
--- a/library/compiler-builtins/compiler-builtins/src/macros.rs
+++ b/library/compiler-builtins/compiler-builtins/src/macros.rs
@@ -256,7 +256,7 @@ macro_rules! intrinsics {
 
         #[cfg(all(target_vendor = "apple", any(target_arch = "x86", target_arch = "x86_64"), not(feature = "mangled-names")))]
         mod $name {
-            #[no_mangle]
+            #[unsafe(no_mangle)]
             #[cfg_attr(not(any(all(windows, target_env = "gnu"), target_os = "cygwin")), linkage = "weak")]
             $(#[$($attr)*])*
             extern $abi fn $name( $($argname: u16),* ) $(-> $ret)? {
@@ -292,7 +292,7 @@ macro_rules! intrinsics {
 
         #[cfg(all(target_vendor = "apple", any(target_arch = "x86", target_arch = "x86_64"), not(feature = "mangled-names")))]
         mod $name {
-            #[no_mangle]
+            #[unsafe(no_mangle)]
             #[cfg_attr(not(any(all(windows, target_env = "gnu"), target_os = "cygwin")), linkage = "weak")]
             $(#[$($attr)*])*
             extern $abi fn $name( $($argname: $ty),* ) -> u16 {
@@ -333,7 +333,7 @@ macro_rules! intrinsics {
 
         #[cfg(all(target_arch = "arm", not(feature = "mangled-names")))]
         mod $name {
-            #[no_mangle]
+            #[unsafe(no_mangle)]
             #[cfg_attr(not(any(all(windows, target_env = "gnu"), target_os = "cygwin")), linkage = "weak")]
             $(#[$($attr)*])*
             extern $abi fn $name( $($argname: $ty),* ) $(-> $ret)? {
@@ -343,7 +343,7 @@ macro_rules! intrinsics {
 
         #[cfg(all(target_arch = "arm", not(feature = "mangled-names")))]
         mod $alias {
-            #[no_mangle]
+            #[unsafe(no_mangle)]
             #[cfg_attr(not(any(all(windows, target_env = "gnu"), target_os = "cygwin")), linkage = "weak")]
             $(#[$($attr)*])*
             extern "aapcs" fn $alias( $($argname: $ty),* ) $(-> $ret)? {
@@ -410,7 +410,7 @@ macro_rules! intrinsics {
         #[cfg(all(feature = "mem", not(feature = "mangled-names")))]
         mod $name {
             $(#[$($attr)*])*
-            #[no_mangle]
+            #[unsafe(no_mangle)]
             #[cfg_attr(not(any(all(windows, target_env = "gnu"), target_os = "cygwin")), linkage = "weak")]
             unsafe extern $abi fn $name( $($argname: $ty),* ) $(-> $ret)? {
                 super::$name($($argname),*)
@@ -485,10 +485,11 @@ macro_rules! intrinsics {
         #[cfg(not(feature = "mangled-names"))]
         mod $name {
             $(#[$($attr)*])*
-            #[no_mangle]
+            #[unsafe(no_mangle)]
             #[cfg_attr(not(any(all(windows, target_env = "gnu"), target_os = "cygwin")), linkage = "weak")]
             $(unsafe $($empty)?)? extern $abi fn $name( $($argname: $ty),* ) $(-> $ret)? {
-                super::$name($($argname),*)
+                // SAFETY: same preconditions.
+                $(unsafe $($empty)?)? { super::$name($($argname),*) }
             }
         }
 
diff --git a/library/compiler-builtins/compiler-builtins/src/mem/mod.rs b/library/compiler-builtins/compiler-builtins/src/mem/mod.rs
index ec160039d0d..6828f3804e0 100644
--- a/library/compiler-builtins/compiler-builtins/src/mem/mod.rs
+++ b/library/compiler-builtins/compiler-builtins/src/mem/mod.rs
@@ -1,5 +1,7 @@
 // Trying to satisfy clippy here is hopeless
 #![allow(clippy::style)]
+// FIXME(e2024): this eventually needs to be removed.
+#![allow(unsafe_op_in_unsafe_fn)]
 
 #[allow(warnings)]
 #[cfg(target_pointer_width = "16")]
diff --git a/library/compiler-builtins/compiler-builtins/src/x86_64.rs b/library/compiler-builtins/compiler-builtins/src/x86_64.rs
index af67e66e28d..fc1190f79b2 100644
--- a/library/compiler-builtins/compiler-builtins/src/x86_64.rs
+++ b/library/compiler-builtins/compiler-builtins/src/x86_64.rs
@@ -44,7 +44,7 @@ intrinsics! {
 // HACK(https://github.com/rust-lang/rust/issues/62785): x86_64-unknown-uefi needs special LLVM
 // support unless we emit the _fltused
 mod _fltused {
-    #[no_mangle]
+    #[unsafe(no_mangle)]
     #[used]
     #[cfg(target_os = "uefi")]
     static _fltused: i32 = 0;