-
-
Notifications
You must be signed in to change notification settings - Fork 472
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
fix(ast_tools): fix miscalculation of enum layouts. #5774
fix(ast_tools): fix miscalculation of enum layouts. #5774
Conversation
Your org has enabled the Graphite merge queue for merging into mainAdd the label “0-merge” to the PR and Graphite will automatically add it to the merge queue when it’s ready to merge. Or use the label “hotfix” to add to the merge queue as a hot fix. You must have a Graphite account and log in to Graphite in order to use the merge queue. Sign up using this link. |
This stack of pull requests is managed by Graphite. Learn more about stacking. |
CodSpeed Performance ReportMerging #5774 will not alter performanceComparing Summary
|
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.
I am not familiar with the layout calculation logic in ast_tools
, so I could be reading it wrong, but it looks like this is taking the niches of the variants' fields into account for niche calculation of the enum.
I don't think this is correct. e.g.: Rust playground:
-
StartNiche
has an unused discriminant at start of theu8
range (0). -
EndNiche
has an unused discriminant at end of theu8
range (255). -
NoNiche
has no unused discriminants at either start or end ofu8
range. -
Option<StartNiche>
andOption<EndNiche>
are 2 bytes (discriminant's niche used asNone
). -
Option<NoNiche>
is 3 bytes (indicatingNoNiche
has no niche).
A couple of conclusions we can draw from this:
- The number of variants is not relevant, only whether there are spare discriminant values at start or end of range (not in the middle).
- Whether the fields have niches or not is also irrelevant. Compiler could have noticed that every variant in
NoNiche
has a field with 254 illegal values, and those illegal values overlap for all fields. It could have used one of those illegal values as a niche (Option<NoNiche>::None
could be stored as 2 bytes[0, 2]
). But it doesn't! An enum only has niches if there are available discriminant values.
You have other PRs stacked on top of this, so feel free to merge this, and then change the niche logic in a follow-up if you like.
Am going to merge this, and then address the issues raised in my comment above in a follow-on. |
Merge activity
|
Fixes a bug with how we were calculating the size of enums when there are different padding on variants and there aren't enough niches. Now it aligns the largest variant size to the largest alignment before consuming niches.
ea1c733
to
e8f8409
Compare
Actually, I can't understand the code at all. To calculate niches correctly, need to know the value of the variant discriminants, which isn't easily available at this stage. I think to make it exactly correct, will need quite a large refactoring. In any case, for AST transfer, we need to know not just how many niches, but their positions and values. So will need a rework for that anyway. I'll return to this later on. Note: The usual niche optimization for |
Follow-on after #5774. Correct the logic for calculating niches in enums. It's still not quite correct - number of niches depends on how many spare discriminant "slots" there are at *start or end* of the range, not in total. But this is closer to correct than it was - we now don't take into account whether enum variant payloads have niches or not, which is not relevant.
Fixes a bug with how we were calculating the size of enums when there are different padding on variants and there aren't enough niches. Now it aligns the largest variant size to the largest alignment before consuming niches.