-
Notifications
You must be signed in to change notification settings - Fork 13k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Do not use scalar layout if there are ZSTs with alignment > 1 #103926
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -901,36 +901,58 @@ pub trait LayoutCalculator { | |
|
||
let optimize = !repr.inhibit_union_abi_opt(); | ||
let mut size = Size::ZERO; | ||
let mut abi = Abi::Aggregate { sized: true }; | ||
let mut abi = None; | ||
let mut biggest_zst_align = align; | ||
let mut biggest_non_zst_align = align; | ||
Comment on lines
+905
to
+906
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This can't be correct, you need the exact field alignment, not some combination. |
||
let index = V::new(0); | ||
for field in &variants[index] { | ||
assert!(field.is_sized()); | ||
align = align.max(field.align); | ||
assert!(!field.is_unsized()); | ||
|
||
// If all non-ZST fields have the same ABI, forward this ABI | ||
if optimize && !field.is_zst() { | ||
// Discard valid range information and allow undef | ||
let field_abi = match field.abi { | ||
Abi::Scalar(x) => Abi::Scalar(x.to_union()), | ||
Abi::ScalarPair(x, y) => Abi::ScalarPair(x.to_union(), y.to_union()), | ||
Abi::Vector { element: x, count } => { | ||
Abi::Vector { element: x.to_union(), count } | ||
} | ||
Abi::Uninhabited | Abi::Aggregate { .. } => Abi::Aggregate { sized: true }, | ||
}; | ||
if optimize { | ||
// If all non-ZST fields have the same ABI, forward this ABI | ||
if field.is_zst() { | ||
biggest_zst_align = biggest_zst_align.max(field.align); | ||
} else { | ||
biggest_non_zst_align = biggest_non_zst_align.max(field.align); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This doesn't seem right. Thing is, you cannot have the same What you want is And then if the |
||
// Discard valid range information and allow undef | ||
let field_abi = match field.abi { | ||
Abi::Scalar(x) => Abi::Scalar(x.to_union()), | ||
Abi::ScalarPair(x, y) => Abi::ScalarPair(x.to_union(), y.to_union()), | ||
Abi::Vector { element: x, count } => { | ||
Abi::Vector { element: x.to_union(), count } | ||
} | ||
Abi::Uninhabited | Abi::Aggregate { .. } => Abi::Aggregate { sized: true }, | ||
}; | ||
|
||
if size == Size::ZERO { | ||
// first non ZST: initialize 'abi' | ||
abi = field_abi; | ||
} else if abi != field_abi { | ||
// different fields have different ABI: reset to Aggregate | ||
abi = Abi::Aggregate { sized: true }; | ||
if let Some(abi) = &mut abi { | ||
if *abi != field_abi { | ||
// different fields have different ABI: reset to Aggregate | ||
*abi = Abi::Aggregate { sized: true }; | ||
} | ||
} else { | ||
abi = Some(field_abi); | ||
} | ||
} | ||
} | ||
|
||
align = align.max(field.align); | ||
size = cmp::max(size, field.size); | ||
} | ||
|
||
let abi = match abi { | ||
None => Abi::Aggregate { sized: true }, | ||
Some(non_zst_abi) => { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What if you move the |
||
if biggest_zst_align.abi > biggest_non_zst_align.abi { | ||
// If a zst has a bigger alignment than the non-zst fields, | ||
// we cannot use scalar layout, because scalar(pair)s can't be | ||
// more aligned than their primitive. | ||
Comment on lines
+946
to
+948
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This comment is misleading. (Also, you don't need Honestly there should be an e.g. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For ScalarPair, my sanity check currently enforces There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe! I'm pretty sure we assume the exact alignment at least... somewhere? Also, it's always an optimization, unlike the other two There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If #105006 passes, the sanity check could also use such a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh wait actually, we currently also allow strengthening the alignment in vectors (i.e., the layout can have stricter alignment than the scalar type would require). And again probably I had a reason to allow that. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. #105006 landed, so looks like you are right -- size and alignment of Scalar/ScalarPair/Vector types are entirely determined by their |
||
Abi::Aggregate { sized: true } | ||
} else { | ||
non_zst_abi | ||
} | ||
} | ||
}; | ||
|
||
if let Some(pack) = repr.pack { | ||
align = align.min(AbiAndPrefAlign::new(pack)); | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you rename this to
common_non_zst_abi
? Feels very misleading as-is.