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