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() {

`