Bug 24522 – Formation and inference of nested type sequences

Status
NEW
Severity
major
Priority
P1
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2024-04-26T16:00:32Z
Last change time
2024-12-13T19:34:51Z
Assigned to
No Owner
Creator
Bolpat
Moved to GitHub: dmd#18234 →

Comments

Comment #0 by qs.il.paperinik — 2024-04-26T16:00:32Z
For a function template, `f(Ts...)(ref Ts args)` works as intended: The number and `ref`-ness of parameters can be inferred from arguments. This works because `ref` is a storage class. If we replace `ref` by ´const`, it works as well: ```d void f(Ts...)(const Ts args) { static foreach (alias arg; args) { pragma(msg, typeof(arg)); } } void main() { int i; f(&i, &i); } ``` Prints ``` const(int*) const(int*) ``` as expected. Use a type constructor instead of a storage class: ```d void f(Ts...)(const(Ts) args) { static foreach (alias arg; args) { pragma(msg, typeof(arg)); } } void main() { int i; f(&i, &i); } ``` Prints ``` int* int* ``` Const is completely ignored! Coming from C++, one would assume that the following works: ```d void f(Ts...)(Ts* args) { static foreach (alias arg; args) { pragma(msg, typeof(arg)); } } void main() { int i; f(&i, &i); } ``` But it fails: ``` Error: template `onlineapp.f` is not callable using argument types `!()(int*, int*)` ``` And it’s not that the compiler just can’t do the inference, providing arguments explicitly: ```d void main() { int i; f!(int, int)(&i, &i); } ``` Fails with the following error: ``` Error: cannot have pointer to `(int, int)` ``` Even weirder, using slice types: Inference fails, but using explicit template arguments: ```d void f(Ts...)(Ts[] args) { static foreach (alias arg; args) { pragma(msg, typeof(arg)); } } void main() { int i; f!(int, int)([i], [i]); } ``` The template instantiation succeeds, it prints ``` int int ``` which is weird, and then fails with an error: ``` Error: template `onlineapp.f` is not callable using argument types `!()(int[], int[])` ``` Other, probably less thought-of type suffixes are function pointer and delegate types: ```d void f(Ts...)(Ts function(int) args) { static foreach (alias arg; args) pragma(msg, typeof(arg)); } void main() { int i; f((int x) => x); } ``` Fails: ``` Error: template `onlineapp.f` is not callable using argument types `!()(int function(int x) pure nothrow @nogc @safe)` ``` And with explicit template arguments: ```d void f(Ts...)(Ts function(int) args) { static foreach (alias arg; args) pragma(msg, typeof(arg)); } void main() { int i; f!int(x => x); } ``` Also fails: ``` Error: functions cannot return a sequence (use `std.typecons.Tuple`) ``` My sense is that when a type tuple is to be inferred and type constructors and type suffixes are applied to it, that should expand element-wise: `const(Ts)[]` expands to `(const(T[0])[],...,const(T[$-1])[])`, and inferring the length and elements of `Ts` should work as well: Inferring the length is trivial, and if the length is inferred, inferring the element types should work as well, since it works for single parameters.
Comment #1 by robert.schadek — 2024-12-13T19:34:51Z
THIS ISSUE HAS BEEN MOVED TO GITHUB https://github.com/dlang/dmd/issues/18234 DO NOT COMMENT HERE ANYMORE, NOBODY WILL SEE IT, THIS ISSUE HAS BEEN MOVED TO GITHUB