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
Fix issue 20607 - Module constructors are visible as regular function #10834
base: master
Are you sure you want to change the base?
Conversation
Thanks for your pull request, @Geod24! Bugzilla references
Testing this PR locallyIf you don't have a local development environment setup, you can use Digger to test this PR: dub run digger -- build "master + dmd#10834" |
@atilaneves : Looks like you guys rely on being able to do |
b75a8a7
to
824a45d
Compare
@@ -3733,12 +3735,14 @@ extern (C++) class StaticDtorDeclaration : FuncDeclaration | |||
|
|||
extern (D) this(const ref Loc loc, const ref Loc endloc, StorageClass stc) | |||
{ | |||
super(loc, endloc, Identifier.generateIdWithLoc("_staticDtor", loc), STC.static_ | stc, null); | |||
this(loc, endloc, "_staticDtor", stc); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What happens now with multiple module constructors in the same file?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nothing changes, because it forwards the call to the other ctor overload, which still uses generateIdWithLoc
test/compilable/issue18097.d
Outdated
@@ -7,6 +7,6 @@ unittest // this first unittest is needed to trigger the bug | |||
|
|||
unittest // second unittest | |||
{ | |||
auto a = &mixin(__traits(identifier, __traits(parent, { }))); | |||
auto a = __traits(identifier, __traits(parent, { })); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This isn't even remotely the same. Before it was a function pointer, now it's a string.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should have added a comment that this was just to see if the other test passed. Indeed that change shouldn't go in as-is.
The reason was presented in the issue itself: https://issues.dlang.org/show_bug.cgi?id=18097 I wrote the test so as to make sure I wouldn't break code that users had written that had previously worked when I change the unittest naming scheme. The test is now broken after this PR however. |
True. I was more interested in the reason one would use @JohanEngelen : Can you tell us more about the reasoning for this ? Perhaps some code example ? And would you be able to replace your reliance on identifier. In any case, it is clear that this would break code, so can't go in as is. |
If |
Looks like it worked; unittest functions are no longer used by identifier by Weka. |
This is somehow taking longer than expected, as there's no really good way to do it. |
809f7c4
to
1289ff1
Compare
FYI, I don’t think this is the only issue. I think basically all compiler generated symbols have the same issue. Another typical example is unnamed function parameters. |
Yep, it's quite a big undertaking... So I decided to restrict this PR to disabling [shared] static {c,d}tors access, because they are the only ones I can think of that actually break the type system. Need to fix |
So apparently we have some module ctors in druntime which have
$ nm /usr/local/lib/libphobos2.a | grep -E '__[sS].*tatic.*_L.*_C'
0000000000000784 S __sharedStaticDtor_L479_C1
00000000000002a8 S __sharedStaticDtor_L479_C1.eh
00000000000003c4 S __staticDtor_L376_C1
00000000000001a8 S __staticDtor_L376_C1.eh Yeah that's pretty broken... I guess we should also deprecate this 🤦♂ |
Blocked on #10858 |
If you want to be really thorough you should make the symbols have, what's called in LLVM (at least), private linkage [1]. But I'm not sure if that backend supports that kind of linkage. [1] https://github.com/dlang/dmd/blob/master/docs/objective-c_abi.md#private-linkage |
My original approach was to avoid putting things in symtab for But then I found that some places in the compiler use the identifier to access the symbol and so would trigger the depreciation message. Not to mention the other bug with So I will probably go to them one by one, make sure nothing uses the identifier, deprecate accessing the identifier, and then make it not accessible. Whether or not we use |
6916d5e
to
db23067
Compare
Alright, this fails because without an identifier, duplicate manglings are generated for childs of This is luckily very obvious, because the compiler generates a Any way I have attempted to fix it, I either found bugs, special cases, or just bloat (hello static foreach). So reverted to the old |
This breaks the type system pretty easily. If the user *really* want to do something funky, they can still declare those as `extern(C)` and there isn't much we can (or will) do about it. But having those functions available in the symtab means they show up in `impHint` and can be called by accident (e.g. a bug in code generation that use `__allMembers`). There are many other instances in DMD where this happens, however we currently rely on magic identifiers too much to fix everything. The test case contains a few other instances which we'll hopefully gradually fix.
This would fix the windows debug info generation: diff --git a/src/dmd/tocvdebug.d b/src/dmd/tocvdebug.d
index 57aaca5e0..b9aea9622 100644
--- a/src/dmd/tocvdebug.d
+++ b/src/dmd/tocvdebug.d
@@ -73,6 +73,7 @@ uint PROTtoATTR(Prot.Kind prot) pure nothrow @safe @nogc
final switch (prot)
{
+ case Prot.Kind.none: // No explicit mapping, treat as private
case Prot.Kind.private_: attribute = 1; break;
case Prot.Kind.package_: attribute = 2; break;
case Prot.Kind.protected_: attribute = 2; break;
@@ -80,7 +81,6 @@ uint PROTtoATTR(Prot.Kind prot) pure nothrow @safe @nogc
case Prot.Kind.export_: attribute = 3; break;
case Prot.Kind.undefined:
- case Prot.Kind.none:
//printf("prot = %d\n", prot);
assert(0);
} |
Ah thanks for the info! I need to put some time into this. I tried a bit last week, but as you can see from the history of comments, the issue is non-trivial... Starting with something simpler (like |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As mentioned in the issue, I think this PR is moving in the wrong direction. Introspection in D and access to compiler/runtime internals is one of D's strengths as a system programming language with strong metaprogramming. Instead, it would be better to fix the problem and only the problem, without introducing breaking changes that affect the ecosystem:
- Ensure that the type system breaking functionality is not accessible is
@safe
code - Explicitly label non-function module members as not functions
Removing them from the allMembers
list is the wrong thing to do. They are members like any other.
Contain two small refactorings, and an actual fix.
Side note:
__traits(allMembers)
is quite inconsistent: It shows the ctors / dtors, some hidden symbols like_Dmain
and theobject
import, but not__invariant1
(when used onBar
) or__unittest_L126_C1
. And honestly I can see more reasons to call the unittest function directly than to call the[shared] static [~]this
...