3 ms·
Iterating over an enum requires a macro (strum::EnumIter is a popular one), which you’d need in order to ensure the test code automatically covers all cases wit
by mplanchard 5y ago
Iterating over an enum requires a macro (strum::EnumIter is a popular one), which you’d need in order to ensure the test code automatically covers all cases without needing updates. This does only work when your variants are non-data variants or data variants whose type implements Default, but it does allow you to force yourself to stay in sync.
Edit: you might could also do some shenanigans using integers, `as` conversions, and #[repr(u8)], but it seems like it would get nasty and potentially unsafe
- Groxx 5y agoAn iterator macro seems fine? You could apply it only during the tests, for example, so it's not like it needs to be exposed in your library.
- nmilo 5y agoAn unsafe block is significantly better than the code proposed in the article.
- justin_oaks 5y agoI know some people get upset when unsafe is used when there's a "safe" alternative, but unsafe isn't too bad in test code, is it? The concerns of undefined behavior, data races, use-after-free, etc. seem a lot less consequential in test code.
- nmilo 5y agoUnsafe isn't too bad in any code. The point of unsafe is that it is a declaration that the programmer has verified the code is safe. It is certainly easier to verify something along the lines of: unsafe { transmute::<u32, Error>(error_code) } than it is to verify that the weird macro code in the article is correct. There is no data races, use-after-free, etc. in that block, it does exactly what the article needs. To me, Rust programmers seem to have a weird notion that just the word "unsafe" is enough to conjure demons and monsters into otherwise totally normal code.
- Nullabillity 5y agoYou'd think so, but that code is far into nasal demon territory. Both because the default byte representation of an enum isn't stable, and because an out-of-bounds enum value (wherever it comes from) is always UB.