about summary refs log tree commit diff
diff options
context:
space:
mode:
authorlqd <remy.rakic+github@gmail.com>2019-07-16 17:32:38 +0200
committerlqd <remy.rakic+github@gmail.com>2019-07-22 12:46:54 +0200
commitd41e002111dd61efa08d996cfc1085fc00472288 (patch)
tree4402b3a222a037eb58c6dc4abd01ee70c486c83d
parent2f3e36f51a7055da3b55253edad7df594b0711d7 (diff)
downloadrust-d41e002111dd61efa08d996cfc1085fc00472288.tar.gz
rust-d41e002111dd61efa08d996cfc1085fc00472288.zip
Add test checking various assignments are accepted in Polonius
-rw-r--r--src/test/ui/nll/polonius/assignment-kills-loans.rs88
1 files changed, 88 insertions, 0 deletions
diff --git a/src/test/ui/nll/polonius/assignment-kills-loans.rs b/src/test/ui/nll/polonius/assignment-kills-loans.rs
new file mode 100644
index 00000000000..8301f603cb4
--- /dev/null
+++ b/src/test/ui/nll/polonius/assignment-kills-loans.rs
@@ -0,0 +1,88 @@
+#![allow(dead_code)]
+
+// This tests the various kinds of assignments there are. Polonius used to generate `killed`
+// facts only on simple assigments, but not projections, incorrectly causing errors to be emitted
+// for code accepted by NLL. They are all variations from example code in the NLL RFC.
+
+// check-pass
+// compile-flags: -Z borrowck=mir -Z polonius
+// ignore-compare-mode-nll
+
+struct List<T> {
+    value: T,
+    next: Option<Box<List<T>>>,
+}
+
+// Assignment to a local: the `list` assignment should clear the existing
+// borrows of `list.value` and `list.next`
+fn assignment_to_local<T>(mut list: &mut List<T>) -> Vec<&mut T> {
+    let mut result = vec![];
+    loop {
+        result.push(&mut list.value);
+        if let Some(n) = list.next.as_mut() {
+            list = n;
+        } else {
+            return result;
+        }
+    }
+}
+
+// Assignment to a deref projection: the `*list` assignment should clear the existing
+// borrows of `list.value` and `list.next`
+fn assignment_to_deref_projection<T>(mut list: Box<&mut List<T>>) -> Vec<&mut T> {
+    let mut result = vec![];
+    loop {
+        result.push(&mut list.value);
+        if let Some(n) = list.next.as_mut() {
+            *list = n;
+        } else {
+            return result;
+        }
+    }
+}
+
+// Assignment to a field projection: the `list.0` assignment should clear the existing
+// borrows of `list.0.value` and `list.0.next`
+fn assignment_to_field_projection<T>(mut list: (&mut List<T>,)) -> Vec<&mut T> {
+    let mut result = vec![];
+    loop {
+        result.push(&mut list.0.value);
+        if let Some(n) = list.0.next.as_mut() {
+            list.0 = n;
+        } else {
+            return result;
+        }
+    }
+}
+
+// Assignment to a deref field projection: the `*list.0` assignment should clear the existing
+// borrows of `list.0.value` and `list.0.next`
+fn assignment_to_deref_field_projection<T>(mut list: (Box<&mut List<T>>,)) -> Vec<&mut T> {
+    let mut result = vec![];
+    loop {
+        result.push(&mut list.0.value);
+        if let Some(n) = list.0.next.as_mut() {
+            *list.0 = n;
+        } else {
+            return result;
+        }
+    }
+}
+
+// Similar to `assignment_to_deref_field_projection` but through a longer projection chain
+fn assignment_through_projection_chain<T>(
+    mut list: (((((Box<&mut List<T>>,),),),),),
+) -> Vec<&mut T> {
+    let mut result = vec![];
+    loop {
+        result.push(&mut ((((list.0).0).0).0).0.value);
+        if let Some(n) = ((((list.0).0).0).0).0.next.as_mut() {
+            *((((list.0).0).0).0).0 = n;
+        } else {
+            return result;
+        }
+    }
+}
+
+fn main() {
+}
\ No newline at end of file