Skip to content

Enum pack/unpack wrong #77

@JonasAlaif

Description

@JonasAlaif

When I run the pcg on the following example (not at all minimised), the match at the let value = match e { line results in an incorrect pcg result.

pub struct Fields {
    pub field_1: u32,
    pub field_2: (),
}

#[repr(i8)]
enum Enum {
    VariantA = 0,
    VariantB(Fields, Option<bool>) = -128,
    VariantC {
        field_1: u32,
        field_2: (),
    } = 127,
}

pub fn enum_test(e: Enum, v: u8) {
    match v {
        0 => {
            let value = match e {
                Enum::VariantA => {
                    0
                }
                Enum::VariantB(f, _) => {
                    f.field_1
                }
                Enum::VariantC { field_1, field_2 } => {
                    field_1
                }
            };
        }
        1 => {
            let Enum::VariantB(a, b) = e else {
                return;
            };
        }
        2 => {
            if let Enum::VariantC { field_1, field_2 } = e {
                
            } else {
                return;
            }
        }
        _ => {
            return;
        }
    }
}

The errors are twofold.

First, at bb11[2] the e@VariantC is unnecessarily packed (and then unpacked again straight away on the next line):
Image

Second (and worse), at the join point at bb14[0] the e@VariantB is left unpacked.
Image
This is not sound since the unpacks along the edges of bb11 -> bb14 and bb13 -> bb14 cannot happen (the enum is not in VariantB in those branches).

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