-
Notifications
You must be signed in to change notification settings - Fork 13.5k
Layout::pad_to_align is infallible #66256
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
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.