Skip to content

Commit 289d5db

Browse files
author
Ulrik Sverdrup
committed
linked_list: Use unsafe properly for Rawlink methods
1 parent a090e1f commit 289d5db

File tree

1 file changed

+70
-48
lines changed

1 file changed

+70
-48
lines changed

src/libcollections/linked_list.rs

Lines changed: 70 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -104,17 +104,23 @@ impl<T> Rawlink<T> {
104104
}
105105

106106
/// Convert the `Rawlink` into an Option value
107-
fn resolve_immut<'a>(&self) -> Option<&'a T> {
108-
unsafe {
109-
self.p.as_ref()
110-
}
107+
///
108+
/// **unsafe** because:
109+
///
110+
/// - Dereference of raw pointer.
111+
/// - Returns reference of arbitrary lifetime.
112+
unsafe fn resolve<'a>(&self) -> Option<&'a T> {
113+
self.p.as_ref()
111114
}
112115

113116
/// Convert the `Rawlink` into an Option value
114-
fn resolve<'a>(&mut self) -> Option<&'a mut T> {
115-
unsafe {
116-
self.p.as_mut()
117-
}
117+
///
118+
/// **unsafe** because:
119+
///
120+
/// - Dereference of raw pointer.
121+
/// - Returns reference of arbitrary lifetime.
122+
unsafe fn resolve_mut<'a>(&mut self) -> Option<&'a mut T> {
123+
self.p.as_mut()
118124
}
119125

120126
/// Return the `Rawlink` and replace with `Rawlink::none()`
@@ -179,7 +185,7 @@ impl<T> LinkedList<T> {
179185
/// Add a Node last in the list
180186
#[inline]
181187
fn push_back_node(&mut self, mut new_tail: Box<Node<T>>) {
182-
match self.list_tail.resolve() {
188+
match unsafe { self.list_tail.resolve_mut() } {
183189
None => return self.push_front_node(new_tail),
184190
Some(tail) => {
185191
self.list_tail = Rawlink::some(&mut *new_tail);
@@ -192,14 +198,16 @@ impl<T> LinkedList<T> {
192198
/// Remove the last Node and return it, or None if the list is empty
193199
#[inline]
194200
fn pop_back_node(&mut self) -> Option<Box<Node<T>>> {
195-
self.list_tail.resolve().map_or(None, |tail| {
196-
self.length -= 1;
197-
self.list_tail = tail.prev;
198-
match tail.prev.resolve() {
199-
None => self.list_head.take(),
200-
Some(tail_prev) => tail_prev.next.take()
201-
}
202-
})
201+
unsafe {
202+
self.list_tail.resolve_mut().and_then(|tail| {
203+
self.length -= 1;
204+
self.list_tail = tail.prev;
205+
match tail.prev.resolve_mut() {
206+
None => self.list_head.take(),
207+
Some(tail_prev) => tail_prev.next.take()
208+
}
209+
})
210+
}
203211
}
204212
}
205213

@@ -246,7 +254,7 @@ impl<T> LinkedList<T> {
246254
/// ```
247255
#[stable(feature = "rust1", since = "1.0.0")]
248256
pub fn append(&mut self, other: &mut LinkedList<T>) {
249-
match self.list_tail.resolve() {
257+
match unsafe { self.list_tail.resolve_mut() } {
250258
None => {
251259
self.length = other.length;
252260
self.list_head = other.list_head.take();
@@ -433,7 +441,9 @@ impl<T> LinkedList<T> {
433441
#[inline]
434442
#[stable(feature = "rust1", since = "1.0.0")]
435443
pub fn back(&self) -> Option<&T> {
436-
self.list_tail.resolve_immut().as_ref().map(|tail| &tail.value)
444+
unsafe {
445+
self.list_tail.resolve().map(|tail| &tail.value)
446+
}
437447
}
438448

439449
/// Provides a mutable reference to the back element, or `None` if the list
@@ -460,7 +470,9 @@ impl<T> LinkedList<T> {
460470
#[inline]
461471
#[stable(feature = "rust1", since = "1.0.0")]
462472
pub fn back_mut(&mut self) -> Option<&mut T> {
463-
self.list_tail.resolve().map(|tail| &mut tail.value)
473+
unsafe {
474+
self.list_tail.resolve_mut().map(|tail| &mut tail.value)
475+
}
464476
}
465477

466478
/// Adds an element first in the list.
@@ -609,12 +621,14 @@ impl<T> LinkedList<T> {
609621
length: len - at
610622
};
611623

612-
// Swap split_node.next with list_head (which is None), nulling out split_node.next,
613-
// as it is the new tail.
614-
mem::swap(&mut split_node.resolve().unwrap().next, &mut splitted_list.list_head);
615-
// Null out list_head.prev. Note this `unwrap` won't fail because if at == len
616-
// we already branched out at the top of the fn to return the empty list.
617-
splitted_list.list_head.as_mut().unwrap().prev = Rawlink::none();
624+
unsafe {
625+
// Swap split_node.next with list_head (which is None), nulling out split_node.next,
626+
// as it is the new tail.
627+
mem::swap(&mut split_node.resolve_mut().unwrap().next, &mut splitted_list.list_head);
628+
// Null out list_head.prev. Note this `unwrap` won't fail because if at == len
629+
// we already branched out at the top of the fn to return the empty list.
630+
splitted_list.list_head.as_mut().unwrap().prev = Rawlink::none();
631+
}
618632
// Fix the tail ptr
619633
self.list_tail = split_node;
620634
self.length = at;
@@ -666,11 +680,13 @@ impl<'a, A> DoubleEndedIterator for Iter<'a, A> {
666680
if self.nelem == 0 {
667681
return None;
668682
}
669-
self.tail.resolve_immut().as_ref().map(|prev| {
670-
self.nelem -= 1;
671-
self.tail = prev.prev;
672-
&prev.value
673-
})
683+
unsafe {
684+
self.tail.resolve().map(|prev| {
685+
self.nelem -= 1;
686+
self.tail = prev.prev;
687+
&prev.value
688+
})
689+
}
674690
}
675691
}
676692

@@ -685,14 +701,16 @@ impl<'a, A> Iterator for IterMut<'a, A> {
685701
if self.nelem == 0 {
686702
return None;
687703
}
688-
self.head.resolve().map(|next| {
689-
self.nelem -= 1;
690-
self.head = match next.next {
691-
Some(ref mut node) => Rawlink::some(&mut **node),
692-
None => Rawlink::none(),
693-
};
694-
&mut next.value
695-
})
704+
unsafe {
705+
self.head.resolve_mut().map(|next| {
706+
self.nelem -= 1;
707+
self.head = match next.next {
708+
Some(ref mut node) => Rawlink::some(&mut **node),
709+
None => Rawlink::none(),
710+
};
711+
&mut next.value
712+
})
713+
}
696714
}
697715

698716
#[inline]
@@ -708,11 +726,13 @@ impl<'a, A> DoubleEndedIterator for IterMut<'a, A> {
708726
if self.nelem == 0 {
709727
return None;
710728
}
711-
self.tail.resolve().map(|prev| {
712-
self.nelem -= 1;
713-
self.tail = prev.prev;
714-
&mut prev.value
715-
})
729+
unsafe {
730+
self.tail.resolve_mut().map(|prev| {
731+
self.nelem -= 1;
732+
self.tail = prev.prev;
733+
&mut prev.value
734+
})
735+
}
716736
}
717737
}
718738

@@ -726,10 +746,10 @@ impl<'a, A> IterMut<'a, A> {
726746
// previously yielded element and self.head.
727747
//
728748
// The inserted node will not appear in further iteration.
729-
match self.head.resolve() {
749+
match unsafe { self.head.resolve_mut() } {
730750
None => { self.list.push_back_node(ins_node); }
731751
Some(node) => {
732-
let prev_node = match node.prev.resolve() {
752+
let prev_node = match unsafe { node.prev.resolve_mut() } {
733753
None => return self.list.push_front_node(ins_node),
734754
Some(prev) => prev,
735755
};
@@ -795,7 +815,9 @@ impl<'a, A> IterMut<'a, A> {
795815
if self.nelem == 0 {
796816
return None
797817
}
798-
self.head.resolve().map(|head| &mut head.value)
818+
unsafe {
819+
self.head.resolve_mut().map(|head| &mut head.value)
820+
}
799821
}
800822
}
801823

@@ -947,7 +969,7 @@ mod tests {
947969
Some(ref node) => node_ptr = &**node,
948970
}
949971
loop {
950-
match (last_ptr, node_ptr.prev.resolve_immut()) {
972+
match unsafe { (last_ptr, node_ptr.prev.resolve()) } {
951973
(None , None ) => {}
952974
(None , _ ) => panic!("prev link for list_head"),
953975
(Some(p), Some(pptr)) => {

0 commit comments

Comments
 (0)