152
|
1 // REQUIRED_ARGS: -o-
|
|
2 /*
|
|
3 TEST_OUTPUT:
|
|
4 ---
|
|
5 ---
|
|
6 */
|
|
7
|
|
8 mixin template Helpers()
|
|
9 {
|
|
10 static if (is(Flags!Move))
|
|
11 {
|
|
12 Flags!Move flags;
|
|
13 }
|
|
14 else
|
|
15 {
|
|
16 pragma(msg, "X: ", __traits(derivedMembers, Flags!Move));
|
|
17 }
|
|
18 }
|
|
19
|
|
20 template Flags(T)
|
|
21 {
|
|
22 mixin({
|
|
23 int defs = 1;
|
|
24 foreach (name; __traits(derivedMembers, Move))
|
|
25 {
|
|
26 defs++;
|
|
27 }
|
|
28 if (defs)
|
|
29 {
|
|
30 return "struct Flags { bool x; }";
|
|
31 }
|
|
32 else
|
|
33 {
|
|
34 return "";
|
|
35 }
|
|
36 }());
|
|
37 }
|
|
38
|
|
39 struct Move
|
|
40 {
|
|
41 int a;
|
|
42 mixin Helpers!();
|
|
43 }
|
|
44
|
|
45 enum a7815 = Move.init.flags;
|
|
46
|
|
47 /+
|
|
48 This originally was an invalid case:
|
|
49 When the Move struct member is analyzed:
|
|
50 1. mixin Helpers!() is instantiated.
|
|
51 2. In Helpers!(), static if and its condition is(Flags!Move)) evaluated.
|
|
52 3. In Flags!Move, string mixin evaluates and CTFE lambda.
|
|
53 4. __traits(derivedMembers, Move) tries to see the member of Move.
|
|
54 4a. mixin Helpers!() member is analyzed.
|
|
55 4b. `static if (is(Flags!Move))` in Helpers!() is evaluated
|
|
56 4c. The Flags!Move instantiation is already in progress, so it cannot be resolved.
|
|
57 4d. `static if` fails because Flags!Move cannot be determined as a type.
|
|
58 5. __traits(derivedMembers, Move) returns a 1-length tuple("a").
|
|
59 6. The lambda in Flags!Move returns a string "struct Flags {...}", then
|
|
60 Flags!Move is instantiated to a new struct Flags.
|
|
61 7. Finally Move struct does not have flags member, then the `enum a7815`
|
|
62 definition will fail in its initializer.
|
|
63
|
|
64 Now, static if will behave like a string mixin: it is invisible during its own expansion.
|
|
65 +/
|