@system blocks and safer @trusted (ST) functions

jfondren julian.fondren at gmail.com
Sun Jul 25 13:14:20 UTC 2021


On Sunday, 25 July 2021 at 12:05:10 UTC, Steven Schveighoffer 
wrote:
> On Sunday, 25 July 2021 at 06:13:41 UTC, jfondren wrote:
>> Instead of people accepting that @safe "isn't really @safe" in 
>> the presence of @trusted blocks, and that the whole body of 
>> the function has to be audited, with this change we'll have 
>> s/@safe/@trusted/ blocks that aren't really @safe in the 
>> presence of @system blocks, and that the whole body of the 
>> function has to be audited. The "you have to audit this" 
>> signifier is the same, an internal lower-protection block, and 
>> all that's gained is that the function attribute's spelled 
>> differently. Is this really worth it?
>
> Yes.

OK. I'll argue the opposite position for a bit, then.

Here's a @trusted function with a non- at safe component:

```d
ulong getAvailableDiskSpace(scope const(char)[] path) @trusted
{
     ULARGE_INTEGER freeBytesAvailable;
     auto err = GetDiskFreeSpaceExW(path.tempCStringW(), 
&freeBytesAvailable, null, null);
     cenforce(err != 0, "Cannot get available disk space");
     return freeBytesAvailable.QuadPart;
}
```

With this proposal, I imagine:

```d
ulong getAvailableDiskSpace(scope const(char)[] path) @trusted
{
     ULARGE_INTEGER freeBytesAvailable;
     auto err = @system GetDiskFreeSpaceExW(path.tempCStringW(), 
&freeBytesAvailable, null, null);  // expression usage?
     @system{ auto err = GetDiskFreeSpaceExW(path.tempCStringW(), 
&freeBytesAvailable, null, null); }  // scopeless block?
     cenforce(err != 0, "Cannot get available disk space");
     return freeBytesAvailable.QuadPart;
}
```

And in current practice:

```d
ulong getAvailableDiskSpace(scope const(char)[] path) @safe
{
     ULARGE_INTEGER freeBytesAvailable;
     auto err = () @trusted {
         return GetDiskFreeSpaceExW(path.tempCStringW(), 
&freeBytesAvailable, null, null);
     } ();
     cenforce(err != 0, "Cannot get available disk space");
     return freeBytesAvailable.QuadPart;
}
```

So a naive take is "the last two versions are literally the 
same", but they become distinct when all three versions are 
framed by how they came to be, respectively:

1. a @trusted function as written by someone trying to properly 
use the language as described by 
https://dlang.org/spec/memory-safe-d.html

2. a @trusted function as written after that document is updated 
to reflect this DIP.

3. a @trusted function in the current "@trusted functions are bad 
because they don't check anything, avoid them" fail state, which 
is ugly because it's a late adaptation to a fault in the language 
rather than a result of deliberate design.

In the first case, @safe/@trusted/@system functions are dutifully 
written and then bugs are later found in the @trusted functions. 
@trusted functions are an attractive nuisance.

In the second case, @safe/@trusted/@system functions are written 
and that doesn't happen. @trusted functions have been 
rehabilitated and have their intended role.

In the last case, only @safe/@system functions are written, and 
some of the @safe functions are secretly, really, @trusted 
functions that have be written in a weird way to work. @trusted 
functions are either a mistake or a shorthand for a @safe 
function whose entire body may as well be in a @trusted block.

Rather than bless the failure state by giving it a better syntax 
(and continuing to have @trusted as a problem for new 
programmers), we'd like to fix @trusted so that @trusted 
functions are worth writing again.

Does that sound about right?


More information about the Digitalmars-d mailing list