Bug 18268 – Inconsistent decay of array types when passed to different callables

Status
NEW
Severity
enhancement
Priority
P4
Component
dmd
Product
D
Version
D2
Platform
x86
OS
Windows
Creation time
2018-01-19T21:36:43Z
Last change time
2024-12-13T18:56:12Z
Assigned to
No Owner
Creator
Simen Kjaeraas
Moved to GitHub: dmd#19366 →

Comments

Comment #0 by simen.kjaras — 2018-01-19T21:36:43Z
Some of these are not like the others: unittest { auto fn1(U)() { auto u = U.init; return u; } alias fn2 = function (t) => t; alias fn3 = delegate (t) => t; auto fn4(U)(U u) { return u; } alias T = const(int[]); alias T1 = typeof((function (t) {return t;})(T.init)); alias T2 = typeof((delegate (t) {return t;})(T.init)); alias T3 = typeof((t => t)(T.init)); alias T4 = typeof(() { auto t = T.init; return t; }()); alias T5 = typeof(fn1!T()); alias T6 = typeof(fn2(T.init)); alias T7 = typeof(fn3(T.init)); alias T8 = typeof(fn4(T.init)); pragma(msg, T1); // const(int[]) // Const array pragma(msg, T2); // const(int[]) pragma(msg, T3); // const(int[]) pragma(msg, T4); // const(int[]) pragma(msg, T5); // const(int[]) pragma(msg, T6); // const(int)[] // Mutable array of const elements pragma(msg, T7); // const(int)[] pragma(msg, T8); // const(int)[] } The exact same behavior can be observed by changing the type of T to const(int*). It seems to me the behavior in T6-T8 is most useful - consider: unittest { import std.range : isInputRange; auto fn1(U)(U u) { return isInputRange!U; } alias fn2 = t => isInputRange!(typeof(t)); alias fn3 = function (t) => isInputRange!(typeof(t)); alias fn4 = delegate (t) => isInputRange!(typeof(t)); alias T = const(int[]); assert(fn1(T.init)); assert(fn2(T.init)); assert(fn3(T.init)); assert(fn4(T.init)); assert(!((t) => isInputRange!(typeof(t)))(T.init)); assert(!(function (t){return isInputRange!(typeof(t));})(T.init)); assert(!(delegate (t){return isInputRange!(typeof(t));})(T.init)); } It is certainly unexpected that t is an input range only in some cases.
Comment #1 by issues.dlang — 2019-08-04T15:28:20Z
When a template is implicitly instantiated with a dynamic array, the type of the slice of that dynamic array is used (which is tail-const if the dynamic array is const or tail-immutable if it's immutable). It does that so that you don't have to explicitly slice dynamic arrays all over the place when using templated code (though unfortunately, it does mean that dynamic arrays are treated a bit special, since nothing like this happens with other types). Explicitly instantiating a template with a dynamic array uses the exact type, because you're providing the exact type rather than using type inference. What I don't know is why lambda stuff ends up inferring the exact type of the dynamic array in some cases and the type you get when slicing it in others.
Comment #2 by robert.schadek — 2024-12-13T18:56:12Z
THIS ISSUE HAS BEEN MOVED TO GITHUB https://github.com/dlang/dmd/issues/19366 DO NOT COMMENT HERE ANYMORE, NOBODY WILL SEE IT, THIS ISSUE HAS BEEN MOVED TO GITHUB