Expand description
A custom attribute for declaring why an unsafe
block is correct.
§Examples
The most basic way this attribute can be used is by annotating an unsafe
block and providing a reason
for why it is valid.
let mut x: u32 = 42;
let x_ptr = &mut x as *mut u32;
#[safe(reason = "This is the only reference to x")]
unsafe {
x_ptr.write(7);
}
Unsafe code often has constraints that must be valid before or after the code is run.
You can provide an assertion which will be executed with debug_assert!()
immediately before the block executes by adding a requires = "..."
to
the attribute.
let x: u32 = 42;
let x_ptr = &x as *const u32;
#[safe(
reason = "The pointer points to a valid integer",
requires = "!x_ptr.is_null()"
)]
unsafe {
assert_eq!(42, x_ptr.read());
}
Likewise, for conditions which must be upheld after the unsafe
block, you
can provide an ensures
assertion.
let mut allocated: *mut u32;
#[safe(
reason = "Malloc will always return a non-null pointer unless there is an out-of-memory error",
ensures = "!allocated.is_null()"
)]
unsafe {
allocated = libc::malloc(std::mem::size_of::<u32>()) as *mut u32;
}
§Nightly Feature Flags
Applying custom attributes to unsafe
blocks currently requires two
nightly
features:
stmt_expr_attributes
- becauseunsafe {}
is technically an expression (tracking issue)proc_macro_hygiene
- the result of expanding the#[safe]
macro is an expression which, in general (but not in our case), can result in possible hygiene issues (tracking issue)
Attribute Macros§
- safe
- A custom attribute for explaining why an
unsafe
block is valid and any invariants which must be upheld.