On 6/8/22 8:44 PM, Ali Çehreli wrote:
> > -- except on
extern(C) interfaces to C code, which by definition is un-@safe
I see it differently: extern(C) interfaces are @trusted but they can't be checked. (More below.)
I was convinced (after having an email exchange with Walter) that unless we assumed extern(C) functions @safe, then nobody would bother marking their declarations as @trusted one-by-one. And whoever marked them as such, they would do it without actually auditing any source code.
What have we gained by disapproving @safe-by-default? Nothing: C API would either not be called and be marked blindly as @trusted. I think this is more embarrassing than @safe-by-default C libraries.
So, D's presumed embarrassment of "C functions are assumed @safe" was against both practicality and the truth: The truth is, we indeed "trust" C functions because we use C libraries all the time without reading their source code. This is the definition of trust. And that's why I say we chose wrong names around this topic.
You are missing the point.
extern(C) void *malloc(size_t);
extern(C) void free(void *); // @safe?
void main() // @safe!
{
auto ptr = malloc(int.sizeof);
int *v = ((p) @trusted => cast(int*)p)(ptr);
free(v);
*v = 5; // @safe??!
}
See, you can trust malloc and free to have valid implementations (read, they are memory safe as long as you obey their rules). But they don't obey @safe
rules. They can't, they aren't written in D, and they aren't checked by D. There is no way to express the invariants that they require, and there certainly isn't a way to infer those invariants based on the types of the parameters.
Marking them @safe
by default is a disaster. It is the complete and utter destruction of memory safety in D. I can't stress this enough.
I wish Walter had not brought this up, because I don't think it's fruitful to have this discussion again.
-Steve