Unsafe Safe Destack code can create and carry raw pointers, because there is nothing directly unsafe about just looking at pointers. Raw pointers are inert: they do not keep storage alive, do not participate in borrow checking, and do not prove exclusivity. Converting a borrow to a raw pointer is still safe because it does not touch the pointed-to memory: class User {} let user = new User(); let borrow: &User = &user; let pointer: *User = borrow; // OK: this only creates a raw pointer value Unsafe begins when code relies on a memory invariant the compiler cannot prove: | Operation | Example | Safe? | Why | |-----------|---------|-------|-----| | create or carry raw pointer values | let pointer: *User = &user, pointer == other | yes | does not touch memory | | reinterpret raw pointer values | pointer as *uint8, 0x1000 as *uint8 | yes | makes no validity claim | | wrapping address arithmetic | raw.wrappingOffset(pointer, 4) | yes | makes no allocation claim | | allocation-relative pointer math | raw.offset(pointer, 4), raw.offsetFrom(pointer, origin) | no | claims same live allocation | | access memory through a pointer | raw.asReference(pointer), raw.read(pointer), raw.write(pointer, value) | no | bypasses borrow checking | | build a raw slice descriptor from raw parts | sliceFromRaw(pointer, length) | no | claims a valid region of T | | raw bytes and layout tricks | raw.copyBytes(dst, src, n), raw.readVolatile(pointer), raw.transmute(value) | no | touches or reinterprets unchecked memory | The compiler rejects unsafe operations, like raw pointer dereferencing, outside explicit @unsafe / @safe contexts.