Feedback Thread: DIP 1028--Make @safe the Default--Final Review
jeckel
jeckel12381236 at gmail.com
Sat Apr 11 16:21:22 UTC 2020
The extern(C) and friends should be @system by default. It is a
special case, the intention is to make the unsafe code harder to
use. Just like with () @trusted { ... }().
While all extern declaration can't be verified as being safe,
this is especially true for extern(C) and extern(C++). As the
mangling does not have whether it was @safe or not, unlike
extern(D). Yes you can still use an extern(D) declaration that is
unsafe, but that is exactly why this is an unsafe feature that
shouldn't be allowed in the first place. For a language that
prioritizes safety.
Take Rust for example. It has no header files, there are no
"declarations", other than C. Cargos are a first class citizen,
and is much safer as a result not relying on user error with
declarations. Declarations to C are unsafe by default. Rust
doesn't have a "safe"/"trusted" keyword, so they cannot be
implied to be "safe". They are *always* unsafe.
Pointing to extern(D) and saying that's unsafe as well, so we
should make extern(C) unsafe too. That's a very bad rationale. We
should fix extern(D) as well to actually be @safe, like with what
Rust has done. We shouldn't introduce more @unsafe code because
something in D is already unsafe.
The declaration itself is what is unsafe. That's why Rust has
done away with them with Cargo, other than C declarations which
default to unsafe. This is where a separe compilation model is
inherently @unsafe. That doesn't mean because one thing that is
already unsafe, should continue to be unsafe.
I can guarantee you there's more extern(C) @unsafe code out there
than there is extern(C) @safe code. So it makes sense to make
extern(C) @unsafe by default, as that is most definitely the
common case. If that's the kind of rationale you are trying to
impose onto extern(C) of why it should be @safe by default. It
large majority of extern(C) code is most definitely not @safe.
Otherwise citation required.
It's not surprising if a declaration has different attributes
than it's definition. If it was, it'll be extremely easy to
figure out. If you use an extern(C) declaration in @safe code,
you'll get an error saying it isn't safe and needs to be
explicitly annotated. There's no gotcha, no surprise down the
line when a bug shows itself. In comparison if there's an unsafe
extern(C) function being used somewhere because extern(C)
declarations can be defined *everywhere* including within the
body of a function.
Even though currently `@safe:` "flows through", it doesn't for
extern(C) declarations.
@safe:
void test() {
extern(C) void foo();
foo(); // error calling @system function
extern(C) void foo2() {
// this is @safe
}
foo2(); // ok foo2 is @safe
}
https://godbolt.org/z/ppsXMG
Even Walter of old knew better than to make extern(C)
declarations implicitly @safe.
The case with nothrow is pretty simple. C doesn't have exceptions
so it can always be nothrow. C++ has a nothrow equivalent and is
included as part of the mangling, so that can be used for C++. So
nothrow can simply be nothrow by default. It isn't that big of an
issue as there isn't a case of calling a nothrow function and it
actually being able to throw an exception. Even if there was, if
an exception is thrown in a C++ nothrow function it simply
terminates the application. Yes extern declarations are still
terrible. It's something that was inherited from C and is
something we should strive to remove, as Rust has done. Possibly
in a future DIP.
More information about the Digitalmars-d
mailing list