Enum crimes - getting the discriminant

Intrinsics are usable under an unstable feature flag. I’m feeling like calling this approach “the only correct way” assumes an interesting meaning of “correct” that includes that calling intrinsics directly using nightly features is somehow a particularly “correct” thing to do, which in my view it isn’t… and as shown by my response it’s not “the only” way. I would agree in that it’s “correct” in the sense that there’s no unsafety involved.

As far as my best guess w.r.t. why the “stabilized version of this intrinsic” features an opaque type that you’re not supposed to transmute or otherwise mess with goes: I would assume, the goal is to keep the precise representation of the enum discriminant an implementation detail that’s allowed to change in the future. Of course, breakage by future changes is something that’s expected using nightly and unstable features already. Even more so using permanently unstable features such as #[feature(core_intrinsics)].

5 Likes

I thought we don’t have custom discriminants yet and only can use integer builtins, am I wrong?

How/why does that matter? If Discriminant has a type that is in any way incompatible with the raw discriminant, then the raw discriminant being a primitive integer doesn't help. There are a good handful of reasons why a Discriminant -> uNN/iNN may be unsound.

100% reliable. It's something Rustc complier had for ages because Firefox needed that.

Now it's stabilized.

Usually it's good idea to go with safe route, but when you have safe options which is not guaranteed to work, which even release announce declares as something you shouldn't use and when there are unsafe options which does works and is supported… I'm not sure but that looks like an attempt to push the “avoid unsafe at all costs” religion too far.

Yes. That's precisely the issue.

Just read the RFC which includes the exact syntax (which uses unsafe) that Firefox uses (and which is thus guaranteed to work).

I guess if that feature would become popular (and it sure looks very nice for many use-cases) there would be a better syntax (maybe we would get guarantees about discriminant, maybe there would be another API), but for now sticking to what is described is working is the best approach IMNSHO. Even if it calls for explicit use of unsafe keyword.

Excuse me? Where does the release announcement say that you shouldn't use mem::Discriminant? It is in fact the exact opposite: it says that you should use it:

In the meantime, if all you need is an opaque handle to the discriminant, please see the std::mem::discriminant function.

And what, in particular, not guaranteed to work about mem::Discriminant? There's nothing in the docs that says it's not guaranteed to work. On the contrary, it says that it's suitable for uniquely identifying each variant.

You shouldn't put words in the mouth of the authors of the release announcement or the official documentation.

Please refrain from non-professional insults.

You are not guaranteed to get the precise values which you assigned in the enum declaration from it.

Only if you show me the important enough crate which uses discriminant with such enums.

I'm not saying that it wouldn't ever work, but just that I have never seen that combo where you want to assign some precise values to enum number yet is happy with getting any random garbage back.

All examples that I have ever seen needed to get the exact same number out of enum (that's why they wanted to assign particular numbers to enum elements and not given the compiler the freedom to choose them).

If you can show me practical examples of where the solution that you are pushing does work then I would take my words back.

Otherwise that's pushing safe-yet-non-working solution in place of unsafe-but-working one. Which doesn't look very “professional” to me.

Exactly this. For example, std might want to change the discriminants on ControlFlow if it ends up making ? more efficient, but if you could find out whether it's Continue or Break that's 0, it wouldn't be able to do that any more.

The eventual plan is to have an opt-in AsRepr kind of trait so that a type can say "yes, I'm promising this to my users", which will also give an elegant way to get the actual discriminant in the specific type -- which is better than as too, since it avoids as u8 mistakes on things that are repr(i16), for example.

3 Likes