ITChap
ITChap

Reputation: 4742

When to use zero-variant enum over unit-like struct

If I understand correctly rust unit-like structs can be used like say atoms in Erlang.

But I don't understand what zero-variant enums provide. Could someone explain what the main purpose of zero-variant enums is and in which cases they might be favored over unit-like structs?

Upvotes: 6

Views: 970

Answers (1)

Chayim Friedman
Chayim Friedman

Reputation: 71300

One usage for zero-variants enum is to express unreachable code. For example, an infallible TryFrom or FromStr. This commonly occurs when using generics. Here's an example: OnceCell has both get_or_init() and get_or_try_init() methods.

enum Void {}
match self.get_or_try_init(|| Ok::<T, Void>(f())) {
    Ok(val) => val,
    Err(void) => match void {},
}

To save code duplication, the get_or_init() method calls get_or_try_init(). However, without using empty enums, this would incur cost at runtime because of the panic for the impossible Err case if the get_or_try_init() call isn't inlined). This is intended to be replaced by the never type once stabilized. Using empty enums has two advantages over unit structs:

  1. They cannot be constructed by mistake.
  2. They can hint the optimizer that this code is unreachable and allow it to remove it. They can also help the developers avoid panics in the code, because an infallible enum may be converted into the never type by match value {}, and the never type may be coerced into any other type. An example is in the once_cell code above.

Another usage is in generics, when you need only a type and not value, for example in the Strategy pattern at compile time, some people prefer zero variants enums to express that this types are not meant to be instantiated.

Upvotes: 4

Related Questions