-preview=safer for D

Jonathan M Davis newsgroup.d at jmdavisprog.com
Sun Dec 15 00:04:06 UTC 2024


On Saturday, December 14, 2024 2:21:55 PM MST Walter Bright via Digitalmars-d wrote:
> On 12/14/2024 2:20 AM, Jonathan M Davis wrote:
> > if I actually want to do that, I can just start
> > putting @safe on my functions, and there's no need for a compiler flag.
>
> We've pushed that for years, but it doesn't work. It doesn't work because of the
> transitive nature of @safe - you can't do it piecemeal, it has to be done all at
> once.
>
> Safer is enabling the checks, but not transitively.

In general, it works just fine if you start from the bottom, since @system
code can call @safe code. You do have some issues with recursion, of course,
particularly when there are several functions involved, but it can be done.
And of course classes have more issues with all of this in general due to
how attributes interact with polymorphism. However, it's starting at the top
of the call stack where it's a disaster, basically requiring @trusted
everywhere as you move down the stack, whereas coming up from the bottom, it
generally is quite possible to make changes in a piecemeal fashion, since
it has no effect on what's up the stack if the stuff below it shifts from
@system to @safe or @trusted.

The bigger problem is really that there isn't enough incentive to actually
bother to mark functions @safe. Anyone who actually cared enough about @safe
for a project to want to go to the effort would have been using @safe
explicitly in the first place, and while @safe definitely finds problems, if
you're not doing a bunch of low level stuff, it often doesn't help much in
practice, so plenty of folks don't bother. And for many of those folks,
@safe by default would be fine so long as the third-party code that they're
calling is @safe, since they wouldn't have to use explicit attributes any
more than they do now when ignoring @safe, and if they're not actually doing
anything @system, then they wouldn't be doing anything for the compiler to
complain about (either with @safe by default or with the flag).

In any case, I'm not against the flag existing as a helper towards moving
code towards @safe by default. I just don't see enough value in it to bother
using it myself, and I'm very much against the idea of ever making it the
default, because without the transitivity, you don't get the actual
guarantees, and you still get most of the pain.

If the flag is the default, then code in general may become more
memory-safe, because folks would then be forced to either mark their code
with @trusted or @system to shut the compiler up, or they'd fix the things
that the flag pointed out. However, it does nothing to solve the problem of
making code in general @safe or to make it easier to transition a code base
to being @safe everywhere. To get the actual guarantees from @safe, the
functions themselves need to also be @safe (that is, they need to be
attributed as @safe by the type system), and that means either going to the
effort of manually marking all of those functions with @safe (or putting
@safe: at the top of the module if it has no templates), or it means having
@safe by default. If you're manually marking functions as @safe, then the
flag isn't helping you, and if we have @safe by default, then the flag isn't
necessary (at best, it would help find issues prior to @safe becoming the
default so that fewer changes need to be made at that point).

>From what I can see, having @safe by default is going to make it easier to
transition a code base to being @safe, whereas the flag will not. That's
because with @safe by default, a lot of code will just magically become
@safe and work, because it's not actually doing anything @system, and in
many cases, the functions that it's calling will then magically become @safe
as well. The code that is then doing something @system will need to be
fixed, but that's true of the flag as well. So, both having the flag be the
default and having @safe be the default require fixing functions which
aren't explicitly marked with an attribute and which are doing something
that isn't memory-safe, but with the flag, you then still have to go to all
of the same effort that you'd have to go to now to explicitly mark functions
with @safe or @trusted to be able to have your functions actually be @safe,
whereas with @safe by default, a lot of functions gets made @safe for you.

As such, if we're going to change the default, I would strongly argue that
we just make @safe the default and not the flag. @safe by default provides
more benefit with less pain - at least if the ultimately goel is to have
@safe functions - because then the compiler is actually helping you mark all
of your functions as @safe rather than just complaining about the places
where your code is doing stuff that is @system.

- Jonathan M Davis





More information about the Digitalmars-d mailing list