Discussion Thread: DIP 1028--Make @safe the Default--Final Review

Jonathan M Davis newsgroup.d at jmdavisprog.com
Thu Mar 26 22:47:10 UTC 2020


On Thursday, March 26, 2020 5:40:41 AM MDT IGotD- via Digitalmars-d wrote:
> On Thursday, 26 March 2020 at 05:14:44 UTC, Jonathan M Davis
>
> wrote:
> > Making it so that all code must be either verified by the
> > compiler to be @safe or be marked by the programmer to be
> > @trusted or @system means that all code which could contain
> > memory safety issues will be segregated by @trusted or system,
> > whereas right now, you can have large swathes of code which is
> > not marked with anything and is unchecked. If the programmer is
> > not using the compiler to verify @safety and is not verifying
> > @system sections of code and marking it as @trusted, then there
> > are no compiler guarantees about memory safety in that code.
> > Sure, the programmer may have done a good enough job that there
> > are no memory safety bugs in the code (and that's far more
> > likely with D code than C/C++ code), but by making @safe the
> > default, it makes it so that none of that will fall through the
> > cracks unless the programmer explicitly tells the compiler to
> > not check.
>
> FFI functions like extern(C) must be @system as the compiler
> cannot check this. Should extern(C) automatically mean @system?
> Well I think so because that's the only feasible possibility.
>
> I think we are heading into the @safe, @trusted, @system
> discussion and that's where I think the problem really lies, that
> @trusted just messes things up. If @safe code can call @system
> code directly then we are good and we can us extern(C) just as
> before (with or without @system block, another discussion) If we
> have this strange "human verified" @trusted nomenclature then
> things starts because fuzzy. What is an FFI function, trusted or
> system?
>
> I think that @trusted must go, then things start to clear up.

Without @trusted, @safe is completely broken. If you just think it through,
that should be clear. Right now, if you have code such as

auto foo(int* ptr) @safe
{
    ...

    ++ptr;

    ...
}

the function will fail to compile, because you're attempting to do something
that's @system inside an @safe function. You may or may not have realized
that you were doing something @system, so it could very well be catching a
bug for you. Either way, you then have four options:

1. Alter the code so that it doesn't need to do anything @system in order to
   do whatever it is that you're trying to do.

2. Mark the function as @trusted to indicate that you know that what you're
   doing is actually @safe.

3. Put the @system code in another function which you mark as @trusted, and
   call it from the @safe function.

4. Make it so that the function is @system instead, requiring that the
   caller verify that what they're doing is @safe and deal with @trusted.

Which solution is best depends on the code in question.

However, what happens if @trusted isn't a thing? Suddenly, there is no way
to make this function @safe. The compiler isn't smart enough to understand
your code to the point that it can determine that what you're doing is
@safe, and you have no way to tell the compiler that you're sure that it's
actually @safe. So, there are then two possibilities:

1. The function must be @system, and every function which calls it must be
   @system. You therefore have no clue where the code is that potentially
   has memory safety problems, and none of that code is being verified by
   the compiler for @safety. Ultimately, you end up with programs that might
   have pockets of @safe code, but in general, they won't be able to do much
   with @safe at all, because all it takes is a single @system operation
   (like calling a C function for I/O), and then nothing in the call stack
   can be @safe.

2. You allow @safe functions to do @system operations. This would then make
   @safe utterly meaningless, because it wouldn't be verifying anything at
   all. You could get partial verification by disallowing @system operations
   in @safe functions while still allowing an @safe function to call an
   @system functions, but that still hides that something @system is
   happening and makes it so that the compiler is neither checking those
   function calls nor flagging them as errors so that you know that you need
   to do something to actually use them in an @safe manner. It would
   introduce a massive hole in the @safety system.

Without @trusted, there is no bridge between @safe and @system code. @safe
needs to be verifying code for memory safety, or it's utterly pointless, and
a program that can't call any @system code is ultimately going to be
useless. The downside to @trusted is of course that it's up to the
programmer to verify it, and they could get it wrong, but since the compiler
isn't smart enough to verify that code for memory safety, there really isn't
an alternative if you want the compiler to be verifying much of your program
for memory safety at all.

Ultimately, we do have to rely on the programmer to get @trusted right, but
if they don't, then the rules of the @safety system make it so that when you
have a memory safety issue, you only have to look at the code that's marked
as @trusted and the @system code that it calls in order to track it down.

It can certainly be argued whether @safe or @system should be the default,
and it can argued whether it really makes sense to have @trusted at the
function level instead of having some kind of @trusted block within a
function, but @trusted itself is vital to how the @safety system works.

- Jonathan M Davis





More information about the Digitalmars-d mailing list