-preview=safer for D

Jonathan M Davis newsgroup.d at jmdavisprog.com
Tue Dec 17 05:19:37 UTC 2024


On Monday, December 16, 2024 2:47:27 AM MST Kagamin via Digitalmars-d wrote:
> On Saturday, 14 December 2024 at 10:20:34 UTC, Jonathan M Davis
> wrote:
> > If I want a function to be @safe, I'll mark it with @safe, and
> > I'll get all of the appropriate checks.
>
> It's not always trivial. For example, I have an array copy
> function, it takes two arrays and calls memmove on them. It's,
> like, 80% safe, but it's not obvious what it would take to make
> it safer.

Whether we're talking about @safe or -preview=safer, they're both going to
flag @system operations, requiring that a function that has @system
operations be either @system or @trusted. The difference is that if you have
a function that can be marked with @safe, and you mark it with @safe, you
have a function that can be called from other @safe functions, whereas with
-preview=safer, all you've done is track down instances where your code is
doing @system operations (and you're then forced to explicitly mark the
function as @system if it can't be @trusted). You still have to mark the
function @safe or @trusted to be able to call it from @safe code.

As for how to make @system code be @safe, the only way to do that is to use
@trusted. The question then is where exactly @trusted should be used, and
that's obviously going to depend on the code in question. In principle, when
you mark a function as @trusted, you're promising that it's 100% memory-safe
in spite of the fact that it's doing something that's @system (though that
obviously relies on the assumption that there are no compiler bugs which
impact memory-safety and that all of the @trusted code that's being called
is actually memory-safe).

If you have a function that's doing something with its arguments which are
@system, and whether you can guarantee that it's actually @safe depends on
the arguments that are given such that you can't guarantee that the code is
memory-safe based solely based on what the function itself is doing, then
that generally means that the function should be marked as @system, and it
should then be documented what the requirements for the arguments are in
order for what the function is doing to be memory-safe. Then the caller
would make sure that it was passing in valid arguments and be marked
@trusted.

One example of something like this would be a function like free. For free
to be considered memory-safe, you have to pass it the correct arguments
(otherwise, you can get issues like double-frees). So, free has to be
@system, and it's the caller's responsibility to make sure that it's passing
valid arguments to free. And if it does that, then it can be marked
@trusted.

As to whether your particular function can be marked @trusted, I don't know,
but it sounds like it probably can't be. If you can't be sure that the
function is actually memory-safe, then that generally means that it's either
doing something wrong that needs to be fixed, or that its memory safety
depends on its arguments, in which case, the @trusted needs to be further up
the call stack. But it's the kind of thing which really depends on what
exactly the code is doing. In principle, to be able to mark a function as
@trusted, it has to present an @safe API, since it's supposed to be
impossible for an @safe function to doing anything that isn't memory-safe.

Either way, if you screw up and put @trusted in the wrong place, at least
you know where to look when something happens which involves memory-safety
having been violated, since only @trusted code can cause @safe code to do
something that isn't memory-safe.

You might want to check out this blog post by Paul Backus:

https://pbackus.github.io/blog/what-does-memory-safety-really-mean-in-d.html

- Jonathan M Davis





More information about the Digitalmars-d mailing list