-
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
Layout::pad_to_align is infallible #66256
Conversation
(rust_highfive has picked a reviewer for you, use r? to override) |
The job Click to expand the log.
I'm a bot! I can only do what humans tell me to, so if this was not helpful or you have suggestions for improvements, please ping or otherwise contact |
Ping from triage |
r? @RalfJung |
Pinging again from triage |
Wrong person pinged. ;) |
Removed the I still maintain that the invariants checked in |
.ok_or(LayoutErr { private: () })?; | ||
// This cannot overflow: it is an invariant of Layout that | ||
// > `size`, when rounded up to the nearest multiple of `align`, | ||
// > must not overflow (i.e., the rounded value must be less than |
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.
"less than"? not "less or equal to"?
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.
This is just quoted from from_size_align
, though I agree lte is probably the correct bound here:
Lines 55 to 94 in 6773064
/// Constructs a `Layout` from a given `size` and `align`, | |
/// or returns `LayoutErr` if either of the following conditions | |
/// are not met: | |
/// | |
/// * `align` must not be zero, | |
/// | |
/// * `align` must be a power of two, | |
/// | |
/// * `size`, when rounded up to the nearest multiple of `align`, | |
/// must not overflow (i.e., the rounded value must be less than | |
/// `usize::MAX`). | |
#[stable(feature = "alloc_layout", since = "1.28.0")] | |
#[inline] | |
pub fn from_size_align(size: usize, align: usize) -> Result<Self, LayoutErr> { | |
if !align.is_power_of_two() { | |
return Err(LayoutErr { private: () }); | |
} | |
// (power-of-two implies align != 0.) | |
// Rounded up size is: | |
// size_rounded_up = (size + align - 1) & !(align - 1); | |
// | |
// We know from above that align != 0. If adding (align - 1) | |
// does not overflow, then rounding up will be fine. | |
// | |
// Conversely, &-masking with !(align - 1) will subtract off | |
// only low-order-bits. Thus if overflow occurs with the sum, | |
// the &-mask cannot subtract enough to undo that overflow. | |
// | |
// Above implies that checking for summation overflow is both | |
// necessary and sufficient. | |
if size > usize::MAX - (align - 1) { | |
return Err(LayoutErr { private: () }); | |
} | |
unsafe { | |
Ok(Layout::from_size_align_unchecked(size, align)) | |
} | |
} |
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.
Looks like this goes back all the way to #42313.... @pnkfelix @alexcrichton do you remember why you made this "less than", not "less or equal"?
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.
usize::MAX
isn't a multiple of two so if you round up to the nearest multiple of align
you're by definition not equal to usize::MAX
nor usize::MAX - 1
, so I don't think that exact phrasing matters here. If I'm wrong then no, I have no recollection of why this one phrase is buried in documentation landed 2 years ago.
Ping from Triage: @CAD97 any updates? |
I've addressed review comments, I believe we're just waiting on review from someone more familiar with this part of the stdlib. |
That's a preeexisting vagueness though, so I think we can @bors r+ this. |
📌 Commit d1e53da has been approved by |
Layout::pad_to_align is infallible As per [this comment](#55724 (comment)) (cc @glandium). > Per https://github.com/rust-lang/rust/blob/eb981a1/src/libcore/alloc.rs#L63-L65, `layout.size()` is always <= `usize::MAX - (layout.align() - 1)`. > > Which means: > > * The maximum value `layout.size()` can have is already aligned for `layout.align()` (`layout.align()` being a power of two, `usize::MAX - (layout.align() - 1)` is a multiple of `layout.align()`) > * Incidentally, any value smaller than that maximum value will align at most to that maximum value. > > IOW, `pad_to_align` can not return `Err(LayoutErr)`, except for the layout not respecting its invariants, but we shouldn't care about that. This PR makes `pad_to_align` return `Layout` directly, representing the fact that it cannot fail.
☀️ Test successful - checks-azure |
Updated to `nightly-x86_64-apple-darwin updated - rustc 1.41.0-nightly (19bd93467 2019-12-18)`. It includes rust-lang/rust#66256, which removed the `unwrap` on `align_to_pad`.
As per this comment (cc @glandium).
This PR makes
pad_to_align
returnLayout
directly, representing the fact that it cannot fail.