Bug 6174 – Initialize const fixed-size array in constructor

Status
RESOLVED
Resolution
FIXED
Severity
normal
Priority
P2
Component
dmd
Product
D
Version
D1 (retired)
Platform
All
OS
All
Creation time
2011-06-18T04:31:54Z
Last change time
2020-09-06T22:20:22Z
Keywords
industry, patch, rejects-valid
Assigned to
No Owner
Creator
bearophile_hugs

Comments

Comment #0 by bearophile_hugs — 2011-06-18T04:31:54Z
This program shows that you are allowed to initialize a single const char inside static this() and struct constructor, but you are not allowed to initialize the items of a char array: const char gc; const char[1] ga; static this() { gc = 'a'; // OK ga[0] = 'a'; // line 5, Err } struct Foo { const char cc; const char[1] array; this(char c) { cc = c; // OK array = [c]; // line 12, Err array[0] = c; // line 12, Err } } void main() {} DMD 2.053: temp.d(5): Error: ga[0] isn't mutable temp.d(12): Error: slice this.array[] is not mutable temp.d(13): Error: this.array[0] isn't mutable I'd like to initialize the arrays too.
Comment #1 by hoganmeier — 2011-08-24T17:19:30Z
This also happens without explicit slicing/indexing: immutable float[3] foo; static this() { foo = [1,2,3]; } In my actual code I need a function to initialize the array. It uses exp and thus isn't CTFEable. Hence static this would be the only to initialize this immutable.
Comment #2 by k.hara.pg — 2011-11-06T11:29:51Z
https://github.com/D-Programming-Language/dmd/pull/166 This patch transitively checks that an expression is part of initializing.
Comment #3 by bearophile_hugs — 2011-11-09T19:29:02Z
See also a comment by Kenji Hara: http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D&article_id=148428 > Inside constructor, compiler can detect that this.a[n] is part of the > fields of 'this' (because static array is value type), then should > allow to bypass const type checking for assignment. > But dynamic array and associative array are reference type, then > compiler cannot detect that the elements of them (this.b[n] and > this.aa[key]) are part of 'this'. Therefore line 8 and 9 cannot bypass > const type checking, even if inside constructor, then should be > rejected. > > I have call this concept "transitively modifiable", and I have > implemented it with dmd/pull/166. > "Transitively modifiable" is only checked inside constructor, and > allow more flexible initializing. > I think this is reasonable improvement. So all this is expected to eventually compile and run: const struct Foo1 { const int[1] a; this(in int x) pure { a[0] = x; // Error } } const struct Foo2 { const int[1] a; this(in int x) pure { a = [x]; // Error } } const struct Foo3 { const int[1] a; this(in int x) pure { a[] = x; // Error } } const struct Foo4 { const int a; this(in int x) pure { a = x; // OK } } void main() {} ------------------ While this is not yet compilable: const struct Foo { const int[] a; const int[int] aa; this(in int n) pure { this.a = new int[5]; this.a[0] = n; // line 6 this.aa[1] = 2; // line 7 } } void main() {} test.d(6): Error: this.a[0] isn't mutable test.d(7): Error: this.aa[1] isn't mutable
Comment #4 by k.hara.pg — 2011-11-12T06:56:29Z
*** Issue 6924 has been marked as a duplicate of this issue. ***
Comment #5 by hsteoh — 2012-04-09T19:42:42Z
*** Issue 7882 has been marked as a duplicate of this issue. ***
Comment #6 by yebblies — 2012-10-07T11:48:48Z
Comment #7 by bearophile_hugs — 2012-10-07T13:01:14Z
This is an improvement of D. std.algorithm.copy can't be used to initialize const array fields, but this is not important: import std.algorithm: copy; class Foo { const int[3] bar; this() { auto data = [10, 20, 30]; foreach (i, d; data) bar[i] = d; // OK copy(data, bar[]); // error } } void main() {}
Comment #8 by bearophile_hugs — 2012-10-07T13:12:27Z
Is this expected? Do you want me to put this in a new bug report? struct Foo { int[1] bar; } const Foo[1] foos; static this() { foreach (i; 0 .. foos.length) foos[i].bar[i] = 1; // OK foreach (i, ref f; foos) f.bar[i] = 1; // Error } void main() {}
Comment #9 by k.hara.pg — 2012-10-08T05:35:43Z
(In reply to comment #8) > Is this expected? Do you want me to put this in a new bug report? > > struct Foo { > int[1] bar; > } > const Foo[1] foos; > static this() { > foreach (i; 0 .. foos.length) > foos[i].bar[i] = 1; // OK > foreach (i, ref f; foos) > f.bar[i] = 1; // Error > } > void main() {} Hmm, it's interesting. The accessed memory through the reference 'f' would specify a part of the constructed fields, and compiler would be able to detect it in statically. Please put in a new report.
Comment #10 by bearophile_hugs — 2012-10-08T10:22:27Z
(In reply to comment #9) > Please put in a new report. OK, Issue 8783 Thank you.
Comment #11 by github-bugzilla — 2013-01-31T01:47:44Z
Commit pushed to master at https://github.com/D-Programming-Language/dmd https://github.com/D-Programming-Language/dmd/commit/aa33955a6ed38ab64df903b2298988f9cde42914 Clean up test cases for issue 6174 Merged similar tests by making them parameterize.
Comment #12 by leandro.lucarella — 2014-03-06T07:56:15Z
This is still failing in D1. Reopening as D1 only.
Comment #13 by pro.mathias.lang — 2020-09-06T22:20:22Z
Works in D2, D1 is gone, closing.