D issues are now tracked on GitHub. This Bugzilla instance remains as a read-only archive.
Issue 6174 - Initialize const fixed-size array in constructor
Summary: Initialize const fixed-size array in constructor
Status: RESOLVED FIXED
Alias: None
Product: D
Classification: Unclassified
Component: dmd (show other issues)
Version: D1 (retired)
Hardware: All All
: P2 normal
Assignee: No Owner
URL:
Keywords: industry, patch, rejects-valid
: 6924 7882 (view as issue list)
Depends on:
Blocks:
 
Reported: 2011-06-18 04:31 UTC by bearophile_hugs
Modified: 2020-09-06 22:20 UTC (History)
5 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this issue.
Description bearophile_hugs 2011-06-18 04:31:54 UTC
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 Trass3r 2011-08-24 17:19:30 UTC
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 Kenji Hara 2011-11-06 11:29:51 UTC
https://github.com/D-Programming-Language/dmd/pull/166

This patch transitively checks that an expression is part of initializing.
Comment 3 bearophile_hugs 2011-11-09 19:29:02 UTC
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 Kenji Hara 2011-11-12 06:56:29 UTC
*** Issue 6924 has been marked as a duplicate of this issue. ***
Comment 5 hsteoh 2012-04-09 19:42:42 UTC
*** Issue 7882 has been marked as a duplicate of this issue. ***
Comment 7 bearophile_hugs 2012-10-07 13:01:14 UTC
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 bearophile_hugs 2012-10-07 13:12:27 UTC
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 Kenji Hara 2012-10-08 05:35:43 UTC
(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 bearophile_hugs 2012-10-08 10:22:27 UTC
(In reply to comment #9)

> Please put in a new report.

OK, Issue 8783
Thank you.
Comment 11 github-bugzilla 2013-01-31 01:47:44 UTC
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 Leandro Lucarella 2014-03-06 07:56:15 UTC
This is still failing in D1. Reopening as D1 only.
Comment 13 Mathias LANG 2020-09-06 22:20:22 UTC
Works in D2, D1 is gone, closing.