1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
|
/******************************************/
// 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;
}
|