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

Steven Schveighoffer schveiguy at gmail.com
Thu Apr 9 15:31:01 UTC 2020


On 4/9/20 5:21 AM, Timon Gehr wrote:
> On 09.04.20 07:12, Steven Schveighoffer wrote:
>> On 4/9/20 12:31 AM, Timon Gehr wrote:
>>> On 08.04.20 22:47, Steven Schveighoffer wrote:
>>>> I never said that @trusted is the same as @system.
>>>
>>> Nor did I claim you did.
>>
>> You just said:
>>
>> "If your opinion is truly that the following two code snippets are 
>> equivalent"
>>
>> and then presented two code snippets that showed the same function 
>> with implementation tagged as @system or @trusted. I don't know how 
>> I'm supposed to interpret your claim other than you think I believe 
>> they are equivalent.
>> ...
> 
> I showed two code snippets with the same runtime semantics and compiler 
> diagnostics. This is precisely the condition you used to conclude that 
> tagging extern(C) prototypes with @safe or @trusted is equivalent.

No, the @system code will not prevent @safe violations, so they are not 
the same diagnostics.

>> The snippets are different than what we are debating.
> 
> Not at all, but apparently I was wrong when I assumed you are aware of 
> that fact, so I wonder why you agreed that this is a waste of time.

They are different. Your example has @trusted code that is compiled by 
the compiler. The example we were discussing does not. It is @system code.

> 
>> We were not talking about trusted code being called from safe code, 
>> rather system code being incorrectly prototyped as @safe or @trusted. 
>> Whether you mark it incorrectly @safe or incorrectly @trusted is 
>> non-essential.
>> ...
> 
> Of course it is essential that if you write only @safe code you can't 
> get memory safety wrong. It does not matter if the @safe annotation is 
> implicit or explicit. If you took quick a step out of the current 
> debate, would you really consider this statement controversial?

I now think this was NOT a waste of time! I didn't quite grasp what you 
are saying, though I still disagree.

I look at the attributes differently. @safe means "any code in here is 
mechanically checked". If I put @safe incorrectly on an extern(C) 
function that is really @trusted or @system, then I am wrong to do so. I 
don't view the compiler as having responsibility to ensure my prototypes 
are correctly marked (or enforce that they should be incorrectly marked, 
as you are suggesting).

Consider a library that is ONLY built with @safe code. It may call 
@trusted code from external sources, but has no @trusted markings 
anywhere. This includes extern(C) implementations and extern(C) 
prototypes for those implementations.

If I can say:

grep -R '@trusted' source

And get no results, I can be satisfied that the library is free from 
safety errors (obviously to a certain degree).

If I have to mark those @safe prototypes @trusted, now I get hits that 
are frivolous. Now, I start to ignore them because they are just 
frivolously required by the compiler, in actuality they are perfectly 
safe. So @trusted starts to lose its importance -- you now have "trusted 
you can ignore" and "trusted you need to check".

> 
>> In both cases, the person who wrote the prototype is to blame, as the 
>> person who wrote the original code clearly meant it to be system, and 
>> the person who wrote the prototype got it wrong.
>> ...
> 
> You can't blame the programmer who wrote only @safe code. It's just not 
> an option. @safe absolves that programmer from any responsibility for 
> memory corruption. That's what @safe is for and how it is advertised.

I only wrote @safe, so I am blameless:

---
pragma(mangle, "_D4core6memory2GC4freeFNaNbNiPvZv")
@safe nothrow @nogc void gcfree(void*p);

void main() @safe
{
     auto p = new int;
     gcfree(p);
     *p = 5;
}
---

This is where we differ -- @safe is to designate functions for the 
compiler to check and to tag prototype functions that have been checked. 
It only can go so far, I would not say that @safe code is undeniable 
*proof* that it's safe. It is a guarantee within a certain set of rules.

> 
> @system means: It's your responsibility to call this correctly.
> @trusted means: I am taking responsibility for memory safety.
> @safe means: The language is taking responsibility for memory safety.

I'm more focused on the mechanical side. @safe is an instruction to the 
compiler for mechanical checking, callability and linking. In practice, 
@safe means you can be reasonably sure that the compiler has checked 
such code, as long as everyone follows the rules. It's always possible 
to break the rules.

>> We have 3 situations:
>>
>> 1. The code is written as extern(C) in D, in which case, the exact 
>> safety attribute should be repeated as the prototype.
> 
> No, in this case ideally you would just use the module system and don't 
> write any separate prototypes.

Ideally yes. But sometimes you need extern(C) code for other reasons. 
For instance, if you want code to be callable from C and D.

To clarify, I meant when specifying prototypes you have 3 situations.

>> In no circumstances should extern(C) code that is written outside D 
>> should be marked @safe.
> 
> The compiler can not check that and has to assume the worst.

Possibly there is a solution that satisfies your requirements. See my 
post here: https://forum.dlang.org/post/r6kvm4$1vq5$1@digitalmars.com

> 
>> I would also consider it an error to write a prototype for an 
>> extern(C) D function other than what it actually is (@safe, @trusted, 
>> @system).
>> ...
> 
> So first you say there is no difference between @safe and @trusted on 
> prototypes, and now suddenly it is wrong to interchange the two anyway.

This is what I mean:

---
extern(C) void systemFun() @system {...}
extern(C) void safeFun() @safe {...}
---

// no measurable difference. A lie is a lie. Both are callable from the 
same places.
extern(C) void systemFun() @safe; // lie
extern(C) void systemFun() @trusted; // lie

// semantic difference, one is correct, one is wrong.
extern(C) void safeFun() @safe; // truth
extern(C) void safeFun() @trusted; // lie
---

-Steve


More information about the Digitalmars-d mailing list