www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - When is a dynamic array really a static array?

reply Steven Schveighoffer <schveiguy gmail.com> writes:
What do you think this should print?

import std.stdio;

void foo(size_t N)(ubyte[N])
{
     writeln("static");
}

void foo()(ubyte[])
{
     writeln("dynamic");
}

void main()
{
     ubyte[16] x;
     foo(x);
     foo(x[]);
}

Up until 2.068.2 (possibly 2.068.0), this printed:

static
dynamic

Since 2.068.2 it now prints

static
static

Why? Is there a good reason for this, or should it be a regression? I 
always thought if you sliced a static array, that became a dynamic array.

Note that doing this:

auto y = x[];
foo(y);

does print dynamic as I expected.

The context for this is https://issues.dlang.org/show_bug.cgi?id=16519. 
I wanted to say in there "at least there's a workaround, just slice the 
input". But I guess that doesn't work!

-Steve
Dec 30 2019
next sibling parent reply Eugene Wissner <belka caraus.de> writes:
On Monday, 30 December 2019 at 15:39:00 UTC, Steven Schveighoffer 
wrote:
 What do you think this should print?

 import std.stdio;

 void foo(size_t N)(ubyte[N])
 {
     writeln("static");
 }

 void foo()(ubyte[])
 {
     writeln("dynamic");
 }

 void main()
 {
     ubyte[16] x;
     foo(x);
     foo(x[]);
 }

 Up until 2.068.2 (possibly 2.068.0), this printed:

 static
 dynamic

 Since 2.068.2 it now prints

 static
 static

 Why? Is there a good reason for this, or should it be a 
 regression? I always thought if you sliced a static array, that 
 became a dynamic array.

 Note that doing this:

 auto y = x[];
 foo(y);

 does print dynamic as I expected.

 The context for this is 
 https://issues.dlang.org/show_bug.cgi?id=16519. I wanted to say 
 in there "at least there's a workaround, just slice the input". 
 But I guess that doesn't work!

 -Steve
It is probably a bug: You can work around with an assignment: void main() { ubyte[16] x; foo(x); auto y = x[]; foo(y); } and typeof(x[]) gives you of course ubyte[], not ubyte[16].
Dec 30 2019
parent Steven Schveighoffer <schveiguy gmail.com> writes:
On 12/30/19 11:14 AM, Eugene Wissner wrote:
 On Monday, 30 December 2019 at 15:39:00 UTC, Steven Schveighoffer wrote:
 Note that doing this:

 auto y = x[];
 foo(y);

 does print dynamic as I expected.
You can work around with an assignment: void main() {     ubyte[16] x;     foo(x);     auto y = x[];     foo(y); }
GMTA ;) -Steve
Dec 30 2019
prev sibling next sibling parent reply Eugene Wissner <belka caraus.de> writes:
On Monday, 30 December 2019 at 15:39:00 UTC, Steven Schveighoffer 
wrote:
 What do you think this should print?

 import std.stdio;

 void foo(size_t N)(ubyte[N])
 {
     writeln("static");
 }

 void foo()(ubyte[])
 {
     writeln("dynamic");
 }

 void main()
 {
     ubyte[16] x;
     foo(x);
     foo(x[]);
 }

 Up until 2.068.2 (possibly 2.068.0), this printed:

 static
 dynamic

 Since 2.068.2 it now prints

 static
 static

 Why? Is there a good reason for this, or should it be a 
 regression? I always thought if you sliced a static array, that 
 became a dynamic array.

 Note that doing this:

 auto y = x[];
 foo(y);

 does print dynamic as I expected.

 The context for this is 
 https://issues.dlang.org/show_bug.cgi?id=16519. I wanted to say 
 in there "at least there's a workaround, just slice the input". 
 But I guess that doesn't work!

 -Steve
:D foo(x[0..1]); becomes ubyte[1] in the template.
Dec 30 2019
parent Steven Schveighoffer <schveiguy gmail.com> writes:
On 12/30/19 11:16 AM, Eugene Wissner wrote:

 
 :D foo(x[0..1]); becomes ubyte[1] in the template.
LOL! I did not expect that one. To have it bind to a static array parameter might be a useful feature, but it should probably prefer a dynamic array. -Steve
Dec 30 2019
prev sibling parent reply MoonlightSentinel <moonlightsentinel disroot.org> writes:
On Monday, 30 December 2019 at 15:39:00 UTC, Steven Schveighoffer 
wrote:
 What do you think this should print?

 import std.stdio;

 void foo(size_t N)(ubyte[N])
 {
     writeln("static");
 }

 void foo()(ubyte[])
 {
     writeln("dynamic");
 }

 void main()
 {
     ubyte[16] x;
     foo(x);
     foo(x[]);
 }

 Up until 2.068.2 (possibly 2.068.0), this printed:

 static
 dynamic

 Since 2.068.2 it now prints

 static
 static

 Why? Is there a good reason for this, or should it be a 
 regression? I always thought if you sliced a static array, that 
 became a dynamic array.

 Note that doing this:

 auto y = x[];
 foo(y);

 does print dynamic as I expected.

 The context for this is 
 https://issues.dlang.org/show_bug.cgi?id=16519. I wanted to say 
 in there "at least there's a workaround, just slice the input". 
 But I guess that doesn't work!

 -Steve
Digger blames https://github.com/dlang/dmd/pull/4779 This is probably a bug but DMD sometimes detects when the sliced array is static and uses this information to enable certain rewrites IIRC, e.g. when initializing another static array
Dec 30 2019
parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On 12/30/19 11:45 AM, MoonlightSentinel wrote:

 Digger blames https://github.com/dlang/dmd/pull/4779
 
 This is probably a bug but DMD sometimes detects when the sliced array 
 is static and uses this information to enable certain rewrites IIRC, 
 e.g. when initializing another static array
Thanks for everyone's replies: https://issues.dlang.org/show_bug.cgi?id=20472 -Steve
Dec 30 2019
parent reply Patrick Schluter <Patrick.Schluter bbox.fr> writes:
On Monday, 30 December 2019 at 18:17:31 UTC, Steven Schveighoffer 
wrote:
 On 12/30/19 11:45 AM, MoonlightSentinel wrote:

 Digger blames https://github.com/dlang/dmd/pull/4779
 
 This is probably a bug but DMD sometimes detects when the 
 sliced array is static and uses this information to enable 
 certain rewrites IIRC, e.g. when initializing another static 
 array
Thanks for everyone's replies: https://issues.dlang.org/show_bug.cgi?id=20472
Is it really a bug? A static array is an array where the compiler handles the pointer/length structure (i.e. they are known at CT) vs a dynamic array, where it is a runtime variable. In contexts where the compiler can deduce completely the type (lifetime of the values) it can be justified to make CT values out of them. While I understand that it can be surprizing that the passed dynamic array becomes a static array again, it is imho only a sign that the compiler was able to deduce completely the lifetime of the passed object. I'm sure it is a good thing even if it might be surprizing in some contexts, but it is in the vein of the basic idea behind the D language to try to resolve things at CT when possible. Just my 2 cents.
Dec 31 2019
next sibling parent Eugene Wissner <belka caraus.de> writes:
On Tuesday, 31 December 2019 at 11:20:31 UTC, Patrick Schluter 
wrote:
 On Monday, 30 December 2019 at 18:17:31 UTC, Steven 
 Schveighoffer wrote:
 On 12/30/19 11:45 AM, MoonlightSentinel wrote:

 Digger blames https://github.com/dlang/dmd/pull/4779
 
 This is probably a bug but DMD sometimes detects when the 
 sliced array is static and uses this information to enable 
 certain rewrites IIRC, e.g. when initializing another static 
 array
Thanks for everyone's replies: https://issues.dlang.org/show_bug.cgi?id=20472
Is it really a bug? A static array is an array where the compiler handles the pointer/length structure (i.e. they are known at CT) vs a dynamic array, where it is a runtime variable. In contexts where the compiler can deduce completely the type (lifetime of the values) it can be justified to make CT values out of them. While I understand that it can be surprizing that the passed dynamic array becomes a static array again, it is imho only a sign that the compiler was able to deduce completely the lifetime of the passed object. I'm sure it is a good thing even if it might be surprizing in some contexts, but it is in the vein of the basic idea behind the D language to try to resolve things at CT when possible. Just my 2 cents.
It is inconsistent. The compiler can't just do whatever it wants. If typeof(x[]) says that the type is char[], then the type should be char[]. How am I supposed to reason about the code if I don't even know the types of my variables, and what overloads are called? There should be strict coercion rules and there is no such rule for converting a dynamic array to a static one just because the compiler knows. And it changes the behaviour if the variable is used in one of the templates.
Dec 31 2019
prev sibling parent reply Paul Backus <snarwin gmail.com> writes:
On Tuesday, 31 December 2019 at 11:20:31 UTC, Patrick Schluter 
wrote:
 Is it really a bug?
Yes. Perhaps this example will convince you: void foo(size_t N)(int[N] arr) { arr[0] = 42; } void foo()(int[] arr) { arr[0] = 42; } void main() { int[16] x; foo(x[]); assert(x[0] == 42); // fails }
Dec 31 2019
parent reply Temtaime <temtaime gmail.com> writes:
On Tuesday, 31 December 2019 at 13:35:42 UTC, Paul Backus wrote:
 On Tuesday, 31 December 2019 at 11:20:31 UTC, Patrick Schluter 
 wrote:
 Is it really a bug?
Yes. Perhaps this example will convince you: void foo(size_t N)(int[N] arr) { arr[0] = 42; } void foo()(int[] arr) { arr[0] = 42; } void main() { int[16] x; foo(x[]); assert(x[0] == 42); // fails }
void foo(size_t N)(int[N] arr) does nothing. I doubt this is a bug too.
Dec 31 2019
parent Steven Schveighoffer <schveiguy gmail.com> writes:
On 12/31/19 12:24 PM, Temtaime wrote:
 On Tuesday, 31 December 2019 at 13:35:42 UTC, Paul Backus wrote:
 On Tuesday, 31 December 2019 at 11:20:31 UTC, Patrick Schluter wrote:
 Is it really a bug?
Yes. Perhaps this example will convince you: void foo(size_t N)(int[N] arr) {     arr[0] = 42; } void foo()(int[] arr) {     arr[0] = 42; } void main() {     int[16] x;     foo(x[]);     assert(x[0] == 42); // fails }
void foo(size_t N)(int[N] arr) does nothing. I doubt this is a bug too.
int[N] foo(size_t N)(int[N] arr) { arr[0] = 42; return arr; } Better? The use case that spurred this discovery is this: ubyte[16] hash; string hexStr = toHexString(hash); // slices a temporary that is immediately removed from scope The fix should be: string hexStr = toHexString(hash[]); But it doesn't do anything different. In order to do it correctly, you have to literally declare another variable, or cast. Hell, I don't even know if the cast will work! -Steve
Dec 31 2019