CapacityHolder WIP · rust-lang/rust@8e6c148 (original) (raw)
`@@ -33,11 +33,33 @@ enum AllocInit {
`
33
33
`Zeroed,
`
34
34
`}
`
35
35
``
``
36
`+
pub trait CapacityHolder: Copy {
`
``
37
`+
fn as_usize(self) -> usize {
`
``
38
`+
if T::IS_ZST {
`
``
39
`+
usize::MAX
`
``
40
`+
} else {
`
``
41
`+
Self::as_usize_raw(self)
`
``
42
`+
}
`
``
43
`+
}
`
``
44
`+
fn as_usize_raw(c: Self) -> usize;
`
``
45
`+
}
`
``
46
+
``
47
`+
#[derive(Copy, Clone)]
`
``
48
`+
pub struct FixedCapacity;
`
``
49
`+
impl CapacityHolder for FixedCapacity {
`
``
50
`+
fn as_usize_raw(_: Self) -> usize { N }
`
``
51
`+
}
`
``
52
+
36
53
`#[repr(transparent)]
`
``
54
`+
#[derive(Copy, Clone)]
`
37
55
`#[cfg_attr(target_pointer_width = "16", rustc_layout_scalar_valid_range_end(0x7fff))]
`
38
56
`#[cfg_attr(target_pointer_width = "32", rustc_layout_scalar_valid_range_end(0x7fff_ffff))]
`
39
57
`#[cfg_attr(target_pointer_width = "64", rustc_layout_scalar_valid_range_end(0x7fff_ffff_ffff_ffff))]
`
40
``
`-
struct Cap(usize);
`
``
58
`+
pub(crate) struct Cap(usize);
`
``
59
+
``
60
`+
impl CapacityHolder for Cap {
`
``
61
`+
fn as_usize_raw(c: Self) -> usize { c.0 }
`
``
62
`+
}
`
41
63
``
42
64
`impl Cap {
`
43
65
`const ZERO: Cap = unsafe { Cap(0) };
`
`@@ -66,14 +88,9 @@ impl Cap {
`
66
88
`` /// usize::MAX. This means that you need to be careful when round-tripping this type with a
``
67
89
`` /// Box<[T]>, since capacity() won't yield the length.
``
68
90
`#[allow(missing_debug_implementations)]
`
69
``
`-
pub(crate) struct RawVec<T, A: Allocator = Global> {
`
``
91
`+
pub(crate) struct RawVec<T, A: Allocator = Global, C: CapacityHolder = Cap> {
`
70
92
`ptr: Unique,
`
71
``
`` -
/// Never used for ZSTs; it's capacity()'s responsibility to return usize::MAX in that case.
``
72
``
`-
///
`
73
``
`-
/// # Safety
`
74
``
`-
///
`
75
``
`` -
/// cap must be in the 0..=isize::MAX range.
``
76
``
`-
cap: Cap,
`
``
93
`+
cap: C,
`
77
94
`alloc: A,
`
78
95
`}
`
79
96
``
`@@ -129,6 +146,27 @@ impl RawVec<T, Global> {
`
129
146
`}
`
130
147
`}
`
131
148
``
``
149
`+
impl<T, A: Allocator, C: CapacityHolder> RawVec<T, A, C> {
`
``
150
`+
fn current_memory(&self) -> Option<(NonNull, Layout)> {
`
``
151
`+
let cap = self.cap.as_usize::();
`
``
152
`+
if T::IS_ZST || cap == 0 {
`
``
153
`+
None
`
``
154
`+
} else {
`
``
155
`+
// We could use Layout::array here which ensures the absence of isize and usize overflows
`
``
156
`+
// and could hypothetically handle differences between stride and size, but this memory
`
``
157
`+
// has already been allocated so we know it can't overflow and currently Rust does not
`
``
158
`+
// support such types. So we can do better by skipping some checks and avoid an unwrap.
`
``
159
`+
const { assert!(mem::size_of::() % mem::align_of::() == 0) };
`
``
160
`+
unsafe {
`
``
161
`+
let align = mem::align_of::();
`
``
162
`+
let size = mem::size_of::().unchecked_mul(cap);
`
``
163
`+
let layout = Layout::from_size_align_unchecked(size, align);
`
``
164
`+
Some((self.ptr.cast().into(), layout))
`
``
165
`+
}
`
``
166
`+
}
`
``
167
`+
}
`
``
168
`+
}
`
``
169
+
132
170
`impl<T, A: Allocator> RawVec<T, A> {
`
133
171
`// Tiny Vecs are dumb. Skip to:
`
134
172
`// - 8 if the element size is 1, because any heap allocators is likely
`
`@@ -296,24 +334,6 @@ impl<T, A: Allocator> RawVec<T, A> {
`
296
334
`&self.alloc
`
297
335
`}
`
298
336
``
299
``
`-
fn current_memory(&self) -> Option<(NonNull, Layout)> {
`
300
``
`-
if T::IS_ZST || self.cap.0 == 0 {
`
301
``
`-
None
`
302
``
`-
} else {
`
303
``
`-
// We could use Layout::array here which ensures the absence of isize and usize overflows
`
304
``
`-
// and could hypothetically handle differences between stride and size, but this memory
`
305
``
`-
// has already been allocated so we know it can't overflow and currently Rust does not
`
306
``
`-
// support such types. So we can do better by skipping some checks and avoid an unwrap.
`
307
``
`-
const { assert!(mem::size_of::() % mem::align_of::() == 0) };
`
308
``
`-
unsafe {
`
309
``
`-
let align = mem::align_of::();
`
310
``
`-
let size = mem::size_of::().unchecked_mul(self.cap.0);
`
311
``
`-
let layout = Layout::from_size_align_unchecked(size, align);
`
312
``
`-
Some((self.ptr.cast().into(), layout))
`
313
``
`-
}
`
314
``
`-
}
`
315
``
`-
}
`
316
``
-
317
337
`` /// Ensures that the buffer contains at least enough space to hold `len +
``
318
338
`` /// additional` elements. If it doesn't already have enough capacity, will
``
319
339
`/// reallocate enough space plus comfortable slack space to get amortized
`
`@@ -576,7 +596,7 @@ where
`
576
596
` memory.map_err(|_| AllocError { layout: new_layout, non_exhaustive: () }.into())
`
577
597
`}
`
578
598
``
579
``
`-
unsafe impl<#[may_dangle] T, A: Allocator> Drop for RawVec<T, A> {
`
``
599
`+
unsafe impl<#[may_dangle] T, A: Allocator, C: CapacityHolder> Drop for RawVec<T, A, C> {
`
580
600
`` /// Frees the memory owned by the RawVec without trying to drop its contents.
``
581
601
`fn drop(&mut self) {
`
582
602
`if let Some((ptr, layout)) = self.current_memory() {
`