Discussion Thread: DIP 1028--Make @safe the Default--Final Review
Timon Gehr
timon.gehr at gmx.ch
Wed Apr 8 19:30:18 UTC 2020
On 08.04.20 15:09, Steven Schveighoffer wrote:
> On 4/7/20 10:01 PM, Timon Gehr wrote:
>> On 07.04.20 23:14, Steven Schveighoffer wrote:
>>> On 4/6/20 2:28 PM, Timon Gehr wrote:
>>>> On 06.04.20 01:38, Steven Schveighoffer wrote:
>>>>> I disagree with disallowing @safe as a specific marking on
>>>>> extern(C) code. You can write @safe extern(C) functions in D, and
>>>>> it makes no sense to require that they are @trusted at the prototype.
>>>>
>>>> The linker can hijack them. The function signature of a @trusted
>>>> function should be @safe anyway.
>>>
>>> The linker can always hijack it.
>>
>> I guess I used the wrong word. What I meant was that there is zero
>> checking that the extern(C) function you are calling was actually
>> checked to be @safe. For extern(D), the language at least makes a
>> small effort to ensure the @safe qualifier has some meaning, but given
>> that return types are not mangled, that also seems like a lie.
>
> If you change the return type, then there can be detectable differences
> at runtime. If you change the @safe vs. @trusted vs. @system, everything
> works *exactly* as before (unless the linker stops it).
>
> The biggest problem is code that works but is wrong in terms of safety.
> In that case, @safe and @trusted on prototypes are identical.
> ...
Wrong. In terms of _language_ and _type system_ design what's most
important is that if code is marked @safe, is actually memory safe
conditional on programmers getting the @trusted annotations right.
That's the promise that the language is giving.
>>
>>> Even without intention. Having it marked @trusted isn't any better
>>> than having it marked @safe in that case.
>>> ...
>>
>> Memory corruption in a @safe context should be traceable to @trusted
>> code. It's the entire point.
>
> And in this case, there is no trusted code.
You are trusting the prototype to be correct.
> It's all @safe, but you have
> a boy-who-cried-wolf effect on the @trusted prototype. "Oh, you can
> ignore those prototypes because the compiler made me do it." In fact I'm
> assuming you will see stuff like:
>
> // really @safe
> @trusted extern(C) ...
>
> causing a reviewer to pass over those as possible problems.
> ...
And of course if the module has no @trusted code at all the reviewer
will be extra careful?
> I'm not saying @safe marking of prototypes isn't prone to issues,
Purely @safe code is not supposed to be prone to issues.
> I'm saying forcing @trusted markings doesn't change that fact.
> ...
@trusted means "there may be issues here". @safe means "no issues here".
>>
>>>>
>>>>> Assuming @safe, no. Explicitly @safe OK, you marked it, you own it.
>>>>> ...
>>>>
>>>> @safe:
>>>>
>>>> // a lot of code
>>>> // ...
>>>>
>>>> extern(C) corrupt_all_the_memory();
>>>
>>> Why would you do this when @safe is the default?
>>> ...
>>
>> To show it's broken.
>>
>> Besides that, it's not currently the default, and if it is, you might
>> want to temporarily switch to @system and back.
>
> In that case, all is well! you properly marked the right ones @system.
> ...
So we're right back to trusting the programmer even though that
programmer did not actually write any @trusted annotations.
> In the current regime, @safe: at the top does the same thing you are
> trying to argue against. So there won't be existing (good) code that
> does this.
>
> In the new regime, @safe is the default, so you wouldn't need to put
> @safe: at the top.
> ...
It does not have to be at the top of the file.
> Any time the compiler forces you to mark things differently than the
> truth, you become more numb to these compiler warnings, and don't put
> any stock into their significance.
> ...
@trusted is the truth, @safe is the lie.
>> In any case, @safe code by definition is code written by untrusted
>> programmers. Why do you insist there should be a good reason? Maybe
>> the programmer was a monkey. Or malicious.
>
> @safe code is mechanically checked. Why shouldn't I be able to declare
> that when it's true?
Because the prototype is not mechanically checked. Programmers who are
not allowed to write @trusted code have no business writing @safe
extern(C) prototypes.
> And if you make me mark it @trusted, and it for
> some reason becomes @system (because it's not @trustable, a very
> unlikely occurrence), having them marked @trusted doesn't help. You
> still have to go find the prototypes (all of them) and mark them @system
> instead.
> ...
It's the prototype maintainer's responsibility to ensure it does not happen.
>>
>>>>
>>>> When did @safe become a matter of "it's your own fault if you shoot
>>>> yourself in the foot, this memory corruption you are having is a
>>>> good thing because it will teach you not to make more mistakes in
>>>> the future"? If something may break @safe-ty as it trusts the
>>>> programmer to get it right, it ought to be @trusted.
>>>
>>> If you mark a @safe extern(C) function @trusted, how does that help?
>>> I'm talking about extern(C) functions that are checked by the
>>> compiler as @safe. Why should I have to mark the prototype of that
>>> function @trusted?
>>
>> Because the extern(C) function can be changed to be @system. Hence you
>> must trust the maintainer of the prototype to keep it in sync with the
>> implementation.
>
> So you are saying this scenario is OK:
>
> Hm... my @safe function is turning into @system. But that's OK because
> everyone had to mark their prototypes @trusted! So now it becomes their
> fault I changed it.
> ...
It is their fault. Why did they make their @safety conditional on the
signature of an extern(C) function that apparently was outside their own
control?
> I don't get how this is helpful. I don't get how this is somehow
> logically superior to the same people being able to mark the functions
> @safe. In both cases, you are pulling the rug from underneath them.
> ...
But the code at the prototype is not lying about it.
> It sounds more like a "good" non-monkey programmer should mark all
> extern(C) function prototypes @system, regardless of the actual safety
> of the function, and require @trusted escapes, because they can change
> at any time without warning and they might get blamed.
If that is in fact a possibility they should absolutely do that.
Otherwise they need to have conventions in place that prevent it from
happening. If the @safety of a piece of code is conditional on such
conventions, it should be marked @trusted.
>> ...
> What if the @safe prototype is auto-generated? Then whenever it changes
> to @system, the prototype will be changed. This means, you have a memory
> issue, you search for @trusted, find all these prototypes that are
> actually prototypes for @safe functions auto generated. You now get into
> the habit of ignoring all @trusted prototypes as possible issues because
> it's just noise. Better to focus on the @trusted implementations, which
> is where the real problem can happen.
> ...
https://www.theregister.co.uk/2016/02/04/underhand_c_2015/
More information about the Digitalmars-d
mailing list