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 #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 #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