]> git.lizzy.rs Git - rust.git/blobdiff - compiler/rustc_data_structures/src/thin_vec.rs
Rollup merge of #100713 - Xiretza:parser-expr-session-diagnostics, r=estebank
[rust.git] / compiler / rustc_data_structures / src / thin_vec.rs
index b5d2d24736cdc4b89d30e9dc4a84e83a84abebc2..fce42e709ab74cfefcf6d81ebff7d2ddc164ea32 100644 (file)
@@ -5,7 +5,7 @@
 /// A vector type optimized for cases where this size is usually 0 (cf. `SmallVec`).
 /// The `Option<Box<..>>` wrapping allows us to represent a zero sized vector with `None`,
 /// which uses only a single (null) pointer.
-#[derive(Clone, Encodable, Decodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug, Hash, Eq, PartialEq)]
 pub struct ThinVec<T>(Option<Box<Vec<T>>>);
 
 impl<T> ThinVec<T> {
@@ -20,6 +20,58 @@ pub fn iter(&self) -> std::slice::Iter<'_, T> {
     pub fn iter_mut(&mut self) -> std::slice::IterMut<'_, T> {
         self.into_iter()
     }
+
+    pub fn push(&mut self, item: T) {
+        match *self {
+            ThinVec(Some(ref mut vec)) => vec.push(item),
+            ThinVec(None) => *self = vec![item].into(),
+        }
+    }
+
+    /// Note: if `set_len(0)` is called on a non-empty `ThinVec`, it will
+    /// remain in the `Some` form. This is required for some code sequences
+    /// (such as the one in `flat_map_in_place`) that call `set_len(0)` before
+    /// an operation that might panic, and then call `set_len(n)` again
+    /// afterwards.
+    pub unsafe fn set_len(&mut self, new_len: usize) {
+        match *self {
+            ThinVec(None) => {
+                // A prerequisite of `Vec::set_len` is that `new_len` must be
+                // less than or equal to capacity(). The same applies here.
+                if new_len != 0 {
+                    panic!("unsafe ThinVec::set_len({})", new_len);
+                }
+            }
+            ThinVec(Some(ref mut vec)) => vec.set_len(new_len),
+        }
+    }
+
+    pub fn insert(&mut self, index: usize, value: T) {
+        match *self {
+            ThinVec(None) => {
+                if index == 0 {
+                    *self = vec![value].into();
+                } else {
+                    panic!("invalid ThinVec::insert");
+                }
+            }
+            ThinVec(Some(ref mut vec)) => vec.insert(index, value),
+        }
+    }
+
+    pub fn remove(&mut self, index: usize) -> T {
+        match self {
+            ThinVec(None) => panic!("invalid ThinVec::remove"),
+            ThinVec(Some(vec)) => vec.remove(index),
+        }
+    }
+
+    pub fn as_slice(&self) -> &[T] {
+        match self {
+            ThinVec(None) => &[],
+            ThinVec(Some(vec)) => vec.as_slice(),
+        }
+    }
 }
 
 impl<T> From<Vec<T>> for ThinVec<T> {
@@ -101,10 +153,7 @@ fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
     }
 
     fn extend_one(&mut self, item: T) {
-        match *self {
-            ThinVec(Some(ref mut vec)) => vec.push(item),
-            ThinVec(None) => *self = vec![item].into(),
-        }
+        self.push(item)
     }
 
     fn extend_reserve(&mut self, additional: usize) {