Range of enum type values
Johan Engelen
j at j.nl
Fri Dec 27 18:12:44 UTC 2019
On Friday, 27 December 2019 at 14:58:59 UTC, Steven Schveighoffer
wrote:
> 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
>>> spec)
>>>
>>> - 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.
>> https://forum.dlang.org/thread/n23bo3$qe$1@digitalmars.com
Thanks for the correction!
I hope someone finds the time to make that more explicit in the
spec.
>> 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
>> change.
>
> 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.
Future:
Several options + lots of discussion ;-) and DIP needed.
Can I summarize it like that?
cheers,
Johan
[*]
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
mailing list