-
Notifications
You must be signed in to change notification settings - Fork 13.7k
Allow borrowing array elements from packed structs with ABI align <= packed align #145419
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
base: master
Are you sure you want to change the base?
Conversation
- Add fallback mechanism in is_disaligned() when layout computation fails - Handle TooGeneric errors by computing element alignment from type structure - Fix packed-array-const-generic.rs test to pass compilation - Resolves issue where const generic parameters couldn't be resolved during alignment checks
r? @SparrowLii rustbot has assigned @SparrowLii. Use |
This comment has been minimized.
This comment has been minimized.
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.
Hey, I’m the bug reporter. Just what I noticed on a first glance.
Ok(normalized) => normalized, | ||
Err(_) => { | ||
// If normalization fails, fall back to the original type | ||
ty |
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.
why? it feels a lot safer to conservatively return true
here, same as when layout_of
fails
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.
still relevant
// For const generic arrays like [u8; CAP], we can make a reasonable assumption | ||
// about their alignment based on the element type. |
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.
we're not making a reasonable assumption. Their layout literally only depend son the layout of their element type, doesn't it?
Getting this right is soundness critical, so we need to be confident about that we don#t introduce false negatives.
Also, please rename this function to is_potentially_disaligned
, to clarify that it's allowed to return false positives, but not false nnegatives
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.
We use "misaligned" elsewhere in the compiler, maybe let's go with that instead of "disaligned" (which I never saw/heard before).
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.
also still relevant
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.
Thanks for the detailed feedback!
I agree with the soundness concern and with using the term “misaligned”.
I will:
- rename the function to
is_potentially_misaligned
and update call sites/docs to clarify that it may return false positives but must not return false negatives (soundness-critical), - avoid relaxing the check when
layout_of(ty)
fails in general.
To still address the motivating case without introducing false negatives, I’ll only add a very small, layout-free special-case:
when ty.kind()
is Array(elem, _)
and elem
is u8
or i8
(which have ABI alignment 1 by definition, independent of the array length), we treat the borrow as not potentially misaligned. All other cases remain conservative and return true
when layout_of(ty)
fails.
This fixes the [u8; CAP]
packed-struct case while keeping the function strictly conservative for any type whose ABI alignment could exceed the packed alignment.
If you’d prefer the even stricter variant (no special-casing at all), I can drop the exception and keep returning true
on layout_of
failure across the board.
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 think ignoring the length and only checking the argument is fine. My issue was with the comment, not the behavior. We already guarantee that the alignment constraints are equal:
you can get a &T
out of an &[T]
, so [T]
must have stronger requirements than &T
you can get a &[T]
from a &T
via std::array::from_ref
, so T
must have stronger requirements than &[T]
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.
Thanks! I’ve updated the comment to formally justify that align([T]) == align(T),
using the two directions you mentioned (&[T] -> &T
and std::array::from_ref(&T)
).
Behavior remains unchanged: we only consider the element type’s ABI alignment and
ignore the array length.
… clarity; Unified to ty::Array(element_ty, _) | ty::Slice(element_ty) => …; Modify Chinese comments to English comments
Some changes occurred to MIR optimizations cc @rust-lang/wg-mir-opt |
Fixed:
Thanks |
I've updated the PR as requested (renamed function, updated comment, removed special-casing). Just let me know if further adjustments are needed. |
// Only allow u8 and i8 arrays when layout computation fails | ||
// Other types are conservatively assumed to be misaligned | ||
match element_ty.kind() { |
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.
properly compute the of the element_ty
here, limiting it to only u8 and i8 feels unnecessary 🤔
#![allow(dead_code)] | ||
|
||
#[repr(C, packed)] | ||
struct PascalStringI8<const CAP: usize> { |
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.
please merge this into a single test and use generic-length
instead of const-generic
in the file name
cc @rust-lang/lang this causes us to no longer lint "due to a borrow of a potentially misaligned field" when borrowing from a I feel like this may be fine without an FCP as it seems like a small enough change 🤷 |
Thanks for the ping. Specifically, we were giving a hard error here, so allowing this is a stabilization. Since we're relatively caught up, it'll be as fast for us to FCP this as to decide not to do so, and lately we've generally been leaning toward FCPing everything that we technically should. We could waive our 10-day period, but it doesn't seem likely that'll affect what release this lands in, so let's just, in the normal way... |
Team member @traviscross has proposed to merge this. The next step is review by the rest of the tagged team members: Concerns:
Once a majority of reviewers approve (and at most 2 approvals are outstanding), this will enter its final comment period. If you spot a major issue that hasn't been raised at any point in this process, please speak up! cc @rust-lang/lang-advisors: FCP proposed for lang, please feel free to register concerns. |
Oh, yeah, thought this was a lint 👍 an FCP seems appropriate |
Yeah, if reverting it would be a breaking change, we've got to FCP the initial merge. 👍 to the general change of being smarter about alignment where possible. @rfcbot reviewed That said, I think we need the rules written up more. Since this is a hard error, it's something that would go into a spec so that other things could make the same checks. @rfcbot concern exact-rules-list Looking at the PR, it looks like it's actually only It reminds me of the experiments that have been done towards having niches for references, which wanted a query for alignment and size (or a sound approximation thereof) that would work even in cases where the full layout couldn't be calculated. This seems like it would like to have the same kind of thing, rather than adding a bunch of ad-hoc layout knowledge into this specific check. |
This comment has been minimized.
This comment has been minimized.
Thanks for the detailed feedback! I’ve updated the PR with the following:
I’ve also drafted the exact rules in the PR description and opened a Reference PR |
Fixes #145376
Summary
This PR fixes a false positive E0793 ("reference to packed field is unaligned")
when borrowing from a
#[repr(C, packed)]
struct field whose type is a const-generic arraywith an element type that has ABI alignment <= the struct's packed alignment.
Example before this change: