1 
2 /******************************************/
3 // 3449
4 
TypeTuple(T...)5 template TypeTuple(T...) { alias TypeTuple = T; }
6 
7 // If module variable has no explicit initializer,
8 // constant folding is not allowed for that.
9 int mg1;
10 const int cg1;
11 immutable int ig1;
this()12 static this()
13 {
14     mg1 = 10;
15     cg1 = 10;
16     ig1 = 10;
17 }
18 static assert(!__traits(compiles, { static assert(mg1 == 0); }));
19 static assert(!__traits(compiles, { static assert(cg1 == 0); }));
20 static assert(!__traits(compiles, { static assert(ig1 == 0); }));
21 
22 // But, if module variable has explicit initializer and
23 // non-mutable type, constant folding is allowed for that..
24 int mg2 = 1;
25 const int cg2 = 1;
26 immutable int ig2 = 1;
this()27 static this()
28 {
29     mg2 = 11;
30     static assert(!__traits(compiles, cg2 = 11));   // not allowed for constant folding
31     static assert(!__traits(compiles, ig2 = 11));   // not allowed for constant folding
32 }
33 static assert(!__traits(compiles, { static assert(mg2 == 1); }));
34                                     static assert(cg2 == 1);    // possible
35                                     static assert(ig2 == 1);    // possible
36 
37 // For aggregate fields, compiler behavior will be changed.
test3449()38 void test3449()
39 {
40     static struct S(T)
41     {
42         T field1;       // doesn't have explicit initializer
43         T field2 = 1;   // has explicit initializer
44 
45         this(int n)
46         {
47             field1 = n; // allowed
48             field2 = n; // NEW! re-assigning during construction is allowed for any qualified fields.
49         }
50     }
51 
52     foreach (T; TypeTuple!(int, const int, immutable int))
53     {
54         alias S!T ST;
55 
56         auto s1 = ST();             // default construction
57         assert(s1.field1 == 0);     // == T.init
58         assert(s1.field2 == 1);     // == specified initializer
59 
60         // Getting address for non-mutable field is allowed.
61         T* s1p1 = &s1.field1;
62         T* s1p2 = &s1.field2;
63         assert(*s1p1 == 0);
64         assert(*s1p2 == 1);
65         static if (is(T == int))
66         {   // If T is mutable,
67             // modification through indirection is allowed
68             *s1p1 = 100, *s1p2 = 101;
69             assert(*s1p1 == 100);
70             assert(*s1p2 == 101);
71         }
72         else
73         {   // If T is not mutable, modification is not allowed
74             static assert(!__traits(compiles, *s1p1 = 100));
75             static assert(!__traits(compiles, *s1p2 = 100));
76         }
77 
78         // Access to non-static non-mutable field is
79         // now correctly rejected by "need this" error.
80         static assert(!__traits(compiles, ST.field1 == 1));
81         static assert(!__traits(compiles, ST.field2 == 0));
82 
83         // So, re-assignment of non-mutable fields
84         // during construction is enough acceptable.
85         auto s2 = ST(10);
86         assert(s2.field1 == 10);
87         assert(s2.field2 == 10);
88     }
89 }
90 
91 /******************************************/
92 // 10643
93 
94 struct S10643
95 {
96     const int[1000] x = void;
97 
thisS1064398     this(int n)
99     {
100         x[] = n;
101     }
102 }
103 static assert(S10643.sizeof == int.sizeof * 1000);
104 
105 /******************************************/
106 
main()107 int main()
108 {
109     test3449();
110 
111     return 0;
112 }
113