Skip to content

Commit 397023f

Browse files
committed
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.
1 parent bf79280 commit 397023f

File tree

6 files changed

+172
-51
lines changed

6 files changed

+172
-51
lines changed

builtins-test-intrinsics/src/main.rs

+10-10
Original file line numberDiff line numberDiff line change
@@ -649,14 +649,14 @@ fn something_with_a_dtor(f: &dyn Fn()) {
649649
f();
650650
}
651651

652-
#[no_mangle]
652+
#[unsafe(no_mangle)]
653653
#[cfg(not(thumb))]
654654
fn main(_argc: core::ffi::c_int, _argv: *const *const u8) -> core::ffi::c_int {
655655
run();
656656
0
657657
}
658658

659-
#[no_mangle]
659+
#[unsafe(no_mangle)]
660660
#[cfg(thumb)]
661661
pub fn _start() -> ! {
662662
run();
@@ -669,30 +669,30 @@ pub fn _start() -> ! {
669669
extern "C" {}
670670

671671
// ARM targets need these symbols
672-
#[no_mangle]
672+
#[unsafe(no_mangle)]
673673
pub fn __aeabi_unwind_cpp_pr0() {}
674674

675-
#[no_mangle]
675+
#[unsafe(no_mangle)]
676676
pub fn __aeabi_unwind_cpp_pr1() {}
677677

678678
#[cfg(not(any(windows, target_os = "cygwin")))]
679679
#[allow(non_snake_case)]
680-
#[no_mangle]
680+
#[unsafe(no_mangle)]
681681
pub fn _Unwind_Resume() {}
682682

683683
#[cfg(not(any(windows, target_os = "cygwin")))]
684684
#[lang = "eh_personality"]
685-
#[no_mangle]
685+
#[unsafe(no_mangle)]
686686
pub extern "C" fn eh_personality() {}
687687

688688
#[cfg(any(all(windows, target_env = "gnu"), target_os = "cygwin"))]
689689
mod mingw_unwinding {
690-
#[no_mangle]
690+
#[unsafe(no_mangle)]
691691
pub fn rust_eh_personality() {}
692-
#[no_mangle]
692+
#[unsafe(no_mangle)]
693693
pub fn rust_eh_unwind_resume() {}
694-
#[no_mangle]
694+
#[unsafe(no_mangle)]
695695
pub fn rust_eh_register_frames() {}
696-
#[no_mangle]
696+
#[unsafe(no_mangle)]
697697
pub fn rust_eh_unregister_frames() {}
698698
}

compiler-builtins/src/arm.rs

+148-33
Original file line numberDiff line numberDiff line change
@@ -76,90 +76,205 @@ intrinsics! {
7676
);
7777
}
7878

79-
// FIXME: The `*4` and `*8` variants should be defined as aliases.
79+
// FIXME(arm): The `*4` and `*8` variants should be defined as aliases.
8080

81+
/// `memcpy` provided with the `aapcs` ABI.
82+
///
83+
/// # Safety
84+
///
85+
/// Usual `memcpy` requirements apply.
8186
#[cfg(not(target_vendor = "apple"))]
82-
pub unsafe extern "aapcs" fn __aeabi_memcpy(dest: *mut u8, src: *const u8, n: usize) {
83-
crate::mem::memcpy(dest, src, n);
87+
pub unsafe extern "aapcs" fn __aeabi_memcpy(dst: *mut u8, src: *const u8, n: usize) {
88+
// SAFETY: memcpy preconditions apply.
89+
unsafe { crate::mem::memcpy(dst, src, n) };
8490
}
8591

92+
/// `memcpy` for 4-byte alignment.
93+
///
94+
/// # Safety
95+
///
96+
/// Usual `memcpy` requirements apply. Additionally, `dest` and `src` must be aligned to
97+
/// four bytes.
8698
#[cfg(not(target_vendor = "apple"))]
87-
pub unsafe extern "aapcs" fn __aeabi_memcpy4(dest: *mut u8, src: *const u8, n: usize) {
99+
pub unsafe extern "aapcs" fn __aeabi_memcpy4(dst: *mut u8, src: *const u8, n: usize) {
88100
// We are guaranteed 4-alignment, so accessing at u32 is okay.
89-
let mut dest = dest as *mut u32;
90-
let mut src = src as *mut u32;
101+
let mut dst = dst.cast::<u32>();
102+
let mut src = src.cast::<u32>();
103+
debug_assert!(dst.is_aligned());
104+
debug_assert!(src.is_aligned());
91105
let mut n = n;
92106

93107
while n >= 4 {
94-
*dest = *src;
95-
dest = dest.offset(1);
96-
src = src.offset(1);
108+
// SAFETY: `dst` and `src` are both valid for at least 4 bytes, from
109+
// `memcpy` preconditions and the loop guard.
110+
unsafe { *dst = *src };
111+
112+
// FIXME(addr): if we can make this end-of-address-space safe without losing
113+
// performance, we may want to consider that.
114+
// SAFETY: memcpy is not expected to work at the end of the address space
115+
unsafe {
116+
dst = dst.offset(1);
117+
src = src.offset(1);
118+
}
119+
97120
n -= 4;
98121
}
99122

100-
__aeabi_memcpy(dest as *mut u8, src as *const u8, n);
123+
// SAFETY: `dst` and `src` will still be valid for `n` bytes
124+
unsafe { __aeabi_memcpy(dst.cast::<u8>(), src.cast::<u8>(), n) };
101125
}
102126

127+
/// `memcpy` for 8-byte alignment.
128+
///
129+
/// # Safety
130+
///
131+
/// Usual `memcpy` requirements apply. Additionally, `dest` and `src` must be aligned to
132+
/// eight bytes.
103133
#[cfg(not(target_vendor = "apple"))]
104-
pub unsafe extern "aapcs" fn __aeabi_memcpy8(dest: *mut u8, src: *const u8, n: usize) {
105-
__aeabi_memcpy4(dest, src, n);
134+
pub unsafe extern "aapcs" fn __aeabi_memcpy8(dst: *mut u8, src: *const u8, n: usize) {
135+
debug_assert!(dst.addr() & 7 == 0);
136+
debug_assert!(src.addr() & 7 == 0);
137+
138+
// SAFETY: memcpy preconditions apply, less strict alignment.
139+
unsafe { __aeabi_memcpy4(dst, src, n) };
106140
}
107141

142+
/// `memmove` provided with the `aapcs` ABI.
143+
///
144+
/// # Safety
145+
///
146+
/// Usual `memmove` requirements apply.
108147
#[cfg(not(target_vendor = "apple"))]
109-
pub unsafe extern "aapcs" fn __aeabi_memmove(dest: *mut u8, src: *const u8, n: usize) {
110-
crate::mem::memmove(dest, src, n);
148+
pub unsafe extern "aapcs" fn __aeabi_memmove(dst: *mut u8, src: *const u8, n: usize) {
149+
// SAFETY: memmove preconditions apply.
150+
unsafe { crate::mem::memmove(dst, src, n) };
111151
}
112152

153+
/// `memmove` for 4-byte alignment.
154+
///
155+
/// # Safety
156+
///
157+
/// Usual `memmove` requirements apply. Additionally, `dest` and `src` must be aligned to
158+
/// four bytes.
113159
#[cfg(not(any(target_vendor = "apple", target_env = "msvc")))]
114-
pub unsafe extern "aapcs" fn __aeabi_memmove4(dest: *mut u8, src: *const u8, n: usize) {
115-
__aeabi_memmove(dest, src, n);
160+
pub unsafe extern "aapcs" fn __aeabi_memmove4(dst: *mut u8, src: *const u8, n: usize) {
161+
debug_assert!(dst.addr() & 3 == 0);
162+
debug_assert!(src.addr() & 3 == 0);
163+
164+
// SAFETY: same preconditions, less strict aligment.
165+
unsafe { __aeabi_memmove(dst, src, n) };
116166
}
117167

168+
/// `memmove` for 8-byte alignment.
169+
///
170+
/// # Safety
171+
///
172+
/// Usual `memmove` requirements apply. Additionally, `dst` and `src` must be aligned to
173+
/// eight bytes.
118174
#[cfg(not(any(target_vendor = "apple", target_env = "msvc")))]
119-
pub unsafe extern "aapcs" fn __aeabi_memmove8(dest: *mut u8, src: *const u8, n: usize) {
120-
__aeabi_memmove(dest, src, n);
175+
pub unsafe extern "aapcs" fn __aeabi_memmove8(dst: *mut u8, src: *const u8, n: usize) {
176+
debug_assert!(dst.addr() & 7 == 0);
177+
debug_assert!(src.addr() & 7 == 0);
178+
179+
// SAFETY: memmove preconditions apply, less strict alignment.
180+
unsafe { __aeabi_memmove(dst, src, n) };
121181
}
122182

183+
/// `memset` provided with the `aapcs` ABI.
184+
///
185+
/// # Safety
186+
///
187+
/// Usual `memset` requirements apply.
123188
#[cfg(not(target_vendor = "apple"))]
124-
pub unsafe extern "aapcs" fn __aeabi_memset(dest: *mut u8, n: usize, c: i32) {
189+
pub unsafe extern "aapcs" fn __aeabi_memset(dst: *mut u8, n: usize, c: i32) {
125190
// Note the different argument order
126-
crate::mem::memset(dest, c, n);
191+
// SAFETY: memset preconditions apply.
192+
unsafe { crate::mem::memset(dst, c, n) };
127193
}
128194

195+
/// `memset` for 4-byte alignment.
196+
///
197+
/// # Safety
198+
///
199+
/// Usual `memset` requirements apply. Additionally, `dest` and `src` must be aligned to
200+
/// four bytes.
129201
#[cfg(not(target_vendor = "apple"))]
130-
pub unsafe extern "aapcs" fn __aeabi_memset4(dest: *mut u8, n: usize, c: i32) {
131-
let mut dest = dest as *mut u32;
202+
pub unsafe extern "aapcs" fn __aeabi_memset4(dst: *mut u8, n: usize, c: i32) {
203+
let mut dst = dst.cast::<u32>();
204+
debug_assert!(dst.is_aligned());
132205
let mut n = n;
133206

134207
let byte = (c as u32) & 0xff;
135208
let c = (byte << 24) | (byte << 16) | (byte << 8) | byte;
136209

137210
while n >= 4 {
138-
*dest = c;
139-
dest = dest.offset(1);
211+
// SAFETY: `dst` is valid for at least 4 bytes, from `memset` preconditions and
212+
// the loop guard.
213+
unsafe { *dst = c };
214+
215+
// FIXME(addr): if we can make this end-of-address-space safe without losing
216+
// performance, we may want to consider that.
217+
// SAFETY: memcpy is not expected to work at the end of the address space
218+
unsafe {
219+
dst = dst.offset(1);
220+
}
140221
n -= 4;
141222
}
142223

143-
__aeabi_memset(dest as *mut u8, n, byte as i32);
224+
// SAFETY: `dst` will still be valid for `n` bytes
225+
unsafe { __aeabi_memset(dst.cast::<u8>(), n, byte as i32) };
144226
}
145227

228+
/// `memset` for 8-byte alignment.
229+
///
230+
/// # Safety
231+
///
232+
/// Usual `memset` requirements apply. Additionally, `dst` and `src` must be aligned to
233+
/// eight bytes.
146234
#[cfg(not(target_vendor = "apple"))]
147-
pub unsafe extern "aapcs" fn __aeabi_memset8(dest: *mut u8, n: usize, c: i32) {
148-
__aeabi_memset4(dest, n, c);
235+
pub unsafe extern "aapcs" fn __aeabi_memset8(dst: *mut u8, n: usize, c: i32) {
236+
debug_assert!(dst.addr() & 7 == 0);
237+
238+
// SAFETY: memset preconditions apply, less strict alignment.
239+
unsafe { __aeabi_memset4(dst, n, c) };
149240
}
150241

242+
/// `memclr` provided with the `aapcs` ABI.
243+
///
244+
/// # Safety
245+
///
246+
/// Usual `memclr` requirements apply.
151247
#[cfg(not(target_vendor = "apple"))]
152-
pub unsafe extern "aapcs" fn __aeabi_memclr(dest: *mut u8, n: usize) {
153-
__aeabi_memset(dest, n, 0);
248+
pub unsafe extern "aapcs" fn __aeabi_memclr(dst: *mut u8, n: usize) {
249+
// SAFETY: memclr preconditions apply, less strict alignment.
250+
unsafe { __aeabi_memset(dst, n, 0) };
154251
}
155252

253+
/// `memclr` for 4-byte alignment.
254+
///
255+
/// # Safety
256+
///
257+
/// Usual `memclr` requirements apply. Additionally, `dest` and `src` must be aligned to
258+
/// four bytes.
156259
#[cfg(not(any(target_vendor = "apple", target_env = "msvc")))]
157-
pub unsafe extern "aapcs" fn __aeabi_memclr4(dest: *mut u8, n: usize) {
158-
__aeabi_memset4(dest, n, 0);
260+
pub unsafe extern "aapcs" fn __aeabi_memclr4(dst: *mut u8, n: usize) {
261+
debug_assert!(dst.addr() & 3 == 0);
262+
263+
// SAFETY: memclr preconditions apply, less strict alignment.
264+
unsafe { __aeabi_memset4(dst, n, 0) };
159265
}
160266

267+
/// `memclr` for 8-byte alignment.
268+
///
269+
/// # Safety
270+
///
271+
/// Usual `memclr` requirements apply. Additionally, `dst` and `src` must be aligned to
272+
/// eight bytes.
161273
#[cfg(not(any(target_vendor = "apple", target_env = "msvc")))]
162-
pub unsafe extern "aapcs" fn __aeabi_memclr8(dest: *mut u8, n: usize) {
163-
__aeabi_memset4(dest, n, 0);
274+
pub unsafe extern "aapcs" fn __aeabi_memclr8(dst: *mut u8, n: usize) {
275+
debug_assert!(dst.addr() & 7 == 0);
276+
277+
// SAFETY: memclr preconditions apply, less strict alignment.
278+
unsafe { __aeabi_memset4(dst, n, 0) };
164279
}
165280
}

compiler-builtins/src/lib.rs

+3
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@
2222
#![allow(clippy::manual_swap)]
2323
// Support compiling on both stage0 and stage1 which may differ in supported stable features.
2424
#![allow(stable_features)]
25+
// By default, disallow this as it is forbidden in edition 2024. There is a lot of unsafe code to
26+
// be migrated, however, so exceptions exist.
27+
#![warn(unsafe_op_in_unsafe_fn)]
2528

2629
// We disable #[no_mangle] for tests so that we can verify the test results
2730
// against the native compiler-rt implementations of the builtins.

compiler-builtins/src/macros.rs

+8-7
Original file line numberDiff line numberDiff line change
@@ -256,7 +256,7 @@ macro_rules! intrinsics {
256256

257257
#[cfg(all(target_vendor = "apple", any(target_arch = "x86", target_arch = "x86_64"), not(feature = "mangled-names")))]
258258
mod $name {
259-
#[no_mangle]
259+
#[unsafe(no_mangle)]
260260
#[cfg_attr(not(any(all(windows, target_env = "gnu"), target_os = "cygwin")), linkage = "weak")]
261261
$(#[$($attr)*])*
262262
extern $abi fn $name( $($argname: u16),* ) $(-> $ret)? {
@@ -292,7 +292,7 @@ macro_rules! intrinsics {
292292

293293
#[cfg(all(target_vendor = "apple", any(target_arch = "x86", target_arch = "x86_64"), not(feature = "mangled-names")))]
294294
mod $name {
295-
#[no_mangle]
295+
#[unsafe(no_mangle)]
296296
#[cfg_attr(not(any(all(windows, target_env = "gnu"), target_os = "cygwin")), linkage = "weak")]
297297
$(#[$($attr)*])*
298298
extern $abi fn $name( $($argname: $ty),* ) -> u16 {
@@ -333,7 +333,7 @@ macro_rules! intrinsics {
333333

334334
#[cfg(all(target_arch = "arm", not(feature = "mangled-names")))]
335335
mod $name {
336-
#[no_mangle]
336+
#[unsafe(no_mangle)]
337337
#[cfg_attr(not(any(all(windows, target_env = "gnu"), target_os = "cygwin")), linkage = "weak")]
338338
$(#[$($attr)*])*
339339
extern $abi fn $name( $($argname: $ty),* ) $(-> $ret)? {
@@ -343,7 +343,7 @@ macro_rules! intrinsics {
343343

344344
#[cfg(all(target_arch = "arm", not(feature = "mangled-names")))]
345345
mod $alias {
346-
#[no_mangle]
346+
#[unsafe(no_mangle)]
347347
#[cfg_attr(not(any(all(windows, target_env = "gnu"), target_os = "cygwin")), linkage = "weak")]
348348
$(#[$($attr)*])*
349349
extern "aapcs" fn $alias( $($argname: $ty),* ) $(-> $ret)? {
@@ -410,7 +410,7 @@ macro_rules! intrinsics {
410410
#[cfg(all(feature = "mem", not(feature = "mangled-names")))]
411411
mod $name {
412412
$(#[$($attr)*])*
413-
#[no_mangle]
413+
#[unsafe(no_mangle)]
414414
#[cfg_attr(not(any(all(windows, target_env = "gnu"), target_os = "cygwin")), linkage = "weak")]
415415
unsafe extern $abi fn $name( $($argname: $ty),* ) $(-> $ret)? {
416416
super::$name($($argname),*)
@@ -485,10 +485,11 @@ macro_rules! intrinsics {
485485
#[cfg(not(feature = "mangled-names"))]
486486
mod $name {
487487
$(#[$($attr)*])*
488-
#[no_mangle]
488+
#[unsafe(no_mangle)]
489489
#[cfg_attr(not(any(all(windows, target_env = "gnu"), target_os = "cygwin")), linkage = "weak")]
490490
$(unsafe $($empty)?)? extern $abi fn $name( $($argname: $ty),* ) $(-> $ret)? {
491-
super::$name($($argname),*)
491+
// SAFETY: same preconditions.
492+
$(unsafe $($empty)?)? { super::$name($($argname),*) }
492493
}
493494
}
494495

compiler-builtins/src/mem/mod.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
// Trying to satisfy clippy here is hopeless
22
#![allow(clippy::style)]
3+
// FIXME(e2024): this eventually needs to be removed.
4+
#![allow(unsafe_op_in_unsafe_fn)]
35

46
#[allow(warnings)]
57
#[cfg(target_pointer_width = "16")]

compiler-builtins/src/x86_64.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ intrinsics! {
4444
// HACK(https://github.com/rust-lang/rust/issues/62785): x86_64-unknown-uefi needs special LLVM
4545
// support unless we emit the _fltused
4646
mod _fltused {
47-
#[no_mangle]
47+
#[unsafe(no_mangle)]
4848
#[used]
4949
#[cfg(target_os = "uefi")]
5050
static _fltused: i32 = 0;

0 commit comments

Comments
 (0)