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.
This commit is contained in:
Trevor Gross 2025-03-19 00:19:04 +00:00 committed by Trevor Gross
parent 99202af075
commit 975617e8d4
6 changed files with 172 additions and 51 deletions

View file

@ -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() {}
}

View file

@ -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) };
}
}

View file

@ -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.

View file

@ -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),*) }
}
}

View file

@ -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")]

View file

@ -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;