Range of enum type values
j at j.nl
Fri Dec 27 18:12:44 UTC 2019
On Friday, 27 December 2019 at 14:58:59 UTC, Steven Schveighoffer
> On 12/27/19 9:12 AM, Timon Gehr wrote:
>> On 27.12.19 13:14, Johan Engelen wrote:
>>> Current compiler behavior results in an infinite value range.
>>> (but it's implicit behavior, i.e. not explicitly mentioned in
>>> - Currently, are operations resulting in a value larger than
>>> the underlying integer storage type UB,
>> They are @safe. You can't have UB in @safe code.
>>> like for normal signed integers?
>> Signed integers have wraparound semantics.
Thanks for the correction!
I hope someone finds the time to make that more explicit in the
>> The spec mentions this for AddExpressions (but the example
>> only shows it for uint): https://dlang.org/spec/expression.html
>> "If both operands are of integral types and an overflow or
>> underflow occurs in the computation, wrapping will happen."
>> There simply _can't_ be any UB in signed integer operations,
>> as they are considered @safe.
I don't accept this argument [*], but no argument needed here.
Just needs some clarification in spec text.
>>> - Should we limit the range of valid values of the Flags enum
>>> (C++ defines valid range to be [0..7])?
>>> - Do we want to limit operations allowed on enum types? Or
>>> change the result type? (e.g. the type of `Flags + Flags` is
>>> `int` instead of `Flags`.
>> I see those options:
>> 1. The valid range is the full range of the underlying type
>> (as DMD treats it now).
>> 2. The range is [1..4]. In this case, the operations have to
>> promote their operands to the enum base type, and most casts
>> to enum types must be @system.
>> 3. The range is [0..7]. In this case, only operations that
>> preserve this range (such as bitwise operators) should yield
>> the enum type, and other operations should promote their
>> operands to the enum base type, and most casts to enum types
>> must be @system.
>> Personally, I think 2 makes most sense (especially with `final
>> switch`, as the current semantics forces compilers to insert
>> default cases there), but this would be a breaking language
> We have another option, which I like. That is, only allow
> bitwise operations on enums that are flagged as allowing
> bitwise operations (either with a uda, or via some other
> mechanism). Many languages actually treat enums just like
> structs, where you can add operators and functions. This is
> also a possibility.
> This is also a breaking change, but also I don't want the
> compiler complaining about final switch on enums where the enum
> is intended not to be a bitwise flag. So I'd prefer 2 over 3.
Let's separate the discussion into what it _currently is_ and
what _it might be in future_.
Current language behavior:
enum value range = full range of base type; integer operations
work as-if the type is the base type.
Several options + lots of discussion ;-) and DIP needed.
Can I summarize it like that?
Let's not go off on a tangent, but there is enough UB in D that I
do not accept that @safe=="no UB" argument. One example that
comes to mind is bitshifting by more than the operand bit width:
"illegal" is what the spec says but that doesn't make sense for
runtime shift values and, in practice, turns into UB at runtime.
More information about the Digitalmars-d