Use case for an enum with a single variant

I have a generic wrapper where I want to forward all method and field accesses to the inner value. Using a struct with a single field will have at least one field name (or .0) which may shadow an inner value's field:

pub struct Wrapper<T>(pub T);

impl<T> std::ops::Deref for Wrapper<T> {
    type Target = T;
    fn deref(&self) -> &T {
        &self.0
    }
}

fn main() {
    let wrapper = Wrapper((5, 8));
    // assert_eq!(wrapper.0, 5); // this doesn't work
    assert_eq!(wrapper.1, 8); // but this does!!
    // Instead:
    assert_eq!(wrapper.0, (5, 8));
}

(Playground)

I wondered if a good solution would be an enum with a single variant:

pub enum Wrapper<T> {
    Wrapped(T),
}

use Wrapper::Wrapped;

impl<T> std::ops::Deref for Wrapper<T> {
    type Target = T;
    fn deref(&self) -> &T {
        let Wrapped(inner) = self;
        inner
    }
}

fn main() {
    let wrapper = Wrapped((5, 8));
    assert_eq!(wrapper.0, 5);
    assert_eq!(wrapper.1, 8);
}

(Playground)

An alternative would be to use a struct with a private field, but I guess that would limit pattern matching capabilities then.

Do you think a single variant enum is reasonable to use?

I also noticed that the Nomicon doesn't mention that enums with a single variant can be made #[repr(transparent)]. I assume it just has been forgotten? The linked RFC 1758 doesn't mention enums. The reference states that it works with single variant enums, and on Playground it seems to work too.

(My use case is deref_owned::Owned, which currently shadows ".0", unlike std::borrow::Cow::Owned, which does not (Playground).)

More like never added, probably. It's RFC 2645 and the enum portion stabilized in 1.42.

1 Like

PR #68122, as referenced in your second link, gives a vague scenario for single variant enums in that context:

This is not a major feature that will unlock new and important use-cases. The utility of repr(transparent) enums is indeed limited. However, there is still some value in it:

  1. It provides conceptual simplification […].
  2. In rare occasions, it might be that the user started out with a univariant enum for whatever reason (e.g. they thought they might extend it later). Now they want to make this enum transparent without breaking users by turning it into a struct. By lifting the restriction here, now they can.

The (supposed) advantage of not exposing any field names while allowing pattern matching isn't mentioned. Maybe it's a too exotic use case for anyone to have come up with it (and I'm still unsure whether I like the syntax).

Anyway, I filed a short issue to fix the Nomicon.


I just noticed that even if Cow doesn't shadow any fields, it still does shadow methods. So maybe it's a bit over the top to try to avoid any shadowing, and I could just use manual dereferencing (or unwrapping) where applicable (Playground).

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.