diff options
6 files changed, 186 insertions, 0 deletions
diff --git a/tests/ui/nll/polonius/iterating-updating-cursor-issue-108704.nll.stderr b/tests/ui/nll/polonius/iterating-updating-cursor-issue-108704.nll.stderr new file mode 100644 index 00000000000..7ac4e5de283 --- /dev/null +++ b/tests/ui/nll/polonius/iterating-updating-cursor-issue-108704.nll.stderr @@ -0,0 +1,12 @@ +error[E0499]: cannot borrow `*elements` as mutable more than once at a time + --> $DIR/iterating-updating-cursor-issue-108704.rs:40:26 + | +LL | for (idx, el) in elements.iter_mut().enumerate() { + | ^^^^^^^^ + | | + | `*elements` was mutably borrowed here in the previous iteration of the loop + | first borrow used here, in later iteration of loop + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0499`. diff --git a/tests/ui/nll/polonius/iterating-updating-cursor-issue-108704.rs b/tests/ui/nll/polonius/iterating-updating-cursor-issue-108704.rs new file mode 100644 index 00000000000..420cb73bed2 --- /dev/null +++ b/tests/ui/nll/polonius/iterating-updating-cursor-issue-108704.rs @@ -0,0 +1,47 @@ +#![crate_type = "lib"] + +// An example from #108704 of the linked-list cursor-like pattern of #46859/#48001. + +//@ ignore-compare-mode-polonius (explicit revisions) +//@ revisions: nll polonius legacy +//@ [nll] known-bug: #108704 +//@ [polonius] check-pass +//@ [polonius] compile-flags: -Z polonius=next +//@ [legacy] check-pass +//@ [legacy] compile-flags: -Z polonius=legacy + +struct Root { + children: Vec<Node>, +} + +struct Node { + name: String, + children: Vec<Node>, +} + +fn merge_tree_ok(root: &mut Root, path: Vec<String>) { + let mut elements = &mut root.children; + + for p in path.iter() { + for (idx, el) in elements.iter_mut().enumerate() { + if el.name == *p { + elements = &mut elements[idx].children; + break; + } + } + } +} + +// NLLs fail here +fn merge_tree_ko(root: &mut Root, path: Vec<String>) { + let mut elements = &mut root.children; + + for p in path.iter() { + for (idx, el) in elements.iter_mut().enumerate() { + if el.name == *p { + elements = &mut el.children; + break; + } + } + } +} diff --git a/tests/ui/nll/polonius/iterating-updating-cursor-issue-57165.nll.stderr b/tests/ui/nll/polonius/iterating-updating-cursor-issue-57165.nll.stderr new file mode 100644 index 00000000000..14e1726e158 --- /dev/null +++ b/tests/ui/nll/polonius/iterating-updating-cursor-issue-57165.nll.stderr @@ -0,0 +1,22 @@ +error[E0499]: cannot borrow `p.0` as mutable more than once at a time + --> $DIR/iterating-updating-cursor-issue-57165.rs:29:20 + | +LL | while let Some(now) = p { + | ^^^ - first borrow used here, in later iteration of loop + | | + | `p.0` was mutably borrowed here in the previous iteration of the loop + +error[E0503]: cannot use `*p` because it was mutably borrowed + --> $DIR/iterating-updating-cursor-issue-57165.rs:29:27 + | +LL | while let Some(now) = p { + | --- ^ + | | | + | | use of borrowed `p.0` + | | borrow later used here + | `p.0` is borrowed here + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0499, E0503. +For more information about an error, try `rustc --explain E0499`. diff --git a/tests/ui/nll/polonius/iterating-updating-cursor-issue-57165.rs b/tests/ui/nll/polonius/iterating-updating-cursor-issue-57165.rs new file mode 100644 index 00000000000..63ec89146d4 --- /dev/null +++ b/tests/ui/nll/polonius/iterating-updating-cursor-issue-57165.rs @@ -0,0 +1,44 @@ +#![crate_type = "lib"] + +// An example from #57165 of the linked-list cursor-like pattern of #46859/#48001. + +//@ ignore-compare-mode-polonius (explicit revisions) +//@ revisions: nll polonius legacy +//@ [nll] known-bug: #57165 +//@ [polonius] check-pass +//@ [polonius] compile-flags: -Z polonius=next +//@ [legacy] check-pass +//@ [legacy] compile-flags: -Z polonius=legacy + +struct X { + next: Option<Box<X>>, +} + +fn no_control_flow() { + let mut b = Some(Box::new(X { next: None })); + let mut p = &mut b; + while let Some(now) = p { + p = &mut now.next; + } +} + +// NLLs fail here +fn conditional() { + let mut b = Some(Box::new(X { next: None })); + let mut p = &mut b; + while let Some(now) = p { + if true { + p = &mut now.next; + } + } +} + +fn conditional_with_indirection() { + let mut b = Some(Box::new(X { next: None })); + let mut p = &mut b; + while let Some(now) = p { + if true { + p = &mut p.as_mut().unwrap().next; + } + } +} diff --git a/tests/ui/nll/polonius/iterating-updating-cursor-issue-63908.nll.stderr b/tests/ui/nll/polonius/iterating-updating-cursor-issue-63908.nll.stderr new file mode 100644 index 00000000000..bf38da566c6 --- /dev/null +++ b/tests/ui/nll/polonius/iterating-updating-cursor-issue-63908.nll.stderr @@ -0,0 +1,18 @@ +error[E0506]: cannot assign to `*node_ref` because it is borrowed + --> $DIR/iterating-updating-cursor-issue-63908.rs:42:5 + | +LL | fn remove_last_node_iterative<T>(mut node_ref: &mut List<T>) { + | - let's call the lifetime of this reference `'1` +LL | loop { +LL | let next_ref = &mut node_ref.as_mut().unwrap().next; + | -------- `*node_ref` is borrowed here +... +LL | node_ref = next_ref; + | ------------------- assignment requires that `*node_ref` is borrowed for `'1` +... +LL | *node_ref = None; + | ^^^^^^^^^ `*node_ref` is assigned to here but it was already borrowed + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0506`. diff --git a/tests/ui/nll/polonius/iterating-updating-cursor-issue-63908.rs b/tests/ui/nll/polonius/iterating-updating-cursor-issue-63908.rs new file mode 100644 index 00000000000..00e48b65fed --- /dev/null +++ b/tests/ui/nll/polonius/iterating-updating-cursor-issue-63908.rs @@ -0,0 +1,43 @@ +#![crate_type = "lib"] + +// An example from #63908 of the linked-list cursor-like pattern of #46859/#48001. + +//@ ignore-compare-mode-polonius (explicit revisions) +//@ revisions: nll polonius legacy +//@ [nll] known-bug: #63908 +//@ [polonius] check-pass +//@ [polonius] compile-flags: -Z polonius=next +//@ [legacy] check-pass +//@ [legacy] compile-flags: -Z polonius=legacy + +struct Node<T> { + value: T, + next: Option<Box<Self>>, +} + +type List<T> = Option<Box<Node<T>>>; + +fn remove_last_node_recursive<T>(node_ref: &mut List<T>) { + let next_ref = &mut node_ref.as_mut().unwrap().next; + + if next_ref.is_some() { + remove_last_node_recursive(next_ref); + } else { + *node_ref = None; + } +} + +// NLLs fail here +fn remove_last_node_iterative<T>(mut node_ref: &mut List<T>) { + loop { + let next_ref = &mut node_ref.as_mut().unwrap().next; + + if next_ref.is_some() { + node_ref = next_ref; + } else { + break; + } + } + + *node_ref = None; +} |
