Skip to main content

tokio/util/
linked_list.rs

1#![cfg_attr(not(feature = "full"), allow(dead_code))]
2// It doesn't make sense to enforce `unsafe_op_in_unsafe_fn` for this module because
3//
4// * The intrusive linked list naturally relies on unsafe operations.
5// * Excessive `unsafe {}` blocks hurt readability significantly.
6// TODO: replace with `#[expect(unsafe_op_in_unsafe_fn)]` after bumpping
7// the MSRV to 1.81.0.
8#![allow(unsafe_op_in_unsafe_fn)]
9
10//! An intrusive double linked list of data.
11//!
12//! The data structure supports tracking pinned nodes. Most of the data
13//! structure's APIs are `unsafe` as they require the caller to ensure the
14//! specified node is actually contained by the list.
15
16use core::cell::UnsafeCell;
17use core::fmt;
18use core::marker::PhantomPinned;
19use core::mem::ManuallyDrop;
20use core::ptr::{self, NonNull};
21
22/// An intrusive linked list.
23///
24/// Currently, the list is not emptied on drop. It is the caller's
25/// responsibility to ensure the list is empty before dropping it.
26pub(crate) struct LinkedList<L: Link> {
27    /// Linked list head
28    head: Option<NonNull<L::Target>>,
29
30    /// Linked list tail
31    tail: Option<NonNull<L::Target>>,
32}
33
34unsafe impl<L: Link> Send for LinkedList<L> where L::Target: Send {}
35unsafe impl<L: Link> Sync for LinkedList<L> where L::Target: Sync {}
36
37/// Defines how a type is tracked within a linked list.
38///
39/// In order to support storing a single type within multiple lists, accessing
40/// the list pointers is decoupled from the entry type.
41///
42/// # Safety
43///
44/// Implementations must guarantee that `Target` types are pinned in memory. In
45/// other words, when a node is inserted, the value will not be moved as long as
46/// it is stored in the list.
47pub(crate) unsafe trait Link {
48    /// Handle to the list entry.
49    ///
50    /// This is usually a pointer-ish type.
51    type Handle;
52
53    /// Node type.
54    type Target;
55
56    /// Convert the handle to a raw pointer without consuming the handle.
57    fn as_raw(handle: &Self::Handle) -> NonNull<Self::Target>;
58
59    /// Convert the raw pointer to a handle
60    unsafe fn from_raw(ptr: NonNull<Self::Target>) -> Self::Handle;
61
62    /// Return the pointers for a node
63    ///
64    /// # Safety
65    ///
66    /// The resulting pointer should have the same tag in the stacked-borrows
67    /// stack as the argument. In particular, the method may not create an
68    /// intermediate reference in the process of creating the resulting raw
69    /// pointer.
70    ///
71    /// The `target` pointer must be valid.
72    unsafe fn pointers(target: NonNull<Self::Target>) -> NonNull<Pointers<Self::Target>>;
73}
74
75/// Previous / next pointers.
76pub(crate) struct Pointers<T> {
77    inner: UnsafeCell<PointersInner<T>>,
78}
79/// We do not want the compiler to put the `noalias` attribute on mutable
80/// references to this type, so the type has been made `!Unpin` with a
81/// `PhantomPinned` field.
82///
83/// Additionally, we never access the `prev` or `next` fields directly, as any
84/// such access would implicitly involve the creation of a reference to the
85/// field, which we want to avoid since the fields are not `!Unpin`, and would
86/// hence be given the `noalias` attribute if we were to do such an access. As
87/// an alternative to accessing the fields directly, the `Pointers` type
88/// provides getters and setters for the two fields, and those are implemented
89/// using `ptr`-specific methods which avoids the creation of intermediate
90/// references.
91///
92/// See this link for more information:
93/// <https://github.com/rust-lang/rust/pull/82834>
94struct PointersInner<T> {
95    /// The previous node in the list. null if there is no previous node.
96    prev: Option<NonNull<T>>,
97
98    /// The next node in the list. null if there is no previous node.
99    next: Option<NonNull<T>>,
100
101    /// This type is !Unpin due to the heuristic from:
102    /// <https://github.com/rust-lang/rust/pull/82834>
103    _pin: PhantomPinned,
104}
105
106unsafe impl<T: Send> Send for Pointers<T> {}
107unsafe impl<T: Sync> Sync for Pointers<T> {}
108
109// ===== impl LinkedList =====
110
111impl<L: Link> LinkedList<L> {
112    /// Creates an empty linked list.
113    pub(crate) const fn new() -> LinkedList<L> {
114        LinkedList {
115            head: None,
116            tail: None,
117        }
118    }
119
120    /// Adds an element first in the list.
121    pub(crate) fn push_front(&mut self, val: L::Handle) {
122        // The value should not be dropped, it is being inserted into the list
123        let val = ManuallyDrop::new(val);
124        let ptr = L::as_raw(&val);
125        assert_ne!(self.head, Some(ptr));
126        unsafe {
127            L::pointers(ptr).as_mut().set_next(self.head);
128            L::pointers(ptr).as_mut().set_prev(None);
129
130            if let Some(head) = self.head {
131                L::pointers(head).as_mut().set_prev(Some(ptr));
132            }
133
134            self.head = Some(ptr);
135
136            if self.tail.is_none() {
137                self.tail = Some(ptr);
138            }
139        }
140    }
141
142    /// Removes the first element from a list and returns it, or None if it is
143    /// empty.
144    pub(crate) fn pop_front(&mut self) -> Option<L::Handle> {
145        unsafe {
146            let head = self.head?;
147            self.head = L::pointers(head).as_ref().get_next();
148
149            if let Some(new_head) = L::pointers(head).as_ref().get_next() {
150                L::pointers(new_head).as_mut().set_prev(None);
151            } else {
152                self.tail = None;
153            }
154
155            L::pointers(head).as_mut().set_prev(None);
156            L::pointers(head).as_mut().set_next(None);
157
158            Some(L::from_raw(head))
159        }
160    }
161
162    /// Removes the last element from a list and returns it, or None if it is
163    /// empty.
164    pub(crate) fn pop_back(&mut self) -> Option<L::Handle> {
165        unsafe {
166            let last = self.tail?;
167            self.tail = L::pointers(last).as_ref().get_prev();
168
169            if let Some(prev) = L::pointers(last).as_ref().get_prev() {
170                L::pointers(prev).as_mut().set_next(None);
171            } else {
172                self.head = None;
173            }
174
175            L::pointers(last).as_mut().set_prev(None);
176            L::pointers(last).as_mut().set_next(None);
177
178            Some(L::from_raw(last))
179        }
180    }
181
182    /// Returns whether the linked list does not contain any node
183    pub(crate) fn is_empty(&self) -> bool {
184        if self.head.is_some() {
185            return false;
186        }
187
188        assert!(self.tail.is_none());
189        true
190    }
191
192    /// Removes the specified node from the list
193    ///
194    /// # Safety
195    ///
196    /// The caller **must** ensure that exactly one of the following is true:
197    /// - `node` is currently contained by `self`,
198    /// - `node` is not contained by any list,
199    /// - `node` is currently contained by some other `GuardedLinkedList` **and**
200    ///   the caller has an exclusive access to that list. This condition is
201    ///   used by the linked list in `sync::Notify`.
202    pub(crate) unsafe fn remove(&mut self, node: NonNull<L::Target>) -> Option<L::Handle> {
203        if let Some(prev) = L::pointers(node).as_ref().get_prev() {
204            debug_assert_eq!(L::pointers(prev).as_ref().get_next(), Some(node));
205            L::pointers(prev)
206                .as_mut()
207                .set_next(L::pointers(node).as_ref().get_next());
208        } else {
209            if self.head != Some(node) {
210                return None;
211            }
212
213            self.head = L::pointers(node).as_ref().get_next();
214        }
215
216        if let Some(next) = L::pointers(node).as_ref().get_next() {
217            debug_assert_eq!(L::pointers(next).as_ref().get_prev(), Some(node));
218            L::pointers(next)
219                .as_mut()
220                .set_prev(L::pointers(node).as_ref().get_prev());
221        } else {
222            // This might be the last item in the list
223            if self.tail != Some(node) {
224                return None;
225            }
226
227            self.tail = L::pointers(node).as_ref().get_prev();
228        }
229
230        L::pointers(node).as_mut().set_next(None);
231        L::pointers(node).as_mut().set_prev(None);
232
233        Some(L::from_raw(node))
234    }
235}
236
237impl<L: Link> fmt::Debug for LinkedList<L> {
238    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
239        f.debug_struct("LinkedList")
240            .field("head", &self.head)
241            .field("tail", &self.tail)
242            .finish()
243    }
244}
245
246#[cfg(any(
247    feature = "fs",
248    feature = "rt",
249    all(unix, feature = "process"),
250    feature = "signal",
251    feature = "sync",
252))]
253impl<L: Link> LinkedList<L> {
254    pub(crate) fn last(&self) -> Option<&L::Target> {
255        let tail = self.tail.as_ref()?;
256        unsafe { Some(&*tail.as_ptr()) }
257    }
258}
259
260impl<L: Link> Default for LinkedList<L> {
261    fn default() -> Self {
262        Self::new()
263    }
264}
265
266// ===== impl DrainFilter =====
267
268cfg_io_driver_impl! {
269    pub(crate) struct DrainFilter<'a, L: Link, F> {
270        list: &'a mut LinkedList<L>,
271        filter: F,
272        curr: Option<NonNull<L::Target>>,
273    }
274
275    impl<L: Link> LinkedList<L> {
276        pub(crate) fn drain_filter<F>(&mut self, filter: F) -> DrainFilter<'_, L, F>
277        where
278            F: FnMut(&L::Target) -> bool,
279        {
280            let curr = self.head;
281            DrainFilter {
282                curr,
283                filter,
284                list: self,
285            }
286        }
287    }
288
289    impl<'a, L: Link, F> Iterator for DrainFilter<'a, L, F>
290    where
291        F: FnMut(&L::Target) -> bool,
292    {
293        type Item = L::Handle;
294
295        fn next(&mut self) -> Option<Self::Item> {
296            while let Some(curr) = self.curr {
297                // safety: the pointer references data contained by the list
298                self.curr = unsafe { L::pointers(curr).as_ref() }.get_next();
299
300                // safety: the value is still owned by the linked list.
301                if (self.filter)(unsafe { &mut *curr.as_ptr() }) {
302                    return unsafe { self.list.remove(curr) };
303                }
304            }
305
306            None
307        }
308    }
309}
310
311cfg_taskdump! {
312    impl<L: Link> LinkedList<L> {
313        pub(crate) fn for_each<F>(&mut self, mut f: F)
314        where
315            F: FnMut(&L::Handle),
316        {
317            let mut next = self.head;
318
319            while let Some(curr) = next {
320                unsafe {
321                    let handle = ManuallyDrop::new(L::from_raw(curr));
322                    f(&handle);
323                    next = L::pointers(curr).as_ref().get_next();
324                }
325            }
326        }
327    }
328}
329
330// ===== impl GuardedLinkedList =====
331
332feature! {
333    #![any(
334        feature = "process",
335        feature = "sync",
336        feature = "rt",
337        feature = "signal",
338    )]
339
340    /// An intrusive linked list, but instead of keeping pointers to the head
341    /// and tail nodes, it uses a special guard node linked with those nodes.
342    /// It means that the list is circular and every pointer of a node from
343    /// the list is not `None`, including pointers from the guard node.
344    ///
345    /// If a list is empty, then both pointers of the guard node are pointing
346    /// at the guard node itself.
347    pub(crate) struct GuardedLinkedList<L: Link> {
348        /// Pointer to the guard node.
349        guard: NonNull<L::Target>,
350    }
351
352    impl<L: Link> LinkedList<L> {
353        /// Turns a linked list into the guarded version by linking the guard node
354        /// with the head and tail nodes. Like with other nodes, you should guarantee
355        /// that the guard node is pinned in memory.
356        pub(crate) fn into_guarded(self, guard_handle: L::Handle) -> GuardedLinkedList<L> {
357            // `guard_handle` is a NonNull pointer, we don't have to care about dropping it.
358            let guard = L::as_raw(&guard_handle);
359
360            unsafe {
361                if let Some(head) = self.head {
362                    debug_assert!(L::pointers(head).as_ref().get_prev().is_none());
363                    L::pointers(head).as_mut().set_prev(Some(guard));
364                    L::pointers(guard).as_mut().set_next(Some(head));
365
366                    // The list is not empty, so the tail cannot be `None`.
367                    let tail = self.tail.unwrap();
368                    debug_assert!(L::pointers(tail).as_ref().get_next().is_none());
369                    L::pointers(tail).as_mut().set_next(Some(guard));
370                    L::pointers(guard).as_mut().set_prev(Some(tail));
371                } else {
372                    // The list is empty.
373                    L::pointers(guard).as_mut().set_prev(Some(guard));
374                    L::pointers(guard).as_mut().set_next(Some(guard));
375                }
376            }
377
378            GuardedLinkedList { guard }
379        }
380    }
381
382    impl<L: Link> GuardedLinkedList<L> {
383        fn tail(&self) -> Option<NonNull<L::Target>> {
384            let tail_ptr = unsafe {
385                L::pointers(self.guard).as_ref().get_prev().unwrap()
386            };
387
388            // Compare the tail pointer with the address of the guard node itself.
389            // If the guard points at itself, then there are no other nodes and
390            // the list is considered empty.
391            if tail_ptr != self.guard {
392                Some(tail_ptr)
393            } else {
394                None
395            }
396        }
397
398        /// Removes the last element from a list and returns it, or None if it is
399        /// empty.
400        pub(crate) fn pop_back(&mut self) -> Option<L::Handle> {
401            unsafe {
402                let last = self.tail()?;
403                let before_last = L::pointers(last).as_ref().get_prev().unwrap();
404
405                L::pointers(self.guard).as_mut().set_prev(Some(before_last));
406                L::pointers(before_last).as_mut().set_next(Some(self.guard));
407
408                L::pointers(last).as_mut().set_prev(None);
409                L::pointers(last).as_mut().set_next(None);
410
411                Some(L::from_raw(last))
412            }
413        }
414    }
415}
416
417// ===== impl Pointers =====
418
419impl<T> Pointers<T> {
420    /// Create a new set of empty pointers
421    pub(crate) fn new() -> Pointers<T> {
422        Pointers {
423            inner: UnsafeCell::new(PointersInner {
424                prev: None,
425                next: None,
426                _pin: PhantomPinned,
427            }),
428        }
429    }
430
431    pub(crate) fn get_prev(&self) -> Option<NonNull<T>> {
432        // SAFETY: Field is accessed immutably through a reference.
433        unsafe { ptr::addr_of!((*self.inner.get()).prev).read() }
434    }
435    pub(crate) fn get_next(&self) -> Option<NonNull<T>> {
436        // SAFETY: Field is accessed immutably through a reference.
437        unsafe { ptr::addr_of!((*self.inner.get()).next).read() }
438    }
439
440    fn set_prev(&mut self, value: Option<NonNull<T>>) {
441        // SAFETY: Field is accessed mutably through a mutable reference.
442        unsafe {
443            ptr::addr_of_mut!((*self.inner.get()).prev).write(value);
444        }
445    }
446    fn set_next(&mut self, value: Option<NonNull<T>>) {
447        // SAFETY: Field is accessed mutably through a mutable reference.
448        unsafe {
449            ptr::addr_of_mut!((*self.inner.get()).next).write(value);
450        }
451    }
452}
453
454impl<T> fmt::Debug for Pointers<T> {
455    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
456        let prev = self.get_prev();
457        let next = self.get_next();
458        f.debug_struct("Pointers")
459            .field("prev", &prev)
460            .field("next", &next)
461            .finish()
462    }
463}
464
465#[cfg(any(test, fuzzing))]
466#[cfg(not(loom))]
467pub(crate) mod tests {
468    use super::*;
469
470    use std::pin::Pin;
471
472    #[derive(Debug)]
473    #[repr(C)]
474    struct Entry {
475        pointers: Pointers<Entry>,
476        val: i32,
477    }
478
479    unsafe impl<'a> Link for &'a Entry {
480        type Handle = Pin<&'a Entry>;
481        type Target = Entry;
482
483        fn as_raw(handle: &Pin<&'_ Entry>) -> NonNull<Entry> {
484            NonNull::from(handle.get_ref())
485        }
486
487        unsafe fn from_raw(ptr: NonNull<Entry>) -> Pin<&'a Entry> {
488            Pin::new_unchecked(&*ptr.as_ptr())
489        }
490
491        unsafe fn pointers(target: NonNull<Entry>) -> NonNull<Pointers<Entry>> {
492            target.cast()
493        }
494    }
495
496    fn entry(val: i32) -> Pin<Box<Entry>> {
497        Box::pin(Entry {
498            pointers: Pointers::new(),
499            val,
500        })
501    }
502
503    fn ptr(r: &Pin<Box<Entry>>) -> NonNull<Entry> {
504        r.as_ref().get_ref().into()
505    }
506
507    fn collect_list(list: &mut LinkedList<&'_ Entry>) -> Vec<i32> {
508        let mut ret = vec![];
509
510        while let Some(entry) = list.pop_back() {
511            ret.push(entry.val);
512        }
513
514        ret
515    }
516
517    fn push_all<'a>(list: &mut LinkedList<&'a Entry>, entries: &[Pin<&'a Entry>]) {
518        for entry in entries.iter() {
519            list.push_front(*entry);
520        }
521    }
522
523    #[cfg(test)]
524    macro_rules! assert_clean {
525        ($e:ident) => {{
526            assert!($e.pointers.get_next().is_none());
527            assert!($e.pointers.get_prev().is_none());
528        }};
529    }
530
531    #[cfg(test)]
532    macro_rules! assert_ptr_eq {
533        ($a:expr, $b:expr) => {{
534            // Deal with mapping a Pin<&mut T> -> Option<NonNull<T>>
535            assert_eq!(Some($a.as_ref().get_ref().into()), $b)
536        }};
537    }
538
539    #[test]
540    fn const_new() {
541        const _: LinkedList<&Entry> = LinkedList::new();
542    }
543
544    #[test]
545    fn push_and_drain() {
546        let a = entry(5);
547        let b = entry(7);
548        let c = entry(31);
549
550        let mut list = LinkedList::new();
551        assert!(list.is_empty());
552
553        list.push_front(a.as_ref());
554        assert!(!list.is_empty());
555        list.push_front(b.as_ref());
556        list.push_front(c.as_ref());
557
558        let items: Vec<i32> = collect_list(&mut list);
559        assert_eq!([5, 7, 31].to_vec(), items);
560
561        assert!(list.is_empty());
562    }
563
564    #[test]
565    fn push_pop_push_pop() {
566        let a = entry(5);
567        let b = entry(7);
568
569        let mut list = LinkedList::<&Entry>::new();
570
571        list.push_front(a.as_ref());
572
573        let entry = list.pop_back().unwrap();
574        assert_eq!(5, entry.val);
575        assert!(list.is_empty());
576
577        list.push_front(b.as_ref());
578
579        let entry = list.pop_back().unwrap();
580        assert_eq!(7, entry.val);
581
582        assert!(list.is_empty());
583        assert!(list.pop_back().is_none());
584    }
585
586    #[test]
587    fn remove_by_address() {
588        let a = entry(5);
589        let b = entry(7);
590        let c = entry(31);
591
592        unsafe {
593            // Remove first
594            let mut list = LinkedList::new();
595
596            push_all(&mut list, &[c.as_ref(), b.as_ref(), a.as_ref()]);
597            assert!(list.remove(ptr(&a)).is_some());
598            assert_clean!(a);
599            // `a` should be no longer there and can't be removed twice
600            assert!(list.remove(ptr(&a)).is_none());
601            assert!(!list.is_empty());
602
603            assert!(list.remove(ptr(&b)).is_some());
604            assert_clean!(b);
605            // `b` should be no longer there and can't be removed twice
606            assert!(list.remove(ptr(&b)).is_none());
607            assert!(!list.is_empty());
608
609            assert!(list.remove(ptr(&c)).is_some());
610            assert_clean!(c);
611            // `b` should be no longer there and can't be removed twice
612            assert!(list.remove(ptr(&c)).is_none());
613            assert!(list.is_empty());
614        }
615
616        unsafe {
617            // Remove middle
618            let mut list = LinkedList::new();
619
620            push_all(&mut list, &[c.as_ref(), b.as_ref(), a.as_ref()]);
621
622            assert!(list.remove(ptr(&a)).is_some());
623            assert_clean!(a);
624
625            assert_ptr_eq!(b, list.head);
626            assert_ptr_eq!(c, b.pointers.get_next());
627            assert_ptr_eq!(b, c.pointers.get_prev());
628
629            let items = collect_list(&mut list);
630            assert_eq!([31, 7].to_vec(), items);
631        }
632
633        unsafe {
634            // Remove middle
635            let mut list = LinkedList::new();
636
637            push_all(&mut list, &[c.as_ref(), b.as_ref(), a.as_ref()]);
638
639            assert!(list.remove(ptr(&b)).is_some());
640            assert_clean!(b);
641
642            assert_ptr_eq!(c, a.pointers.get_next());
643            assert_ptr_eq!(a, c.pointers.get_prev());
644
645            let items = collect_list(&mut list);
646            assert_eq!([31, 5].to_vec(), items);
647        }
648
649        unsafe {
650            // Remove last
651            // Remove middle
652            let mut list = LinkedList::new();
653
654            push_all(&mut list, &[c.as_ref(), b.as_ref(), a.as_ref()]);
655
656            assert!(list.remove(ptr(&c)).is_some());
657            assert_clean!(c);
658
659            assert!(b.pointers.get_next().is_none());
660            assert_ptr_eq!(b, list.tail);
661
662            let items = collect_list(&mut list);
663            assert_eq!([7, 5].to_vec(), items);
664        }
665
666        unsafe {
667            // Remove first of two
668            let mut list = LinkedList::new();
669
670            push_all(&mut list, &[b.as_ref(), a.as_ref()]);
671
672            assert!(list.remove(ptr(&a)).is_some());
673
674            assert_clean!(a);
675
676            // a should be no longer there and can't be removed twice
677            assert!(list.remove(ptr(&a)).is_none());
678
679            assert_ptr_eq!(b, list.head);
680            assert_ptr_eq!(b, list.tail);
681
682            assert!(b.pointers.get_next().is_none());
683            assert!(b.pointers.get_prev().is_none());
684
685            let items = collect_list(&mut list);
686            assert_eq!([7].to_vec(), items);
687        }
688
689        unsafe {
690            // Remove last of two
691            let mut list = LinkedList::new();
692
693            push_all(&mut list, &[b.as_ref(), a.as_ref()]);
694
695            assert!(list.remove(ptr(&b)).is_some());
696
697            assert_clean!(b);
698
699            assert_ptr_eq!(a, list.head);
700            assert_ptr_eq!(a, list.tail);
701
702            assert!(a.pointers.get_next().is_none());
703            assert!(a.pointers.get_prev().is_none());
704
705            let items = collect_list(&mut list);
706            assert_eq!([5].to_vec(), items);
707        }
708
709        unsafe {
710            // Remove last item
711            let mut list = LinkedList::new();
712
713            push_all(&mut list, &[a.as_ref()]);
714
715            assert!(list.remove(ptr(&a)).is_some());
716            assert_clean!(a);
717
718            assert!(list.head.is_none());
719            assert!(list.tail.is_none());
720            let items = collect_list(&mut list);
721            assert!(items.is_empty());
722        }
723
724        unsafe {
725            // Remove missing
726            let mut list = LinkedList::<&Entry>::new();
727
728            list.push_front(b.as_ref());
729            list.push_front(a.as_ref());
730
731            assert!(list.remove(ptr(&c)).is_none());
732        }
733    }
734
735    /// This is a fuzz test. You run it by entering `cargo fuzz run fuzz_linked_list` in CLI in `/tokio/` module.
736    #[cfg(fuzzing)]
737    pub fn fuzz_linked_list(ops: &[u8]) {
738        enum Op {
739            Push,
740            Pop,
741            Remove(usize),
742        }
743        use std::collections::VecDeque;
744
745        let ops = ops
746            .iter()
747            .map(|i| match i % 3u8 {
748                0 => Op::Push,
749                1 => Op::Pop,
750                2 => Op::Remove((i / 3u8) as usize),
751                _ => unreachable!(),
752            })
753            .collect::<Vec<_>>();
754
755        let mut ll = LinkedList::<&Entry>::new();
756        let mut reference = VecDeque::new();
757
758        let entries: Vec<_> = (0..ops.len()).map(|i| entry(i as i32)).collect();
759
760        for (i, op) in ops.iter().enumerate() {
761            match op {
762                Op::Push => {
763                    reference.push_front(i as i32);
764                    assert_eq!(entries[i].val, i as i32);
765
766                    ll.push_front(entries[i].as_ref());
767                }
768                Op::Pop => {
769                    if reference.is_empty() {
770                        assert!(ll.is_empty());
771                        continue;
772                    }
773
774                    let v = reference.pop_back();
775                    assert_eq!(v, ll.pop_back().map(|v| v.val));
776                }
777                Op::Remove(n) => {
778                    if reference.is_empty() {
779                        assert!(ll.is_empty());
780                        continue;
781                    }
782
783                    let idx = n % reference.len();
784                    let expect = reference.remove(idx).unwrap();
785
786                    unsafe {
787                        let entry = ll.remove(ptr(&entries[expect as usize])).unwrap();
788                        assert_eq!(expect, entry.val);
789                    }
790                }
791            }
792        }
793    }
794}