mirror of
				https://github.com/rust-lang/rust.git
				synced 2025-10-31 21:16:44 +00:00 
			
		
		
		
	 b38106b6d8
			
		
	
	
		b38106b6d8
		
	
	
	
	
		
			
			`rustc_data_structures::thin_vec::ThinVec` looks like this: ``` pub struct ThinVec<T>(Option<Box<Vec<T>>>); ``` It's just a zero word if the vector is empty, but requires two allocations if it is non-empty. So it's only usable in cases where the vector is empty most of the time. This commit removes it in favour of `thin_vec::ThinVec`, which is also word-sized, but stores the length and capacity in the same allocation as the elements. It's good in a wider variety of situation, e.g. in enum variants where the vector is usually/always non-empty. The commit also: - Sorts some `Cargo.toml` dependency lists, to make additions easier. - Sorts some `use` item lists, to make additions easier. - Changes `clean_trait_ref_with_bindings` to take a `ThinVec<TypeBinding>` rather than a `&[TypeBinding]`, because this avoid some unnecessary allocations.
		
			
				
	
	
		
			80 lines
		
	
	
		
			2.4 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
			
		
		
	
	
			80 lines
		
	
	
		
			2.4 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
| use smallvec::{Array, SmallVec};
 | |
| use std::ptr;
 | |
| use thin_vec::ThinVec;
 | |
| 
 | |
| pub trait MapInPlace<T>: Sized {
 | |
|     fn map_in_place<F>(&mut self, mut f: F)
 | |
|     where
 | |
|         F: FnMut(T) -> T,
 | |
|     {
 | |
|         self.flat_map_in_place(|e| Some(f(e)))
 | |
|     }
 | |
| 
 | |
|     fn flat_map_in_place<F, I>(&mut self, f: F)
 | |
|     where
 | |
|         F: FnMut(T) -> I,
 | |
|         I: IntoIterator<Item = T>;
 | |
| }
 | |
| 
 | |
| // The implementation of this method is syntactically identical for all the
 | |
| // different vector types.
 | |
| macro_rules! flat_map_in_place {
 | |
|     () => {
 | |
|         fn flat_map_in_place<F, I>(&mut self, mut f: F)
 | |
|         where
 | |
|             F: FnMut(T) -> I,
 | |
|             I: IntoIterator<Item = T>,
 | |
|         {
 | |
|             let mut read_i = 0;
 | |
|             let mut write_i = 0;
 | |
|             unsafe {
 | |
|                 let mut old_len = self.len();
 | |
|                 self.set_len(0); // make sure we just leak elements in case of panic
 | |
| 
 | |
|                 while read_i < old_len {
 | |
|                     // move the read_i'th item out of the vector and map it
 | |
|                     // to an iterator
 | |
|                     let e = ptr::read(self.as_ptr().add(read_i));
 | |
|                     let iter = f(e).into_iter();
 | |
|                     read_i += 1;
 | |
| 
 | |
|                     for e in iter {
 | |
|                         if write_i < read_i {
 | |
|                             ptr::write(self.as_mut_ptr().add(write_i), e);
 | |
|                             write_i += 1;
 | |
|                         } else {
 | |
|                             // If this is reached we ran out of space
 | |
|                             // in the middle of the vector.
 | |
|                             // However, the vector is in a valid state here,
 | |
|                             // so we just do a somewhat inefficient insert.
 | |
|                             self.set_len(old_len);
 | |
|                             self.insert(write_i, e);
 | |
| 
 | |
|                             old_len = self.len();
 | |
|                             self.set_len(0);
 | |
| 
 | |
|                             read_i += 1;
 | |
|                             write_i += 1;
 | |
|                         }
 | |
|                     }
 | |
|                 }
 | |
| 
 | |
|                 // write_i tracks the number of actually written new items.
 | |
|                 self.set_len(write_i);
 | |
|             }
 | |
|         }
 | |
|     };
 | |
| }
 | |
| 
 | |
| impl<T> MapInPlace<T> for Vec<T> {
 | |
|     flat_map_in_place!();
 | |
| }
 | |
| 
 | |
| impl<T, A: Array<Item = T>> MapInPlace<T> for SmallVec<A> {
 | |
|     flat_map_in_place!();
 | |
| }
 | |
| 
 | |
| impl<T> MapInPlace<T> for ThinVec<T> {
 | |
|     flat_map_in_place!();
 | |
| }
 |