December 08, 2021

On Wednesday, 8 December 2021 at 15:46:31 UTC, Steven Schveighoffer wrote:

>

[snip]

I proposed during the discussion that you can assume extern(C) functions are @safe as long as they are mangled differently. I think that would both solve the problems people had, and allow extern(C) to be safe by default.

Walter seemingly ignored it, but silently hated it, so I don't see that happening.

-Steve

I think Walter (and likely Atila too) might come down on avoiding special casing as an important design goal.

To me, the best way to ensure that is to moving @safe from a black list to an white list. That is, @safe is currently structured so that you cannot do certain things. If instead it is structured so that only certain things are allowed, then something like having the body of the function available could be on that list. There would be no more special casing and it would only break code to the extent that the white list and black list do not match up (which might be considerable, who knows)

December 08, 2021
On Wed, Dec 08, 2021 at 04:47:20PM +0000, jmh530 via Digitalmars-d wrote:
> On Wednesday, 8 December 2021 at 15:46:31 UTC, Steven Schveighoffer wrote:
[...]
> > I proposed [during the
> > discussion](https://forum.dlang.org/post/r6kvm4$1vq5$1@digitalmars.com)
> > that you can assume `extern(C)` functions are `@safe` as long as
> > they are mangled differently. I think that would both solve the
> > problems people had, and allow `extern(C)` to be safe by default.
> > 
> > Walter seemingly ignored it, but silently [hated it](https://forum.dlang.org/post/ra7958$2r8v$1@digitalmars.com), so I don't see that happening.
[...]
> I think Walter (and likely Atila too) might come down on avoiding special casing as an important design goal.
> 
> To me, the best way to ensure that is to moving @safe from a black list to an white list. That is, @safe is currently structured so that you cannot do certain things. If instead it is structured so that only certain things are allowed, then something like having the body of the function available could be on that list. There would be no more special casing and it would only break code to the extent that the white list and black list do not match up (which might be considerable, who knows)

Whether @safe is as a blacklist vs a whitelist is IMO an implementation detail.  I think what Walter is concerned about is more on the higher level language perspective: special cases tend to cause unexpected interactions with other language features, and such interactions tend to percolate throughout the language, adding complexity.

I'm somewhat sympathetic to this view, but I think in this case it has unfortunately devolved into the perfect being the enemy of the good. For pragmatic reasons I would have allowed this, had the decision been up to me.


T

-- 
I am a consultant. My job is to make your job redundant. -- Mr Tom
December 08, 2021
On Thursday, 2 December 2021 at 20:51:56 UTC, Paul Backus wrote:
>     extern(C) void sayHello() // @system by default
>     {
>         writeln("Hello!");
>     }
>
>     void main() // @safe by default
>     {
>         sayHello();
>         // Error: @safe function `main` cannot call @system function `sayHello`
>     }

extern(C) with a function body should be @safe by default too, because the compiler knows the function is implemented in D. extern(C) without a function body should be @system by default, because the compiler has no idea what language the function is written in. So the above code would not error.
December 08, 2021
On 08.12.21 18:26, H. S. Teoh wrote:
> Whether @safe is as a blacklist vs a whitelist is IMO an implementation
> detail.  I think what Walter is concerned about is more on the higher
> level language perspective: special cases tend to cause unexpected
> interactions with other language features, and such interactions tend to
> percolate throughout the language, adding complexity.

It's not a "special case", it's keeping the core promise of @safe...

Framing this as a special case is just not productive. At that point you could just as well reason that pointer arithmetic should be allowed in @safe code. After all, banning it introduces a weird special case that is inconsistent with how other D code works.

This is a pretty obvious safety hole:

```d
void main()@safe{
    struct S{
        pragma(mangle,"foo"):
        static extern(C) void foo(int){
            import core.stdc.stdlib;
            free(cast(void*)0xDEADBEEF);
        }
        static extern(C) void foo()@safe;
    }
    S.foo();
}
```

There is no @trusted code in that snippet and it frees an invented pointer. "Memory safety guarantees". The code is not at fault. It's the language. I am all for pragmatism, but it seems awfully out of touch in this case.
December 10, 2021
On Wednesday, 8 December 2021 at 18:14:36 UTC, Timon Gehr wrote:
> This is a pretty obvious safety hole:
>
> ```d
> void main()@safe{
>     struct S{
>         pragma(mangle,"foo"):
>         static extern(C) void foo(int){
>             import core.stdc.stdlib;
>             free(cast(void*)0xDEADBEEF);
>         }
>         static extern(C) void foo()@safe;
>     }
>     S.foo();
> }
> ```
>
> There is no @trusted code in that snippet and it frees an invented pointer.

It seems pragma(mangle) should require that the function it applies to is not @safe. But even without pragma(mangle), foo can be made a free function with the same problem.

Forbidding @safe on a function prototype would fix that, requiring @trusted instead. Enforcing that is necessary anyway for when the function body is not available to be mechanically checked for memory safety.

1 2 3 4 5 6
Next ›   Last »