C-like enums should have another way to extract underlying integral values aka discriminant


#1

Today we can write

let e: MyEnum = ...;
let i = e as i32;

but the way I see it is, the as keyword plays too many roles in the language, including all sorts of integral casts which are not making Rust more robust than C/C++.

We should have something like e.into() for enum-to-integral conversion and prefer it over the as keyword whenever possible, so that we can more carefully verify the remaining occurrences of the as keyword.


#2

What about this:

impl MyEnum {
    fn into(self) -> i32 {
        self as i32
    }
}

This way you only have one occurrence of as i32 to review. Everything else can use .into() (You could also implement std::convert::Into<i32> if you want)


#3

What about the bugs caused by “as” misuse by all the other Rust programmers that are not defining that impl?


#4

How about a #[derive(Into)] that only works on repr(inttype) enums and it will implement Into<inttype> (i.e. the same type that was specified in the repr)?


#5

Well, there’s TryFrom!; going the other way is trivial.


#6

Related RFC: addition of a new intrinsic which will work in this way:

assert!(discriminant_value(std::cmp::Ordering::Greater) == 2u64);

(cf. https://doc.rust-lang.org/std/cmp/enum.Ordering.html)

But that’s not for the general public.


#7

It cannot handle enums written by someone else, such as std::cmp::Ordering, can it?


#8

Well that’d be implementing an external trait for an external type, so no. That macro is for implementing TryFrom on types you define.


#9

I like the Ida of implementing Into for such types, through instead of having some “special” Into I think it would be nice, if all repr(<inttype>) repr’s would imply that a impl for Into is generated.

But this might lead to some problems when the actual repr is more of a implementation detail (e.g. with a C interface) and some Into<inttype> should be implemented witch does not directly represents the underlying value (but then having such a structure is generally a bad idea I think)

Another question is if another .into() is the best choice of name or if it might make sens to show that this is “just” the internal repr of the enum, e.g. .into_raw() or so. Having a explicity method name for this as-usage would prevent the problem mentioned above and enable a automatic implementation of the respecting trait. Oh, and it fits with the into_raw methods of Box, and CString witch do roughly the same in a situation where as cannot be used.