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
Make in
a first-class storage class, not a const [scope]
alias
#11474
Conversation
Thanks for your pull request, @Geod24! 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#11474" |
For a long time, the 'in' storage class was only a second class citizen, merely an alias for 'const', which is a type constructor. While it was also documented for a long time as being 'scope', this was removed when 'scope' actually started to have an effect (when DIP1000 started to be implemented). Currently, a switch (-preview=in) allows to get back this 'scope'. However, the 'in' storage class does not really exists, it gets lowered to 'const [scope]' at an early stage by the compiler, which means that we expose what is essentially an implementation detail to the user. There is a PR in DMD (dlang/dmd#11474) that aims to give 'in' an actual identity, instead of it being lowered to 'const [scope]'. The underlying motivation is to allow for extending 'in''s functionality, giving it the ability to pass by 'ref' when necessary, and accept rvalues. However, regardless of the second goal, having proper support for 'in' would lead to less confusing messages, better code generation, and less confusion w.r.t. the behavior of `std.traits.ParameterStorageClass`.
For a long time, the 'in' storage class was only a second class citizen, merely an alias for 'const', which is a type constructor. While it was also documented for a long time as being 'scope', this was removed when 'scope' actually started to have an effect (when DIP1000 started to be implemented). Currently, a switch (-preview=in) allows to get back this 'scope'. However, the 'in' storage class does not really exists, it gets lowered to 'const [scope]' at an early stage by the compiler, which means that we expose what is essentially an implementation detail to the user. There is a PR in DMD (dlang/dmd#11474) that aims to give 'in' an actual identity, instead of it being lowered to 'const [scope]'. The underlying motivation is to allow for extending 'in''s functionality, giving it the ability to pass by 'ref' when necessary, and accept rvalues. However, regardless of the second goal, having proper support for 'in' would lead to less confusing messages, better code generation, and less confusion w.r.t. the behavior of `std.traits.ParameterStorageClass`.
For a long time, the 'in' storage class was only a second class citizen, merely an alias for 'const', which is a type constructor. While it was also documented for a long time as being 'scope', this was removed when 'scope' actually started to have an effect (when DIP1000 started to be implemented). Currently, a switch (-preview=in) allows to get back this 'scope'. However, the 'in' storage class does not really exists, it gets lowered to 'const [scope]' at an early stage by the compiler, which means that we expose what is essentially an implementation detail to the user. There is a PR in DMD (dlang/dmd#11474) that aims to give 'in' an actual identity, instead of it being lowered to 'const [scope]'. The underlying motivation is to allow for extending 'in''s functionality, giving it the ability to pass by 'ref' when necessary, and accept rvalues. However, regardless of the second goal, having proper support for 'in' would lead to less confusing messages, better code generation, and less confusion w.r.t. the behavior of `std.traits.ParameterStorageClass`.
For a long time, the 'in' storage class was only a second class citizen, merely an alias for 'const', which is a type constructor. While it was also documented for a long time as being 'scope', this was removed when 'scope' actually started to have an effect (when DIP1000 started to be implemented). Currently, a switch (-preview=in) allows to get back this 'scope'. However, the 'in' storage class does not really exists, it gets lowered to 'const [scope]' at an early stage by the compiler, which means that we expose what is essentially an implementation detail to the user. There is a PR in DMD (dlang/dmd#11474) that aims to give 'in' an actual identity, instead of it being lowered to 'const [scope]'. The underlying motivation is to allow for extending 'in''s functionality, giving it the ability to pass by 'ref' when necessary, and accept rvalues. However, regardless of the second goal, having proper support for 'in' would lead to less confusing messages, better code generation, and less confusion w.r.t. the behavior of `std.traits.ParameterStorageClass`.
One question I have is, should |
My proposal (#10526) was to add |
39087e4
to
d4b0800
Compare
Thanks, I have integrated that part now.
I mostly had issues with covariance (you can see that's a good chunk of the tests). I think the main difference with your approach is that I don't try to infer I just ran the unittests with the companion Phobos PR mentioned in the op and it passed (OSX). |
Maybe the issues I noticed where related to that.
"Inferring scope" (I guess that's what you meant) was probably not the correct term. It referred to the fact that it doesn't appear in the mangling, because it uses |
With the mangling added, we might want to resurrect dlang/druntime#2847 |
Neither does it here. It's either |
Ah, ok. Thanks for explanation. |
d4b0800
to
0ec8d21
Compare
For a long time, the 'in' storage class was only a second class citizen, merely an alias for 'const', which is a type constructor. While it was also documented for a long time as being 'scope', this was removed when 'scope' actually started to have an effect (when DIP1000 started to be implemented). Currently, a switch (-preview=in) allows to get back this 'scope'. However, the 'in' storage class does not really exists, it gets lowered to 'const [scope]' at an early stage by the compiler, which means that we expose what is essentially an implementation detail to the user. There is a PR in DMD (dlang/dmd#11474) that aims to give 'in' an actual identity, instead of it being lowered to 'const [scope]'. The underlying motivation is to allow for extending 'in''s functionality, giving it the ability to pass by 'ref' when necessary, and accept rvalues. However, regardless of the second goal, having proper support for 'in' would lead to less confusing messages, better code generation, and less confusion w.r.t. the behavior of `std.traits.ParameterStorageClass`.
A shorter name, which also ties it to the switch name. This is in support of a later commit that changes the meaning on the switch, and would render the name extremely long if the same scheme was used ('inMeansConstScopeMaybeRefAcceptRvalue' is a bit much). Additionally, the test case was renamed for the same reason.
5940e2f
to
760944d
Compare
As explained in details in dlang/dmd#11000 and dlang/dmd#11474, 'in' has been for a very long time lowered to simply 'const', or 'scope const' when v2.092.0's '-preview=in' switch is used. DMD PR 11474 aims to change this, so 'in' is not (visibly) lowered, and shows up in any user-visible string. This includes header generation, error messages, and stringof. Since this code was testing stringof directly, it is affected by the change. To support testing of both aforementioned DMD PRs, the change is not tied to a version, but uses the (soon-to-be) old way as a fallback.
760944d
to
91be7f4
Compare
The Phobos fix has been merged, this should now go green on the auto-tester. |
As explained in details in dlang/dmd#11000 and dlang/dmd#11474, 'in' has been for a very long time lowered to simply 'const', or 'scope const' when v2.092.0's '-preview=in' switch is used. DMD PR 11474 aims to change this, so 'in' is not (visibly) lowered, and shows up in any user-visible string. This includes header generation, error messages, and stringof. Since this code was testing stringof directly, it is affected by the change. To support testing of both aforementioned DMD PRs, the change is not tied to a version, but uses the (soon-to-be) old way as a fallback.
|
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.
Looks fine, no tests for mangles though.
91be7f4
to
0a47e9e
Compare
Added a mangling test (piggybacking on the fail_compilation test, but it works). |
For a long time, the 'in' storage class was only a second class citizen, merely an alias for 'const', which is a type constructor. While it was also documented for a long time as being 'scope', this was removed when 'scope' actually started to have an effect (when DIP1000 started to be implemented). Currently, a switch (-preview=in) allows to get back this 'scope'. However, the 'in' storage class does not really exists, it gets lowered to 'const [scope]' at an early stage by the compiler, which means that we expose what is essentially an implementation detail to the user. This led to a variety of problems for both developers and users. The most obvious one was that functions involving `in` would show up simply as `const` (or `const scope`), both in generated header and error messagges, hindering the ability to do header generation with `-preview=in` as the same value for this switch was needed for both producer and consumer. Another issue was that the result of `__traits(getParameterStorageClass)` was inaccurate, giving either an empty tuple or `scope`. Lastly, the lack of mangling for `in` means that stack trace would show the wrong signature for a function, potentially confusing the users. For compiler developers, the `in` storage class simply couldn't be relied on, as it was replaced by `const [scope]` rather early in the semantic phase (in TypeFunction's semantic), which lead to some dead code (e.g. in dmangle). After this change, the class will show up properly in error message, and in `getParameterStorageClass`, which can be a surprising change for users. However, it is not expected that code can break as a result, unless they break as a result of using the `-preview=in` switch.
0a47e9e
to
df74268
Compare
Actually, I also added a changelog to explain what happens (and one of the possible shortcomings). |
@@ -79,7 +79,7 @@ private immutable char[TMAX] mangleChar = | |||
Tfunction : 'F', // D function | |||
Tsarray : 'G', | |||
Taarray : 'H', | |||
Tident : 'I', |
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.
I am wondering why this change does not seem to break tests.
Where was Tident used? in templates?
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.
It isn't used (dlang/druntime#2847 (comment))
Seems fairly uncontroversial. |
Splitted off #11000 . I believe this changeset is useful on its own, but #11000 might provide an additional reasoning for why we need it.
Companion Phobos PR: dlang/phobos#7570
Spec PR / changelog pending more discussions, including #11000 .
Commit message follows: