Bug 11637 – Statically disallow sparse array literals and associative array literals with duplicate indexes

Status
NEW
Severity
normal
Priority
P3
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2013-11-28T14:51:33Z
Last change time
2024-12-13T18:14:34Z
Keywords
accepts-invalid
Assigned to
No Owner
Creator
bearophile_hugs
See also
https://issues.dlang.org/show_bug.cgi?id=15290
Moved to GitHub: dmd#18726 →

Comments

Comment #0 by bearophile_hugs — 2013-11-28T14:51:33Z
This bug report is borderline with being an enhancement request. DMD 2.065alpha accepts code like this, where duplicated keys in both dynamic array literals and in associative array literals defined with the sparse syntax: void main() { int[] a = [0:10, 0:20]; int[int] aa = [0:10, 0:20]; } I don't want to use this language "feature", and on the other hand I have had some mistakes like this in my D code not caught statically by the compiler. So I propose for D to statically disallow duplicated keys in both those cases, and give two compilation errors. I think that's just a possible source of bugs with no enough usefulness. -------------- Note that here I am not asking about disallowing inserting multiple times a key-pair in an associative array, this is normal and useful: void main() { int[int] aa; aa[0] = 10; aa[0] = 20; } -------------- The compiler didn't catch a bug of mine in a large dynamic array literal defined with the sparse syntax, I have assumed it was safer to specify enum keys like this, but currently this compiles with no errors: import std.traits, std.range, std.algorithm; enum Foo : size_t { f1, f2, f3 } enum Bar : size_t { b1, b2 } // Assert that both enums are usable as array indexes. static assert(__traits(compiles, { size_t x = Foo.init; })); static assert([EnumMembers!Foo].equal(EnumMembers!Foo.length.iota)); static assert(__traits(compiles, { size_t x = Bar.init; })); static assert([EnumMembers!Bar].equal(EnumMembers!Bar.length.iota)); void main() { with (Foo) with (Bar) int[EnumMembers!Foo.length][EnumMembers!Bar.length] A = [b1: [f1:1, b1:2, f3:3], b2: [f1:4, f2:5, f3:4]]; } Note in that code there is one "b1" index that logically is of the wrong _type_ because it should be a Foo.f2 instead of Bar.b1. But currently there is no way in D to strongly specify the type of the indexes of an array (as in Ada language). In D you can only specify the type of the keys of associative arrays, and here indeed D catches that type mismatch bug: import std.traits: EnumMembers; enum Foo : size_t { f1, f2, f3 } enum Bar : size_t { b1, b2 } void main() { with (Foo) with (Bar) { int[Foo][Bar] AA; AA = [b1: [f1:1, b1:2, f3:3], b2: [f1:4, f2:5, f3:4]]; } } temp.d(7): Error: cannot implicitly convert expression (cast(Bar)0) of type Bar to Foo But associative arrays are slow at run-time compared to a regular fixed-size 2D array, so I have has to use the sparse syntax to define a fixed-size 2D array. Note that: assert(cast(size_t)Bar.b1 == cast(size_t)Foo.f1); So the value of the index in the fixed-size 2D array "A" defined using the sparse syntax is duplicated, yet D has not found my mistake. To help me avoid such mistakes I propose to statically (at compile-time) disallow array literals with duplicate keys. From the answers in the D newsgroup people seem to accept the idea: http://forum.dlang.org/thread/[email protected] (I'd also like in D arrays with strongly typed indexes (not associative arrays, just arrays) as in Ada, but that's an enhancement request left for other places. One of the many advantages of having strongly typed indexes is that with them sometime there is no need to verify array bounds even in non-release mode.)
Comment #1 by nick — 2017-06-11T11:22:29Z
Also, current behaviour is inconsistent with struct named member initialization: struct S { int a; } S s = { a: 2, a: -5 }; //Error: duplicate initializer for field 'a'
Comment #2 by robert.schadek — 2024-12-13T18:14:34Z
THIS ISSUE HAS BEEN MOVED TO GITHUB https://github.com/dlang/dmd/issues/18726 DO NOT COMMENT HERE ANYMORE, NOBODY WILL SEE IT, THIS ISSUE HAS BEEN MOVED TO GITHUB