Bug 21891 – Cannot alias every kind that can be passed via variadic templates

Status
NEW
Severity
major
Priority
P2
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2021-05-03T19:52:16Z
Last change time
2024-12-13T19:16:09Z
Assigned to
No Owner
Creator
Andrei Alexandrescu
Moved to GitHub: dmd#19919 →

Comments

Comment #0 by andrei — 2021-05-03T19:52:16Z
Consider: template A(X...) { alias Y = X[0]; } void main() { auto x = A!(1).Y; } This code fails because the expression `1` cannot be aliased. Everything that can be passed via variadic arguments MUST also be bindable to an alias. Otherwise - as is currently the case - there are subtle differences between what can be passed as alias parameter vs. variadic parameter. The infuriating part is that this _does_ compile! template A(alias X) { alias Y = X; } void main() { auto x = A!(1).Y; } So in fact 1 is bindable to an alias but somehow not in all contexts!
Comment #1 by hsteoh — 2021-05-03T21:27:24Z
This makes me wonder why alias parameters were introduced in the first place. Phobos makes extensive use of alias parameters for binding to lambdas, for example, so it appears that it was a deliberate decision to distinguish between unmarked template parameters receiving types vs alias parameters receiving things that might not be types. But yeah, this subtle and mostly-arbitrary distinction is the source of a number of weird corner cases and inhomogeneities in Phobos and also in the language in general. My inclination is to get rid of this arbitrary distinction so that the language has less special cases.
Comment #2 by snarwin+bugzilla — 2021-05-03T22:07:12Z
(In reply to Andrei Alexandrescu from comment #0) > So in fact 1 is bindable to an alias but somehow not in all contexts! Specifically: an expression can bind to a template alias parameter, but is not allowed on the right-hand side of an alias declaration. The reason `alias Y = X;` works but `alias Y = X[0];` doesn't is that `X` by itself on the right-hand side is parsed as a symbol, not an expression. The variadic parameter is a distraction.
Comment #3 by andrei — 2021-05-04T17:50:09Z
(In reply to Paul Backus from comment #2) > (In reply to Andrei Alexandrescu from comment #0) > > So in fact 1 is bindable to an alias but somehow not in all contexts! > > Specifically: an expression can bind to a template alias parameter, but is > not allowed on the right-hand side of an alias declaration. > > The reason `alias Y = X;` works but `alias Y = X[0];` doesn't is that `X` by > itself on the right-hand side is parsed as a symbol, not an expression. The > variadic parameter is a distraction. Very interesting, thank you!
Comment #4 by andrei — 2021-05-04T19:43:57Z
(In reply to Paul Backus from comment #2) > (In reply to Andrei Alexandrescu from comment #0) > > So in fact 1 is bindable to an alias but somehow not in all contexts! > > Specifically: an expression can bind to a template alias parameter, but is > not allowed on the right-hand side of an alias declaration. > > The reason `alias Y = X;` works but `alias Y = X[0];` doesn't is that `X` by > itself on the right-hand side is parsed as a symbol, not an expression. The > variadic parameter is a distraction. Hm... how does this fit then? Just found it in core.internal.traits: template maxAlignment(U...) { static if (U.length == 0) static assert(0); else static if (U.length == 1) enum maxAlignment = U[0].alignof; else static if (U.length == 2) enum maxAlignment = U[0].alignof > U[1].alignof ? U[0].alignof : U[1].alignof; else { enum a = maxAlignment!(U[0 .. ($+1)/2]); enum b = maxAlignment!(U[($+1)/2 .. $]); enum maxAlignment = a > b ? a : b; } } template classInstanceAlignment(T) if (is(T == class)) { alias classInstanceAlignment = maxAlignment!(void*, typeof(T.tupleof)); } Does that work because there's a template instantiation on the right-hand side?
Comment #5 by snarwin+bugzilla — 2021-05-04T21:06:08Z
(In reply to Andrei Alexandrescu from comment #4) > template classInstanceAlignment(T) > if (is(T == class)) > { > alias classInstanceAlignment = maxAlignment!(void*, typeof(T.tupleof)); > } > > > Does that work because there's a template instantiation on the right-hand > side? Yes. It's the same reason that `Alias!(expr)` sometimes works when `expr` doesn't.
Comment #6 by robert.schadek — 2024-12-13T19:16:09Z
THIS ISSUE HAS BEEN MOVED TO GITHUB https://github.com/dlang/dmd/issues/19919 DO NOT COMMENT HERE ANYMORE, NOBODY WILL SEE IT, THIS ISSUE HAS BEEN MOVED TO GITHUB