cl_structures/
stack.rs

1//! A contiguous collection with constant capacity.
2//!
3//! Since the capacity of a [Stack] may be [*known at compile time*](Sized),
4//! it may live on the call stack.
5//!
6//!
7//! # Examples
8//!
9//! Unlike a [Vec], the [Stack] doesn't grow when it reaches capacity.
10//! ```should_panic
11//! # use cl_structures::stack::*;
12//! let mut v = stack![1];
13//! v.push("This should work");
14//! v.push("This will panic!");
15//! ```
16//! To get around this limitation, the methods [try_push](Stack::try_push) and
17//! [try_insert](Stack::try_insert) are provided:
18//! ```
19//! # use cl_structures::stack::*;
20//! let mut v = stack![1];
21//! v.push("This should work");
22//! v.try_push("This should produce an err").unwrap_err();
23//! ```
24//!
25//! As the name suggests, a [Stack] enforces a stack discipline:
26//! ```
27//! # use cl_structures::stack::*;
28//! let mut v = stack![100];
29//!
30//! assert_eq!(100, v.capacity());
31//! assert_eq!(0, v.len());
32//!
33//! // Elements are pushed one at a time onto the stack
34//! v.push("foo");
35//! v.push("bar");
36//! assert_eq!(2, v.len());
37//!
38//! // The stack can be used anywhere a slice is expected
39//! assert_eq!(Some(&"foo"), v.get(0));
40//! assert_eq!(Some(&"bar"), v.last());
41//!
42//! // Elements are popped from the stack in reverse order
43//! assert_eq!(Some("bar"), v.pop());
44//! assert_eq!(Some("foo"), v.pop());
45//! assert_eq!(None, v.pop());
46//! ```
47
48// yar har! here there be unsafe code! Tread carefully.
49
50use core::slice;
51use std::{
52    fmt::Debug,
53    marker::PhantomData,
54    mem::{ManuallyDrop, MaybeUninit},
55    ops::{Deref, DerefMut},
56    ptr,
57};
58
59/// Creates a [`stack`] containing the arguments
60///
61/// # Examples
62///
63/// Creates a *full* [`Stack`] containing a list of elements
64/// ```
65/// # use cl_structures::stack::stack;
66/// let mut v = stack![1, 2, 3];
67///
68/// assert_eq!(Some(3), v.pop());
69/// assert_eq!(Some(2), v.pop());
70/// assert_eq!(Some(1), v.pop());
71/// assert_eq!(None, v.pop());
72/// ```
73///
74/// Creates a *full* [`Stack`] from a given element and size
75/// ```
76/// # use cl_structures::stack::stack;
77/// let mut v = stack![1; 2];
78///
79/// assert_eq!(Some(1), v.pop());
80/// assert_eq!(Some(1), v.pop());
81/// assert_eq!(None, v.pop());
82/// ```
83///
84/// Creates an *empty* [`Stack`] from a given size
85/// ```
86/// # use cl_structures::stack::{Stack, stack};
87/// let mut v = stack![10];
88///
89/// assert_eq!(0, v.len());
90/// assert_eq!(10, v.capacity());
91///
92/// v.push(10);
93/// assert_eq!(Some(&10), v.last());
94/// ```
95pub macro stack {
96    ($capacity:literal) => {
97        Stack::<_, $capacity>::new()
98    },
99    ($value:expr ; $count:literal) => {{
100        let mut stack: Stack<_, $count> = Stack::new();
101        for _ in 0..$count {
102            stack.push($value)
103        }
104        stack
105    }},
106    ($value:expr ; $count:literal ; $capacity:literal) => {{
107        let mut stack: Stack<_, $capacity> = Stack::new();
108        for _ in 0..$count {
109            stack.push($value)
110        }
111        stack
112    }},
113    ($($values:expr),* $(,)?) => {
114        Stack::from([$($values),*])
115    }
116}
117
118/// A contiguous collection with constant capacity
119pub struct Stack<T, const N: usize> {
120    _data: PhantomData<T>,
121    buf: [MaybeUninit<T>; N],
122    len: usize,
123}
124
125impl<T: Clone, const N: usize> Clone for Stack<T, N> {
126    fn clone(&self) -> Self {
127        let mut new = Self::new();
128        for value in self.iter() {
129            new.push(value.clone())
130        }
131        new
132    }
133}
134
135impl<T: Debug, const N: usize> Debug for Stack<T, N> {
136    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
137        f.debug_list().entries(self.iter()).finish()
138    }
139}
140
141impl<T, const N: usize> Default for Stack<T, N> {
142    fn default() -> Self {
143        Self::new()
144    }
145}
146
147impl<T, const N: usize> Deref for Stack<T, N> {
148    type Target = [T];
149
150    #[inline]
151    fn deref(&self) -> &Self::Target {
152        self.as_slice()
153    }
154}
155
156impl<T, const N: usize> DerefMut for Stack<T, N> {
157    #[inline]
158    fn deref_mut(&mut self) -> &mut Self::Target {
159        self.as_mut_slice()
160    }
161}
162
163// requires dropck-eyepatch for elements with contravariant lifetimes
164unsafe impl<#[may_dangle] T, const N: usize> Drop for Stack<T, N> {
165    #[inline]
166    fn drop(&mut self) {
167        // Safety: Elements in [0..self.len] are initialized
168        if std::mem::needs_drop::<T>() {
169            unsafe { core::ptr::drop_in_place(self.as_mut_slice()) };
170        }
171    }
172}
173
174impl<T, const N: usize> Extend<T> for Stack<T, N> {
175    fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
176        for value in iter {
177            self.push(value)
178        }
179    }
180}
181
182impl<T, const N: usize> From<[T; N]> for Stack<T, N> {
183    fn from(value: [T; N]) -> Self {
184        let value = ManuallyDrop::new(value);
185        if std::mem::size_of::<[T; N]>() == 0 {
186            // Safety: since [T; N] is zero-sized, and there are no other fields,
187            // it should be okay to interpret N as Self
188            unsafe { ptr::read(&N as *const _ as *const _) }
189        } else {
190            // Safety:
191            // - `value` is ManuallyDrop, so its destructor won't run
192            // - All elements are assumed to be initialized (so len is N)
193            Self {
194                buf: unsafe { ptr::read(&value as *const _ as *const _) },
195                len: N,
196                ..Default::default()
197            }
198        }
199    }
200}
201
202impl<T, const N: usize> Stack<T, N> {
203    /// Constructs a new, empty [Stack]
204    ///
205    /// # Examples
206    ///
207    /// ```
208    /// # use cl_structures::stack::Stack;
209    /// let mut v: Stack<_, 3> = Stack::new();
210    ///
211    /// v.try_push(1).unwrap();
212    /// v.try_push(2).unwrap();
213    /// v.try_push(3).unwrap();
214    /// // Trying to push a 4th element will fail, and return the failed element
215    /// assert_eq!(4, v.try_push(4).unwrap_err());
216    ///
217    /// assert_eq!(Some(3), v.pop());
218    /// ```
219    pub const fn new() -> Self {
220        Self { buf: [const { MaybeUninit::uninit() }; N], len: 0, _data: PhantomData }
221    }
222
223    /// Constructs a new [Stack] from an array of [`MaybeUninit<T>`] and an initialized length
224    ///
225    /// # Safety
226    ///
227    /// - Elements from `0..len` must be initialized
228    /// - len must not exceed the length of the array
229    ///
230    /// # Examples
231    ///
232    /// ```
233    /// # use cl_structures::stack::Stack;
234    /// # use core::mem::MaybeUninit;
235    /// let mut v = unsafe { Stack::from_raw_parts([MaybeUninit::new(100)], 1) };
236    ///
237    /// assert_eq!(1, v.len());
238    /// assert_eq!(1, v.capacity());
239    /// assert_eq!(Some(100), v.pop());
240    /// assert_eq!(None, v.pop());
241    /// ```
242    pub const unsafe fn from_raw_parts(buf: [MaybeUninit<T>; N], len: usize) -> Self {
243        Self { buf, len, _data: PhantomData }
244    }
245
246    /// Converts a [Stack] into an array of [`MaybeUninit<T>`] and the initialized length
247    ///
248    /// # Examples
249    ///
250    /// ```
251    /// # use cl_structures::stack::Stack;
252    /// let mut v: Stack<_, 10> = Stack::new();
253    /// v.push(0);
254    /// v.push(1);
255    ///
256    /// let (buf, len) = v.into_raw_parts();
257    ///
258    /// assert_eq!(0, unsafe { buf[0].assume_init() });
259    /// assert_eq!(1, unsafe { buf[1].assume_init() });
260    /// assert_eq!(2, len);
261    /// ```
262    #[inline]
263    pub fn into_raw_parts(self) -> ([MaybeUninit<T>; N], usize) {
264        let this = ManuallyDrop::new(self);
265        // Safety: since
266        (unsafe { ptr::read(&this.buf) }, this.len)
267    }
268
269    /// Returns a raw pointer to the stack's buffer
270    pub const fn as_ptr(&self) -> *const T {
271        self.buf.as_ptr().cast()
272    }
273
274    /// Returns an unsafe mutable pointer to the stack's buffer
275    pub const fn as_mut_ptr(&mut self) -> *mut T {
276        self.buf.as_mut_ptr().cast()
277    }
278
279    /// Extracts a slice containing the entire vector
280    pub const fn as_slice(&self) -> &[T] {
281        // Safety:
282        // - We have ensured all elements from 0 to len have been initialized
283        // - self.elem[0] came from a reference, and so is aligned to T
284        // unsafe { &*(&self.buf[0..self.len] as *const [_] as *const [T]) }
285        unsafe { slice::from_raw_parts(self.buf.as_ptr().cast(), self.len) }
286    }
287
288    /// Extracts a mutable slice containing the entire vector
289    pub const fn as_mut_slice(&mut self) -> &mut [T] {
290        // Safety:
291        // - See Stack::as_slice
292        unsafe { slice::from_raw_parts_mut(self.buf.as_mut_ptr().cast(), self.len) }
293    }
294
295    /// Returns the total number of elements the stack can hold
296    pub const fn capacity(&self) -> usize {
297        N
298    }
299
300    /// Moves an existing stack into an allocation of a (potentially) different size,
301    /// truncating if necessary.
302    ///
303    /// This can be used to easily construct a half-empty stack
304    ///
305    /// # Examples
306    ///
307    /// You can grow a stack to fit more elements
308    /// ```
309    /// # use cl_structures::stack::Stack;
310    /// let v = Stack::from([0, 1, 2, 3, 4]);
311    /// assert_eq!(5, v.capacity());
312    ///
313    /// let mut v = v.resize::<10>();
314    /// assert_eq!(10, v.capacity());
315    ///
316    /// v.push(5);
317    /// ```
318    ///
319    /// You can truncate a stack, dropping elements off the end
320    /// ```
321    /// # use cl_structures::stack::Stack;
322    /// let v = Stack::from([0, 1, 2, 3, 4, 5, 6, 7]);
323    /// assert_eq!(8, v.capacity());
324    ///
325    /// let v = v.resize::<5>();
326    /// assert_eq!(5, v.capacity());
327    /// ```
328    pub fn resize<const M: usize>(mut self) -> Stack<T, M> {
329        // Drop elements until new length is reached
330        while self.len > M {
331            drop(self.pop());
332        }
333        let (old, len) = self.into_raw_parts();
334        let mut new: Stack<T, M> = Stack::new();
335
336        // Safety:
337        // - new and old are separate allocations
338        // - len <= M
339        unsafe {
340            ptr::copy_nonoverlapping(old.as_ptr(), new.buf.as_mut_ptr(), len);
341        }
342
343        new.len = len;
344        new
345    }
346
347    /// Push a new element onto the end of the stack
348    ///
349    /// # May Panic
350    ///
351    /// Panics if the new length exceeds capacity
352    ///
353    /// # Examples
354    ///
355    /// ```
356    /// # use cl_structures::stack::Stack;
357    /// let mut v: Stack<_, 4> = Stack::new();
358    ///
359    /// v.push(0);
360    /// v.push(1);
361    /// v.push(2);
362    /// v.push(3);
363    /// assert_eq!(&[0, 1, 2, 3], v.as_slice());
364    /// ```
365    pub const fn push(&mut self, value: T) {
366        if self.len >= N {
367            panic!("Attempted to push into full stack")
368        }
369        // Safety: len is confirmed to be less than capacity
370        unsafe { self.push_unchecked(value) };
371    }
372
373    /// Push a new element onto the end of the stack
374    ///
375    /// Returns [`Err(value)`](Result::Err) if the new length would exceed capacity
376    pub const fn try_push(&mut self, value: T) -> Result<(), T> {
377        if self.len >= N {
378            return Err(value);
379        }
380        // Safety: len is confirmed to be less than capacity
381        unsafe { self.push_unchecked(value) };
382        Ok(())
383    }
384
385    /// Push a new element onto the end of the stack, without checking capacity
386    ///
387    /// # Safety
388    ///
389    /// len after push must not exceed capacity N
390    #[inline]
391    const unsafe fn push_unchecked(&mut self, value: T) {
392        unsafe {
393            // self.buf.get_unchecked_mut(self.len).write(value); // TODO: This is non-const
394            ptr::write(self.as_mut_ptr().add(self.len), value)
395        }
396        self.len += 1; // post inc
397    }
398
399    /// Pops the last element off the end of the stack, and returns it
400    ///
401    /// Returns None if the stack is empty
402    ///
403    /// # Examples
404    ///
405    /// ```
406    /// # use cl_structures::stack::Stack;
407    /// let mut v = Stack::from([0, 1, 2, 3]);
408    ///
409    /// assert_eq!(Some(3), v.pop());
410    /// assert_eq!(Some(2), v.pop());
411    /// assert_eq!(Some(1), v.pop());
412    /// assert_eq!(Some(0), v.pop());
413    /// assert_eq!(None, v.pop());
414    /// ```
415    pub const fn pop(&mut self) -> Option<T> {
416        if self.len == 0 {
417            None
418        } else {
419            self.len -= 1;
420            // Safety: MaybeUninit<T> implies ManuallyDrop<T>,
421            // therefore should not get dropped twice
422            // Some(unsafe { self.buf.get_unchecked_mut(self.len).assume_init_read() })
423            Some(unsafe { ptr::read(self.as_ptr().add(self.len).cast()) })
424        }
425    }
426
427    /// Removes and returns the element at the given index,
428    /// shifting other elements toward the start
429    ///
430    /// # Examples
431    ///
432    /// ```
433    /// # use cl_structures::stack::Stack;
434    /// let mut v = Stack::from([0, 1, 2, 3, 4]);
435    ///
436    /// assert_eq!(2, v.remove(2));
437    /// assert_eq!(&[0, 1, 3, 4], v.as_slice());
438    /// ```
439    pub fn remove(&mut self, index: usize) -> T {
440        if index >= self.len {
441            panic!("Index {index} exceeded length {}", self.len)
442        }
443        let len = self.len - 1;
444        let base = self.as_mut_ptr();
445        let out = unsafe { ptr::read(base.add(index)) };
446
447        unsafe { ptr::copy(base.add(index + 1), base.add(index), len - index) };
448        self.len = len;
449        out
450    }
451
452    /// Removes and returns the element at the given index,
453    /// swapping it with the last element.
454    ///
455    /// # May Panic
456    ///
457    /// Panics if `index >= len`.
458    ///
459    /// # Examples
460    ///
461    /// ```
462    /// # use cl_structures::stack::Stack;
463    /// let mut v = Stack::from([0, 1, 2, 3, 4]);
464    ///
465    /// assert_eq!(2, v.swap_remove(2));
466    ///
467    /// assert_eq!(&[0, 1, 4, 3], v.as_slice());
468    /// ```
469    pub fn swap_remove(&mut self, index: usize) -> T {
470        if index >= self.len {
471            panic!("Index {index} exceeds length {}", self.len);
472        }
473        let len = self.len - 1;
474        let ptr = self.as_mut_ptr();
475        let out = unsafe { ptr::read(ptr.add(index)) };
476
477        unsafe { ptr::copy(ptr.add(len), ptr.add(index), 1) };
478        self.len = len;
479        out
480    }
481
482    /// Inserts an element at position `index` in the stack,
483    /// shifting all elements after it to the right.
484    ///
485    /// # May Panic
486    ///
487    /// Panics if `index > len` or [`self.is_full()`](Stack::is_full)
488    ///
489    /// # Examples
490    ///
491    /// ```
492    /// # use cl_structures::stack::Stack;
493    /// let mut v = Stack::from([0, 1, 2, 3, 4]).resize::<6>();
494    ///
495    /// v.insert(3, 0xbeef);
496    /// assert_eq!(&[0, 1, 2, 0xbeef, 3, 4], v.as_slice());
497    /// ```
498    pub fn insert(&mut self, index: usize, data: T) {
499        if index > self.len {
500            panic!("Index {index} exceeded length {}", self.len)
501        }
502        if self.is_full() {
503            panic!("Attempted to insert into full stack")
504        }
505        unsafe { self.insert_unchecked(index, data) };
506    }
507
508    /// Attempts to insert an element at position `index` in the stack,
509    /// shifting all elements after it to the right.
510    ///
511    /// If the stack is at capacity, returns the original element and an [InsertFailed] error.
512    ///
513    /// # Examples
514    ///
515    /// ```
516    /// use cl_structures::stack::Stack;
517    /// let mut v: Stack<_, 2> = Stack::new();
518    ///
519    /// assert_eq!(Ok(()), v.try_insert(0, 0));
520    /// ```
521    pub const fn try_insert(&mut self, index: usize, data: T) -> Result<(), (T, InsertFailed<N>)> {
522        if index > self.len {
523            return Err((data, InsertFailed::Bounds(index)));
524        }
525        if self.is_full() {
526            return Err((data, InsertFailed::Full));
527        }
528        // Safety: index < self.len && !self.is_full()
529        unsafe { self.insert_unchecked(index, data) };
530        Ok(())
531    }
532
533    /// # Safety:
534    /// - index must be less than self.len
535    /// - length after insertion must be <= N
536    #[inline]
537    const unsafe fn insert_unchecked(&mut self, index: usize, data: T) {
538        let base = self.as_mut_ptr();
539
540        unsafe { ptr::copy(base.add(index), base.add(index + 1), self.len - index) }
541
542        self.len += 1;
543        self.buf[index] = MaybeUninit::new(data);
544    }
545
546    /// Clears the stack
547    ///
548    /// # Examples
549    ///
550    /// ```
551    /// # use cl_structures::stack::Stack;
552    ///
553    /// let mut v = Stack::from([0, 1, 2, 3, 4]);
554    /// assert_eq!(v.as_slice(), &[0, 1, 2, 3, 4]);
555    ///
556    /// v.clear();
557    /// assert_eq!(v.as_slice(), &[]);
558    /// ```
559    pub fn clear(&mut self) {
560        // Hopefully copy elision takes care of this lmao
561        while !self.is_empty() {
562            drop(self.pop());
563        }
564    }
565
566    /// Returns the number of elements in the stack
567    /// ```
568    /// # use cl_structures::stack::*;
569    /// let v = Stack::from([0, 1, 2, 3, 4]);
570    ///
571    /// assert_eq!(5, v.len());
572    /// ```
573    pub const fn len(&self) -> usize {
574        self.len
575    }
576
577    /// Returns true if the stack is at (or over) capacity
578    ///
579    /// # Examples
580    ///
581    /// ```
582    /// # use cl_structures::stack::*;
583    /// let v = Stack::from([(); 10]);
584    ///
585    /// assert!(v.is_full());
586    /// ```
587    #[inline]
588    pub const fn is_full(&self) -> bool {
589        self.len >= N
590    }
591
592    /// Returns true if the stack contains no elements
593    ///
594    /// # Examples
595    ///
596    /// ```
597    /// # use cl_structures::stack::*;
598    /// let v: Stack<(), 10> = Stack::new();
599    ///
600    /// assert!(v.is_empty());
601    /// ```
602    #[inline]
603    pub const fn is_empty(&self) -> bool {
604        self.len == 0
605    }
606}
607
608#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
609pub enum InsertFailed<const N: usize> {
610    Bounds(usize),
611    Full,
612}
613impl<const N: usize> std::error::Error for InsertFailed<N> {}
614impl<const N: usize> std::fmt::Display for InsertFailed<N> {
615    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
616        match self {
617            InsertFailed::Bounds(idx) => write!(f, "Index {idx} exceeded length {N}"),
618            InsertFailed::Full => {
619                write!(f, "Attempt to insert into full stack (length {N})")
620            }
621        }
622    }
623}
624
625#[cfg(test)]
626mod tests {
627    use super::*;
628    #[test]
629    fn zero_sized() {
630        let v: Stack<(), { usize::MAX }> = Stack::new();
631        assert_eq!(usize::MAX, v.capacity());
632        assert_eq!(std::mem::size_of::<usize>(), std::mem::size_of_val(&v))
633    }
634    #[test]
635    fn from_usize_max_zst_array() {
636        let mut v = Stack::from([(); usize::MAX]);
637        assert_eq!(v.len(), usize::MAX);
638        v.pop();
639        assert_eq!(v.len(), usize::MAX - 1);
640    }
641
642    #[test]
643    fn new() {
644        let v: Stack<(), 255> = Stack::new();
645        assert_eq!(0, v.len());
646        assert_eq!(255, v.capacity());
647    }
648
649    #[test]
650    fn push() {
651        let mut v: Stack<_, 64> = Stack::new();
652        v.push(10);
653    }
654
655    #[test]
656    #[should_panic = "Attempted to push into full stack"]
657    fn push_overflow() {
658        let mut v = Stack::from([]);
659        v.push(10);
660    }
661
662    #[test]
663    fn pop() {
664        let mut v = Stack::from([1, 2, 3, 4, 5, 6, 7, 8, 9]);
665        assert_eq!(Some(9), v.pop());
666        assert_eq!(Some(8), v.pop());
667        assert_eq!(Some(7), v.pop());
668        assert_eq!(Some(6), v.pop());
669        assert_eq!(Some(5), v.pop());
670        assert_eq!(Some(4), v.pop());
671        assert_eq!(Some(3), v.pop());
672        assert_eq!(Some(2), v.pop());
673        assert_eq!(Some(1), v.pop());
674        assert_eq!(None, v.pop());
675    }
676
677    #[test]
678    fn resize_smaller() {
679        let v = Stack::from([1, 2, 3, 4, 5, 6, 7, 8, 9]);
680        let mut v = v.resize::<2>();
681
682        assert_eq!(2, v.capacity());
683
684        assert_eq!(Some(2), v.pop());
685        assert_eq!(Some(1), v.pop());
686        assert_eq!(None, v.pop());
687    }
688
689    #[test]
690    fn resize_bigger() {
691        let v = Stack::from([1, 2, 3, 4]);
692        let mut v: Stack<_, 10> = v.resize();
693
694        assert_eq!(Some(4), v.pop());
695        assert_eq!(Some(3), v.pop());
696        assert_eq!(Some(2), v.pop());
697        assert_eq!(Some(1), v.pop());
698        assert_eq!(None, v.pop());
699    }
700    #[test]
701    fn dangle() {
702        let mut v: Stack<_, 2> = Stack::new();
703        let a = 0;
704        let b = 1;
705        v.push(&a);
706        v.push(&b);
707        println!("{v:?}");
708    }
709    #[test]
710    fn remove() {
711        let mut v = Stack::from([0, 1, 2, 3, 4, 5]);
712
713        assert_eq!(3, v.remove(3));
714        assert_eq!(4, v.remove(3));
715        assert_eq!(5, v.remove(3));
716        assert_eq!(Some(2), v.pop());
717        assert_eq!(Some(1), v.pop());
718        assert_eq!(Some(0), v.pop());
719        assert_eq!(None, v.pop());
720    }
721
722    #[test]
723    fn swap_remove() {
724        let mut v = Stack::from([0, 1, 2, 3, 4, 5]);
725        assert_eq!(3, v.swap_remove(3));
726        assert_eq!(&[0, 1, 2, 5, 4], v.as_slice());
727    }
728    #[test]
729    fn swap_remove_last() {
730        let mut v = Stack::from([0, 1, 2, 3, 4, 5]);
731        assert_eq!(5, v.swap_remove(5));
732        assert_eq!(&[0, 1, 2, 3, 4], v.as_slice())
733    }
734
735    #[test]
736    fn insert() {
737        let mut v = Stack::from([0, 1, 2, 4, 5, 0x41414141]);
738        v.pop();
739        v.insert(3, 3);
740
741        assert_eq!(&[0, 1, 2, 3, 4, 5], v.as_slice())
742    }
743
744    #[test]
745    #[should_panic = "Attempted to insert into full stack"]
746    fn insert_overflow() {
747        let mut v = Stack::from([0]);
748        v.insert(0, 1);
749    }
750
751    #[test]
752    fn drop() {
753        let v = Stack::from([
754            Box::new(0),
755            Box::new(1),
756            Box::new(2),
757            Box::new(3),
758            Box::new(4),
759        ]);
760        std::mem::drop(std::hint::black_box(v));
761    }
762
763    #[test]
764    fn drop_zst() {
765        struct Droppable;
766        impl Drop for Droppable {
767            fn drop(&mut self) {
768                use std::sync::atomic::{AtomicU32, Ordering};
769                static V: AtomicU32 = AtomicU32::new(1);
770                eprintln!("{}", V.fetch_add(1, Ordering::Relaxed));
771            }
772        }
773
774        let v = Stack::from([const { Droppable }; 10]);
775        std::mem::drop(v);
776    }
777}