| // REQUIRED_ARGS: -o- |
| mixin template Helpers() |
| { |
| static if (is(Flags!Move)) |
| { |
| Flags!Move flags; |
| } |
| else |
| { |
| pragma(msg, "X: ", __traits(derivedMembers, Flags!Move)); |
| } |
| } |
| |
| template Flags(T) |
| { |
| mixin({ |
| int defs = 1; |
| foreach (name; __traits(derivedMembers, Move)) |
| { |
| defs++; |
| } |
| if (defs) |
| { |
| return "struct Flags { bool x; }"; |
| } |
| else |
| { |
| return ""; |
| } |
| }()); |
| } |
| |
| struct Move |
| { |
| int a; |
| mixin Helpers!(); |
| } |
| |
| enum a7815 = Move.init.flags; |
| |
| /+ |
| This originally was an invalid case: |
| When the Move struct member is analyzed: |
| 1. mixin Helpers!() is instantiated. |
| 2. In Helpers!(), static if and its condition is(Flags!Move)) evaluated. |
| 3. In Flags!Move, string mixin evaluates and CTFE lambda. |
| 4. __traits(derivedMembers, Move) tries to see the member of Move. |
| 4a. mixin Helpers!() member is analyzed. |
| 4b. `static if (is(Flags!Move))` in Helpers!() is evaluated |
| 4c. The Flags!Move instantiation is already in progress, so it cannot be resolved. |
| 4d. `static if` fails because Flags!Move cannot be determined as a type. |
| 5. __traits(derivedMembers, Move) returns a 1-length tuple("a"). |
| 6. The lambda in Flags!Move returns a string "struct Flags {...}", then |
| Flags!Move is instantiated to a new struct Flags. |
| 7. Finally Move struct does not have flags member, then the `enum a7815` |
| definition will fail in its initializer. |
| |
| Now, static if will behave like a string mixin: it is invisible during its own expansion. |
| +/ |