about summary refs log tree commit diff
diff options
context:
space:
mode:
authorFelix S. Klock II <pnkfelix@pnkfx.org>2019-06-21 12:50:18 +0200
committerFelix S. Klock II <pnkfelix@pnkfx.org>2019-06-21 12:52:54 +0200
commit3b8ef010309f732d4ab04e63ba454383b69db2de (patch)
treed0e2d49bd1b23fd9c7ab654d568a36d74951dfa9
parent241ceeda046b23651aec95a6bd59cca7aaa69ecc (diff)
downloadrust-3b8ef010309f732d4ab04e63ba454383b69db2de.tar.gz
rust-3b8ef010309f732d4ab04e63ba454383b69db2de.zip
Add test that our handling of projections hasn't gone too far:
overwriting one field should not allow reborrow of an unrelated field.
-rw-r--r--src/test/ui/nll/issue-62007-assign-differing-fields.rs25
-rw-r--r--src/test/ui/nll/issue-62007-assign-differing-fields.stderr27
2 files changed, 52 insertions, 0 deletions
diff --git a/src/test/ui/nll/issue-62007-assign-differing-fields.rs b/src/test/ui/nll/issue-62007-assign-differing-fields.rs
new file mode 100644
index 00000000000..29d92b7b85c
--- /dev/null
+++ b/src/test/ui/nll/issue-62007-assign-differing-fields.rs
@@ -0,0 +1,25 @@
+// Double-check we didn't go too far with our resolution to issue
+// #62007: assigning over a field projection (`list.1 = n;` in this
+// case) should kill only borrows of `list.1`; `list.0` can *not*
+// necessarily be borrowed on the next iteration through the loop.
+
+#![allow(dead_code)]
+
+struct List<T> {
+    value: T,
+    next: Option<Box<List<T>>>,
+}
+
+fn to_refs<'a, T>(mut list: (&'a mut List<T>, &'a mut List<T>)) -> Vec<&'a mut T> {
+    let mut result = vec![];
+    loop {
+        result.push(&mut (list.0).value); //~ ERROR cannot borrow `list.0.value` as mutable
+        if let Some(n) = (list.0).next.as_mut() { //~ ERROR cannot borrow `list.0.next` as mutable
+            list.1 = n;
+        } else {
+            return result;
+        }
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/issue-62007-assign-differing-fields.stderr b/src/test/ui/nll/issue-62007-assign-differing-fields.stderr
new file mode 100644
index 00000000000..f942d7628b5
--- /dev/null
+++ b/src/test/ui/nll/issue-62007-assign-differing-fields.stderr
@@ -0,0 +1,27 @@
+error[E0499]: cannot borrow `list.0.value` as mutable more than once at a time
+  --> $DIR/issue-62007-assign-differing-fields.rs:16:21
+   |
+LL | fn to_refs<'a, T>(mut list: (&'a mut List<T>, &'a mut List<T>)) -> Vec<&'a mut T> {
+   |            -- lifetime `'a` defined here
+...
+LL |         result.push(&mut (list.0).value);
+   |                     ^^^^^^^^^^^^^^^^^^^ mutable borrow starts here in previous iteration of loop
+...
+LL |             return result;
+   |                    ------ returning this value requires that `list.0.value` is borrowed for `'a`
+
+error[E0499]: cannot borrow `list.0.next` as mutable more than once at a time
+  --> $DIR/issue-62007-assign-differing-fields.rs:17:26
+   |
+LL | fn to_refs<'a, T>(mut list: (&'a mut List<T>, &'a mut List<T>)) -> Vec<&'a mut T> {
+   |            -- lifetime `'a` defined here
+...
+LL |         if let Some(n) = (list.0).next.as_mut() {
+   |                          ^^^^^^^^^^^^^---------
+   |                          |
+   |                          mutable borrow starts here in previous iteration of loop
+   |                          argument requires that `list.0.next` is borrowed for `'a`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0499`.