diff --git a/std/conv.d b/std/conv.d index 9318f6fba5b..94014eaf62f 100644 --- a/std/conv.d +++ b/std/conv.d @@ -1308,7 +1308,7 @@ fit in the narrower type. */ T toImpl(T, S)(S value) if (!isImplicitlyConvertible!(S, T) && - (isNumeric!S || isSomeChar!S) && !is(S == enum) && + (isNumeric!S || isSomeChar!S) && (isNumeric!T || isSomeChar!T) && !is(T == enum)) { enum sSmallest = mostNegative!S; @@ -1360,6 +1360,29 @@ T toImpl(T, S)(S value) dchar to4 = to!dchar(from4); } +unittest +{ + // Narrowing conversions from enum -> integral should be allowed, but they + // should throw at runtime if the enum value doesn't fit in the target + // type. + enum E1 : ulong { A = 1, B = 1UL<<48 } + assert(to!int(E1.A) == 1); + assertThrown!ConvOverflowException(to!int(E1.B)); // E1.B overflows int + + enum E2 : long { A = -1L<<48, B = -1<<31, C = 1<<31 } + assertThrown!ConvOverflowException(to!int(E2.A)); // E2.A overflows int + assertThrown!ConvOverflowException(to!uint(E2.B)); // E2.B overflows uint + assert(to!int(E2.B) == -1<<31); // but does not overflow int + assert(to!int(E2.C) == 1<<31); // E2.C does not overflow int + + enum E3 : int { A = -1, B = 1, C = 255 } + assertThrown!ConvOverflowException(to!ubyte(E3.A)); + assert(to!byte(E3.A) == -1); + assert(to!byte(E3.B) == 1); + assert(to!ubyte(E3.C) == 255); + assertThrown!ConvOverflowException(to!byte(E3.C)); +} + /** Array-to-array conversion (except when target is a string type) converts each element in turn by using $(D to). diff --git a/std/format.d b/std/format.d index e5c1417e2c9..fc80fd2f2e0 100644 --- a/std/format.d +++ b/std/format.d @@ -5929,3 +5929,12 @@ unittest formattedWrite(stream, "%2$.*1$d", 12, 10); assert(stream.data == "000000000010", stream.data); } + +unittest +{ + // bug 6893 + enum E : ulong { A, B, C } + auto stream = appender!(char[])(); + formattedWrite(stream, "%s", E.C); + assert(stream.data == "C"); +}