April 05, 2020
On 04.04.20 08:53, Walter Bright wrote:
> On 4/3/2020 2:06 PM, Steven Schveighoffer wrote:
>> I want to make sure you understand that we are not talking about extern(C) functions that are written in D.
> 
> I understand totally what you are talking about.
> 
> 
>> But what should absolutely not compile is:
>>
>> extern(C) int free(void *);
>>
>> void foo(int *ptr) // now inferred @safe
>> {
>>     free(ptr);
>> }
> 
> I understand your proposal. You want C functions without bodies to be @system.
> 
> 
>> The fact that we cannot control where/how people define their prototypes means we have to be firm on this. They need to opt-in to @safe with extern(C), it cannot be default.
> 
> On the other hand, special cases like this tend to cause unexpected problems in the future.

This is the special case! @safe is supposed to mean the compiler has verified this function to not cause memory corruption. Why should extern(C) functions be an exception to that rule?

Your are essentially saying something like: "why should pointer arithmetic be disallowed in @safe functions when there are other operations on pointers that are okay? This seems like a special case rule that will cause problems in the future."

> Experience pretty much guarantees it. It's likely to be tricky to implement as well.
> ...

I really doubt that. It's a simple rule. The version that is easiest to implement is you simply disallow extern(C) functions without body to be marked @safe. It's a single `if` statement in an appropriate place.

> People remember simple rules. They don't remember rules with odd exceptions to them, that always winds up with trouble and bug reports. 

I think you are the only one in this thread who considers this to be the odd exception instead of the general rule.

> Simple rules applied evenly lead to a compiler that works and is reliable. I'm afraid the weight of all the special rules will crush D.
> 
> Now, as to what to do. I spent a few minutes and added `@system:` in to the C headers in druntime for windows, posix, and linux. Done. I hope someone else will do it for freebsd, etc., if not I'll go do that to.
> 
>  > is going to cause huge issues.
> 
> I doubt that for the simple reason that @system by default has not caused huge issues.
> ...

That makes no sense at all. You are arguing in favor of _@trusted_ by default! It should not even be _possible_ to mark an extern(C) function @safe, it has to be either @system or @trusted. The compiler does not do any checking here.

> The rule is simple:
> 
> "For a D module with a bunch of C declarations in it, start it with `@system:`."
> ...

So it's memory safety by convention.

> It's not a hard rule to check. It's one line. D's C interface has always relied on the user to get right. Recall that C doesn't do any name mangling at all:
> 
>    ----- mylib.di
>      extern (C) int addOne(int i);
> 
>    ----- mylib.c
>      double addOne(double d) { return d + 1; }
> 
> 
> That'll link fine and yet fail at runtime. Oops! Calling it @system will not help at all. If the C implementation is bad, there's not a damn thing D can do about it, with or without @system. It's always going to be this way.

Right. How can you claim that this is @safe code?
April 05, 2020
On Sunday, 5 April 2020 at 19:22:59 UTC, Timon Gehr wrote:
> That makes no sense at all. You are arguing in favor of _@trusted_ by default! It should not even be _possible_ to mark an extern(C) function @safe, it has to be either @system or @trusted. The compiler does not do any checking here.

I agree completely with this: it should be a compile-time error to declare a bodyless extern(C) function @safe, regardless of whether it is done implicitly by default, or explicitly with an annotation.

The only distinction between @safe and @trusted is the compiler verification of the safety of a function's implementation. If that compiler verification wasn't done, then @safe cannot rightly apply.

If having a different implicit default for bodyless extern(C) functions is too complicated, then just don't have a default for them at all: require all such declarations to be explicitly annotated either @system or @trusted.
April 05, 2020
On 04.04.20 08:58, Walter Bright wrote:
> On 4/3/2020 2:42 PM, Joseph Rushton Wakeling wrote:
>> Now I'm not suggesting that D should do it because Rust does ;-) But their reasoning seems sound, and I don't see an obvious reason for assuming @safe-ty of functions that the D compiler cannot verify.
> 
> In both Rust and D the reliance is on the programmer when calling functions in another language. D gives you the option to allow the programmer to treat them as safe if he wants to.

Which is fully unnecessary because @trusted fills that role perfectly fine.

The real D innovation that you appear to be arguing in favor of is that D allows you to treat the function as @safe by accident, i.e., even if you don't want to. :)

I don't understand your "elite C hacker" attitude towards this. If (teams of) programmers never make mistakes, they don't need @safe.


(BTW: I am still getting new messages from up to two days ago. Not sure what's up with that.)
April 05, 2020
On 04.04.20 08:55, Walter Bright wrote:
> On 4/3/2020 5:44 PM, Jonathan M Davis wrote:
>> Well, I don't think that you've actually acknowledged any of it, and what
>> responses you do have make it seem like you're not aware of it or are
>> ignoring it.
> 
> I have replied to it more than once.

It however seems you have yet to reply in a way that makes sense to anyone (perhaps besides yourself).

You could argue that the underlying problem is that it is even allowed to mark extern(C) functions as @safe, and that this is a language design bug that exists today and is independent of DIP 1028, but acknowledging the problem (silent API breakage, insanely error prone defaults for extern functions) and then dismissing it as irrelevant by pointing out that there is no problem if you just fix all the existing code and then proceed to make no further mistakes is somewhat ridiculous.
April 05, 2020
On 4/5/20 3:57 PM, tsbockman wrote:
> On Sunday, 5 April 2020 at 19:22:59 UTC, Timon Gehr wrote:
>> That makes no sense at all. You are arguing in favor of _@trusted_ by default! It should not even be _possible_ to mark an extern(C) function @safe, it has to be either @system or @trusted. The compiler does not do any checking here.
> 
> I agree completely with this: it should be a compile-time error to declare a bodyless extern(C) function @safe, regardless of whether it is done implicitly by default, or explicitly with an annotation.
> 
> The only distinction between @safe and @trusted is the compiler verification of the safety of a function's implementation. If that compiler verification wasn't done, then @safe cannot rightly apply.
> 
> If having a different implicit default for bodyless extern(C) functions is too complicated, then just don't have a default for them at all: require all such declarations to be explicitly annotated either @system or @trusted.

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. Assuming @safe, no. Explicitly @safe OK, you marked it, you own it.

We have similar problems with inout -- preventing obvious incorrect cases makes sense, until it doesn't. I wish now I could go back and change what I thought, but unfortunately I'm not well-versed in the compiler to make the changes myself.

-Steve
April 06, 2020
On Saturday, 4 April 2020 at 06:53:57 UTC, Walter Bright wrote:
> [....]
> Now, as to what to do. I spent a few minutes and added `@system:` in to the C headers in druntime for windows, posix, and linux. Done. I hope someone else will do it for freebsd, etc., if not I'll go do that to.
>

The thought crossed my mind that this same reasoning could be applied as a counter-argument for this DIP:

... So functions are not safe by default?

Now, as to what to do. I spent a few minutes and added
`@safe:` in to the source files in druntime for windows, posix,
and linux. Done. I hope someone else will do it for freebsd,
etc., if not I'll go do that to.

That being said, it seems like a weak argument, so I don't think it changes much, but I thought it was interesting.

April 06, 2020
On Monday, 6 April 2020 at 00:09:41 UTC, Jonathan Marler wrote:
> Now, as to what to do. I spent a few minutes and added
> `@safe:` in to the source files in druntime for windows, posix,
> and linux. Done.

That's my preferred solution to all this. It is a breaking change but much less of one. I wrote about it a few months ago in my blog:

http://dpldocs.info/this-week-in-d/Blog.Posted_2020_01_13.html#my-attribute-proposal---no-changes-to-defaults

April 05, 2020
On Sunday, April 5, 2020 5:38:21 PM MDT Steven Schveighoffer via Digitalmars-d wrote:
> On 4/5/20 3:57 PM, tsbockman wrote:
> > On Sunday, 5 April 2020 at 19:22:59 UTC, Timon Gehr wrote:
> >> That makes no sense at all. You are arguing in favor of _@trusted_ by default! It should not even be _possible_ to mark an extern(C) function @safe, it has to be either @system or @trusted. The compiler does not do any checking here.
> >
> > I agree completely with this: it should be a compile-time error to declare a bodyless extern(C) function @safe, regardless of whether it is done implicitly by default, or explicitly with an annotation.
> >
> > The only distinction between @safe and @trusted is the compiler verification of the safety of a function's implementation. If that compiler verification wasn't done, then @safe cannot rightly apply.
> >
> > If having a different implicit default for bodyless extern(C) functions is too complicated, then just don't have a default for them at all: require all such declarations to be explicitly annotated either @system or @trusted.
>
> 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. Assuming @safe, no. Explicitly @safe OK, you marked it, you own it.
>
> We have similar problems with inout -- preventing obvious incorrect cases makes sense, until it doesn't. I wish now I could go back and change what I thought, but unfortunately I'm not well-versed in the compiler to make the changes myself.

Except that it _does_ make sense to mark it as @trusted, because the information about the body having been verified by the compiler to be @safe is lost due to the lack of extern(D) name mangling. The compiler has no way of knowing whether the function was written in D and compiled by dmd elsewhere or whether it was compiled as C code elsewhere. When you mark an extern(C) declaration with anything other than @system, you're telling the compiler that it's @safe, and @trusted is the appropriate attribute for the programmer to be telling the compiler that a function is @safe, whereas @safe is the approrpiate attribute for when the compiler does it on its own.

Allowing @safe on extern(C) declarations doesn't help at all over adding @trusted on them, and it makes it easier for them to be accidentally treated as @safe without the compiler verifying them if someone uses

@safe:

Also - and perhaps most importantly - if an extern(C) function must be marked with @trusted or @system and cannot be marked with @safe, then when there's a memory safety bug, you know that you only have to look for @trusted code (and what it calls) to find the problem. Barring compiler bugs, you can ignore all @safe code. However, if @safe is allowed on non-extern(D) declarations, then you also have to go searching for all non-extern(D) declarations to make sure that they were not incorrectly marked with @safe. Being able to find code with memory safety bugs by grepping for @trusted is supposed to be a key feature of the @safety system, but it doesn't work if @safe is allowed on code that the compiler didn't explicitly verify - and it has no way of knowing whether the body of an extern(C) function was verified when all it sees is the declaration.

@safe should _only_ be used when the compiler is promising that it's mechanically verified the code for @safety. @trusted is what should be used if the programmer verified it, and in the case of extern(C) declarations, it's always going to be the programmer that verifies it regardless of whether the body itself was verified for @safety by the D compiler. To allow @safe on extern(C) declarations just muddies what @safe means and makes it harder to track down bugs.

If there were a way for the compiler to know that the extern(C) definition had been verified for @safety, then the situation would be different, and it would be reasonable to mark the declaration as @safe, but the compiler has no way of knowing that, so @safe on extern(C) declarations is inappropriate and should be illegal.

- Jonathan M Davis



April 06, 2020
On 06.04.20 02:09, Jonathan Marler wrote:
> On Saturday, 4 April 2020 at 06:53:57 UTC, Walter Bright wrote:
>> [....]
>> Now, as to what to do. I spent a few minutes and added `@system:` in to the C headers in druntime for windows, posix, and linux. Done. I hope someone else will do it for freebsd, etc., if not I'll go do that to.
>>
> 
> The thought crossed my mind that this same reasoning could be applied as a counter-argument for this DIP:
> 
> ... So functions are not safe by default?
> 
> Now, as to what to do. I spent a few minutes and added
> `@safe:` in to the source files in druntime for windows, posix,
> and linux. Done. I hope someone else will do it for freebsd,
> etc., if not I'll go do that to.
> ...

So you annotated all those extern(C) function prototypes as @safe? :)

> That being said, it seems like a weak argument, so I don't think it changes much, but I thought it was interesting.
> 

April 05, 2020
On 4/5/2020 12:22 PM, Timon Gehr wrote:
> Right. How can you claim that this is @safe code?

Extern declarations are always going to rely on the user declaring them correctly. It's an inherent property of a language that supports separate compilation.