Skip to content

Commit 056cfff

Browse files
committed
Unit tests for issue rust-lang#54556. Some were also taken from issues rust-lang#21114, rust-lang#46413.
1 parent 37f1003 commit 056cfff

17 files changed

+529
-0
lines changed

src/test/ui/nll/issue-21114-ebfull.rs

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// (this works, but only in NLL)
2+
// compile-pass
3+
#![feature(nll)]
4+
5+
use std::collections::HashMap;
6+
use std::sync::Mutex;
7+
8+
fn i_used_to_be_able_to(foo: &Mutex<HashMap<usize, usize>>) -> Vec<(usize, usize)> {
9+
let mut foo = foo.lock().unwrap();
10+
11+
foo.drain().collect()
12+
}
13+
14+
fn but_after_nightly_update_now_i_gotta(foo: &Mutex<HashMap<usize, usize>>) -> Vec<(usize, usize)> {
15+
let mut foo = foo.lock().unwrap();
16+
17+
return foo.drain().collect();
18+
}
19+
20+
fn main() {}
+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// (this works, but only in NLL)
2+
// compile-pass
3+
#![feature(nll)]
4+
5+
fn from_stdin(min: u64) -> Vec<u64> {
6+
use std::io::BufRead;
7+
8+
let stdin = std::io::stdin();
9+
let stdin = stdin.lock();
10+
11+
stdin.lines()
12+
.map(Result::unwrap)
13+
.map(|val| val.parse())
14+
.map(Result::unwrap)
15+
.filter(|val| *val >= min)
16+
.collect()
17+
}
18+
19+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
error[E0597]: `counter` does not live long enough
2+
--> $DIR/issue-54556-niconii.rs:22:20
3+
|
4+
LL | if let Ok(_) = counter.lock() { }
5+
| ^^^^^^^-------
6+
| |
7+
| borrowed value does not live long enough
8+
| a temporary with access to the borrow is created here ...
9+
...
10+
LL | }
11+
| -
12+
| |
13+
| `counter` dropped here while still borrowed
14+
| ... and the borrow might be used here, when that temporary is dropped and runs the destructor for type `std::result::Result<MutexGuard<'_>, ()>`
15+
|
16+
= note: The temporary is part of an expression at the end of a block. Consider adding semicolon after the expression so its temporaries are dropped sooner, before the local variables declared by the block are dropped.
17+
18+
error: aborting due to previous error
19+
20+
For more information about this error, try `rustc --explain E0597`.
+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// This is a reduction of a concrete test illustrating a case that was
2+
// annoying to Rust developer niconii (see comment thread on #21114).
3+
//
4+
// With resolving issue #54556, pnkfelix hopes that the new diagnostic
5+
// output produced by NLL helps to *explain* the semantic significance
6+
// of temp drop order, and thus why inserting a semi-colon after the
7+
// `if let` expression in `main` works.
8+
9+
struct Mutex;
10+
struct MutexGuard<'a>(&'a Mutex);
11+
12+
impl Drop for Mutex { fn drop(&mut self) { println!("Mutex::drop"); } }
13+
impl<'a> Drop for MutexGuard<'a> { fn drop(&mut self) { println!("MutexGuard::drop"); } }
14+
15+
impl Mutex {
16+
fn lock(&self) -> Result<MutexGuard, ()> { Ok(MutexGuard(self)) }
17+
}
18+
19+
fn main() {
20+
let counter = Mutex;
21+
22+
if let Ok(_) = counter.lock() { }
23+
24+
// With this code as written, the dynamic semantics here implies
25+
// that `Mutex::drop` for `counter` runs *before*
26+
// `MutexGuard::drop`, which would be unsound since `MutexGuard`
27+
// still has a reference to `counter`.
28+
//
29+
// The goal of #54556 is to explain that within a compiler
30+
// diagnostic.
31+
}
+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
error[E0597]: `counter` does not live long enough
2+
--> $DIR/issue-54556-niconii.rs:22:20
3+
|
4+
LL | if let Ok(_) = counter.lock() { }
5+
| ^^^^^^^ borrowed value does not live long enough
6+
...
7+
LL | }
8+
| - `counter` dropped here while still borrowed
9+
|
10+
= note: values in a scope are dropped in the opposite order they are created
11+
12+
error: aborting due to previous error
13+
14+
For more information about this error, try `rustc --explain E0597`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
error[E0597]: `stmt` does not live long enough
2+
--> $DIR/issue-54556-stephaneyfx.rs:27:21
3+
|
4+
LL | let rows = Rows(&stmt);
5+
| ^^^^^ borrowed value does not live long enough
6+
LL | rows.map(|row| row).next()
7+
| ------------------- a temporary with access to the borrow is created here ...
8+
...
9+
LL | }
10+
| -
11+
| |
12+
| `stmt` dropped here while still borrowed
13+
| ... and the borrow might be used here, when that temporary is dropped and runs the destructor for type `std::iter::Map<Rows<'_>, [closure@$DIR/issue-54556-stephaneyfx.rs:28:14: 28:23]>`
14+
|
15+
= note: The temporary is part of an expression at the end of a block. Consider forcing this temporary to be dropped sooner, before the block's local variables are dropped. For example, you could save the expression's value in a new local variable `x` and then make `x` be the expression at the end of the block.
16+
17+
error: aborting due to previous error
18+
19+
For more information about this error, try `rustc --explain E0597`.
+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// This is a reduction of a concrete test illustrating a case that was
2+
// annoying to Rust developer stephaneyfx (see issue #46413).
3+
//
4+
// With resolving issue #54556, pnkfelix hopes that the new diagnostic
5+
// output produced by NLL helps to *explain* the semantic significance
6+
// of temp drop order, and thus why storing the result in `x` and then
7+
// returning `x` works.
8+
9+
pub struct Statement;
10+
11+
pub struct Rows<'stmt>(&'stmt Statement);
12+
13+
impl<'stmt> Drop for Rows<'stmt> {
14+
fn drop(&mut self) {}
15+
}
16+
17+
impl<'stmt> Iterator for Rows<'stmt> {
18+
type Item = String;
19+
20+
fn next(&mut self) -> Option<Self::Item> {
21+
None
22+
}
23+
}
24+
25+
fn get_names() -> Option<String> {
26+
let stmt = Statement;
27+
let rows = Rows(&stmt);
28+
rows.map(|row| row).next()
29+
// let x = rows.map(|row| row).next();
30+
// x
31+
//
32+
// Removing the map works too as does removing the Drop impl.
33+
}
34+
35+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
error[E0597]: `stmt` does not live long enough
2+
--> $DIR/issue-54556-stephaneyfx.rs:27:22
3+
|
4+
LL | let rows = Rows(&stmt);
5+
| ^^^^ borrowed value does not live long enough
6+
...
7+
LL | }
8+
| - `stmt` dropped here while still borrowed
9+
|
10+
= note: values in a scope are dropped in the opposite order they are created
11+
12+
error: aborting due to previous error
13+
14+
For more information about this error, try `rustc --explain E0597`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
error[E0597]: `_thing1` does not live long enough
2+
--> $DIR/issue-54556-temps-in-tail-diagnostic.rs:5:11
3+
|
4+
LL | D(&_thing1).end()
5+
| --^^^^^^^^-
6+
| | |
7+
| | borrowed value does not live long enough
8+
| a temporary with access to the borrow is created here ...
9+
LL | }
10+
| - `_thing1` dropped here while still borrowed
11+
LL |
12+
LL | ;
13+
| - ... and the borrow might be used here, when that temporary is dropped and runs the `Drop` code for type `D`
14+
|
15+
= note: The temporary is part of an expression at the end of a block. Consider adding semicolon after the expression so its temporaries are dropped sooner, before the local variables declared by the block are dropped.
16+
17+
error: aborting due to previous error
18+
19+
For more information about this error, try `rustc --explain E0597`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
fn main() {
2+
{
3+
let mut _thing1 = D(Box::new("thing1"));
4+
// D("other").next(&_thing1).end()
5+
D(&_thing1).end()
6+
}
7+
8+
;
9+
}
10+
11+
#[derive(Debug)]
12+
struct D<T: std::fmt::Debug>(T);
13+
14+
impl<T: std::fmt::Debug> Drop for D<T> {
15+
fn drop(&mut self) {
16+
println!("dropping {:?})", self);
17+
}
18+
}
19+
20+
impl<T: std::fmt::Debug> D<T> {
21+
fn next<U: std::fmt::Debug>(&self, _other: U) -> D<U> { D(_other) }
22+
fn end(&self) { }
23+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
error[E0597]: `_thing1` does not live long enough
2+
--> $DIR/issue-54556-temps-in-tail-diagnostic.rs:5:12
3+
|
4+
LL | D(&_thing1).end()
5+
| ^^^^^^^ borrowed value does not live long enough
6+
LL | }
7+
| - `_thing1` dropped here while still borrowed
8+
LL |
9+
LL | ;
10+
| - borrowed value needs to live until here
11+
12+
error: aborting due to previous error
13+
14+
For more information about this error, try `rustc --explain E0597`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
error[E0597]: `_t1` does not live long enough
2+
--> $DIR/issue-54556-used-vs-unused-tails.rs:10:55
3+
|
4+
LL | { let mut _t1 = D(Box::new("t1")); D(&_t1).end() } ; // suggest `;`
5+
| --^^^^- - - ... and the borrow might be used here, when that temporary is dropped and runs the `Drop` code for type `D`
6+
| | | |
7+
| | | `_t1` dropped here while still borrowed
8+
| | borrowed value does not live long enough
9+
| a temporary with access to the borrow is created here ...
10+
|
11+
= note: The temporary is part of an expression at the end of a block. Consider adding semicolon after the expression so its temporaries are dropped sooner, before the local variables declared by the block are dropped.
12+
13+
error[E0597]: `_t1` does not live long enough
14+
--> $DIR/issue-54556-used-vs-unused-tails.rs:12:55
15+
|
16+
LL | { { let mut _t1 = D(Box::new("t1")); D(&_t1).end() } } ; // suggest `;`
17+
| --^^^^- - - ... and the borrow might be used here, when that temporary is dropped and runs the `Drop` code for type `D`
18+
| | | |
19+
| | | `_t1` dropped here while still borrowed
20+
| | borrowed value does not live long enough
21+
| a temporary with access to the borrow is created here ...
22+
|
23+
= note: The temporary is part of an expression at the end of a block. Consider adding semicolon after the expression so its temporaries are dropped sooner, before the local variables declared by the block are dropped.
24+
25+
error[E0597]: `_t1` does not live long enough
26+
--> $DIR/issue-54556-used-vs-unused-tails.rs:14:55
27+
|
28+
LL | { { let mut _t1 = D(Box::new("t1")); D(&_t1).end() }; } // suggest `;`
29+
| --^^^^- -- ... and the borrow might be used here, when that temporary is dropped and runs the `Drop` code for type `D`
30+
| | | |
31+
| | | `_t1` dropped here while still borrowed
32+
| | borrowed value does not live long enough
33+
| a temporary with access to the borrow is created here ...
34+
|
35+
= note: The temporary is part of an expression at the end of a block. Consider adding semicolon after the expression so its temporaries are dropped sooner, before the local variables declared by the block are dropped.
36+
37+
error[E0597]: `_t1` does not live long enough
38+
--> $DIR/issue-54556-used-vs-unused-tails.rs:16:55
39+
|
40+
LL | let _ = { let mut _t1 = D(Box::new("t1")); D(&_t1).end() } ; // suggest `;`
41+
| --^^^^- - - ... and the borrow might be used here, when that temporary is dropped and runs the `Drop` code for type `D`
42+
| | | |
43+
| | | `_t1` dropped here while still borrowed
44+
| | borrowed value does not live long enough
45+
| a temporary with access to the borrow is created here ...
46+
|
47+
= note: The temporary is part of an expression at the end of a block. Consider adding semicolon after the expression so its temporaries are dropped sooner, before the local variables declared by the block are dropped.
48+
49+
error[E0597]: `_t1` does not live long enough
50+
--> $DIR/issue-54556-used-vs-unused-tails.rs:18:55
51+
|
52+
LL | let _u = { let mut _t1 = D(Box::new("t1")); D(&_t1).unit() } ; // suggest `;`
53+
| --^^^^- - - ... and the borrow might be used here, when that temporary is dropped and runs the `Drop` code for type `D`
54+
| | | |
55+
| | | `_t1` dropped here while still borrowed
56+
| | borrowed value does not live long enough
57+
| a temporary with access to the borrow is created here ...
58+
|
59+
= note: The temporary is part of an expression at the end of a block. Consider adding semicolon after the expression so its temporaries are dropped sooner, before the local variables declared by the block are dropped.
60+
61+
error[E0597]: `_t1` does not live long enough
62+
--> $DIR/issue-54556-used-vs-unused-tails.rs:20:55
63+
|
64+
LL | let _x = { let mut _t1 = D(Box::new("t1")); D(&_t1).end() } ; // `let x = ...; x`
65+
| --^^^^- - - ... and the borrow might be used here, when that temporary is dropped and runs the `Drop` code for type `D`
66+
| | | |
67+
| | | `_t1` dropped here while still borrowed
68+
| | borrowed value does not live long enough
69+
| a temporary with access to the borrow is created here ...
70+
|
71+
= note: The temporary is part of an expression at the end of a block. Consider forcing this temporary to be dropped sooner, before the block's local variables are dropped. For example, you could save the expression's value in a new local variable `x` and then make `x` be the expression at the end of the block.
72+
73+
error[E0597]: `_t1` does not live long enough
74+
--> $DIR/issue-54556-used-vs-unused-tails.rs:24:55
75+
|
76+
LL | _y = { let mut _t1 = D(Box::new("t1")); D(&_t1).end() } ; // `let x = ...; x`
77+
| --^^^^- - - ... and the borrow might be used here, when that temporary is dropped and runs the `Drop` code for type `D`
78+
| | | |
79+
| | | `_t1` dropped here while still borrowed
80+
| | borrowed value does not live long enough
81+
| a temporary with access to the borrow is created here ...
82+
|
83+
= note: The temporary is part of an expression at the end of a block. Consider forcing this temporary to be dropped sooner, before the block's local variables are dropped. For example, you could save the expression's value in a new local variable `x` and then make `x` be the expression at the end of the block.
84+
85+
error[E0597]: `_t1` does not live long enough
86+
--> $DIR/issue-54556-used-vs-unused-tails.rs:30:55
87+
|
88+
LL | fn f_local_ref() { let mut _t1 = D(Box::new("t1")); D(&_t1).unit() } // suggest `;`
89+
| --^^^^- -
90+
| | | |
91+
| | | `_t1` dropped here while still borrowed
92+
| | | ... and the borrow might be used here, when that temporary is dropped and runs the `Drop` code for type `D`
93+
| | borrowed value does not live long enough
94+
| a temporary with access to the borrow is created here ...
95+
|
96+
= note: The temporary is part of an expression at the end of a block. Consider adding semicolon after the expression so its temporaries are dropped sooner, before the local variables declared by the block are dropped.
97+
98+
error[E0597]: `_t1` does not live long enough
99+
--> $DIR/issue-54556-used-vs-unused-tails.rs:32:55
100+
|
101+
LL | fn f() -> String { let mut _t1 = D(Box::new("t1")); D(&_t1).end() } // `let x = ...; x`
102+
| --^^^^- -
103+
| | | |
104+
| | | `_t1` dropped here while still borrowed
105+
| | | ... and the borrow might be used here, when that temporary is dropped and runs the `Drop` code for type `D`
106+
| | borrowed value does not live long enough
107+
| a temporary with access to the borrow is created here ...
108+
|
109+
= note: The temporary is part of an expression at the end of a block. Consider forcing this temporary to be dropped sooner, before the block's local variables are dropped. For example, you could save the expression's value in a new local variable `x` and then make `x` be the expression at the end of the block.
110+
111+
error: aborting due to 9 previous errors
112+
113+
For more information about this error, try `rustc --explain E0597`.

0 commit comments

Comments
 (0)