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
33 println!("{} {}", a, b);
37 <anon>:3:18: 3:22 error: cannot borrow immutable indexed content `x[..]` as mutable
38 <anon>:3 let a = &mut x[0];
40 <anon>:4:18: 4:22 error: cannot borrow immutable indexed content `x[..]` as mutable
41 <anon>:4 let b = &mut x[1];
43 error: aborting due to 2 previous errors
46 While it was plausible that borrowck could understand this simple case, it's
47 pretty clearly hopeless for borrowck to understand disjointness in general
48 container types like a tree, especially if distinct keys actually *do* map
51 In order to "teach" borrowck that what we're doing is ok, we need to drop down
52 to unsafe code. For instance, mutable slices expose a `split_at_mut` function
53 that consumes the slice and returns *two* mutable slices. One for everything to
54 the left of the index, and one for everything to the right. Intuitively we know
55 this is safe because the slices don't overlap, and therefore alias. However
56 the implementation requires some unsafety:
59 fn split_at_mut(&mut self, mid: usize) -> (&mut [T], &mut [T]) {
61 let ptr = self.as_mut_ptr();
64 (from_raw_parts_mut(ptr, mid),
65 from_raw_parts_mut(ptr.offset(mid as isize), len - mid))
70 This is actually a bit subtle. So as to avoid ever making two `&mut`'s to the
71 same value, we explicitly construct brand-new slices through raw pointers.
73 However more subtle is how iterators that yield mutable references work.
74 The iterator trait is defined as follows:
80 fn next(&mut self) -> Option<Self::Item>;
84 Given this definition, Self::Item has *no* connection to `self`. This means that
85 we can call `next` several times in a row, and hold onto all the results
86 *concurrently*. This is perfectly fine for by-value iterators, which have
87 exactly these semantics. It's also actually fine for shared references, as they
88 admit arbitrarily many references to the same thing (although the iterator needs
89 to be a separate object from the thing being shared).
91 But mutable references make this a mess. At first glance, they might seem
92 completely incompatible with this API, as it would produce multiple mutable
93 references to the same object!
95 However it actually *does* work, exactly because iterators are one-shot objects.
96 Everything an IterMut yields will be yielded *at most* once, so we don't
97 *actually* ever yield multiple mutable references to the same piece of data.
99 Perhaps surprisingly, mutable iterators *don't* require unsafe code to be
100 implemented for many types!
102 For instance here's a singly linked list:
106 type Link<T> = Option<Box<Node<T>>>;
113 pub struct LinkedList<T> {
117 pub struct IterMut<'a, T: 'a>(Option<&'a mut Node<T>>);
119 impl<T> LinkedList<T> {
120 fn iter_mut(&mut self) -> IterMut<T> {
121 IterMut(self.head.as_mut().map(|node| &mut **node))
125 impl<'a, T> Iterator for IterMut<'a, T> {
126 type Item = &'a mut T;
128 fn next(&mut self) -> Option<Self::Item> {
129 self.0.take().map(|node| {
130 self.0 = node.next.as_mut().map(|node| &mut **node);
137 Here's a mutable slice:
143 pub struct IterMut<'a, T: 'a>(&'a mut[T]);
145 impl<'a, T> Iterator for IterMut<'a, T> {
146 type Item = &'a mut T;
148 fn next(&mut self) -> Option<Self::Item> {
149 let slice = mem::replace(&mut self.0, &mut []);
150 if slice.is_empty() { return None; }
152 let (l, r) = slice.split_at_mut(1);
158 impl<'a, T> DoubleEndedIterator for IterMut<'a, T> {
159 fn next_back(&mut self) -> Option<Self::Item> {
160 let slice = mem::replace(&mut self.0, &mut []);
161 if slice.is_empty() { return None; }
163 let new_len = slice.len() - 1;
164 let (l, r) = slice.split_at_mut(new_len);
171 And here's a binary tree:
175 use std::collections::VecDeque;
177 type Link<T> = Option<Box<Node<T>>>;
189 struct NodeIterMut<'a, T: 'a> {
190 elem: Option<&'a mut T>,
191 left: Option<&'a mut Node<T>>,
192 right: Option<&'a mut Node<T>>,
195 enum State<'a, T: 'a> {
197 Node(&'a mut Node<T>),
200 pub struct IterMut<'a, T: 'a>(VecDeque<NodeIterMut<'a, T>>);
203 pub fn iter_mut(&mut self) -> IterMut<T> {
204 let mut deque = VecDeque::new();
205 self.root.as_mut().map(|root| deque.push_front(root.iter_mut()));
211 pub fn iter_mut(&mut self) -> NodeIterMut<T> {
213 elem: Some(&mut self.elem),
214 left: self.left.as_mut().map(|node| &mut **node),
215 right: self.right.as_mut().map(|node| &mut **node),
221 impl<'a, T> Iterator for NodeIterMut<'a, T> {
222 type Item = State<'a, T>;
224 fn next(&mut self) -> Option<Self::Item> {
225 match self.left.take() {
226 Some(node) => Some(State::Node(node)),
227 None => match self.elem.take() {
228 Some(elem) => Some(State::Elem(elem)),
229 None => match self.right.take() {
230 Some(node) => Some(State::Node(node)),
238 impl<'a, T> DoubleEndedIterator for NodeIterMut<'a, T> {
239 fn next_back(&mut self) -> Option<Self::Item> {
240 match self.right.take() {
241 Some(node) => Some(State::Node(node)),
242 None => match self.elem.take() {
243 Some(elem) => Some(State::Elem(elem)),
244 None => match self.left.take() {
245 Some(node) => Some(State::Node(node)),
253 impl<'a, T> Iterator for IterMut<'a, T> {
254 type Item = &'a mut T;
255 fn next(&mut self) -> Option<Self::Item> {
257 match self.0.front_mut().and_then(|node_it| node_it.next()) {
258 Some(State::Elem(elem)) => return Some(elem),
259 Some(State::Node(node)) => self.0.push_front(node.iter_mut()),
260 None => if let None = self.0.pop_front() { return None },
266 impl<'a, T> DoubleEndedIterator for IterMut<'a, T> {
267 fn next_back(&mut self) -> Option<Self::Item> {
269 match self.0.back_mut().and_then(|node_it| node_it.next_back()) {
270 Some(State::Elem(elem)) => return Some(elem),
271 Some(State::Node(node)) => self.0.push_back(node.iter_mut()),
272 None => if let None = self.0.pop_back() { return None },
279 All of these are completely safe and work on stable Rust! This ultimately
280 falls out of the simple struct case we saw before: Rust understands that you
281 can safely split a mutable reference into subfields. We can then encode
282 permanently consuming a reference via Options (or in the case of slices,
283 replacing with an empty slice).