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