|
| 1 | +# `unsafe extern` blocks |
| 2 | + |
| 3 | +🚧 The 2024 Edition has not yet been released and hence this section is still "under construction". |
| 4 | +More information may be found in the tracking issue at <https://github.com/rust-lang/rust/issues/123743>. |
| 5 | + |
| 6 | +## Summary |
| 7 | + |
| 8 | +- [`extern` blocks] must now be marked with the `unsafe` keyword. |
| 9 | + |
| 10 | +[`extern` blocks]: ../../reference/items/external-blocks.html |
| 11 | + |
| 12 | +## Details |
| 13 | + |
| 14 | +Rust 1.xx <!--TODO--> added the ability in all editions to mark [`extern` blocks] with the `unsafe` keyword.[^RFC3484] 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. |
| 15 | + |
| 16 | +The syntax for an unsafe `extern` block looks like this: |
| 17 | + |
| 18 | +```rust |
| 19 | +# #![feature(unsafe_extern_blocks)] |
| 20 | + |
| 21 | +unsafe extern "C" { |
| 22 | + // sqrt (from libm) may be called with any `f64` |
| 23 | + pub safe fn sqrt(x: f64) -> f64; |
| 24 | + |
| 25 | + // strlen (from libc) requires a valid pointer, |
| 26 | + // so we mark it as being an unsafe fn |
| 27 | + pub unsafe fn strlen(p: *const std::ffi::c_char) -> usize; |
| 28 | + |
| 29 | + // this function doesn't say safe or unsafe, so it defaults to unsafe |
| 30 | + pub fn free(p: *mut core::ffi::c_void); |
| 31 | + |
| 32 | + pub safe static IMPORTANT_BYTES: [u8; 256]; |
| 33 | +} |
| 34 | +``` |
| 35 | + |
| 36 | +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. |
| 37 | + |
| 38 | +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. |
| 39 | + |
| 40 | +[^RFC3484]: See [RFC 3484](https://github.com/rust-lang/rfcs/blob/master/text/3484-unsafe-extern-blocks.md) for the original proposal. |
| 41 | + |
| 42 | +## Migration |
| 43 | + |
| 44 | +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: |
| 45 | + |
| 46 | +```sh |
| 47 | +cargo fix --edition |
| 48 | +``` |
| 49 | + |
| 50 | +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. |
| 51 | + |
| 52 | +Alternatively, you can manually enable the lint to find places where there are `unsafe` blocks that need to be updated. |
| 53 | + |
| 54 | +```rust |
| 55 | +// Add this to the root of your crate to do a manual migration. |
| 56 | +#![warn(missing_unsafe_on_extern)] |
| 57 | +``` |
| 58 | + |
| 59 | +[`missing_unsafe_on_extern`]: ../../rustc/lints/listing/allowed-by-default.html#missing-unsafe-on-extern |
0 commit comments