summaryrefslogtreecommitdiffstats
path: root/tests/ui/nll/polonius/assignment-kills-loans.rs
diff options
context:
space:
mode:
Diffstat (limited to 'tests/ui/nll/polonius/assignment-kills-loans.rs')
-rw-r--r--tests/ui/nll/polonius/assignment-kills-loans.rs87
1 files changed, 87 insertions, 0 deletions
diff --git a/tests/ui/nll/polonius/assignment-kills-loans.rs b/tests/ui/nll/polonius/assignment-kills-loans.rs
new file mode 100644
index 000000000..696bf61ce
--- /dev/null
+++ b/tests/ui/nll/polonius/assignment-kills-loans.rs
@@ -0,0 +1,87 @@
+#![allow(dead_code)]
+
+// This tests the various kinds of assignments there are. Polonius used to generate `killed`
+// facts only on simple assignments, 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 polonius
+
+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() {
+}