Bug 6893 – Write of enum member represented with ubyte or ulong
Status
RESOLVED
Resolution
FIXED
Severity
normal
Priority
P2
Component
phobos
Product
D
Version
D2
Platform
x86
OS
Windows
Creation time
2011-11-05T04:05:00Z
Last change time
2013-08-24T02:36:53Z
Keywords
pull
Assigned to
nobody
Creator
bearophile_hugs
Comments
Comment #0 by bearophile_hugs — 2011-11-05T04:05:46Z
import std.stdio;
enum E1 : uint { A, B, C };
enum E2 : ubyte { A, B, C };
enum E3 : ulong { A, B, C };
void main() {
writeln(E1.C);
writeln(E2.C);
writeln(E3.C);
}
Output dmd 2.057head:
C
<error>
Expected output:
C
C
C
Comment #1 by andrej.mitrovich — 2012-12-02T10:35:38Z
First two are ok now but the 3rd has become a massive template instance error (2.061).
Comment #2 by hsteoh — 2013-08-22T17:21:19Z
The problem appears to be std.format.getNthInt, under "static if (isIntegral!...)": the code assumes that if a type is integral, it can be converted to int, but this is not true when the base type of the enum is ulong.
Comment #3 by hsteoh — 2013-08-22T17:31:41Z
Hmm actually, there appears to be a bug somewhere else. The spec shouldn't be spec.DYNAMIC at all, since the default spec for enums is "%s". So something went wrong before this point.
Comment #4 by andrej.mitrovich — 2013-08-22T17:33:31Z
(In reply to comment #3)
> Hmm actually, there appears to be a bug somewhere else. The spec shouldn't be
> spec.DYNAMIC at all, since the default spec for enums is "%s". So something
> went wrong before this point.
Last time I tried to fix this I lost my head in the formatting jungle. Good luck!
Comment #5 by hsteoh — 2013-08-22T17:45:59Z
Aha! I found the reason: getNthInt is called from a *compile-time* check, so even if the spec for enum is "%s", the compiler still has to compile this branch of the code. So the fix is for getNthInt to *statically* verify convertibility to int before attempting to call to!int.
Comment #6 by hsteoh — 2013-08-22T18:08:22Z
Argh. I wish bugzilla allowed editing of comments... What I meant was: getNthInt is called from inside a *runtime* if-condition that evaluates to false when the spec is "%s" and the argument is a ulong enum, but since this if-condition can only be checked at runtime, getNthInt must be able to compile in that case. Currently it doesn't compile because it assumes isIntegral!T means T can be implicitly converted to int, which is not true if the argument is a ulong (or a ulong enum). So the fix is to replace isIntegral with is(typeof(to!int(...))) so that at compile-time the compiler will hardcode the function to throw an exception when an invalid argument is given. (It won't actually throw at runtime if the if-condition in the caller evaluates to false at runtime.)