-
Notifications
You must be signed in to change notification settings - Fork 12.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
- Loading branch information
Showing
17 changed files
with
529 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
// (this works, but only in NLL) | ||
// compile-pass | ||
#![feature(nll)] | ||
|
||
use std::collections::HashMap; | ||
use std::sync::Mutex; | ||
|
||
fn i_used_to_be_able_to(foo: &Mutex<HashMap<usize, usize>>) -> Vec<(usize, usize)> { | ||
let mut foo = foo.lock().unwrap(); | ||
|
||
foo.drain().collect() | ||
} | ||
|
||
fn but_after_nightly_update_now_i_gotta(foo: &Mutex<HashMap<usize, usize>>) -> Vec<(usize, usize)> { | ||
let mut foo = foo.lock().unwrap(); | ||
|
||
return foo.drain().collect(); | ||
} | ||
|
||
fn main() {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
// (this works, but only in NLL) | ||
// compile-pass | ||
#![feature(nll)] | ||
|
||
fn from_stdin(min: u64) -> Vec<u64> { | ||
use std::io::BufRead; | ||
|
||
let stdin = std::io::stdin(); | ||
let stdin = stdin.lock(); | ||
|
||
stdin.lines() | ||
.map(Result::unwrap) | ||
.map(|val| val.parse()) | ||
.map(Result::unwrap) | ||
.filter(|val| *val >= min) | ||
.collect() | ||
} | ||
|
||
fn main() {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
error[E0597]: `counter` does not live long enough | ||
--> $DIR/issue-54556-niconii.rs:22:20 | ||
| | ||
LL | if let Ok(_) = counter.lock() { } | ||
| ^^^^^^^------- | ||
| | | ||
| borrowed value does not live long enough | ||
| a temporary with access to the borrow is created here ... | ||
... | ||
LL | } | ||
| - | ||
| | | ||
| `counter` dropped here while still borrowed | ||
| ... and the borrow might be used here, when that temporary is dropped and runs the destructor for type `std::result::Result<MutexGuard<'_>, ()>` | ||
| | ||
= 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. | ||
|
||
error: aborting due to previous error | ||
|
||
For more information about this error, try `rustc --explain E0597`. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
// This is a reduction of a concrete test illustrating a case that was | ||
// annoying to Rust developer niconii (see comment thread on #21114). | ||
// | ||
// With resolving issue #54556, pnkfelix hopes that the new diagnostic | ||
// output produced by NLL helps to *explain* the semantic significance | ||
// of temp drop order, and thus why inserting a semi-colon after the | ||
// `if let` expression in `main` works. | ||
|
||
struct Mutex; | ||
struct MutexGuard<'a>(&'a Mutex); | ||
|
||
impl Drop for Mutex { fn drop(&mut self) { println!("Mutex::drop"); } } | ||
impl<'a> Drop for MutexGuard<'a> { fn drop(&mut self) { println!("MutexGuard::drop"); } } | ||
|
||
impl Mutex { | ||
fn lock(&self) -> Result<MutexGuard, ()> { Ok(MutexGuard(self)) } | ||
} | ||
|
||
fn main() { | ||
let counter = Mutex; | ||
|
||
if let Ok(_) = counter.lock() { } | ||
|
||
// With this code as written, the dynamic semantics here implies | ||
// that `Mutex::drop` for `counter` runs *before* | ||
// `MutexGuard::drop`, which would be unsound since `MutexGuard` | ||
// still has a reference to `counter`. | ||
// | ||
// The goal of #54556 is to explain that within a compiler | ||
// diagnostic. | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
error[E0597]: `counter` does not live long enough | ||
--> $DIR/issue-54556-niconii.rs:22:20 | ||
| | ||
LL | if let Ok(_) = counter.lock() { } | ||
| ^^^^^^^ borrowed value does not live long enough | ||
... | ||
LL | } | ||
| - `counter` dropped here while still borrowed | ||
| | ||
= note: values in a scope are dropped in the opposite order they are created | ||
|
||
error: aborting due to previous error | ||
|
||
For more information about this error, try `rustc --explain E0597`. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
error[E0597]: `stmt` does not live long enough | ||
--> $DIR/issue-54556-stephaneyfx.rs:27:21 | ||
| | ||
LL | let rows = Rows(&stmt); | ||
| ^^^^^ borrowed value does not live long enough | ||
LL | rows.map(|row| row).next() | ||
| ------------------- a temporary with access to the borrow is created here ... | ||
... | ||
LL | } | ||
| - | ||
| | | ||
| `stmt` dropped here while still borrowed | ||
| ... 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]>` | ||
| | ||
= 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. | ||
|
||
error: aborting due to previous error | ||
|
||
For more information about this error, try `rustc --explain E0597`. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
// This is a reduction of a concrete test illustrating a case that was | ||
// annoying to Rust developer stephaneyfx (see issue #46413). | ||
// | ||
// With resolving issue #54556, pnkfelix hopes that the new diagnostic | ||
// output produced by NLL helps to *explain* the semantic significance | ||
// of temp drop order, and thus why storing the result in `x` and then | ||
// returning `x` works. | ||
|
||
pub struct Statement; | ||
|
||
pub struct Rows<'stmt>(&'stmt Statement); | ||
|
||
impl<'stmt> Drop for Rows<'stmt> { | ||
fn drop(&mut self) {} | ||
} | ||
|
||
impl<'stmt> Iterator for Rows<'stmt> { | ||
type Item = String; | ||
|
||
fn next(&mut self) -> Option<Self::Item> { | ||
None | ||
} | ||
} | ||
|
||
fn get_names() -> Option<String> { | ||
let stmt = Statement; | ||
let rows = Rows(&stmt); | ||
rows.map(|row| row).next() | ||
// let x = rows.map(|row| row).next(); | ||
// x | ||
// | ||
// Removing the map works too as does removing the Drop impl. | ||
} | ||
|
||
fn main() {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
error[E0597]: `stmt` does not live long enough | ||
--> $DIR/issue-54556-stephaneyfx.rs:27:22 | ||
| | ||
LL | let rows = Rows(&stmt); | ||
| ^^^^ borrowed value does not live long enough | ||
... | ||
LL | } | ||
| - `stmt` dropped here while still borrowed | ||
| | ||
= note: values in a scope are dropped in the opposite order they are created | ||
|
||
error: aborting due to previous error | ||
|
||
For more information about this error, try `rustc --explain E0597`. |
19 changes: 19 additions & 0 deletions
19
src/test/ui/nll/issue-54556-temps-in-tail-diagnostic.nll.stderr
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
error[E0597]: `_thing1` does not live long enough | ||
--> $DIR/issue-54556-temps-in-tail-diagnostic.rs:5:11 | ||
| | ||
LL | D(&_thing1).end() | ||
| --^^^^^^^^- | ||
| | | | ||
| | borrowed value does not live long enough | ||
| a temporary with access to the borrow is created here ... | ||
LL | } | ||
| - `_thing1` dropped here while still borrowed | ||
LL | | ||
LL | ; | ||
| - ... and the borrow might be used here, when that temporary is dropped and runs the `Drop` code for type `D` | ||
| | ||
= 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. | ||
|
||
error: aborting due to previous error | ||
|
||
For more information about this error, try `rustc --explain E0597`. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
fn main() { | ||
{ | ||
let mut _thing1 = D(Box::new("thing1")); | ||
// D("other").next(&_thing1).end() | ||
D(&_thing1).end() | ||
} | ||
|
||
; | ||
} | ||
|
||
#[derive(Debug)] | ||
struct D<T: std::fmt::Debug>(T); | ||
|
||
impl<T: std::fmt::Debug> Drop for D<T> { | ||
fn drop(&mut self) { | ||
println!("dropping {:?})", self); | ||
} | ||
} | ||
|
||
impl<T: std::fmt::Debug> D<T> { | ||
fn next<U: std::fmt::Debug>(&self, _other: U) -> D<U> { D(_other) } | ||
fn end(&self) { } | ||
} |
14 changes: 14 additions & 0 deletions
14
src/test/ui/nll/issue-54556-temps-in-tail-diagnostic.stderr
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
error[E0597]: `_thing1` does not live long enough | ||
--> $DIR/issue-54556-temps-in-tail-diagnostic.rs:5:12 | ||
| | ||
LL | D(&_thing1).end() | ||
| ^^^^^^^ borrowed value does not live long enough | ||
LL | } | ||
| - `_thing1` dropped here while still borrowed | ||
LL | | ||
LL | ; | ||
| - borrowed value needs to live until here | ||
|
||
error: aborting due to previous error | ||
|
||
For more information about this error, try `rustc --explain E0597`. |
113 changes: 113 additions & 0 deletions
113
src/test/ui/nll/issue-54556-used-vs-unused-tails.nll.stderr
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
error[E0597]: `_t1` does not live long enough | ||
--> $DIR/issue-54556-used-vs-unused-tails.rs:10:55 | ||
| | ||
LL | { let mut _t1 = D(Box::new("t1")); D(&_t1).end() } ; // suggest `;` | ||
| --^^^^- - - ... and the borrow might be used here, when that temporary is dropped and runs the `Drop` code for type `D` | ||
| | | | | ||
| | | `_t1` dropped here while still borrowed | ||
| | borrowed value does not live long enough | ||
| a temporary with access to the borrow is created here ... | ||
| | ||
= 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. | ||
|
||
error[E0597]: `_t1` does not live long enough | ||
--> $DIR/issue-54556-used-vs-unused-tails.rs:12:55 | ||
| | ||
LL | { { let mut _t1 = D(Box::new("t1")); D(&_t1).end() } } ; // suggest `;` | ||
| --^^^^- - - ... and the borrow might be used here, when that temporary is dropped and runs the `Drop` code for type `D` | ||
| | | | | ||
| | | `_t1` dropped here while still borrowed | ||
| | borrowed value does not live long enough | ||
| a temporary with access to the borrow is created here ... | ||
| | ||
= 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. | ||
|
||
error[E0597]: `_t1` does not live long enough | ||
--> $DIR/issue-54556-used-vs-unused-tails.rs:14:55 | ||
| | ||
LL | { { let mut _t1 = D(Box::new("t1")); D(&_t1).end() }; } // suggest `;` | ||
| --^^^^- -- ... and the borrow might be used here, when that temporary is dropped and runs the `Drop` code for type `D` | ||
| | | | | ||
| | | `_t1` dropped here while still borrowed | ||
| | borrowed value does not live long enough | ||
| a temporary with access to the borrow is created here ... | ||
| | ||
= 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. | ||
|
||
error[E0597]: `_t1` does not live long enough | ||
--> $DIR/issue-54556-used-vs-unused-tails.rs:16:55 | ||
| | ||
LL | let _ = { let mut _t1 = D(Box::new("t1")); D(&_t1).end() } ; // suggest `;` | ||
| --^^^^- - - ... and the borrow might be used here, when that temporary is dropped and runs the `Drop` code for type `D` | ||
| | | | | ||
| | | `_t1` dropped here while still borrowed | ||
| | borrowed value does not live long enough | ||
| a temporary with access to the borrow is created here ... | ||
| | ||
= 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. | ||
|
||
error[E0597]: `_t1` does not live long enough | ||
--> $DIR/issue-54556-used-vs-unused-tails.rs:18:55 | ||
| | ||
LL | let _u = { let mut _t1 = D(Box::new("t1")); D(&_t1).unit() } ; // suggest `;` | ||
| --^^^^- - - ... and the borrow might be used here, when that temporary is dropped and runs the `Drop` code for type `D` | ||
| | | | | ||
| | | `_t1` dropped here while still borrowed | ||
| | borrowed value does not live long enough | ||
| a temporary with access to the borrow is created here ... | ||
| | ||
= 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. | ||
|
||
error[E0597]: `_t1` does not live long enough | ||
--> $DIR/issue-54556-used-vs-unused-tails.rs:20:55 | ||
| | ||
LL | let _x = { let mut _t1 = D(Box::new("t1")); D(&_t1).end() } ; // `let x = ...; x` | ||
| --^^^^- - - ... and the borrow might be used here, when that temporary is dropped and runs the `Drop` code for type `D` | ||
| | | | | ||
| | | `_t1` dropped here while still borrowed | ||
| | borrowed value does not live long enough | ||
| a temporary with access to the borrow is created here ... | ||
| | ||
= 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. | ||
|
||
error[E0597]: `_t1` does not live long enough | ||
--> $DIR/issue-54556-used-vs-unused-tails.rs:24:55 | ||
| | ||
LL | _y = { let mut _t1 = D(Box::new("t1")); D(&_t1).end() } ; // `let x = ...; x` | ||
| --^^^^- - - ... and the borrow might be used here, when that temporary is dropped and runs the `Drop` code for type `D` | ||
| | | | | ||
| | | `_t1` dropped here while still borrowed | ||
| | borrowed value does not live long enough | ||
| a temporary with access to the borrow is created here ... | ||
| | ||
= 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. | ||
|
||
error[E0597]: `_t1` does not live long enough | ||
--> $DIR/issue-54556-used-vs-unused-tails.rs:30:55 | ||
| | ||
LL | fn f_local_ref() { let mut _t1 = D(Box::new("t1")); D(&_t1).unit() } // suggest `;` | ||
| --^^^^- - | ||
| | | | | ||
| | | `_t1` dropped here while still borrowed | ||
| | | ... and the borrow might be used here, when that temporary is dropped and runs the `Drop` code for type `D` | ||
| | borrowed value does not live long enough | ||
| a temporary with access to the borrow is created here ... | ||
| | ||
= 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. | ||
|
||
error[E0597]: `_t1` does not live long enough | ||
--> $DIR/issue-54556-used-vs-unused-tails.rs:32:55 | ||
| | ||
LL | fn f() -> String { let mut _t1 = D(Box::new("t1")); D(&_t1).end() } // `let x = ...; x` | ||
| --^^^^- - | ||
| | | | | ||
| | | `_t1` dropped here while still borrowed | ||
| | | ... and the borrow might be used here, when that temporary is dropped and runs the `Drop` code for type `D` | ||
| | borrowed value does not live long enough | ||
| a temporary with access to the borrow is created here ... | ||
| | ||
= 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. | ||
|
||
error: aborting due to 9 previous errors | ||
|
||
For more information about this error, try `rustc --explain E0597`. |
Oops, something went wrong.