DIP1028 - Rationale for accepting as is

Johannes Loher johannes.loher at fg4f.de
Sun May 24 10:40:11 UTC 2020


On Sunday, 24 May 2020 at 08:55:32 UTC, Walter Bright wrote:
> I infer your position is the idea that putting @trusted on the 
> declarations isn't greenwashing, while @safe is.
>
> I can't see a practical difference between:
>
> @safe extern (C) void whatevs(parameters);
> @trusted extern (C) void whatevs(parameters);
>
> Both require that whatevs() provide a safe interface. The 
> difference between them is in the implementation of those 
> functions, not the interface. Since the D compiler cannot see 
> those implementations, they are immaterial to the compiler and 
> user.

 From my perspective, there is a clear difference in meaning 
between them: @safe means verified by the compiler (which as you 
mentioned can never be true for declarations where the code is 
not available, hence it always is a lie in that case) and 
@trusted means verified by the developer.

Whenever @trusted is slapped on _anything_, it is clear that 
extra caution is needed (in codereviews etc.) and as others have 
mentioned, it is easily searchable.

When I put @safe on a piece of code, my expectation is that it is 
actually verified by the compiler. If that is not possible, it 
should not compile.

The same reasoning also applies to the case where the annotations 
are not added by the developer explicitly and the defaults are 
used instead:

If the default is @safe and the code for an unannotated 
declaration is not available, it should not compile.

Making @trusted the default is not an option because as mentioned 
earlier, one of the points of @trusted is for it to be actually 
seen, which is not the case if it is the default, so I will not 
elaborate on that.

If @sytem is the default, there is no issue but of course the 
whole point of this DIP is to move away from that.

I understand that today it is possible to slap @safe on 
declarations without code without the compiler complaining but it 
really _should_ be an error in order to have a consistent meaning 
of @safe, @trusted and @system (@safe = compiler verified, 
@trusted = user verified, @system = not verified) also in the 
case of declarations where no code is available.

Let's assume this is indeed the way to go, then there are 2 
possible solutions for this DIP regarding how to handle this:

1. Make declarations without code default to @system instead of 
@safe. This is what many here have been arguing for but as you 
mentioned several times, it has the drawback of adding special 
cases to the language. As a user, it does not seem that 
problematic though because the compiler can easily tell you what 
is going on when there is an issue (i.e. calling an unannotated 
declaration without code from a @safe function could result in 
compiler error message that explains why this does not work). But 
I admit that it is still a bit weird to have 2 different 
defaults. Additionally, explicitly annotating such declarations 
with @safe should be a compile error.

2. Make @safe the default for _all_ declarations but still make 
@safe on declarations without code a compile error (because the 
compiler cannot verify it). This means that annotating function 
declarations without code with @system or @trusted is now 
mandatory. This is what Timon has been arguing for if I 
understood him correctly.

3. There may be a third option if we introduce something like 
conditional safety but I do not completely understand that yet. 
This is what H.S. Theo has been suggesting.

Option 1 and 2 both have the „issue“ that people might 
„greenwash“ things by simply slapping @trusted: at the top of a 
file. But that can always be done anyways and at least it is 
explicit and searchable. As mentioned, using @trusted now has the 
meaning that it is user verified so it always needs extra caution.

Personally I prefer option 2 because it is a lot more consistent: 
There are no special cases.

Until now, I did not discuss whether or not all of this should 
apply only to extern(C) function declarations without code or all 
function declarations without code. This is because it is a 
separate point. Both are possible and have pros and cons:

If it applies to extern(C) function declarations without code 
only, then we can still have @safe extern(D) declarations. They 
are not verified by the compiler but you get linker errors 
instead because @safe is part of the mangling. The benefit is 
that you get more @safe code by default, the drawback is that it 
relies on linker errors instead of compiler errors and that it 
introduces a special case.

If it applies to all function declarations without code, also 
extern(D) function declarations without bodies need to be 
annotated with @trusted explicitly if they are @safe or @trusted. 
If they are @system, we still get linker errors due to name 
mangling. The benefit is that it is a very consistent solution, 
no special cases are needed. The drawback is that it requires 
more manual effort to add the additional annotations (but then, 
don't we want to encourage people to explicitly annotate things 
anyways...?).

Personally, I prefer the second option because of its simplicity. 
Also you mentioned somewhere that linker errors are not that 
helpful to the user and I couldn’t agree more. Also I personally 
don't use extern(D) function declarations without bodies a lot, 
so the drawback is negligible for me. Others' experiences might 
be different though.

Steven actually made a proposal regarding creating 2 different 
manglings for extern(C) functions that are implemented in D. 
Regardless of which of the solutions  is taken, this could 
provide the same benefits that we have for extern(D) functions 
(linker errors if @safety does not match in the mangling). 
However, it sounds like a complicated solution (in an answer to 
him, you already mentioned that there might be technical 
difficulties regarding some object formats, debugging symbols, 
etc.) and I am not sure it's worth it. It also makes swapping out 
the libraries a bit weird: if you use an actual C library, it 
will always link but if swap to a library implemented in D, it 
only links if the @saftey mangling matches.


Coming back to the original point: I think it is really important 
that we give @safe, @trusted and @sytem their clear meaning (as 
explained above) also for declarations without bodies. In my 
opinion, we should choose the second option in both of the 
questions I presented.


More information about the Digitalmars-d-announce mailing list