https://issues.dlang.org/show_bug.cgi?id=20443
--- Comment #4 from Walter Bright <[email protected]> --- https://github.com/pbackus/sumtype/issues/35#issuecomment-563452054 reproduced here for convenience: ------------------------------ Here's my best attempt at an explanation: During semantic analysis of CallbackType1, the forward reference to Class1 triggers on-demand semantic analysis of Class1, which in turn triggers on-demand semantic analysis of SumType!CallbackType1. Normally, this would trigger on-demand analysis of CallbackType1, but the compiler notices it's already started analyzing CallbackType1 and terminates the recursion. While analyzing SumType!CallbackType1, the compiler evaluates isCopyable!CallbackType1. The source code for isCopyable looks like this: enum isCopyable(S) = is(typeof( { S foo = S.init; S copy = foo; } )); When the lambda inside isCopyable attempts to declare an instance of CallbackType1 as a local variable, it fails, because semantic analysis of CallbackType1 is still in progress and its size is not yet known. You can verify this by copy & pasting the lambda above into the reduced version of SumType, before the static if statement. Doing so will produce the following error: Error: struct `onlineapp.CallbackType1` no size because of forward reference Because of this error, compilation of the lambda fails, and isCopyable!CallbackType1 evaluates to false. Swapping the order of the declarations fixes the issue because it changes DMD's semantic-analysis "call stack" from this: CallbackType1 → Class1 → SumType!CallbackType1 to this: Class1 → SumType!CallbackType1 → CallbackType1 As long as SumType!CallbackType1 is encountered before CallbackType1, DMD is able to finish analyzing CallbackType1 before it evaluates isCopyable!CallbackType1, and thus does not encounter the error described above. Fixing this in DMD is likely to be quite difficult. However, it may be possible to find a workaround for isCopyable that allows it to work with incomplete types. --
