3 The mutual exclusion property of mutable references can be very limiting when
4 working with a composite structure. The borrow checker understands some basic
5 stuff, but will fall over pretty easily. It *does* understand structs
6 sufficiently to know that it's possible to borrow disjoint fields of a struct
7 simultaneously. So this works today:
16 let mut x = Foo {a: 0, b: 0, c: 0};
23 println!("{} {} {} {}", a, b, c, c2);
26 However borrowck doesn't understand arrays or slices in any way, so this doesn't
30 let mut x = [1, 2, 3];
33 println!("{} {}", a, b);
37 <anon>:4:14: 4:18 error: cannot borrow `x[..]` as mutable more than once at a time
38 <anon>:4 let b = &mut x[1];
40 <anon>:3:14: 3:18 note: previous borrow of `x[..]` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x[..]` until the borrow ends
41 <anon>:3 let a = &mut x[0];
43 <anon>:6:2: 6:2 note: previous borrow ends here
45 <anon>:2 let mut x = [1, 2, 3];
46 <anon>:3 let a = &mut x[0];
47 <anon>:4 let b = &mut x[1];
48 <anon>:5 println!("{} {}", a, b);
51 error: aborting due to 2 previous errors
54 While it was plausible that borrowck could understand this simple case, it's
55 pretty clearly hopeless for borrowck to understand disjointness in general
56 container types like a tree, especially if distinct keys actually *do* map
59 In order to "teach" borrowck that what we're doing is ok, we need to drop down
60 to unsafe code. For instance, mutable slices expose a `split_at_mut` function
61 that consumes the slice and returns *two* mutable slices. One for everything to
62 the left of the index, and one for everything to the right. Intuitively we know
63 this is safe because the slices don't overlap, and therefore alias. However
64 the implementation requires some unsafety:
67 fn split_at_mut(&mut self, mid: usize) -> (&mut [T], &mut [T]) {
69 let ptr = self.as_mut_ptr();
72 (from_raw_parts_mut(ptr, mid),
73 from_raw_parts_mut(ptr.offset(mid as isize), len - mid))
78 This is actually a bit subtle. So as to avoid ever making two `&mut`'s to the
79 same value, we explicitly construct brand-new slices through raw pointers.
81 However more subtle is how iterators that yield mutable references work.
82 The iterator trait is defined as follows:
88 fn next(&mut self) -> Option<Self::Item>;
92 Given this definition, Self::Item has *no* connection to `self`. This means that
93 we can call `next` several times in a row, and hold onto all the results
94 *concurrently*. This is perfectly fine for by-value iterators, which have
95 exactly these semantics. It's also actually fine for shared references, as they
96 admit arbitrarily many references to the same thing (although the iterator needs
97 to be a separate object from the thing being shared).
99 But mutable references make this a mess. At first glance, they might seem
100 completely incompatible with this API, as it would produce multiple mutable
101 references to the same object!
103 However it actually *does* work, exactly because iterators are one-shot objects.
104 Everything an IterMut yields will be yielded *at most* once, so we don't
105 *actually* ever yield multiple mutable references to the same piece of data.
107 Perhaps surprisingly, mutable iterators *don't* require unsafe code to be
108 implemented for many types!
110 For instance here's a singly linked list:
114 type Link<T> = Option<Box<Node<T>>>;
121 pub struct LinkedList<T> {
125 pub struct IterMut<'a, T: 'a>(Option<&'a mut Node<T>>);
127 impl<T> LinkedList<T> {
128 fn iter_mut(&mut self) -> IterMut<T> {
129 IterMut(self.head.as_mut().map(|node| &mut **node))
133 impl<'a, T> Iterator for IterMut<'a, T> {
134 type Item = &'a mut T;
136 fn next(&mut self) -> Option<Self::Item> {
137 self.0.take().map(|node| {
138 self.0 = node.next.as_mut().map(|node| &mut **node);
145 Here's a mutable slice:
151 pub struct IterMut<'a, T: 'a>(&'a mut[T]);
153 impl<'a, T> Iterator for IterMut<'a, T> {
154 type Item = &'a mut T;
156 fn next(&mut self) -> Option<Self::Item> {
157 let slice = mem::replace(&mut self.0, &mut []);
158 if slice.is_empty() { return None; }
160 let (l, r) = slice.split_at_mut(1);
166 impl<'a, T> DoubleEndedIterator for IterMut<'a, T> {
167 fn next_back(&mut self) -> Option<Self::Item> {
168 let slice = mem::replace(&mut self.0, &mut []);
169 if slice.is_empty() { return None; }
171 let new_len = slice.len() - 1;
172 let (l, r) = slice.split_at_mut(new_len);
179 And here's a binary tree:
183 use std::collections::VecDeque;
185 type Link<T> = Option<Box<Node<T>>>;
197 struct NodeIterMut<'a, T: 'a> {
198 elem: Option<&'a mut T>,
199 left: Option<&'a mut Node<T>>,
200 right: Option<&'a mut Node<T>>,
203 enum State<'a, T: 'a> {
205 Node(&'a mut Node<T>),
208 pub struct IterMut<'a, T: 'a>(VecDeque<NodeIterMut<'a, T>>);
211 pub fn iter_mut(&mut self) -> IterMut<T> {
212 let mut deque = VecDeque::new();
213 self.root.as_mut().map(|root| deque.push_front(root.iter_mut()));
219 pub fn iter_mut(&mut self) -> NodeIterMut<T> {
221 elem: Some(&mut self.elem),
222 left: self.left.as_mut().map(|node| &mut **node),
223 right: self.right.as_mut().map(|node| &mut **node),
229 impl<'a, T> Iterator for NodeIterMut<'a, T> {
230 type Item = State<'a, T>;
232 fn next(&mut self) -> Option<Self::Item> {
233 match self.left.take() {
234 Some(node) => Some(State::Node(node)),
235 None => match self.elem.take() {
236 Some(elem) => Some(State::Elem(elem)),
237 None => match self.right.take() {
238 Some(node) => Some(State::Node(node)),
246 impl<'a, T> DoubleEndedIterator for NodeIterMut<'a, T> {
247 fn next_back(&mut self) -> Option<Self::Item> {
248 match self.right.take() {
249 Some(node) => Some(State::Node(node)),
250 None => match self.elem.take() {
251 Some(elem) => Some(State::Elem(elem)),
252 None => match self.left.take() {
253 Some(node) => Some(State::Node(node)),
261 impl<'a, T> Iterator for IterMut<'a, T> {
262 type Item = &'a mut T;
263 fn next(&mut self) -> Option<Self::Item> {
265 match self.0.front_mut().and_then(|node_it| node_it.next()) {
266 Some(State::Elem(elem)) => return Some(elem),
267 Some(State::Node(node)) => self.0.push_front(node.iter_mut()),
268 None => if let None = self.0.pop_front() { return None },
274 impl<'a, T> DoubleEndedIterator for IterMut<'a, T> {
275 fn next_back(&mut self) -> Option<Self::Item> {
277 match self.0.back_mut().and_then(|node_it| node_it.next_back()) {
278 Some(State::Elem(elem)) => return Some(elem),
279 Some(State::Node(node)) => self.0.push_back(node.iter_mut()),
280 None => if let None = self.0.pop_back() { return None },
287 All of these are completely safe and work on stable Rust! This ultimately
288 falls out of the simple struct case we saw before: Rust understands that you
289 can safely split a mutable reference into subfields. We can then encode
290 permanently consuming a reference via Options (or in the case of slices,
291 replacing with an empty slice).