Skip to content

Commit 205249c

Browse files
committed
Cleanup
1 parent 3bf26f8 commit 205249c

File tree

2 files changed

+46
-102
lines changed

2 files changed

+46
-102
lines changed

library/alloc/src/raw_vec.rs

+39-102
Original file line numberDiff line numberDiff line change
@@ -83,59 +83,11 @@ struct MonoRawVec<A: Allocator = Global> {
8383
}
8484

8585
#[inline]
86-
const fn max_size_for_align(align: usize) -> usize {
87-
// (power-of-two implies align != 0.)
88-
89-
// Rounded up size is:
90-
// size_rounded_up = (size + align - 1) & !(align - 1);
91-
//
92-
// We know from above that align != 0. If adding (align - 1)
93-
// does not overflow, then rounding up will be fine.
94-
//
95-
// Conversely, &-masking with !(align - 1) will subtract off
96-
// only low-order-bits. Thus if overflow occurs with the sum,
97-
// the &-mask cannot subtract enough to undo that overflow.
98-
//
99-
// Above implies that checking for summation overflow is both
100-
// necessary and sufficient.
101-
isize::MAX as usize - (align - 1)
102-
}
103-
104-
#[inline]
105-
fn layout_array(cap: usize, size: usize, align: usize) -> Result<Layout, TryReserveError> {
106-
// We need to check two things about the size:
107-
// - That the total size won't overflow a `usize`, and
108-
// - That the total size still fits in an `isize`.
109-
// By using division we can check them both with a single threshold.
110-
// That'd usually be a bad idea, but thankfully here the element size
111-
// and alignment are constants, so the compiler will fold all of it.
112-
if size != 0 && cap > max_size_for_align(align) / size {
113-
return Err(CapacityOverflow.into());
114-
}
115-
116-
// SAFETY: We just checked that we won't overflow `usize` when we multiply.
117-
// This is a useless hint inside this function, but after inlining this helps
118-
// deduplicate checks for whether the overall capacity is zero (e.g., in RawVec's
119-
// allocation path) before/after this multiplication.
120-
let array_size = unsafe { size.unchecked_mul(cap) };
121-
122-
// SAFETY: We just checked above that the `array_size` will not
123-
// exceed `isize::MAX` even when rounded up to the alignment.
124-
// And `Alignment` guarantees it's a power of two.
125-
unsafe { Ok(Layout::from_size_align_unchecked(array_size, align)) }
86+
fn layout_array(cap: usize, elem_layout: Layout) -> Result<Layout, TryReserveError> {
87+
elem_layout.repeat(cap).map(|(layout, _pad)| layout).map_err(|_| CapacityOverflow.into())
12688
}
12789

12890
impl<A: Allocator> MonoRawVec<A> {
129-
#[inline]
130-
fn ptr<T>(&self) -> *mut T {
131-
unsafe { core::mem::transmute(self.ptr) }
132-
}
133-
134-
#[inline]
135-
fn non_null<T>(&self) -> NonNull<T> {
136-
unsafe { core::mem::transmute(self.ptr) }
137-
}
138-
13991
/// # Safety:
14092
///
14193
/// `cap` must not exceed `isize::MAX`.
@@ -149,8 +101,8 @@ impl<A: Allocator> MonoRawVec<A> {
149101
}
150102

151103
#[inline]
152-
fn current_memory(&self, size: usize, align: usize) -> Option<(NonNull<u8>, Layout)> {
153-
if size == 0 || self.cap.0 == 0 {
104+
fn current_memory(&self, elem_layout: Layout) -> Option<(NonNull<u8>, Layout)> {
105+
if elem_layout.size() == 0 || self.cap.0 == 0 {
154106
return None;
155107
}
156108

@@ -159,21 +111,19 @@ impl<A: Allocator> MonoRawVec<A> {
159111
// has already been allocated so we know it can't overflow and currently Rust does not
160112
// support such types. So we can do better by skipping some checks and avoid an unwrap.
161113
unsafe {
162-
let size = size.unchecked_mul(self.cap.0);
163-
let layout = Layout::from_size_align_unchecked(size, align);
114+
let alloc_size = elem_layout.size().unchecked_mul(self.cap.0);
115+
let layout = Layout::from_size_align_unchecked(alloc_size, elem_layout.align());
164116
Some((self.ptr.into(), layout))
165117
}
166118
}
167119

168-
#[inline]
169120
fn grow_amortized(
170121
&mut self,
171122
len: usize,
172123
additional: usize,
173-
size: usize,
174-
align: usize,
124+
elem_layout: Layout,
175125
) -> Result<(), TryReserveError> {
176-
if size == 0 {
126+
if elem_layout.size() == 0 {
177127
// Since we return a capacity of `usize::MAX` when `elem_size` is
178128
// 0, getting to here necessarily means the `RawVec` is overfull.
179129
return Err(CapacityOverflow.into());
@@ -185,36 +135,34 @@ impl<A: Allocator> MonoRawVec<A> {
185135
// This guarantees exponential growth. The doubling cannot overflow
186136
// because `cap <= isize::MAX` and the type of `cap` is `usize`.
187137
let cap = cmp::max(self.cap.0 * 2, required_cap);
188-
let cap = cmp::max(min_non_zero_cap(size), cap);
138+
let cap = cmp::max(min_non_zero_cap(elem_layout.size()), cap);
189139

190-
let new_layout = layout_array(cap, size, align)?;
140+
let new_layout = layout_array(cap, elem_layout)?;
191141

192142
// `finish_grow` is non-generic over `T`.
193-
let ptr = finish_grow(new_layout, self.current_memory(size, align), &mut self.alloc)?;
143+
let ptr = finish_grow(new_layout, self.current_memory(elem_layout), &mut self.alloc)?;
194144
// SAFETY: finish_grow would have resulted in a capacity overflow if we tried to allocate more than isize::MAX items
195145
unsafe { self.set_ptr_and_cap(ptr, cap) };
196146
Ok(())
197147
}
198148

199-
#[inline]
200149
fn grow_exact(
201150
&mut self,
202151
len: usize,
203152
additional: usize,
204-
size: usize,
205-
align: usize,
153+
elem_layout: Layout,
206154
) -> Result<(), TryReserveError> {
207-
if size == 0 {
155+
if elem_layout.size() == 0 {
208156
// Since we return a capacity of `usize::MAX` when the type size is
209157
// 0, getting to here necessarily means the `RawVec` is overfull.
210158
return Err(CapacityOverflow.into());
211159
}
212160

213161
let cap = len.checked_add(additional).ok_or(CapacityOverflow)?;
214-
let new_layout = layout_array(cap, size, align)?;
162+
let new_layout = layout_array(cap, elem_layout)?;
215163

216164
// `finish_grow` is non-generic over `T`.
217-
let ptr = finish_grow(new_layout, self.current_memory(size, align), &mut self.alloc)?;
165+
let ptr = finish_grow(new_layout, self.current_memory(elem_layout), &mut self.alloc)?;
218166
// SAFETY: finish_grow would have resulted in a capacity overflow if we tried to allocate more than isize::MAX items
219167
unsafe {
220168
self.set_ptr_and_cap(ptr, cap);
@@ -223,27 +171,27 @@ impl<A: Allocator> MonoRawVec<A> {
223171
}
224172

225173
#[cfg(not(no_global_oom_handling))]
226-
#[inline]
227-
fn shrink(&mut self, cap: usize, size: usize, align: usize) -> Result<(), TryReserveError> {
228-
if size > 0 {
174+
fn shrink(&mut self, cap: usize, elem_layout: Layout) -> Result<(), TryReserveError> {
175+
if elem_layout.size() > 0 {
229176
assert!(cap <= self.cap.0, "Tried to shrink to a larger capacity");
230177
}
231178

232179
let (ptr, layout) =
233-
if let Some(mem) = self.current_memory(size, align) { mem } else { return Ok(()) };
180+
if let Some(mem) = self.current_memory(elem_layout) { mem } else { return Ok(()) };
234181

235182
// If shrinking to 0, deallocate the buffer. We don't reach this point
236183
// for the T::IS_ZST case since current_memory() will have returned
237184
// None.
238185
if cap == 0 {
239186
unsafe { self.alloc.deallocate(ptr, layout) };
240-
self.ptr = unsafe { Unique::new_unchecked(ptr::without_provenance_mut(align)) };
187+
self.ptr =
188+
unsafe { Unique::new_unchecked(ptr::without_provenance_mut(elem_layout.align())) };
241189
self.cap = Cap::ZERO;
242190
} else {
243191
let ptr = unsafe {
244192
// `Layout::array` cannot overflow here because it would have
245193
// overflowed earlier when capacity was larger.
246-
let new_size = size.unchecked_mul(cap);
194+
let new_size = elem_layout.size().unchecked_mul(cap);
247195
let new_layout = Layout::from_size_align_unchecked(new_size, layout.align());
248196
self.alloc
249197
.shrink(ptr, layout, new_layout)
@@ -264,21 +212,19 @@ impl<A: Allocator> MonoRawVec<A> {
264212
Self { ptr, cap: Cap::ZERO, alloc }
265213
}
266214

267-
#[inline]
268215
fn try_allocate_in(
269216
capacity: usize,
270217
init: AllocInit,
271218
alloc: A,
272-
size: usize,
273-
align: usize,
219+
elem_layout: Layout,
274220
) -> Result<Self, TryReserveError> {
275221
// Don't allocate here because `Drop` will not deallocate when `capacity` is 0.
276-
if size == 0 || capacity == 0 {
277-
Ok(Self::new_in(alloc, align))
222+
if elem_layout.size() == 0 || capacity == 0 {
223+
Ok(Self::new_in(alloc, elem_layout.align()))
278224
} else {
279225
// We avoid `unwrap_or_else` here because it bloats the amount of
280226
// LLVM IR generated.
281-
let layout = match layout_array(capacity, size, align) {
227+
let layout = match layout_array(capacity, elem_layout) {
282228
Ok(layout) => layout,
283229
Err(_) => return Err(CapacityOverflow.into()),
284230
};
@@ -304,10 +250,8 @@ impl<A: Allocator> MonoRawVec<A> {
304250
}
305251
}
306252

307-
#[inline]
308-
#[rustc_no_mir_inline]
309-
fn drop_if_needed(&mut self, size: usize, align: usize) {
310-
if let Some((ptr, layout)) = self.current_memory(size, align) {
253+
fn drop_if_needed(&mut self, elem_layout: Layout) {
254+
if let Some((ptr, layout)) = self.current_memory(elem_layout) {
311255
unsafe { self.alloc.deallocate(ptr, layout) }
312256
}
313257
}
@@ -449,13 +393,7 @@ impl<T, A: Allocator> RawVec<T, A> {
449393
init: AllocInit,
450394
alloc: A,
451395
) -> Result<Self, TryReserveError> {
452-
match MonoRawVec::try_allocate_in(
453-
capacity,
454-
init,
455-
alloc,
456-
mem::size_of::<T>(),
457-
mem::align_of::<T>(),
458-
) {
396+
match MonoRawVec::try_allocate_in(capacity, init, alloc, T::LAYOUT) {
459397
Ok(inner) => Ok(Self { inner, _phantom: PhantomData }),
460398
Err(e) => Err(e),
461399
}
@@ -499,23 +437,24 @@ impl<T, A: Allocator> RawVec<T, A> {
499437
/// be careful.
500438
#[inline]
501439
pub fn ptr(&self) -> *mut T {
502-
self.inner.ptr()
440+
unsafe { core::mem::transmute(self.inner.ptr) }
503441
}
504442

505443
#[inline]
506444
pub fn non_null(&self) -> NonNull<T> {
507-
self.inner.non_null()
445+
unsafe { core::mem::transmute(self.inner.ptr) }
508446
}
509447

510448
/// Gets the capacity of the allocation.
511449
///
512450
/// This will always be `usize::MAX` if `T` is zero-sized.
513-
#[inline(always)]
451+
#[inline]
514452
pub fn capacity(&self) -> usize {
515453
if T::IS_ZST { usize::MAX } else { self.inner.cap.0 }
516454
}
517455

518456
/// Returns a shared reference to the allocator backing this `RawVec`.
457+
#[inline]
519458
pub fn allocator(&self) -> &A {
520459
&self.inner.alloc
521460
}
@@ -645,6 +584,7 @@ impl<T, A: Allocator> RawVec<T, A> {
645584
impl<T, A: Allocator> RawVec<T, A> {
646585
/// Returns if the buffer needs to grow to fulfill the needed extra capacity.
647586
/// Mainly used to make inlining reserve-calls possible without inlining `grow`.
587+
#[inline]
648588
fn needs_to_grow(&self, len: usize, additional: usize) -> bool {
649589
additional > self.capacity().wrapping_sub(len)
650590
}
@@ -656,27 +596,25 @@ impl<T, A: Allocator> RawVec<T, A> {
656596
// so that all of the code that depends on `T` is within it, while as much
657597
// of the code that doesn't depend on `T` as possible is in functions that
658598
// are non-generic over `T`.
599+
#[inline]
659600
fn grow_amortized(&mut self, len: usize, additional: usize) -> Result<(), TryReserveError> {
660-
const { assert!(mem::size_of::<T>() % mem::align_of::<T>() == 0) };
661-
662601
// This is ensured by the calling contexts.
663602
debug_assert!(additional > 0);
664603

665-
self.inner.grow_amortized(len, additional, mem::size_of::<T>(), mem::align_of::<T>())
604+
self.inner.grow_amortized(len, additional, T::LAYOUT)
666605
}
667606

668607
// The constraints on this method are much the same as those on
669608
// `grow_amortized`, but this method is usually instantiated less often so
670609
// it's less critical.
610+
#[inline]
671611
fn grow_exact(&mut self, len: usize, additional: usize) -> Result<(), TryReserveError> {
672-
const { assert!(mem::size_of::<T>() % mem::align_of::<T>() == 0) };
673-
self.inner.grow_exact(len, additional, mem::size_of::<T>(), mem::align_of::<T>())
612+
self.inner.grow_exact(len, additional, T::LAYOUT)
674613
}
675614

676615
#[cfg(not(no_global_oom_handling))]
677616
fn shrink(&mut self, cap: usize) -> Result<(), TryReserveError> {
678-
const { assert!(mem::size_of::<T>() % mem::align_of::<T>() == 0) };
679-
self.inner.shrink(cap, mem::size_of::<T>(), mem::align_of::<T>())
617+
self.inner.shrink(cap, T::LAYOUT)
680618
}
681619
}
682620

@@ -712,8 +650,7 @@ where
712650
unsafe impl<#[may_dangle] T, A: Allocator> Drop for RawVec<T, A> {
713651
/// Frees the memory owned by the `RawVec` *without* trying to drop its contents.
714652
fn drop(&mut self) {
715-
const { assert!(mem::size_of::<T>() % mem::align_of::<T>() == 0) };
716-
self.inner.drop_if_needed(mem::size_of::<T>(), mem::align_of::<T>());
653+
self.inner.drop_if_needed(T::LAYOUT);
717654
}
718655
}
719656

library/core/src/mem/mod.rs

+7
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
66
#![stable(feature = "rust1", since = "1.0.0")]
77

8+
use crate::alloc::Layout;
89
use crate::clone;
910
use crate::cmp;
1011
use crate::fmt;
@@ -1235,6 +1236,12 @@ pub trait SizedTypeProperties: Sized {
12351236
#[doc(hidden)]
12361237
#[unstable(feature = "sized_type_properties", issue = "none")]
12371238
const IS_ZST: bool = size_of::<Self>() == 0;
1239+
1240+
#[doc(hidden)]
1241+
#[unstable(feature = "sized_type_properties", issue = "none")]
1242+
const LAYOUT: Layout =
1243+
// SAFETY: By construction
1244+
unsafe { Layout::from_size_align_unchecked(size_of::<Self>(), align_of::<Self>()) };
12381245
}
12391246
#[doc(hidden)]
12401247
#[unstable(feature = "sized_type_properties", issue = "none")]

0 commit comments

Comments
 (0)