diff options
| author | Yuki Okushi <huyuumi.dev@gmail.com> | 2020-02-12 18:55:44 +0900 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-02-12 18:55:44 +0900 |
| commit | 9bc003da11ce9eb227514b26384f3dd8273c4b90 (patch) | |
| tree | c1e3b99fbe19a2eebfdda3bb72f52801ed078fc1 /src/liballoc | |
| parent | 9b51a52084933656947f04e31d2d8c083a7cb6ee (diff) | |
| parent | 25de80ad232b84ce581fe67cc08b43e9db6b0b1f (diff) | |
| download | rust-9bc003da11ce9eb227514b26384f3dd8273c4b90.tar.gz rust-9bc003da11ce9eb227514b26384f3dd8273c4b90.zip | |
Rollup merge of #69026 - TimDiekmann:common-usage, r=Amanieu
Remove common usage pattern from `AllocRef`
This removes the common usage patterns from `AllocRef`:
- `alloc_one`
- `dealloc_one`
- `alloc_array`
- `realloc_array`
- `dealloc_array`
Actually, they add nothing to `AllocRef` except a [convenience wrapper around `Layout` and other methods in this trait](https://doc.rust-lang.org/1.41.0/src/core/alloc.rs.html#1076-1240) but have a major flaw: The documentation of `AllocRefs` notes, that
> some higher-level allocation methods (`alloc_one`, `alloc_array`) are well-defined on zero-sized types and can optionally support them: it is left up to the implementor whether to return `Err`, or to return `Ok` with some pointer.
With the current API, `GlobalAlloc` does not have those methods, so they cannot be overridden for `liballoc::Global`, which means that even if the global allocator would support zero-sized allocations, `alloc_one`, `alloc_array`, and `realloc_array` for `liballoc::Global` will error, while calling `alloc` with a zeroed-size `Layout` could succeed. Even worse: allocating with `alloc` and deallocating with `dealloc_{one,array}` could end up with not calling `dealloc` at all!
For the full discussion please see https://github.com/rust-lang/wg-allocators/issues/18
r? @Amanieu
Diffstat (limited to 'src/liballoc')
| -rw-r--r-- | src/liballoc/raw_vec.rs | 13 |
1 files changed, 7 insertions, 6 deletions
diff --git a/src/liballoc/raw_vec.rs b/src/liballoc/raw_vec.rs index e1b549bed18..144654946a2 100644 --- a/src/liballoc/raw_vec.rs +++ b/src/liballoc/raw_vec.rs @@ -280,7 +280,7 @@ impl<T, A: AllocRef> RawVec<T, A> { // 0, getting to here necessarily means the `RawVec` is overfull. assert!(elem_size != 0, "capacity overflow"); - let (new_cap, uniq) = match self.current_layout() { + let (new_cap, ptr) = match self.current_layout() { Some(cur) => { // Since we guarantee that we never allocate more than // `isize::MAX` bytes, `elem_size * self.cap <= isize::MAX` as @@ -297,7 +297,7 @@ impl<T, A: AllocRef> RawVec<T, A> { alloc_guard(new_size).unwrap_or_else(|_| capacity_overflow()); let ptr_res = self.a.realloc(NonNull::from(self.ptr).cast(), cur, new_size); match ptr_res { - Ok(ptr) => (new_cap, ptr.cast().into()), + Ok(ptr) => (new_cap, ptr), Err(_) => handle_alloc_error(Layout::from_size_align_unchecked( new_size, cur.align(), @@ -308,13 +308,14 @@ impl<T, A: AllocRef> RawVec<T, A> { // Skip to 4 because tiny `Vec`'s are dumb; but not if that // would cause overflow. let new_cap = if elem_size > (!0) / 8 { 1 } else { 4 }; - match self.a.alloc_array::<T>(new_cap) { - Ok(ptr) => (new_cap, ptr.into()), - Err(_) => handle_alloc_error(Layout::array::<T>(new_cap).unwrap()), + let layout = Layout::array::<T>(new_cap).unwrap(); + match self.a.alloc(layout) { + Ok(ptr) => (new_cap, ptr), + Err(_) => handle_alloc_error(layout), } } }; - self.ptr = uniq; + self.ptr = ptr.cast().into(); self.cap = new_cap; } } |
