Bug 12753 – All enum members trait, and missing function return values

Status
RESOLVED
Resolution
INVALID
Severity
enhancement
Priority
P1
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2014-05-16T09:21:00Z
Last change time
2014-05-16T10:05:57Z
Assigned to
nobody
Creator
bearophile_hugs

Comments

Comment #0 by bearophile_hugs — 2014-05-16T09:21:13Z
import std.traits: EnumMembers; enum Foo { A, B, C } int bar1(immutable Foo x) { foreach (immutable pos, immutable y; EnumMembers!Foo) if (x == y) return pos; } int bar2(immutable Foo x) { foreach (immutable pos, immutable y; [EnumMembers!Foo]) if (x == y) return pos; } void main() {} With dmd 2.066alpha gives errors: temp.d(3,5): Error: function temp.bar1 no return exp; or assert(0); at end of function temp.d(8,5): Error: function temp.bar2 no return exp; or assert(0); at end of function But I think the D compiler should be able to understand that a foreach on the whole range of an enum (found with EnumMembers) covers its all possible values, so those two functions always return a value and don't need the assert(0) at the end. To do this the D compiler should know that EnumMembers gives all the members of an enum. One way to do this is to introduce in D a built-in operation to get all members of an enum, something like this, re-using allMembers: int bar3(immutable Foo x) { foreach (immutable pos, immutable y; __traits(allMembers, Foo)) if (x == y) return pos; } I think the Ada compiler is able to do this, accepting simple code like (the 'Range is an Ada built-in operation): type Foo is (One, Two, Three, Four, Five); function Test(X: Foo) return Integer is begin for Y in Foo'Range loop if X = Y then return Foo'Pos(Y); end if; end loop; end Test;
Comment #1 by k.hara.pg — 2014-05-16T09:26:04Z
(In reply to bearophile_hugs from comment #0) > import std.traits: EnumMembers; > enum Foo { A, B, C } > int bar1(immutable Foo x) { > foreach (immutable pos, immutable y; EnumMembers!Foo) > if (x == y) > return pos; > } > int bar2(immutable Foo x) { > foreach (immutable pos, immutable y; [EnumMembers!Foo]) > if (x == y) > return pos; > } > void main() {} > > > With dmd 2.066alpha gives errors: > > temp.d(3,5): Error: function temp.bar1 no return exp; or assert(0); at end > of function > temp.d(8,5): Error: function temp.bar2 no return exp; or assert(0); at end > of function > > > But I think the D compiler should be able to understand that a foreach on > the whole range of an enum (found with EnumMembers) covers its all possible > values, so those two functions always return a value and don't need the > assert(0) at the end. It's wrong assumption. By using cast, you can give undefined enum value to bar1 and bar2. bar1(cast(Foo)99); bar2(cast(Foo)99); Therefore, the compiler error is legitimate.
Comment #2 by bearophile_hugs — 2014-05-16T09:53:40Z
(In reply to Kenji Hara from comment #1) > It's wrong assumption. By using cast, you can give undefined enum value to > bar1 and bar2. > > bar1(cast(Foo)99); > bar2(cast(Foo)99); > > Therefore, the compiler error is legitimate. What about this similar code: enum Foo { A, B, C } int bar4(immutable Foo x) { final switch (x) with (Foo) { case A: return 0; case B: return 1; case C: return 2; } } void main() {} Here there is no return at the end of the function.
Comment #3 by k.hara.pg — 2014-05-16T10:05:57Z
(In reply to bearophile_hugs from comment #2) > enum Foo { A, B, C } > int bar4(immutable Foo x) { > final switch (x) with (Foo) { > case A: return 0; > case B: return 1; > case C: return 2; > } > } > void main() {} > > > Here there is no return at the end of the function. Because it will throw SwitchError in runtime. void main() { bar4(cast(Foo)99); } core.exception.SwitchError@test(3): No appropriate switch clause found