| |
| /******************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=3449 |
| |
| template TypeTuple(T...) { alias TypeTuple = T; } |
| |
| // If module variable has no explicit initializer, |
| // constant folding is not allowed for that. |
| int mg1; |
| const int cg1; |
| immutable int ig1; |
| static this() |
| { |
| mg1 = 10; |
| cg1 = 10; |
| } |
| |
| shared static this() |
| { |
| ig1 = 10; |
| } |
| static assert(!__traits(compiles, { static assert(mg1 == 0); })); |
| static assert(!__traits(compiles, { static assert(cg1 == 0); })); |
| static assert(!__traits(compiles, { static assert(ig1 == 0); })); |
| |
| // But, if module variable has explicit initializer and |
| // non-mutable type, constant folding is allowed for that.. |
| int mg2 = 1; |
| const int cg2 = 1; |
| immutable int ig2 = 1; |
| static this() |
| { |
| mg2 = 11; |
| static assert(!__traits(compiles, cg2 = 11)); // not allowed for constant folding |
| static assert(!__traits(compiles, ig2 = 11)); // not allowed for constant folding |
| } |
| static assert(!__traits(compiles, { static assert(mg2 == 1); })); |
| static assert(cg2 == 1); // possible |
| static assert(ig2 == 1); // possible |
| |
| // For aggregate fields, compiler behavior will be changed. |
| void test3449() |
| { |
| static struct S(T) |
| { |
| T field1; // doesn't have explicit initializer |
| T field2 = 1; // has explicit initializer |
| |
| this(int n) |
| { |
| field1 = n; // allowed |
| field2 = n; // NEW! re-assigning during construction is allowed for any qualified fields. |
| } |
| } |
| |
| foreach (T; TypeTuple!(int, const int, immutable int)) |
| { |
| alias S!T ST; |
| |
| auto s1 = ST(); // default construction |
| assert(s1.field1 == 0); // == T.init |
| assert(s1.field2 == 1); // == specified initializer |
| |
| // Getting address for non-mutable field is allowed. |
| T* s1p1 = &s1.field1; |
| T* s1p2 = &s1.field2; |
| assert(*s1p1 == 0); |
| assert(*s1p2 == 1); |
| static if (is(T == int)) |
| { // If T is mutable, |
| // modification through indirection is allowed |
| *s1p1 = 100, *s1p2 = 101; |
| assert(*s1p1 == 100); |
| assert(*s1p2 == 101); |
| } |
| else |
| { // If T is not mutable, modification is not allowed |
| static assert(!__traits(compiles, *s1p1 = 100)); |
| static assert(!__traits(compiles, *s1p2 = 100)); |
| } |
| |
| // Access to non-static non-mutable field is |
| // now correctly rejected by "need this" error. |
| static assert(!__traits(compiles, ST.field1 == 1)); |
| static assert(!__traits(compiles, ST.field2 == 0)); |
| |
| // So, re-assignment of non-mutable fields |
| // during construction is enough acceptable. |
| auto s2 = ST(10); |
| assert(s2.field1 == 10); |
| assert(s2.field2 == 10); |
| } |
| } |
| |
| /******************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=10643 |
| |
| struct S10643 |
| { |
| const int[1000] x = void; |
| |
| this(int n) |
| { |
| x[] = n; |
| } |
| } |
| static assert(S10643.sizeof == int.sizeof * 1000); |
| |
| /******************************************/ |
| |
| int main() |
| { |
| test3449(); |
| |
| return 0; |
| } |