|  |  | @ -16,10 +16,6 @@ want to use `dangling` because there's no real allocation to talk about but | 
			
		
	
		
		
			
				
					
					|  |  |  | So: |  |  |  | So: | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | ```rust,ignore |  |  |  | ```rust,ignore | 
			
		
	
		
		
			
				
					
					|  |  |  | #![feature(alloc, heap_api)] |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | use std::mem; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | impl<T> Vec<T> { |  |  |  | impl<T> Vec<T> { | 
			
		
	
		
		
			
				
					
					|  |  |  |     fn new() -> Self { |  |  |  |     fn new() -> Self { | 
			
		
	
		
		
			
				
					
					|  |  |  |         assert!(mem::size_of::<T>() != 0, "We're not ready to handle ZSTs"); |  |  |  |         assert!(mem::size_of::<T>() != 0, "We're not ready to handle ZSTs"); | 
			
		
	
	
		
		
			
				
					|  |  | @ -76,9 +72,7 @@ compiler to be able to reason about data dependencies and aliasing. | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | As a simple example, consider the following fragment of code: |  |  |  | As a simple example, consider the following fragment of code: | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | ```rust |  |  |  | ```rust,ignore | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | # let x = &mut 0; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | # let y = &mut 0; |  |  |  |  | 
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  | *x *= 7; |  |  |  | *x *= 7; | 
			
		
	
		
		
			
				
					
					|  |  |  | *y *= 3; |  |  |  | *y *= 3; | 
			
		
	
		
		
			
				
					
					|  |  |  | ``` |  |  |  | ``` | 
			
		
	
	
		
		
			
				
					|  |  | @ -158,22 +152,18 @@ such we will guard against this case explicitly. | 
			
		
	
		
		
			
				
					
					|  |  |  | Ok with all the nonsense out of the way, let's actually allocate some memory: |  |  |  | Ok with all the nonsense out of the way, let's actually allocate some memory: | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | ```rust,ignore |  |  |  | ```rust,ignore | 
			
		
	
		
		
			
				
					
					|  |  |  | use std::alloc::oom; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | fn grow(&mut self) { |  |  |  | fn grow(&mut self) { | 
			
		
	
		
		
			
				
					
					|  |  |  |     // this is all pretty delicate, so let's say it's all unsafe |  |  |  |     // this is all pretty delicate, so let's say it's all unsafe | 
			
		
	
		
		
			
				
					
					|  |  |  |     unsafe { |  |  |  |     unsafe { | 
			
		
	
		
		
			
				
					
					|  |  |  |         // current API requires us to specify size and alignment manually. |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |         let align = mem::align_of::<T>(); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |         let elem_size = mem::size_of::<T>(); |  |  |  |         let elem_size = mem::size_of::<T>(); | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |         let (new_cap, ptr) = if self.cap == 0 { |  |  |  |         let (new_cap, ptr) = if self.cap == 0 { | 
			
		
	
		
		
			
				
					
					|  |  |  |             let ptr = heap::allocate(elem_size, align); |  |  |  |             let ptr = Global.allocate(Layout::array::<T>(1).unwrap()); | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |             (1, ptr) |  |  |  |             (1, ptr) | 
			
		
	
		
		
			
				
					
					|  |  |  |         } else { |  |  |  |         } else { | 
			
		
	
		
		
			
				
					
					|  |  |  |             // as an invariant, we can assume that `self.cap < isize::MAX`, |  |  |  |             // as an invariant, we can assume that `self.cap < isize::MAX`, | 
			
		
	
		
		
			
				
					
					|  |  |  |             // so this doesn't need to be checked. |  |  |  |             // so this doesn't need to be checked. | 
			
		
	
		
		
			
				
					
					|  |  |  |             let new_cap = self.cap * 2; |  |  |  |             let new_cap = 2 * self.cap; | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |             // Similarly this can't overflow due to previously allocating this |  |  |  |             // Similarly this can't overflow due to previously allocating this | 
			
		
	
		
		
			
				
					
					|  |  |  |             let old_num_bytes = self.cap * elem_size; |  |  |  |             let old_num_bytes = self.cap * elem_size; | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
	
		
		
			
				
					|  |  | @ -186,18 +176,24 @@ fn grow(&mut self) { | 
			
		
	
		
		
			
				
					
					|  |  |  |             assert!(old_num_bytes <= (isize::MAX as usize) / 2, |  |  |  |             assert!(old_num_bytes <= (isize::MAX as usize) / 2, | 
			
		
	
		
		
			
				
					
					|  |  |  |                     "capacity overflow"); |  |  |  |                     "capacity overflow"); | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |             let new_num_bytes = old_num_bytes * 2; |  |  |  |             let c: NonNull<T> = self.ptr.into(); | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |             let ptr = heap::reallocate(self.ptr.as_ptr() as *mut _, |  |  |  |             let ptr = Global.grow(c.cast(), | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |                                         old_num_bytes, |  |  |  |                                   Layout::array::<T>(self.cap).unwrap(), | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |                                         new_num_bytes, |  |  |  |                                   Layout::array::<T>(new_cap).unwrap()); | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |                                         align); |  |  |  |  | 
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |             (new_cap, ptr) |  |  |  |             (new_cap, ptr) | 
			
		
	
		
		
			
				
					
					|  |  |  |         }; |  |  |  |         }; | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |         // If allocate or reallocate fail, we'll get `null` back |  |  |  |         // If allocate or reallocate fail, oom | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |         if ptr.is_null() { oom(); } |  |  |  |         if ptr.is_err() { | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             handle_alloc_error(Layout::from_size_align_unchecked( | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 new_cap * elem_size, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 mem::align_of::<T>(), | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             )) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         let ptr = ptr.unwrap(); | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |         self.ptr = Unique::new(ptr as *mut _); |  |  |  |         self.ptr = Unique::new_unchecked(ptr.as_ptr() as *mut _); | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |         self.cap = new_cap; |  |  |  |         self.cap = new_cap; | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
	
		
		
			
				
					|  |  | @ -205,4 +201,3 @@ fn grow(&mut self) { | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | Nothing particularly tricky here. Just computing sizes and alignments and doing |  |  |  | Nothing particularly tricky here. Just computing sizes and alignments and doing | 
			
		
	
		
		
			
				
					
					|  |  |  | some careful multiplication checks. |  |  |  | some careful multiplication checks. | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  |  | 
			
		
	
	
		
		
			
				
					|  |  | 
 |