Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Safe by default v2 #228

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions DIPs/DIP1044.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,7 @@ it will no longer link because the mangling will be different. But for `extern (
safety is not part of the mangling and it will compile and link without error. This has always
relied on the user getting it correct.

Interfaces to extern C and C++ functions should always be explicitly marked.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was going to write such a DIP myself; I was waiting for -preview=dip1000 to become the default. I think that any and all declarations with no body should have explicit @safe/@trusted/@system attributes and that even considering linkage is a mistake.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How is that considered a mistake?

You are interfacing with a language that has no notion of any safety guarantees. Ignoring differences between languages and the interfaces between them is a mistake.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because extern(C) does not mean "this is C code", it means "C linkage" and could very well be @safe D code.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The problem is, a @safe extern(C) function that is not defined in-place is not verified by the compiler – and @safe means that the compiler checked it (up to calls to @trusted). I’m no expert on this, but as far as I understand it’s about mangling. Attributes are not part of the signature of extern(C) functions. extern(C) void f() @safe; could be defined elsewhere as extern(C) void f() @system { … }. I think D needs some solution to this; Maybe I’m naïve, but it could be as easy as generating mock symbols that actually include attributes that lead to linker errors when the attributes don’t match.

At least until 2.096.0, this worked:

import a;
extern(C) void f() @safe;
void main() @safe { f(); }
module a;
extern(C) void f() @system { int* p;  int a;  p = &a; }

If you change extern(C) to extern(D), you get the link error.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because extern(C) does not mean "this is C code", it means "C linkage" and could very well be @safe D code.

If it's @safe D code then they can just import it. It doesn't matter if it's C code, or linkage, it is still going by C's rules. Just cause safe D code can have C linkage doesn't mean it should expose a C linkage of safe.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They can indeed just import it, but it'll be extern(C) all the same. I don't know what "going by C's rules" means.

If it's D code with C linkage and it's @safe, well, it's @safe.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Importing does not safeguard you from calling a @safe annotated extern(C) declared function (e.g. from a .di file) whose definition (implementation in a .d file) is annotated @system. That’s because the annotation is not visible for the linker.
I guess the easiest way would be to allow extern(C) @safe function declarations only if they’re also definitions. The proper way would be for D to do something that safeguards you at least in simple and obvious cases.


Any unmarked `extern` C and C++ functions will remain `@system`.
Any unmarked `extern` C and C++ declarations will remain `@system`. C and C++ functions with bodies will be @safe by default.

### 3rd Party Libraries

Expand Down