Unsafe extern
blocks
Summary
extern
blocks must now be marked with theunsafe
keyword.
Details
Rust 1.82 added the ability in all editions to mark extern
blocks with the unsafe
keyword.1 Adding the unsafe
keyword helps to emphasize that it is the responsibility of the author of the extern
block to ensure that the signatures are correct. If the signatures are not correct, then it may result in undefined behavior.
The syntax for an unsafe extern
block looks like this:
#![allow(unused)] fn main() { unsafe extern "C" { // sqrt (from libm) may be called with any `f64` pub safe fn sqrt(x: f64) -> f64; // strlen (from libc) requires a valid pointer, // so we mark it as being an unsafe fn pub unsafe fn strlen(p: *const std::ffi::c_char) -> usize; // this function doesn't say safe or unsafe, so it defaults to unsafe pub fn free(p: *mut core::ffi::c_void); pub safe static IMPORTANT_BYTES: [u8; 256]; } }
In addition to being able to mark an extern
block as unsafe
, you can also specify if individual items in the extern
block are safe
or unsafe
. Items marked as safe
can be used without an unsafe
block.
Starting with the 2024 Edition, it is now required to include the unsafe
keyword on an extern
block. This is intended to make it very clear that there are safety requirements that must be upheld by the extern definitions.
See RFC 3484 for the original proposal.
Migration
The missing_unsafe_on_extern
lint can update extern
blocks to add the unsafe
keyword. The lint is part of the rust-2024-compatibility
lint group which is included in the automatic edition migration. In order to migrate your code to be Rust 2024 Edition compatible, run:
cargo fix --edition
Just beware that this automatic migration will not be able to verify that the signatures in the extern
block are correct. It is still your responsibility to manually review their definition.
Alternatively, you can manually enable the lint to find places where there are unsafe
blocks that need to be updated.
#![allow(unused)] fn main() { // Add this to the root of your crate to do a manual migration. #![warn(missing_unsafe_on_extern)] }