@system blocks and safer @trusted (ST) functions

jfondren julian.fondren at gmail.com
Sun Jul 25 06:13:41 UTC 2021

On Sunday, 25 July 2021 at 05:05:44 UTC, Bruce Carneal wrote:
> The presence of one or more @system blocks would enable @safe 
> checking elsewhere in the enclosing @trusted function.

This has an unfortunate result: if in maintenance you edit a 
@trusted function to remove its @system blocks, it'll quietly no 
longer be checked as @safe.

Of the current behavior, Walter's said that he doesn't want 
@trusted blocks because they should be discouraged in @safe code. 
With this change, we'll have exactly what he doesn't want with 
different names: s/@trusted/@system/, s/@safe/@trusted/, and the 
exact same behavior: @system blocks are just what @trusted blocks 
would've been, and @trusted code with @system blocks in it is 
just @safe code with a different name.

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?

One way to avoid the "unfortunate result" above is to permit 
@trusted blocks in @safe code. Which results in Rust equivalent 
functionality: @safe code is checked as @safe, @safe code with 
internal @trusted blocks is still checked as @safe but people 
know to audit it, and @system code isn't checked as @safe.

People like Rust's unsafe system, the current @trusted-lambda 
abuse is a simulation of unsafe, Phobos already uses @trusted 
lambdas in exactly the same way as unsafe blocks are used in 
Rust, and this proposed behavior is 99.9% identical to unsafe 
except it has this bonus "you can silently, accidentally remove 
@safe checks from your code now" feature.

I appreciate that there's a vision also to 
@safe/@trusted/@system, but it doesn't seem to have stuck, with 
Phobos having more than twice as many @trusted lambdas than 
@trusted functions:

phobos$ grep -rP '\W\(\) @trusted' --include '*.d'|wc -l
phobos$ grep -rP '\w\(\) @trusted' --include '*.d'|wc -l

I don't think that Rust has everything right. And, I don't pay 
attention to the Rust community at all; maybe they've a lot of 
gripes about how they're using unsafe blocks and unsafe 
functions. But, just look at all those @trusted lambadas. If you 
run the first command without the "|wc -l" on the end you'll see 
they're almost all single statements or expressions.

Adding a @trusted block to @safe code doesn't discard the 
@safe/@trusted/@system vision, it just lets people follow the 
unsafe vision that they're already following  without so many 
complaints about how ugly the workaround is, when D's good looks 
are one of its advantages over Rust.

This proposal also doesn't immediately discard the 
@safe/@trusted/@system vision, but it introduces a minor footgun 
because of a subtle conflict with that vision, and as people 
adopt it they'll also want another --preview switch to deal with 
the footgun, and that switch will break all current @trusted code 
that's currently assuming no @safe checks, and so there will a 
long deprecation cycle...

@trusted blocks win this. Or rather--not to be rude--but if you 
came out and said that this DIP was just some triangulation to 
get people to accept @trusted blocks, I would say: "good job! It 
got me thinking!" If not, I'm sorry.

More information about the Digitalmars-d mailing list