Repository navigation
NonEmptyLayout - #163739
NonEmptyLayout#163739clarfonthey wants to merge 1 commit into
NonEmptyLayout#163739Conversation
|
|
bb5d997 to
780ffd0
Compare
|
Was there an ACP for this? It seems like a decently big thing if we ever want to stabilise it (understandable if we want to keep it internal though, i see the rationale there). in particular regarding extending i could see the case for extra provided methods on the base trait to use this. little worried about vtable size there but would need a benchmark |
|
There was explicitly no ACP for this, since I mostly just wanted to see how not-awful this would be to implement. In terms of actually making allocators that use it, we definitely wanna have some kind of ACP, since the motivation here is basically in this thread: #t-libs/wg-allocators > Are we sure about zero-sized allocations? Essentially, it might be useful to define specifically the exact behaviour of |
This comment has been minimized.
This comment has been minimized.
780ffd0 to
b334e28
Compare
|
The job Click to see the possible cause of the failure (guessed by this bot) |
|
|
||
| /// Layout of a *non-empty* block of memory. | ||
| /// | ||
| /// This is equivalent to [`Layout`], but with the added restriction that the |
There was a problem hiding this comment.
truncated sentence
| } | ||
|
|
||
| #[inline] | ||
| const fn is_size_align_valid(size: usize, align: usize) -> bool { |
There was a problem hiding this comment.
This can be made branchless via
pub const fn is_size_align_valid(size: usize, align: usize) -> bool {
let Some(alignment) = Alignment::new(align) else { return false };
Self::is_nonzero_size_alignment_valid(size, alignment)
}
const fn is_nonzero_size_alignment_valid(size: usize, alignment: Alignment) -> bool {
size.wrapping_sub(1) < max_size_for_alignment(alignment)
}There was a problem hiding this comment.
If you want to optimize the case where size is known to be non-zero,
const fn is_nonzero_size_alignment_valid(size: usize, alignment: Alignment) -> bool {
if is_val_statically_known(size > 0) {
size <= max_size_for_alignment(alignment)
} else {
size.wrapping_sub(1) < max_size_for_alignment(alignment)
}
}| let Ok(result) = (if let Some(k) = n.checked_sub(1) { | ||
| let Ok(repeated) = padded.repeat_packed(k) else { | ||
| return Err(LayoutError); | ||
| }; | ||
| repeated.extend_packed(self.get()) | ||
| } else { | ||
| debug_assert!(n == 0); | ||
| self.repeat_packed(0) | ||
| }) else { | ||
| return Err(LayoutError); | ||
| }; |
There was a problem hiding this comment.
This is super confusing to read, can the if let Some(k) = ... part be factored out into a separate variable?
Also, self.repeat_packed(0) is guaranteed to error, so that branch could just be return Err(LayoutError)
There was a problem hiding this comment.
Maybe this instead?
| let Ok(result) = (if let Some(k) = n.checked_sub(1) { | |
| let Ok(repeated) = padded.repeat_packed(k) else { | |
| return Err(LayoutError); | |
| }; | |
| repeated.extend_packed(self.get()) | |
| } else { | |
| debug_assert!(n == 0); | |
| self.repeat_packed(0) | |
| }) else { | |
| return Err(LayoutError); | |
| }; | |
| let result = if let Some(k) = n.checked_sub(1) { | |
| let Ok(repeated) = padded.repeat_packed(k) else { | |
| return Err(LayoutError); | |
| }; | |
| let Ok(result) = repeated.extend_packed(self.get()) else { | |
| return Err(LayoutError); | |
| }; | |
| result | |
| } else { | |
| debug_assert!(n == 0); | |
| return Err(LayoutError); | |
| }; |
Notes:
NonEmptyLayoutversusNonZeroLayoutversusNonZero<Layout>later.LayoutandNonEmptyLayoutexplicitlyrepr(C)or something to allow literally transmuting fromLayouttoOption<NonEmptyLayout>. I didn't do this here because I know thatrepr(C)might cause other undesirable side effects.new::<T>()uses a const assertion to verify thatTis non-zero-sized butnew_for(&val)returnsOption, with an unchecked variant. Is this the right approach?BoxandVecto avoid the ZST special-casing on allocations specifically (note: there will still be types that need special-casing, likeslice::Iter)r? nia-e (but I guess you can pass it to someone else if you want)