Closed
Description
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
.
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,
},
},
}
Metadata
Metadata
Assignees
Labels
No labels