Skip to content

Commit 1dfff2e

Browse files
committed
Move to unchecked_sub as suggested by @the8472
Signed-off-by: Alex Saveau <[email protected]>
1 parent fdb7ada commit 1dfff2e

File tree

6 files changed

+96
-47
lines changed

6 files changed

+96
-47
lines changed

library/alloc/src/collections/vec_deque/mod.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -756,8 +756,8 @@ impl<T, A: Allocator> VecDeque<T, A> {
756756
let old_cap = self.capacity();
757757

758758
if new_cap > old_cap {
759-
self.buf.reserve_exact(self.len, additional);
760759
unsafe {
760+
self.buf.reserve_exact(self.len, additional);
761761
self.handle_capacity_increase(old_cap);
762762
}
763763
}
@@ -787,8 +787,8 @@ impl<T, A: Allocator> VecDeque<T, A> {
787787
if new_cap > old_cap {
788788
// we don't need to reserve_exact(), as the size doesn't have
789789
// to be a power of 2.
790-
self.buf.reserve(self.len, additional);
791790
unsafe {
791+
self.buf.reserve(self.len, additional);
792792
self.handle_capacity_increase(old_cap);
793793
}
794794
}
@@ -838,8 +838,8 @@ impl<T, A: Allocator> VecDeque<T, A> {
838838
let old_cap = self.capacity();
839839

840840
if new_cap > old_cap {
841-
self.buf.try_reserve_exact(self.len, additional)?;
842841
unsafe {
842+
self.buf.try_reserve_exact(self.len, additional)?;
843843
self.handle_capacity_increase(old_cap);
844844
}
845845
}
@@ -886,8 +886,8 @@ impl<T, A: Allocator> VecDeque<T, A> {
886886
let old_cap = self.capacity();
887887

888888
if new_cap > old_cap {
889-
self.buf.try_reserve(self.len, additional)?;
890889
unsafe {
890+
self.buf.try_reserve(self.len, additional)?;
891891
self.handle_capacity_increase(old_cap);
892892
}
893893
}

library/alloc/src/raw_vec.rs

+32-18
Original file line numberDiff line numberDiff line change
@@ -276,10 +276,6 @@ impl<T, A: Allocator> RawVec<T, A> {
276276
/// *O*(1) behavior. Will limit this behavior if it would needlessly cause
277277
/// itself to panic.
278278
///
279-
/// If `len` exceeds `self.capacity()`, this may fail to actually allocate
280-
/// the requested space. This is not really unsafe, but the unsafe
281-
/// code *you* write that relies on the behavior of this function may break.
282-
///
283279
/// This is ideal for implementing a bulk-push operation like `extend`.
284280
///
285281
/// # Panics
@@ -289,9 +285,13 @@ impl<T, A: Allocator> RawVec<T, A> {
289285
/// # Aborts
290286
///
291287
/// Aborts on OOM.
288+
///
289+
/// # Safety
290+
///
291+
/// `len` must be less than or equal to the capacity of this [`RawVec`].
292292
#[cfg(not(no_global_oom_handling))]
293293
#[inline]
294-
pub fn reserve(&mut self, len: usize, additional: usize) {
294+
pub unsafe fn reserve(&mut self, len: usize, additional: usize) {
295295
// Callers expect this function to be very cheap when there is already sufficient capacity.
296296
// Therefore, we move all the resizing and error-handling logic from grow_amortized and
297297
// handle_reserve behind a call, while making sure that this function is likely to be
@@ -305,7 +305,7 @@ impl<T, A: Allocator> RawVec<T, A> {
305305
handle_reserve(slf.grow_amortized(len, additional));
306306
}
307307

308-
if self.needs_to_grow(len, additional) {
308+
if unsafe { self.needs_to_grow(len, additional) } {
309309
do_reserve_and_handle(self, len, additional);
310310
}
311311
unsafe {
@@ -323,8 +323,16 @@ impl<T, A: Allocator> RawVec<T, A> {
323323
}
324324

325325
/// The same as `reserve`, but returns on errors instead of panicking or aborting.
326-
pub fn try_reserve(&mut self, len: usize, additional: usize) -> Result<(), TryReserveError> {
327-
if self.needs_to_grow(len, additional) {
326+
///
327+
/// # Safety
328+
///
329+
/// `len` must be less than or equal to the capacity of this [`RawVec`].
330+
pub unsafe fn try_reserve(
331+
&mut self,
332+
len: usize,
333+
additional: usize,
334+
) -> Result<(), TryReserveError> {
335+
if unsafe { self.needs_to_grow(len, additional) } {
328336
self.grow_amortized(len, additional)?;
329337
}
330338
unsafe {
@@ -340,29 +348,35 @@ impl<T, A: Allocator> RawVec<T, A> {
340348
/// exactly the amount of memory necessary, but in principle the allocator
341349
/// is free to give back more than we asked for.
342350
///
343-
/// If `len` exceeds `self.capacity()`, this may fail to actually allocate
344-
/// the requested space. This is not really unsafe, but the unsafe code
345-
/// *you* write that relies on the behavior of this function may break.
346-
///
347351
/// # Panics
348352
///
349353
/// Panics if the new capacity exceeds `isize::MAX` _bytes_.
350354
///
351355
/// # Aborts
352356
///
353357
/// Aborts on OOM.
358+
///
359+
/// # Safety
360+
///
361+
/// `len` must be less than or equal to the capacity of this [`RawVec`].
354362
#[cfg(not(no_global_oom_handling))]
355-
pub fn reserve_exact(&mut self, len: usize, additional: usize) {
356-
handle_reserve(self.try_reserve_exact(len, additional));
363+
pub unsafe fn reserve_exact(&mut self, len: usize, additional: usize) {
364+
unsafe {
365+
handle_reserve(self.try_reserve_exact(len, additional));
366+
}
357367
}
358368

359369
/// The same as `reserve_exact`, but returns on errors instead of panicking or aborting.
360-
pub fn try_reserve_exact(
370+
///
371+
/// # Safety
372+
///
373+
/// `len` must be less than or equal to the capacity of this [`RawVec`].
374+
pub unsafe fn try_reserve_exact(
361375
&mut self,
362376
len: usize,
363377
additional: usize,
364378
) -> Result<(), TryReserveError> {
365-
if self.needs_to_grow(len, additional) {
379+
if unsafe { self.needs_to_grow(len, additional) } {
366380
self.grow_exact(len, additional)?;
367381
}
368382
unsafe {
@@ -391,8 +405,8 @@ impl<T, A: Allocator> RawVec<T, A> {
391405
impl<T, A: Allocator> RawVec<T, A> {
392406
/// Returns if the buffer needs to grow to fulfill the needed extra capacity.
393407
/// Mainly used to make inlining reserve-calls possible without inlining `grow`.
394-
pub(crate) fn needs_to_grow(&self, len: usize, additional: usize) -> bool {
395-
additional > self.capacity().wrapping_sub(len)
408+
pub(crate) unsafe fn needs_to_grow(&self, len: usize, additional: usize) -> bool {
409+
unsafe { additional > self.capacity().unchecked_sub(len) }
396410
}
397411

398412
/// # Safety:

library/alloc/src/raw_vec/tests.rs

+37-16
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,10 @@ fn allocator_param() {
4343
let a = BoundedAlloc { fuel: Cell::new(500) };
4444
let mut v: RawVec<u8, _> = RawVec::with_capacity_in(50, a);
4545
assert_eq!(v.alloc.fuel.get(), 450);
46-
v.reserve(50, 150); // (causes a realloc, thus using 50 + 150 = 200 units of fuel)
46+
unsafe {
47+
// (causes a realloc, thus using 50 + 150 = 200 units of fuel)
48+
v.reserve(50, 150);
49+
}
4750
assert_eq!(v.alloc.fuel.get(), 250);
4851
}
4952

@@ -52,25 +55,35 @@ fn reserve_does_not_overallocate() {
5255
{
5356
let mut v: RawVec<u32> = RawVec::new();
5457
// First, `reserve` allocates like `reserve_exact`.
55-
v.reserve(0, 9);
58+
unsafe {
59+
v.reserve(0, 9);
60+
}
5661
assert_eq!(9, v.capacity());
5762
}
5863

5964
{
6065
let mut v: RawVec<u32> = RawVec::new();
61-
v.reserve(0, 7);
66+
unsafe {
67+
v.reserve(0, 7);
68+
}
6269
assert_eq!(7, v.capacity());
6370
// 97 is more than double of 7, so `reserve` should work
6471
// like `reserve_exact`.
65-
v.reserve(7, 90);
72+
unsafe {
73+
v.reserve(7, 90);
74+
}
6675
assert_eq!(97, v.capacity());
6776
}
6877

6978
{
7079
let mut v: RawVec<u32> = RawVec::new();
71-
v.reserve(0, 12);
80+
unsafe {
81+
v.reserve(0, 12);
82+
}
7283
assert_eq!(12, v.capacity());
73-
v.reserve(12, 3);
84+
unsafe {
85+
v.reserve(12, 3);
86+
}
7487
// 3 is less than half of 12, so `reserve` must grow
7588
// exponentially. At the time of writing this test grow
7689
// factor is 2, so new capacity is 24, however, grow factor
@@ -116,24 +129,28 @@ fn zst() {
116129

117130
// Check all these operations work as expected with zero-sized elements.
118131

119-
assert!(!v.needs_to_grow(100, usize::MAX - 100));
120-
assert!(v.needs_to_grow(101, usize::MAX - 100));
132+
assert!(unsafe { !v.needs_to_grow(100, usize::MAX - 100) });
133+
assert!(unsafe { v.needs_to_grow(101, usize::MAX - 100) });
121134
zst_sanity(&v);
122135

123-
v.reserve(100, usize::MAX - 100);
136+
unsafe {
137+
v.reserve(100, usize::MAX - 100);
138+
}
124139
//v.reserve(101, usize::MAX - 100); // panics, in `zst_reserve_panic` below
125140
zst_sanity(&v);
126141

127-
v.reserve_exact(100, usize::MAX - 100);
142+
unsafe {
143+
v.reserve_exact(100, usize::MAX - 100);
144+
}
128145
//v.reserve_exact(101, usize::MAX - 100); // panics, in `zst_reserve_exact_panic` below
129146
zst_sanity(&v);
130147

131-
assert_eq!(v.try_reserve(100, usize::MAX - 100), Ok(()));
132-
assert_eq!(v.try_reserve(101, usize::MAX - 100), cap_err);
148+
assert_eq!(unsafe { v.try_reserve(100, usize::MAX - 100) }, Ok(()));
149+
assert_eq!(unsafe { v.try_reserve(101, usize::MAX - 100) }, cap_err);
133150
zst_sanity(&v);
134151

135-
assert_eq!(v.try_reserve_exact(100, usize::MAX - 100), Ok(()));
136-
assert_eq!(v.try_reserve_exact(101, usize::MAX - 100), cap_err);
152+
assert_eq!(unsafe { v.try_reserve_exact(100, usize::MAX - 100) }, Ok(()));
153+
assert_eq!(unsafe { v.try_reserve_exact(101, usize::MAX - 100) }, cap_err);
137154
zst_sanity(&v);
138155

139156
assert_eq!(v.grow_amortized(100, usize::MAX - 100), cap_err);
@@ -151,7 +168,9 @@ fn zst_reserve_panic() {
151168
let mut v: RawVec<ZST> = RawVec::new();
152169
zst_sanity(&v);
153170

154-
v.reserve(101, usize::MAX - 100);
171+
unsafe {
172+
v.reserve(101, usize::MAX - 100);
173+
}
155174
}
156175

157176
#[test]
@@ -160,7 +179,9 @@ fn zst_reserve_exact_panic() {
160179
let mut v: RawVec<ZST> = RawVec::new();
161180
zst_sanity(&v);
162181

163-
v.reserve_exact(101, usize::MAX - 100);
182+
unsafe {
183+
v.reserve_exact(101, usize::MAX - 100);
184+
}
164185
}
165186

166187
#[test]

library/alloc/src/string.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -1152,7 +1152,7 @@ impl String {
11521152
self.vec.reserve(additional);
11531153
unsafe {
11541154
// Inform the optimizer that the reservation has succeeded or wasn't needed
1155-
intrinsics::assume(additional <= self.capacity().wrapping_sub(self.len()));
1155+
intrinsics::assume(additional <= self.capacity().unchecked_sub(self.len()));
11561156
}
11571157
}
11581158

@@ -1206,7 +1206,7 @@ impl String {
12061206
self.vec.reserve_exact(additional);
12071207
unsafe {
12081208
// Inform the optimizer that the reservation has succeeded or wasn't needed
1209-
intrinsics::assume(additional <= self.capacity().wrapping_sub(self.len()));
1209+
intrinsics::assume(additional <= self.capacity().unchecked_sub(self.len()));
12101210
}
12111211
}
12121212

@@ -1246,7 +1246,7 @@ impl String {
12461246
self.vec.try_reserve(additional)?;
12471247
unsafe {
12481248
// Inform the optimizer that the reservation has succeeded or wasn't needed
1249-
intrinsics::assume(additional <= self.capacity().wrapping_sub(self.len()));
1249+
intrinsics::assume(additional <= self.capacity().unchecked_sub(self.len()));
12501250
}
12511251
Ok(())
12521252
}
@@ -1293,7 +1293,7 @@ impl String {
12931293
self.vec.try_reserve_exact(additional)?;
12941294
unsafe {
12951295
// Inform the optimizer that the reservation has succeeded or wasn't needed
1296-
intrinsics::assume(additional <= self.capacity().wrapping_sub(self.len()));
1296+
intrinsics::assume(additional <= self.capacity().unchecked_sub(self.len()));
12971297
}
12981298
Ok(())
12991299
}

library/alloc/src/vec/mod.rs

+16-4
Original file line numberDiff line numberDiff line change
@@ -909,7 +909,10 @@ impl<T, A: Allocator> Vec<T, A> {
909909
#[stable(feature = "rust1", since = "1.0.0")]
910910
#[inline]
911911
pub fn reserve(&mut self, additional: usize) {
912-
self.buf.reserve(self.len, additional);
912+
// SAFETY: len <= capacity
913+
unsafe {
914+
self.buf.reserve(self.len, additional);
915+
}
913916
unsafe {
914917
// Inform the optimizer that the reservation has succeeded or wasn't needed
915918
intrinsics::assume(!self.buf.needs_to_grow(self.len, additional));
@@ -944,7 +947,10 @@ impl<T, A: Allocator> Vec<T, A> {
944947
#[stable(feature = "rust1", since = "1.0.0")]
945948
#[inline]
946949
pub fn reserve_exact(&mut self, additional: usize) {
947-
self.buf.reserve_exact(self.len, additional);
950+
// SAFETY: len <= capacity
951+
unsafe {
952+
self.buf.reserve_exact(self.len, additional);
953+
}
948954
unsafe {
949955
// Inform the optimizer that the reservation has succeeded or wasn't needed
950956
intrinsics::assume(!self.buf.needs_to_grow(self.len, additional));
@@ -986,7 +992,10 @@ impl<T, A: Allocator> Vec<T, A> {
986992
#[stable(feature = "try_reserve", since = "1.57.0")]
987993
#[inline]
988994
pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> {
989-
self.buf.try_reserve(self.len, additional)?;
995+
// SAFETY: len <= capacity
996+
unsafe {
997+
self.buf.try_reserve(self.len, additional)?;
998+
}
990999
unsafe {
9911000
// Inform the optimizer that the reservation has succeeded or wasn't needed
9921001
intrinsics::assume(!self.buf.needs_to_grow(self.len, additional));
@@ -1035,7 +1044,10 @@ impl<T, A: Allocator> Vec<T, A> {
10351044
#[stable(feature = "try_reserve", since = "1.57.0")]
10361045
#[inline]
10371046
pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveError> {
1038-
self.buf.try_reserve_exact(self.len, additional)?;
1047+
// SAFETY: len <= capacity
1048+
unsafe {
1049+
self.buf.try_reserve_exact(self.len, additional)?;
1050+
}
10391051
unsafe {
10401052
// Inform the optimizer that the reservation has succeeded or wasn't needed
10411053
intrinsics::assume(!self.buf.needs_to_grow(self.len, additional));

library/alloc/src/vec/splice.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,9 @@ impl<T, A: Allocator> Drain<'_, T, A> {
126126
unsafe fn move_tail(&mut self, additional: usize) {
127127
let vec = unsafe { self.vec.as_mut() };
128128
let len = self.tail_start + self.tail_len;
129-
vec.buf.reserve(len, additional);
129+
unsafe {
130+
vec.buf.reserve(len, additional);
131+
}
130132

131133
let new_tail_start = self.tail_start + additional;
132134
unsafe {

0 commit comments

Comments
 (0)