-
-
Notifications
You must be signed in to change notification settings - Fork 606
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
Add @standalone
attribute for module constructors
#15537
Add @standalone
attribute for module constructors
#15537
Conversation
Thanks for your pull request and interest in making D better, @dkorpel! We are looking forward to reviewing it, and you should be hearing from a maintainer soon.
Please see CONTRIBUTING.md for more information. If you have addressed all reviews or aren't sure how to proceed, don't hesitate to ping us with a simple comment. Bugzilla referencesYour PR doesn't reference any Bugzilla issue. If your PR contains non-trivial changes, please reference a Bugzilla issue or create a manual changelog. 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#15537" |
0407048
to
216f69e
Compare
@standalone
attribute@standalone
attribute for module constructors
/** | ||
* Returns: true if the given expression is an enum from `core.attribute` named `id` | ||
*/ | ||
bool isEnumAttribute(Expression e, Identifier id) |
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.
Might be cleaner to return a pointer, the other is
functions in DMD do this so its a common pattern to keep going.
StaticDtorDeclarations ectorgates; | ||
symbols sdtors; | ||
symbols stests; | ||
|
||
symbols ssharedctors; | ||
symbols ssharedctors; // shared static constructors | ||
symbols sisharedctors; // standalone shared static constructors | ||
SharedStaticDtorDeclarations esharedctorgates; |
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.
Ugly naming convention. Unfortunate.
Seems worth a try out. |
{ | ||
auto trust = sharedCtor.type.isTypeFunction().trust; | ||
if (trust != TRUST.system && trust != TRUST.trusted) | ||
error(e.loc, "a module constructor using `@%s` must be `@system` or `@trusted`", Id.udaStandalone.toChars()); |
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.
why not @standalone
directly ?
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.
So the name can't be out of sync with the attribute I guess. Really, I just mimicked how @mustuse
did it
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.
There will be more of these in future, can it be made into a reusable function?
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.
to be frank, this is not a hot path. It's just that it's useless to add N kilobytes of code while the static data is already there.
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.
can it be made into a reusable function
What part of the error would other attributes re-use?
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.
That's up to your judgement - "I just mimicked" hinted at some repetition. If there is no overlap then don't, but it would be really good to make these types of logic declarative. I'll write a sketch hang on.
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.
The 'repetition' is also using @%s
and Id.udaStandalone.toChars()
instead of @standalone
, that's too small of a thing to extract to a function.
sharedCtor.standalone = true; | ||
} | ||
else | ||
.error(e.loc, "`@%s` can only be used on shared static constructors", Id.udaStandalone.toChars()); |
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.
ditto
The |
P.S. the number of pre-defined attributes is getting a little large, and we're running out of space in the integer mask for them! |
I don't see why that's a rule.
|
Then you'd be happy to know that none of the attributes in |
This is a very much appreciated feature to have. Weka struggles a lot with these, and we run our unittests with The hacky solution "just create another module" is not a feasible thing for large codebases. |
Based on our codebases I think I'd prefer an attribute than a pragma. |
Pragma is already used for |
It shouldn't be. It's just defining how it should behave. We should have this since the beginning |
@ljmf00 The acyclic static constructor creates a correctness hole in the language. It should stand out with a different syntax, one like the crt_constructor which also creates a correctness hole. Using an attribute implies it is more central to the language. |
Attributes are the correct solution here. Please don't force it to be a pragma, that'd make it much harder to use in stable codebases. |
Hello, this is a nice feature and all, but there is a fundamental problem: D should be all about making it work more by writing less, it is a well suited language for a beginner to learn and putting this attribute instead of really solving the problem and making it just works is just a step backwards. If you take a look into the forums, people already calls that as IMO, this is just more unnecessary friction in the language, more cluttering in symbols (yes, |
It'd be great if it was done automatically but that's not realistically going to happen. D is supposed to be a practical, real world language. This PR serves a practical, real world use case. If the implementation were to ever automatically infer this, the attribute doesn't harm anything in any way while solving a real problem. Merge ASAP. |
It's a library attribute though (druntime/core/attribute), not a reserved language attribute. I could make it uglier by adding underscores, but historically, I don't think that refrained people from using |
I agree, and we considered this in the monthly meeting, but the complexity and fragility of inference of |
Debugging the failure will have to wait until after DConf. In the meantime, the bike shedding about the syntax may continue! 🙂 |
Sure but its the same argument as the @trusted attribute. It also open holes, but sometimes is needed, if we dont want to degrade performance in some specific cases, as we do assumptions. |
This is still an important need for D, it slipped my mind for a month but I hit yet another case where it would be useful. What's the current situation? |
I'll look into the test failure this week |
216f69e
to
8883675
Compare
ping again |
importing the module is the correct behavior. |
This needs formal approval from @WalterBright . |
@ryuukk 's comment about the syntax #15537 (comment) is persuasive. What is the compelling advantage to using the attribute, with its rather clumsy looking syntax and double underscore? One of the objections to pragma's was resolved by @adamdruppe 's PR #15893 Doesn't:
just look nice? |
Whaaaa? All this time you've been arguing that |
I support multiple years of D compilers in the ecosystem. This means I can only use a new feature if either 1) it can be tested and enabled selectively in the code itself or 2) has been in the language for over 3 years, such that the oldest supported compiler has it. the pragma objection stands until 2027. It is good it is going to be fixed some day, but I can't go breaking my client's code until then, so if this is a pragma, it is useless to me for years, whereas the attribute can be committed to library code right now, heck, before the feature is even merged. |
@WalterBright The main reason why The pragma problem is that one would need to Even if this was done right now, it would take some years for it being considered in various codebases since most don't want to keep updating their compilers all the time. |
I have a mtg to go to, so will address all points later. |
@dkorpel : @__standalone is just ugly. Can I change my mind about that? Even worse, though, is the required import:
The more I look at it, the worse the inconsistency and aesthetics of xxx() look. Another peculiar inconsistency of this is it being the only compiler recognized attribute that is not part of the grammar. I am hesitant to embark down that road. I didn't know you were committed to supporting 3 years worth of compilers, thanks for telling me. Even though your initiative to ignore unsupported pragmas has been merged, I understand it won't work with older compilers. But I do have a solution! Consider modules A and B which import each other. We want an acyclic constructor in A. This can be done with:
This should work on all versions of D. @MrcSnm : There is currently no |
You can't do those extern(C) import tricks in |
One of the beauties of using attributes is you don't need more special cases. The existing language supports all this stuff for them already - reflection, grouping, name conflict resolution, and more - the only magic thing about them is the compiler recognizes them. It is extremely beneficial to use this instead of adding more and more special cases for every little thing that comes up.
ldc and gdc have tons of compiler recognized attributes. Why would being part of the grammar be beneficial at all anyway? I also don't think mustUse is in the grammar and even dmd supports that one. |
|
I'll think about the template mixin case.
If the |
You reviewed and accepted the DIP. Either way, |
I'll remove the underscores. The import is not ergonomic, but remember that this is a once-in-100KLOC feature, not something the user is supposed to reach to quickly (by your own account). As for consistency, import core.attribute : standalone;
shared static this()
{
// normal sctor
}
@standalone @system
shared static this()
{
// standalone sctor
} Which looks fine to me. |
471df16
to
ca4923a
Compare
@__standalone
attribute for module constructors@standalone
attribute for module constructors
This is the status quo, so there's no regression. But the situation is iffy:
This is a global switch that is not suitable for libraries in general - it can have unpredictable side effects when combined with other code - but is the only option at this time to move forward with the use case, so we use it and hope for the best. Having |
Ok, @dkorpel and @adamdruppe make a good case, thank you. |
Splendid, thank you, this is gonna solve a long annoyance. |
Is there a reason why |
I just don't think there's an existing cycle-independent list for thread local ones, whereas there was for global ones so it just a factor of convenience. |
No, both cycles are detected independently. Lines 517 to 518 in 03f1497
|
Yes, but So before (or simultaneously with) standalone can be added for tls ctors, some kind of |
Huh, I never knew about the ictor thing. What I am talking about is the See Line 478 in 03f1497
Now I have no idea exactly what this PR is doing... |
https://issues.dlang.org/show_bug.cgi?id=24425 Please comment if I'm off base here. |
I think that would work, indeed, that was one of my first ideas to implement this but when i looked at the code, |
No description provided.