Skip to content

Decoding failing for enum with negative discriminant type #848

@dkcumming

Description

@dkcumming

Decoding an enum alloc fails when the discriminant is negative typed value. Consider two programs (A and B) which are semantically equivalent:

Program A - passing

#[repr(i8)]
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum AccountState {
    Uninitialized = 0,
    Initialized = 1,
    Frozen = -1,
}

fn main() {
    let lhs = unsafe { core::mem::transmute::<i8, AccountState>(0) };
    let rhs = AccountState::Uninitialized;
    assert_eq!(lhs, rhs);
}

Program B - failing

#[repr(i8)]
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum AccountState {
    Uninitialized = 0,
    Initialized = 1,
    Frozen = -1,
}

fn main() {
    unsafe {
        assert_eq!(core::mem::transmute::<i8, AccountState>(0), AccountState::Uninitialized);
    }
}

A is passing and B is failing. The difference is that B has the attempts to decode the AccountState::Uninitialized from allocated bytes. It is not the transmute / lhs that is failing, that cast (#cast ( Integer ( 0 , 8 , true ) , castKindTransmute , ty ( 2 ) , ty ( 37 ) )) correctly evaluates into the enum value (Aggregate ( variantIdx ( 0 ) , .List )). It is the rhs / decoding the enum that fails... (ty(37) is AccountState)

thunk ( #decodeConstant ( constantKindAllocated ( allocation ( ... bytes: b"\x00\x00\x00\x00\x00\x00\x00\x00" , provenance: provenanceMap ( ... ptrs: provenanceMapEntry ( ... offset: 0 , allocId: allocId ( 0 ) )  .ProvenanceMapEntries ) , align: align ( 8 ) , mutability: mutabilityMut ) ) , ty ( 25 ) , typeInfoRefType ( ty ( 37 ) ) ) )

We need to look at the decoding rules for enums

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions