kenji hara wrote:
> 2011/11/3 knommad <[email protected]>: >> Hi, >> >> I'm a relative newcomer to D, and am enjoying the experience. >> >> I have a small testcase here that causes what seems to be a spurious >> warning from the compiler (resulting code still works, however). >> >> Am I missing something?? >> >> import std.stdio; >> import std.traits; >> >> enum TestEnum >> { >> ONE = 1, >> TWO = 2, >> THREE = 3, >> FOUR = 4 >> } >> >> void main() >> { >> // Generates warning - works as expected though >> foreach( TestEnum member; EnumMembers!TestEnum ) >> { >> if ( member == TestEnum.TWO ) >> continue; >> writeln( "A: ", member ); >> } >> >> // No warning generated >> foreach( TestEnum member; EnumMembers!TestEnum ) >> { >> if ( member == TestEnum.TWO ) >> continue; >> else >> writeln( "B: ", member ); >> } >> >> // No warning generated >> auto list = EnumMembers!TestEnum; >> foreach( TestEnum member; list ) >> { >> if ( member == TestEnum.TWO ) >> continue; >> writeln( "C: ", member ); >> } >> >> } >> >> compiled with: dmd -wi -oftest test.d >> >> (dmd version 2.056) >> >> output is as expected: >> A: ONE >> A: THREE >> A: FOUR >> B: ONE >> B: THREE >> B: FOUR >> C: ONE >> C: THREE >> C: FOUR >> >> >> regards, >> ted >> >> -- >> Money can't buy happiness. But it can buy marshmallows, which are kinda >> the same thing. >> >> > > EnumMember returns tuple, it is compile-time sequence. > And foreach with tuple unrolls its body. Then, Loop A is unrolled like > follows. > > __foreachEntry0: { > if ( TestEnum.ONE == TestEnum.TWO ) > goto __foreachEntry1; > writeln( "A: ", TestEnum.ONE ); > } > __foreachEntry1: { > if ( TestEnum.TWO == TestEnum.TWO ) > goto __foreachEntry2; > writeln( "A: ", TestEnum.TWO ); // LineX > } > __foreachEntry2: { > if ( TestEnum.THREE == TestEnum.TWO ) > goto __foreachEntry3; > writeln( "A: ", TestEnum.THREE ); > } > __foreachEntry3: { > if ( TestEnum.FOUR == TestEnum.TWO ) > goto __foreachEntry4; > writeln( "A: ", TestEnum.FOUR ); > } > __foreachEntry4: > ; > > And, when member == TestEnum.TWO, the LineX is not reachable. > > With loop B, unrolling is similar, but dmd does not warn the > unreachable else block. > Because dmd treats it as that is stated by programmers as "may become > unreachable branch". > (This is reasonable assumption, sometimes the condition of if > statement folded to constant.) > > With loop C, list is "tuple of local variable symbols", it is similar > to follows. > > auto __list0 = TestEnum.ONE; > auto __list1 = TestEnum.TWO; > auto __list2 = TestEnum.THREE; > auto __list3 = TestEnum.FOUR; > alias TypeTuple!(list0, list1, list2, list3) list; > > list itself is compile time tuple, but its elements are evaluated at > runtime. Loop C is unrolled like A and B, but the conditions are > evaluated at runtime, then compiler does not warn the branches as > unreachable. > > Kenji Hara Hi, Thanks for the detailed and informative answer. I am puzzled, however, that there is an inconsistency. There were 3 examples in the test case, which I would have expected to yield the same compiler output - but it only generates a warning in the first example. regards, ted -- If you're not failing every now and again, it's a sign you're not doing anything very innovative. -- Woody Allen
