Unsafety

Guideline: All unsafe code shall be contained inside a sound safe abstraction gui_goekLVFUAjSM
status: draft
tags: undefined-behavior
category: required
decidability: undecidable
scope: module
release: -

A safe abstraction is considered sound, when it is impossible to build a safe program using the safe abstraction that invokes undefined behavior.

Safe abstractions shall be kept as small as possible and only include features that cannot be built on top in safe Rust.

Rationale: rat_3FoizIv2mZ4Z
status: draft
parent needs: gui_goekLVFUAjSM

Unsound safe abstractions leak the possibility for undefined behavior to safe Rust. With violations of this rule, it would no longer suffice to only focus on unsafe modules as the root cause of undefined behavior

Because safe abstractions are more difficult to review compared to safe code due to the subtle semantics of unsafe operations, their size need to be minimized.

Non-Compliant Example: non_compl_ex_4Rj4YQkr1Nr4
status: draft
parent needs: gui_goekLVFUAjSM

The following module with a safe API uses unsafe code and is therefore a safe abstraction. However, when passing a data slice with an index that is outside the range of the slice, the safe function will cause undefined behavior.

pub mod bad {
    pub fn get_value(data: &[i32], index: usize) -> i32 {
        unsafe {
            data.get_unchecked(usize)
        }
    }
}
Compliant Example: compl_ex_aM7w7UbgSdvT
status: draft
parent needs: gui_goekLVFUAjSM

This safe module checks that its argument are valid, (i.e., they satisfy the safety precondition of the unsafe operation) before performing the unsafe operation.

pub mod good {
    pub fn get_value(data: &[i32], index: usize) -> i32 {
        assert!(usize < data.len());
        unsafe {
            data.get_unchecked(usize)
        }
    }
}