Skip to content

Commit d6dc363

Browse files
committed
add multiple known-bugs for NLL problem case 3
these are fixed by polonius=next and polonius=legacy
1 parent 9b1a30e commit d6dc363

20 files changed

+778
-0
lines changed
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
error[E0506]: cannot assign to `*opt` because it is borrowed
2+
--> $DIR/nll-problem-case-3-issue-112087.rs:23:5
3+
|
4+
LL | fn issue_112087<'a>(opt: &'a mut Option<i32>, b: bool) -> Result<&'a mut Option<i32>, &'a mut i32> {
5+
| -- lifetime `'a` defined here
6+
LL | if let Some(v) = opt {
7+
| - `*opt` is borrowed here
8+
LL | if b {
9+
LL | return Err(v);
10+
| ------ returning this value requires that `opt.0` is borrowed for `'a`
11+
...
12+
LL | *opt = None;
13+
| ^^^^^^^^^^^ `*opt` is assigned to here but it was already borrowed
14+
15+
error: aborting due to 1 previous error
16+
17+
For more information about this error, try `rustc --explain E0506`.
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
#![crate_type = "lib"]
2+
3+
// This is part of a collection of regression tests related to the NLL problem case 3 that was
4+
// deferred from the implementation of the NLL RFC, and left to be implemented by polonius. They are
5+
// from open issues, e.g. tagged fixed-by-polonius, to ensure that the polonius alpha analysis does
6+
// handle them, as does the datalog implementation.
7+
8+
//@ ignore-compare-mode-polonius (explicit revisions)
9+
//@ revisions: nll polonius legacy
10+
//@ [nll] known-bug: #112087
11+
//@ [polonius] check-pass
12+
//@ [polonius] compile-flags: -Z polonius=next
13+
//@ [legacy] check-pass
14+
//@ [legacy] compile-flags: -Z polonius=legacy
15+
16+
fn issue_112087<'a>(opt: &'a mut Option<i32>, b: bool) -> Result<&'a mut Option<i32>, &'a mut i32> {
17+
if let Some(v) = opt {
18+
if b {
19+
return Err(v);
20+
}
21+
}
22+
23+
*opt = None;
24+
return Ok(opt);
25+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
error[E0506]: cannot assign to `self.status` because it is borrowed
2+
--> $DIR/nll-problem-case-3-issue-123839.rs:37:9
3+
|
4+
LL | fn foo(self: &mut Self) -> Result<(), &str> {
5+
| - let's call the lifetime of this reference `'1`
6+
LL | self.bar()?; // rust reports this line conflicts with the next line
7+
| -----------
8+
| |
9+
| `self.status` is borrowed here
10+
| returning this value requires that `*self` is borrowed for `'1`
11+
LL | self.status = 1; // and this line is the victim
12+
| ^^^^^^^^^^^^^^^ `self.status` is assigned to here but it was already borrowed
13+
14+
error: aborting due to 1 previous error
15+
16+
For more information about this error, try `rustc --explain E0506`.
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
#![crate_type = "lib"]
2+
3+
// This is part of a collection of regression tests related to the NLL problem case 3 that was
4+
// deferred from the implementation of the NLL RFC, and left to be implemented by polonius. They are
5+
// from open issues, e.g. tagged fixed-by-polonius, to ensure that the polonius alpha analysis does
6+
// handle them, as does the datalog implementation.
7+
8+
//@ ignore-compare-mode-polonius (explicit revisions)
9+
//@ revisions: nll polonius legacy
10+
//@ [nll] known-bug: #123839
11+
//@ [polonius] check-pass
12+
//@ [polonius] compile-flags: -Z polonius=next
13+
//@ [legacy] check-pass
14+
//@ [legacy] compile-flags: -Z polonius=legacy
15+
16+
struct Foo {
17+
val: i32,
18+
status: i32,
19+
err_str: String,
20+
}
21+
22+
impl Foo {
23+
fn bar(self: &mut Self) -> Result<(), &str> {
24+
if self.val == 0 {
25+
self.status = -1;
26+
Err("val is zero")
27+
} else if self.val < 0 {
28+
self.status = -2;
29+
self.err_str = format!("unexpected negative val {}", self.val);
30+
Err(&self.err_str)
31+
} else {
32+
Ok(())
33+
}
34+
}
35+
fn foo(self: &mut Self) -> Result<(), &str> {
36+
self.bar()?; // rust reports this line conflicts with the next line
37+
self.status = 1; // and this line is the victim
38+
Ok(())
39+
}
40+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
error[E0502]: cannot borrow `self.field` as immutable because it is also borrowed as mutable
2+
--> $DIR/nll-problem-case-3-issue-124070.rs:28:16
3+
|
4+
LL | fn f(&mut self) -> &str {
5+
| - let's call the lifetime of this reference `'1`
6+
LL | let a = &mut self.field;
7+
| --------------- mutable borrow occurs here
8+
...
9+
LL | return a;
10+
| - returning this value requires that `self.field` is borrowed for `'1`
11+
...
12+
LL | return &self.field;
13+
| ^^^^^^^^^^^ immutable borrow occurs here
14+
15+
error: aborting due to 1 previous error
16+
17+
For more information about this error, try `rustc --explain E0502`.
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
#![crate_type = "lib"]
2+
3+
// This is part of a collection of regression tests related to the NLL problem case 3 that was
4+
// deferred from the implementation of the NLL RFC, and left to be implemented by polonius. They are
5+
// from open issues, e.g. tagged fixed-by-polonius, to ensure that the polonius alpha analysis does
6+
// handle them, as does the datalog implementation.
7+
8+
//@ ignore-compare-mode-polonius (explicit revisions)
9+
//@ revisions: nll polonius legacy
10+
//@ [nll] known-bug: #124070
11+
//@ [polonius] check-pass
12+
//@ [polonius] compile-flags: -Z polonius=next
13+
//@ [legacy] check-pass
14+
//@ [legacy] compile-flags: -Z polonius=legacy
15+
16+
struct S {
17+
field: String,
18+
}
19+
20+
impl S {
21+
fn f(&mut self) -> &str {
22+
let a = &mut self.field;
23+
24+
if false {
25+
return a;
26+
}
27+
28+
return &self.field;
29+
}
30+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
error[E0499]: cannot borrow `list[_]` as mutable more than once at a time
2+
--> $DIR/nll-problem-case-3-issue-124254.rs:30:5
3+
|
4+
LL | fn find_lowest_or_first_empty_pos(list: &mut [Option<u8>]) -> &mut Option<u8> {
5+
| - let's call the lifetime of this reference `'1`
6+
LL | let mut low_pos_val: Option<(usize, u8)> = None;
7+
LL | for (idx, i) in list.iter_mut().enumerate() {
8+
| ---- first mutable borrow occurs here
9+
LL | let Some(s) = i else {
10+
LL | return i;
11+
| - returning this value requires that `*list` is borrowed for `'1`
12+
...
13+
LL | &mut list[lowest_idx]
14+
| ^^^^^^^^^^^^^^^^^^^^^ second mutable borrow occurs here
15+
16+
error[E0503]: cannot use `*list` because it was mutably borrowed
17+
--> $DIR/nll-problem-case-3-issue-124254.rs:30:10
18+
|
19+
LL | fn find_lowest_or_first_empty_pos(list: &mut [Option<u8>]) -> &mut Option<u8> {
20+
| - let's call the lifetime of this reference `'1`
21+
LL | let mut low_pos_val: Option<(usize, u8)> = None;
22+
LL | for (idx, i) in list.iter_mut().enumerate() {
23+
| ---- `*list` is borrowed here
24+
LL | let Some(s) = i else {
25+
LL | return i;
26+
| - returning this value requires that `*list` is borrowed for `'1`
27+
...
28+
LL | &mut list[lowest_idx]
29+
| ^^^^^^^^^^^^^^^^ use of borrowed `*list`
30+
31+
error: aborting due to 2 previous errors
32+
33+
Some errors have detailed explanations: E0499, E0503.
34+
For more information about an error, try `rustc --explain E0499`.
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// This is part of a collection of regression tests related to the NLL problem case 3 that was
2+
// deferred from the implementation of the NLL RFC, and left to be implemented by polonius. They are
3+
// from open issues, e.g. tagged fixed-by-polonius, to ensure that the polonius alpha analysis does
4+
// handle them, as does the datalog implementation.
5+
6+
//@ ignore-compare-mode-polonius (explicit revisions)
7+
//@ revisions: nll polonius legacy
8+
//@ [nll] known-bug: #124254
9+
//@ [polonius] check-pass
10+
//@ [polonius] compile-flags: -Z polonius=next
11+
//@ [legacy] check-pass
12+
//@ [legacy] compile-flags: -Z polonius=legacy
13+
14+
fn find_lowest_or_first_empty_pos(list: &mut [Option<u8>]) -> &mut Option<u8> {
15+
let mut low_pos_val: Option<(usize, u8)> = None;
16+
for (idx, i) in list.iter_mut().enumerate() {
17+
let Some(s) = i else {
18+
return i;
19+
};
20+
21+
low_pos_val = match low_pos_val {
22+
Some((_oidx, oval)) if oval > *s => Some((idx, *s)),
23+
Some(old) => Some(old),
24+
None => Some((idx, *s)),
25+
};
26+
}
27+
let Some((lowest_idx, _)) = low_pos_val else {
28+
unreachable!("Can't have zero length list!");
29+
};
30+
&mut list[lowest_idx]
31+
}
32+
33+
fn main() {
34+
let mut list = [Some(1), Some(2), None, Some(3)];
35+
let v = find_lowest_or_first_empty_pos(&mut list);
36+
assert!(v.is_none());
37+
assert_eq!(v as *mut _ as usize, list.as_ptr().wrapping_add(2) as usize);
38+
39+
let mut list = [Some(1), Some(2), Some(3), Some(0)];
40+
let v = find_lowest_or_first_empty_pos(&mut list);
41+
assert_eq!(v, &mut Some(0));
42+
assert_eq!(v as *mut _ as usize, list.as_ptr().wrapping_add(3) as usize);
43+
44+
println!("pass");
45+
}
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
error[E0499]: cannot borrow `*map` as mutable more than once at a time
2+
--> $DIR/nll-problem-case-3-issue-21906.rs:26:13
3+
|
4+
LL | fn from_the_rfc<'r, K: Hash + Eq + Copy, V: Default>(
5+
| -- lifetime `'r` defined here
6+
...
7+
LL | match map.get_mut(&key) {
8+
| - --- first mutable borrow occurs here
9+
| _____|
10+
| |
11+
LL | | Some(value) => value,
12+
LL | | None => {
13+
LL | | map.insert(key, V::default());
14+
| | ^^^ second mutable borrow occurs here
15+
... |
16+
LL | | }
17+
| |_____- returning this value requires that `*map` is borrowed for `'r`
18+
19+
error[E0499]: cannot borrow `*map` as mutable more than once at a time
20+
--> $DIR/nll-problem-case-3-issue-21906.rs:27:13
21+
|
22+
LL | fn from_the_rfc<'r, K: Hash + Eq + Copy, V: Default>(
23+
| -- lifetime `'r` defined here
24+
...
25+
LL | match map.get_mut(&key) {
26+
| - --- first mutable borrow occurs here
27+
| _____|
28+
| |
29+
LL | | Some(value) => value,
30+
LL | | None => {
31+
LL | | map.insert(key, V::default());
32+
LL | | map.get_mut(&key).unwrap()
33+
| | ^^^ second mutable borrow occurs here
34+
LL | | }
35+
LL | | }
36+
| |_____- returning this value requires that `*map` is borrowed for `'r`
37+
38+
error[E0499]: cannot borrow `*self` as mutable more than once at a time
39+
--> $DIR/nll-problem-case-3-issue-21906.rs:44:21
40+
|
41+
LL | fn two(&mut self) -> &i32 {
42+
| - let's call the lifetime of this reference `'1`
43+
LL | loop {
44+
LL | let k = self.one();
45+
| ^^^^ `*self` was mutably borrowed here in the previous iteration of the loop
46+
LL | if *k > 10i32 {
47+
LL | return k;
48+
| - returning this value requires that `*self` is borrowed for `'1`
49+
50+
error[E0502]: cannot borrow `x.data` as immutable because it is also borrowed as mutable
51+
--> $DIR/nll-problem-case-3-issue-21906.rs:62:22
52+
|
53+
LL | fn foo(x: &mut Foo) -> Option<&mut i32> {
54+
| - let's call the lifetime of this reference `'1`
55+
LL | if let Some(y) = x.data.as_mut() {
56+
| ------ mutable borrow occurs here
57+
LL | return Some(y);
58+
| ------- returning this value requires that `x.data` is borrowed for `'1`
59+
...
60+
LL | println!("{:?}", x.data);
61+
| ^^^^^^ immutable borrow occurs here
62+
|
63+
= note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
64+
65+
error[E0499]: cannot borrow `*vec` as mutable more than once at a time
66+
--> $DIR/nll-problem-case-3-issue-21906.rs:77:9
67+
|
68+
LL | fn f(vec: &mut Vec<u8>) -> &u8 {
69+
| - let's call the lifetime of this reference `'1`
70+
LL | if let Some(n) = vec.iter_mut().find(|n| **n == 1) {
71+
| --- first mutable borrow occurs here
72+
LL | *n = 10;
73+
LL | n
74+
| - returning this value requires that `*vec` is borrowed for `'1`
75+
LL | } else {
76+
LL | vec.push(10);
77+
| ^^^ second mutable borrow occurs here
78+
79+
error[E0502]: cannot borrow `*vec` as immutable because it is also borrowed as mutable
80+
--> $DIR/nll-problem-case-3-issue-21906.rs:78:9
81+
|
82+
LL | fn f(vec: &mut Vec<u8>) -> &u8 {
83+
| - let's call the lifetime of this reference `'1`
84+
LL | if let Some(n) = vec.iter_mut().find(|n| **n == 1) {
85+
| --- mutable borrow occurs here
86+
LL | *n = 10;
87+
LL | n
88+
| - returning this value requires that `*vec` is borrowed for `'1`
89+
...
90+
LL | vec.last().unwrap()
91+
| ^^^ immutable borrow occurs here
92+
93+
error: aborting due to 6 previous errors
94+
95+
Some errors have detailed explanations: E0499, E0502.
96+
For more information about an error, try `rustc --explain E0499`.

0 commit comments

Comments
 (0)