#safety of getting the discriminant of a zeroed enum variant

24 messages · Page 1 of 1 (latest)

plain reef
#

is this a "safe" way of getting the std::mem::Discriminant value for an enum variant without actually initializing the variant? obviously cursed but would it ever really cause problems?

unsafe {
    let value = std::mem::MaybeUninit::new(Enum::Variant {
        a: std::mem::MaybeUninit::zeroed().assume_init(),
        b: std::mem::MaybeUninit::zeroed().assume_init(),
    });
    std::mem::discriminant(value.assume_init_ref())
}

I guess it depends on whether the discriminant function does anything with the non-discriminant memory, but surely not?

topaz pond
mossy cedar
#

it would be better here to have a separate enum EnumKind that doesn't hold any data

topaz pond
#

Ah, you're using zeroed, not uninit. It's still almost certainly not, as few types can safely hold the all-zero pattern

#

(Refs, for example, cannot be all-zero due to the rule that they must be non-null. So if a or b are refs, you're looking at UB.)

plain reef
#

what does "instant undefined behavior" mean in this context? the compiler might rearrange instructions with the assumption that they're valid and this might break things?

storm mason
#

Zero isn't a valid value for all enums, even for the discriminant. For example: enum A { One = 1 } So there can't be a safe way that works for any enum. It's probably better to repr it and look at the bytes directly.

topaz pond
warm linden
#

it means that creating a reference that's all zeros (or any other invalid value) is not a well-defined operation in the abstract machine, and the compiler can do whatever it wants if you try it

#

there are some enum definitions where this would not be unsound but most generally will not allow this

#

why are you writing this code? what do you want to do?

topaz pond
storm mason
#

are you able to use Default?

#

using repr still would work

topaz pond
warm linden
#

repr doesnt affect whether an all-zero bit pattern is valid

#

oh nvm

#

i misunderstood

storm mason
#

I was thinking of it as a way around using discriminant

#

so you don't need to build the enum

plain reef
#

yeah I'll probably just use something like Default or a separate definition for the id. I'm using the discriminant as a unique identifier (for HashMap and other things) but I want to get the variant's discriminant/identifier without needing to construct all of the variant's fields. Maybe premature optimization but the mind wanders

topaz pond
#

Also, @mossy cedar doesn't strum have a macro for exactly this?

mossy cedar
#

I believe so