www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - partial initialization of fixed size ("static") arrays

reply kdevel <kdevel vogtner.de> writes:
Today I stumbled across three issues with partial initialization 
of "static" arrays:

~~~i1.d
void main ()
{
    char [7] b = [ 1: 'x' ]; // okay
    char [7] a = [ 0: 'x' ]; // i1.d(4): Error: mismatched array 
lengths, 7 and 1
}
~~~

~~~i2.d
import std.stdio;

void main ()
{
    char [7] c7 = [ 1: 'x' ];
    writeln (cast (ubyte [7]) c7); // [255, 120, 255, 255, 255, 
255, 255] okay
    char [7] d7 = "x";
    writeln (cast (ubyte [7]) d7); // [120, 0, 0, 0, 0, 0, 0] 
would have expected
                                   // [120, 255, 255, 255, 255, 
255, 255]
}
~~~

~~~i3.d
// i3.d
void main ()
{
    string s = "x";
    static assert (is (typeof (s) == typeof ("x")));
    assert (s == "x");
    char [7] c7 = s; // throws RangeError
}

$ dmd -g i3
$ ./i3
core.exception.RangeError i3.d(7): Range violation
----------------
??:? _d_arrayboundsp [...]
i3.d:7 _Dmain [...]
~~~

Shall I file them to bugzilla?
Aug 14 2021
next sibling parent Tejas <notrealemail gmail.com> writes:
On Saturday, 14 August 2021 at 09:40:54 UTC, kdevel wrote:
 Today I stumbled across three issues with partial 
 initialization of "static" arrays:

 ~~~i1.d
 void main ()
 {
    char [7] b = [ 1: 'x' ]; // okay
    char [7] a = [ 0: 'x' ]; // i1.d(4): Error: mismatched array 
 lengths, 7 and 1
 }
 ~~~

 ~~~i2.d
 import std.stdio;

 void main ()
 {
    char [7] c7 = [ 1: 'x' ];
    writeln (cast (ubyte [7]) c7); // [255, 120, 255, 255, 255, 
 255, 255] okay
    char [7] d7 = "x";
    writeln (cast (ubyte [7]) d7); // [120, 0, 0, 0, 0, 0, 0] 
 would have expected
                                   // [120, 255, 255, 255, 255, 
 255, 255]
 }
 ~~~

 ~~~i3.d
 // i3.d
 void main ()
 {
    string s = "x";
    static assert (is (typeof (s) == typeof ("x")));
    assert (s == "x");
    char [7] c7 = s; // throws RangeError
 }

 $ dmd -g i3
 $ ./i3
 core.exception.RangeError i3.d(7): Range violation
 ----------------
 ??:? _d_arrayboundsp [...]
 i3.d:7 _Dmain [...]
 ~~~

 Shall I file them to bugzilla?
Static arrays really don't get any love :( I also recently filed a bug: https://issues.dlang.org/show_bug.cgi?id=22198 I think you should also file these ones. If they're wrong, it'll just get ```RESOLVED INVALID```. Even better, someone here can tell why the above mentioned behaviours aren't bugs and you can just do it yourself.
Aug 14 2021
prev sibling parent reply frame <frame86 live.com> writes:
On Saturday, 14 August 2021 at 09:40:54 UTC, kdevel wrote:

 Shall I file them to bugzilla?
I would say case 2 and 3 are not bugs. It's just the element type conversion and mismatched lengths of the ranges. Not sure about the first one.
Aug 14 2021
next sibling parent Tejas <notrealemail gmail.com> writes:
On Saturday, 14 August 2021 at 13:01:13 UTC, frame wrote:
 On Saturday, 14 August 2021 at 09:40:54 UTC, kdevel wrote:

 Shall I file them to bugzilla?
I would say case 2 and 3 are not bugs. It's just the element type conversion and mismatched lengths of the ranges. Not sure about the first one.
Yeah, I jumped the train :( Replace ```string``` with ```char``` and double quotes with single quotes then case 2 and 3 give the expected output 1 is 100% a bug, please report that.
Aug 14 2021
prev sibling parent reply kdevel <kdevel vogtner.de> writes:
On Saturday, 14 August 2021 at 13:01:13 UTC, frame wrote:
 I would say case [...] 3 is not [a bug]. It's just the element 
 type conversion and mismatched lengths of the ranges.
~~~ char [7] d7 = "x"; // okay string s = "x"; char [7] c7 = s; // throws RangeError ~~~ What justifies that the compiler behaves differently on two terms ('s', '"x"') which are of equal size, type, length and value?
Aug 14 2021
next sibling parent reply Tejas <notrealemail gmail.com> writes:
On Saturday, 14 August 2021 at 14:04:47 UTC, kdevel wrote:
 On Saturday, 14 August 2021 at 13:01:13 UTC, frame wrote:
 I would say case [...] 3 is not [a bug]. It's just the element 
 type conversion and mismatched lengths of the ranges.
~~~ char [7] d7 = "x"; // okay string s = "x"; char [7] c7 = s; // throws RangeError ~~~ What justifies that the compiler behaves differently on two terms ('s', '"x"') which are of equal size, type, length and value?
They are not. assert(string.sizeof != char.sizeof);
Aug 14 2021
parent reply kdevel <kdevel vogtner.de> writes:
On Saturday, 14 August 2021 at 14:18:57 UTC, Tejas wrote:
 On Saturday, 14 August 2021 at 14:04:47 UTC, kdevel wrote:
 On Saturday, 14 August 2021 at 13:01:13 UTC, frame wrote:
 I would say case [...] 3 is not [a bug]. It's just the 
 element type conversion and mismatched lengths of the ranges.
~~~ char [7] d7 = "x"; // okay string s = "x"; char [7] c7 = s; // throws RangeError ~~~ What justifies that the compiler behaves differently on two terms ('s', '"x"') which are of equal size, type, length and value?
They are not. assert(string.sizeof != char.sizeof);
The terms are s and "x": ~~~r.d void main () { string s = "x"; assert (s.sizeof == "x".sizeof); } ~~~
Aug 14 2021
parent Tejas <notrealemail gmail.com> writes:
On Saturday, 14 August 2021 at 14:33:42 UTC, kdevel wrote:
 On Saturday, 14 August 2021 at 14:18:57 UTC, Tejas wrote:
 On Saturday, 14 August 2021 at 14:04:47 UTC, kdevel wrote:
 On Saturday, 14 August 2021 at 13:01:13 UTC, frame wrote:
 I would say case [...] 3 is not [a bug]. It's just the 
 element type conversion and mismatched lengths of the ranges.
~~~ char [7] d7 = "x"; // okay string s = "x"; char [7] c7 = s; // throws RangeError ~~~ What justifies that the compiler behaves differently on two terms ('s', '"x"') which are of equal size, type, length and value?
They are not. assert(string.sizeof != char.sizeof);
The terms are s and "x": ~~~r.d void main () { string s = "x"; assert (s.sizeof == "x".sizeof); } ~~~
It did implicit conversion on the literal but not the variable. Basically, ```d char[7] a = cast(char[7])"x"; // works string s = "x"; char[7] b = cast(char[7])s; //fails ``` That's my best guess. Hopefully someone more experienced chimes in.
Aug 14 2021
prev sibling next sibling parent frame <frame86 live.com> writes:
On Saturday, 14 August 2021 at 14:04:47 UTC, kdevel wrote:
 On Saturday, 14 August 2021 at 13:01:13 UTC, frame wrote:
 I would say case [...] 3 is not [a bug]. It's just the element 
 type conversion and mismatched lengths of the ranges.
~~~ char [7] d7 = "x"; // okay string s = "x"; char [7] c7 = s; // throws RangeError ~~~ What justifies that the compiler behaves differently on two terms ('s', '"x"') which are of equal size, type, length and value?
One is pure initialization, CTFE magic for strings or something like that. The other one is an assignment of an already created range where length check kicks in. The compiler is fine with that as it compiles. It's the bound checker at runtime level that bails out.
Aug 14 2021
prev sibling parent reply Paul Backus <snarwin gmail.com> writes:
On Saturday, 14 August 2021 at 14:04:47 UTC, kdevel wrote:
 ~~~
    char [7] d7 = "x"; // okay

    string s = "x";
    char [7] c7 = s; // throws RangeError
 ~~~

 What justifies that the compiler behaves differently on two 
 terms ('s', '"x"') which are of equal size, type, length and 
 value?
Literals in D can have different types in different contexts. For example: ```d byte b = 16; // 16 is treated as a byte literal int n = 16; // 16 is treated as an int literal b = n; // Error: cannot convert int to byte ``` Similarly, the string literal `"x"` can be treated either as a `string` (a dynamic array of `immutable(char)`) or as a static array of `char`, depending on the type of variable it's assigned to.
Aug 14 2021
parent kdevel <kdevel vogtner.de> writes:
On Saturday, 14 August 2021 at 23:09:14 UTC, Paul Backus wrote:
 On Saturday, 14 August 2021 at 14:04:47 UTC, kdevel wrote:
 ~~~
    char [7] d7 = "x"; // okay

    string s = "x";
    char [7] c7 = s; // throws RangeError
 ~~~

 What justifies that the compiler behaves differently on two 
 terms ('s', '"x"') which are of equal size, type, length and 
 value?
Literals in D can have different types in different contexts. For example: ```d byte b = 16; // 16 is treated as a byte literal int n = 16; // 16 is treated as an int literal b = n; // Error: cannot convert int to byte ```
The wording of the error message ~~~d void main () // bi.d { byte b = 257; } $ dmd bi.d bi.d(3): Error: cannot implicitly convert expression `257` of type `int` to `byte` ~~~ does not seem to support your interpretation. The term `257` does not encode a ‘polymorphic’ entity but the int value 257 which is used to initialize a variable. If necessary, the value is converted. The literal is not “typeless” as in Go [1] either.
 Similarly, the string literal `"x"` can be treated either as a 
 `string` (a dynamic array of `immutable(char)`) or as a static 
 array of `char`, depending on the type of variable it's 
 assigned to.
[1] https://blog.golang.org/constants
Aug 15 2021