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.