[][src]Crate safe

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 - because unsafe {} 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.