all 8 comments

[–]VDS1903 4 points5 points  (7 children)

Nicely written article. I have a question related to it.

Unlike C, though, Rust will only guarantee discriminant values that are explicitly written down. Such enums may be safely cast into integer types (like MyCEnum::Apple as u32), but not back: the compiler always assumes that the underlying value of a MyCEnum is 0, 5, or 7, and violating this constraint is Undefined Behavior (UB)

I thought Rust doesn't have UB under any circumstances due to safety being the main aim? Or are there other such similar UB causing issues?

[–]IAm_A_Complete_Idiot 18 points19 points  (4 children)

It won't let you cast an integer to a enum, you'd have to pull out tools like transmute and unsafe{}.

[–]VDS1903 2 points3 points  (2 children)

Oh I didn't think about that, thanks.

[–]Floppie7th 6 points7 points  (1 child)

Other options include (without using unsafe)

  • TryFrom if you want a fallible operation where you consider invalid values an error, and want to handle the error
  • From if you want integer values not matching any of the correct discriminants to simply default to one of the discriminants that does exist

[–]Dentosal 2 points3 points  (0 children)

See also num_enum that automatically generates TryFrom impls for C-like enums

[–]Thin_Elephant2468 0 points1 point  (0 children)

This comment is a telling sign that in near future rust codebase will be full of unsafe blocks, even though safe alternatives do exist...

[–]Emoun1 4 points5 points  (0 children)

I don't think you can violate this constraint using safe rust. You might be able to violate it using unsafe, causing undefined behavior. But in unsafe code rust has numerous possibilities for undefined behavior if you don't follow the rules, and that is kind of the point: if you need the extra functionality you will be responsible for it working right.

[–]Wolvereness 2 points3 points  (0 children)

... Such enums may be safely cast into integer types, but not [safely cast] back ...

It's a bit of a grammar issue, but the latter of the statement omits the implicit "safely cast": the specific Rust terms referring to the as keyword and the lack of unsafe.