On Tuesday, 15 November 2022 at 14:05:42 UTC, Siarhei Siamashka wrote:
> On Tuesday, 15 November 2022 at 13:16:18 UTC, Paul Backus wrote:
> D's safety model is the same. In @safe
code, D will reject anything that the compiler cannot say for sure is memory safe. However, unlike in Rust, @safe
is not the default in D, so you must mark your code as @safe
manually if you want to benefit from these checks.
I specifically asked for Ali's opinion. Because the context is that the compiler couldn't catch a memory safety bug in the code that was annotated as @safe (but without -dip1000) and Ali commented that "the compiler cannot do anything about it in all cases and we wouldn't want it to spend infinite amount of time to try to determine everything". This sounds like he justifies the compiler's failure and accepts this as something normal.
The https://dlang.org/spec/memory-safe-d.html page also provides a rather vague statement: "@safe functions have a number of restrictions on what they may do and are intended to disallow operations that may cause memory corruption". Which kinda means that it makes some effort to catch some memory safety bugs. This weasel language isn't very reassuring, compared to a very clear Rust documentation.
The goal of @safe
is to ensure that memory corruption cannot possibly occur in @safe
code, period--only in @system
or @trusted
code. If the documentation isn't clear about this, that's failure of the documentation.
However, there are some known issues with @safe
that require breaking changes to fix, and to make migration easier for existing code, those changes have been hidden behind the -dip1000
flag. So in practice, if you are using @safe
without -dip1000
, you may run into compiler bugs that compromise memory safety.
That's what happened in your example. Slicing a stack-allocated static array shouldn't be allowed in @safe
code without -dip1000
, but the compiler allows it anyway, due to a bug, and the fix for that bug is enabled by the -dip1000
switch.