Memory Safety

32.1 @safe, @trusted, @system

The compiler verifies memory safety: no pointer arithmetic, unsafe casts, void* reinterpretation, __gshared access, or calls to @system code

The programmer guarantees safety. Callable from @safe. Keep it minimal and reviewed.

No checks (the default for non-template functions today) Templates and auto functions infer attributes. Mark public APIs @safe explicitly.

"Safe by default" is planned via editions. Write @safe code now.

@safe int[] firstN(int[] arr, size_t n) { return arr[0 .. n]; }   // bounds-checked slicing

@trusted void zeroBuffer(ubyte[] buf)
{
    import core.stdc.string : memset;
    memset(buf.ptr, 0, buf.length);   // unsafe call wrapped with a safe interface
}

@safe:                               // apply to the rest of the module

32.2 DIP1000: Scope Pointers (-preview=dip1000)

DIP1000 enables @safe stack allocation, scope classes, and safe slicing of static arrays. It's on by default in newer compilers, so check your version's default.

@live (an experimental ownership/borrowing checker) is available for functions marked @live.

@safe int* escape()
{
    int x;
    return &x;                       // error with dip1000: reference to a local escapes
}

@safe void process(scope int[] data) { }   // `data` can't escape (stored in a global or returned)

@safe ref int first(return ref int[2] arr) { return arr[0]; }   // `return ref`: result tied to arr's lifetime
@safe int* ptr(return scope int* p) { return p; }

32.3 Other Safety Features

Array bounds checking (-boundscheck=on|safeonly|off), null-dereference segfaults (no UB optimization in DMD), default initialization, no implicit narrowing, final switch, contracts, and immutable thread sharing.