From 2e67cfed79d6d28147aeecc342b6108959e3b502 Mon Sep 17 00:00:00 2001 From: Mark Simulacrum Date: Mon, 10 Jul 2017 11:28:35 -0600 Subject: [PATCH 1/2] Update to use the new allocator APIs. --- src/destructors.md | 35 ++++++++++++++--------------------- src/vec-final.md | 28 +++++++++++++--------------- 2 files changed, 27 insertions(+), 36 deletions(-) diff --git a/src/destructors.md b/src/destructors.md index 6c7b2c9..522e835 100644 --- a/src/destructors.md +++ b/src/destructors.md @@ -26,14 +26,15 @@ this is totally fine. For instance, a custom implementation of `Box` might write `Drop` like this: ```rust -#![feature(alloc, heap_api, unique)] +#![feature(alloc, heap_api, unique, allocator_api)] extern crate alloc; use std::ptr::{drop_in_place, Unique}; use std::mem; -use alloc::heap; +use alloc::allocator::{Layout, Alloc}; +use alloc::heap::Heap; struct Box{ ptr: Unique } @@ -41,9 +42,7 @@ impl Drop for Box { fn drop(&mut self) { unsafe { drop_in_place(self.ptr.as_ptr()); - heap::deallocate(self.ptr.as_ptr() as *mut u8, - mem::size_of::(), - mem::align_of::()); + Heap.dealloc(self.ptr.as_ptr() as *mut u8, Layout::new::()) } } } @@ -57,14 +56,15 @@ use-after-free the `ptr` because when drop exits, it becomes inaccessible. However this wouldn't work: ```rust -#![feature(alloc, heap_api, unique)] +#![feature(alloc, allocator_api, heap_api, unique)] extern crate alloc; use std::ptr::{drop_in_place, Unique}; use std::mem; -use alloc::heap; +use alloc::allocator::{Layout, Alloc}; +use alloc::heap::Heap; struct Box{ ptr: Unique } @@ -72,9 +72,7 @@ impl Drop for Box { fn drop(&mut self) { unsafe { drop_in_place(self.ptr.as_ptr()); - heap::deallocate(self.ptr.as_ptr() as *mut u8, - mem::size_of::(), - mem::align_of::()); + Heap.dealloc(self.ptr.as_ptr() as *mut u8, Layout::new::()); } } } @@ -86,9 +84,7 @@ impl Drop for SuperBox { unsafe { // Hyper-optimized: deallocate the box's contents for it // without `drop`ing the contents - heap::deallocate(self.my_box.ptr.as_ptr() as *mut u8, - mem::size_of::(), - mem::align_of::()); + Heap.dealloc(self.my_box.ptr.as_ptr() as *mut u8, Layout::new::()); } } } @@ -135,14 +131,15 @@ The classic safe solution to overriding recursive drop and allowing moving out of Self during `drop` is to use an Option: ```rust -#![feature(alloc, heap_api, unique)] +#![feature(alloc, allocator_api, heap_api, unique)] extern crate alloc; use std::ptr::{drop_in_place, Unique}; use std::mem; -use alloc::heap; +use alloc::allocator::{Layout, Alloc}; +use alloc::heap::Heap; struct Box{ ptr: Unique } @@ -150,9 +147,7 @@ impl Drop for Box { fn drop(&mut self) { unsafe { drop_in_place(self.ptr.as_ptr()); - heap::deallocate(self.ptr.as_ptr() as *mut u8, - mem::size_of::(), - mem::align_of::()); + Heap.dealloc(self.ptr.as_ptr() as *mut u8, Layout::new::()); } } } @@ -166,9 +161,7 @@ impl Drop for SuperBox { // without `drop`ing the contents. Need to set the `box` // field as `None` to prevent Rust from trying to Drop it. let my_box = self.my_box.take().unwrap(); - heap::deallocate(my_box.ptr.as_ptr() as *mut u8, - mem::size_of::(), - mem::align_of::()); + Heap.dealloc(my_box.ptr.as_ptr() as *mut u8, Layout::new::()); mem::forget(my_box); } } diff --git a/src/vec-final.md b/src/vec-final.md index cfea0d6..f74fe36 100644 --- a/src/vec-final.md +++ b/src/vec-final.md @@ -2,7 +2,7 @@ ```rust #![feature(unique)] -#![feature(alloc, heap_api)] +#![feature(alloc, allocator_api, heap_api)] extern crate alloc; @@ -11,7 +11,8 @@ use std::mem; use std::ops::{Deref, DerefMut}; use std::marker::PhantomData; -use alloc::heap; +use alloc::allocator::{Layout, Alloc}; +use alloc::heap::Heap; struct RawVec { ptr: Unique, @@ -35,22 +36,22 @@ impl RawVec { // 0, getting to here necessarily means the Vec is overfull. assert!(elem_size != 0, "capacity overflow"); - let align = mem::align_of::(); - let (new_cap, ptr) = if self.cap == 0 { - let ptr = heap::allocate(elem_size, align); + let ptr = Heap.alloc(Layout::array::(1).unwrap()); (1, ptr) } else { let new_cap = 2 * self.cap; - let ptr = heap::reallocate(self.ptr.as_ptr() as *mut _, - self.cap * elem_size, - new_cap * elem_size, - align); + let ptr = Heap.realloc(self.ptr.as_ptr() as *mut _, + Layout::array::(self.cap).unwrap(), + Layout::array::(new_cap).unwrap()); (new_cap, ptr) }; - // If allocate or reallocate fail, we'll get `null` back - if ptr.is_null() { oom() } + // If allocate or reallocate fail, oom + let ptr = match ptr { + Ok(ptr) => ptr, + Err(err) => Heap.oom(err), + }; self.ptr = Unique::new(ptr as *mut _); self.cap = new_cap; @@ -62,11 +63,8 @@ impl Drop for RawVec { fn drop(&mut self) { let elem_size = mem::size_of::(); if self.cap != 0 && elem_size != 0 { - let align = mem::align_of::(); - - let num_bytes = elem_size * self.cap; unsafe { - heap::deallocate(self.ptr.as_ptr() as *mut _, num_bytes, align); + Heap.dealloc(self.ptr.as_ptr() as *mut _, Layout::array::(self.cap).unwrap()); } } } From 56d90fa3c37cd5d1228dc299e1296019fe57140d Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 10 Jul 2017 10:39:43 -0700 Subject: [PATCH 2/2] Touch up where `Alloc` is imported from --- src/destructors.md | 26 +++++++------------------- src/vec-final.md | 15 ++++----------- 2 files changed, 11 insertions(+), 30 deletions(-) diff --git a/src/destructors.md b/src/destructors.md index 522e835..5b3f546 100644 --- a/src/destructors.md +++ b/src/destructors.md @@ -26,15 +26,11 @@ this is totally fine. For instance, a custom implementation of `Box` might write `Drop` like this: ```rust -#![feature(alloc, heap_api, unique, allocator_api)] +#![feature(unique, allocator_api)] -extern crate alloc; - -use std::ptr::{drop_in_place, Unique}; +use std::heap::{Heap, Alloc, Layout}; use std::mem; - -use alloc::allocator::{Layout, Alloc}; -use alloc::heap::Heap; +use std::ptr::{drop_in_place, Unique}; struct Box{ ptr: Unique } @@ -56,16 +52,12 @@ use-after-free the `ptr` because when drop exits, it becomes inaccessible. However this wouldn't work: ```rust -#![feature(alloc, allocator_api, heap_api, unique)] - -extern crate alloc; +#![feature(allocator_api, unique)] +use std::heap::{Heap, Alloc, Layout}; use std::ptr::{drop_in_place, Unique}; use std::mem; -use alloc::allocator::{Layout, Alloc}; -use alloc::heap::Heap; - struct Box{ ptr: Unique } impl Drop for Box { @@ -131,16 +123,12 @@ The classic safe solution to overriding recursive drop and allowing moving out of Self during `drop` is to use an Option: ```rust -#![feature(alloc, allocator_api, heap_api, unique)] - -extern crate alloc; +#![feature(allocator_api, unique)] +use std::heap::{Alloc, Heap, Layout}; use std::ptr::{drop_in_place, Unique}; use std::mem; -use alloc::allocator::{Layout, Alloc}; -use alloc::heap::Heap; - struct Box{ ptr: Unique } impl Drop for Box { diff --git a/src/vec-final.md b/src/vec-final.md index f74fe36..fd6c592 100644 --- a/src/vec-final.md +++ b/src/vec-final.md @@ -2,17 +2,13 @@ ```rust #![feature(unique)] -#![feature(alloc, allocator_api, heap_api)] - -extern crate alloc; +#![feature(allocator_api)] use std::ptr::{Unique, self}; use std::mem; use std::ops::{Deref, DerefMut}; use std::marker::PhantomData; - -use alloc::allocator::{Layout, Alloc}; -use alloc::heap::Heap; +use std::heap::{Alloc, Layout, Heap}; struct RawVec { ptr: Unique, @@ -64,16 +60,13 @@ impl Drop for RawVec { let elem_size = mem::size_of::(); if self.cap != 0 && elem_size != 0 { unsafe { - Heap.dealloc(self.ptr.as_ptr() as *mut _, Layout::array::(self.cap).unwrap()); + Heap.dealloc(self.ptr.as_ptr() as *mut _, + Layout::array::(self.cap).unwrap()); } } } } - - - - pub struct Vec { buf: RawVec, len: usize,