Skip to content

For enums with ScalarPair ABI, some variants have Aggregate ABI #96221

@RalfJung

Description

@RalfJung

I noticed this while working on #96185: I added the following sanity check in Miri's operand_downcast:

--- a/compiler/rustc_const_eval/src/interpret/operand.rs
+++ b/compiler/rustc_const_eval/src/interpret/operand.rs
@@ -441,6 +441,14 @@ pub fn operand_downcast(
                 // (In particular, no check about whether this is even the active variant -- that's by design,
                 // see https://github.com/rust-lang/rust/issues/93688#issuecomment-1032929496.)
                 let layout = op.layout.for_variant(self, variant);
+                if matches!(op.layout.abi, Abi::ScalarPair { .. }) {
+                    assert!(
+                        matches!(layout.abi, Abi::ScalarPair { .. } | Abi::Scalar { .. }),
+                        "downcast to {variant:?} turned ScalarPair layout into non-scalar layout: {:#?} to {:#?}",
+                        op.layout,
+                        layout,
+                    );
+                }
                 OpTy { layout, ..*op }
             }
         })

This assertion indeed fails. When downcasting std::option::Option<*mut std::ffi::c_void> to variant 1, the ABI changes from ScalarPair to Aggegreate.

Details
downcast to 1 turned ScalarPair layout into non-scalar layout: TyAndLayout {
    ty: std::option::Option<*mut std::ffi::c_void>,
    layout: Layout {
        fields: Arbitrary {
            offsets: [
                Size {
                    raw: 0,
                },
            ],
            memory_index: [
                0,
            ],
        },
        variants: Multiple {
            tag: Initialized {
                value: Int(
                    I64,
                    false,
                ),
                valid_range: 0..=1,
            },
            tag_encoding: Direct,
            tag_field: 0,
            variants: [
                Layout {
                    fields: Arbitrary {
                        offsets: [],
                        memory_index: [],
                    },
                    variants: Single {
                        index: 0,
                    },
                    abi: Aggregate {
                        sized: true,
                    },
                    largest_niche: None,
                    align: AbiAndPrefAlign {
                        abi: Align {
                            pow2: 0,
                        },
                        pref: Align {
                            pow2: 3,
                        },
                    },
                    size: Size {
                        raw: 8,
                    },
                },
                Layout {
                    fields: Arbitrary {
                        offsets: [
                            Size {
                                raw: 8,
                            },
                        ],
                        memory_index: [
                            0,
                        ],
                    },
                    variants: Single {
                        index: 1,
                    },
                    abi: Aggregate {
                        sized: true,
                    },
                    largest_niche: None,
                    align: AbiAndPrefAlign {
                        abi: Align {
                            pow2: 3,
                        },
                        pref: Align {
                            pow2: 3,
                        },
                    },
                    size: Size {
                        raw: 16,
                    },
                },
            ],
        },
        abi: ScalarPair(
            Initialized {
                value: Int(
                    I64,
                    false,
                ),
                valid_range: 0..=1,
            },
            Initialized {
                value: Pointer,
                valid_range: 0..=18446744073709551615,
            },
        ),
        largest_niche: Some(
            Niche {
                offset: Size {
                    raw: 0,
                },
                value: Int(
                    I64,
                    false,
                ),
                valid_range: 0..=1,
            },
        ),
        align: AbiAndPrefAlign {
            abi: Align {
                pow2: 3,
            },
            pref: Align {
                pow2: 3,
            },
        },
        size: Size {
            raw: 16,
        },
    },
} to TyAndLayout {
    ty: std::option::Option<*mut std::ffi::c_void>,
    layout: Layout {
        fields: Arbitrary {
            offsets: [
                Size {
                    raw: 8,
                },
            ],
            memory_index: [
                0,
            ],
        },
        variants: Single {
            index: 1,
        },
        abi: Aggregate {
            sized: true,
        },
        largest_niche: None,
        align: AbiAndPrefAlign {
            abi: Align {
                pow2: 3,
            },
            pref: Align {
                pow2: 3,
            },
        },
        size: Size {
            raw: 16,
        },
    },
}

Cc @oli-obk @erikdesjardins

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions