From 056cfffd1ba69e2e80d87c728d8475944dfbe050 Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Wed, 3 Oct 2018 17:47:23 +0200 Subject: [PATCH] Unit tests for issue #54556. Some were also taken from issues #21114, #46413. --- src/test/ui/nll/issue-21114-ebfull.rs | 20 ++++ src/test/ui/nll/issue-21114-kixunil.rs | 19 +++ .../ui/nll/issue-54556-niconii.nll.stderr | 20 ++++ src/test/ui/nll/issue-54556-niconii.rs | 31 +++++ src/test/ui/nll/issue-54556-niconii.stderr | 14 +++ .../ui/nll/issue-54556-stephaneyfx.nll.stderr | 19 +++ src/test/ui/nll/issue-54556-stephaneyfx.rs | 35 ++++++ .../ui/nll/issue-54556-stephaneyfx.stderr | 14 +++ ...-54556-temps-in-tail-diagnostic.nll.stderr | 19 +++ .../issue-54556-temps-in-tail-diagnostic.rs | 23 ++++ ...ssue-54556-temps-in-tail-diagnostic.stderr | 14 +++ ...ssue-54556-used-vs-unused-tails.nll.stderr | 113 ++++++++++++++++++ .../nll/issue-54556-used-vs-unused-tails.rs | 48 ++++++++ .../issue-54556-used-vs-unused-tails.stderr | 86 +++++++++++++ .../ui/nll/issue-54556-wrap-it-up.nll.stderr | 14 +++ src/test/ui/nll/issue-54556-wrap-it-up.rs | 28 +++++ src/test/ui/nll/issue-54556-wrap-it-up.stderr | 12 ++ 17 files changed, 529 insertions(+) create mode 100644 src/test/ui/nll/issue-21114-ebfull.rs create mode 100644 src/test/ui/nll/issue-21114-kixunil.rs create mode 100644 src/test/ui/nll/issue-54556-niconii.nll.stderr create mode 100644 src/test/ui/nll/issue-54556-niconii.rs create mode 100644 src/test/ui/nll/issue-54556-niconii.stderr create mode 100644 src/test/ui/nll/issue-54556-stephaneyfx.nll.stderr create mode 100644 src/test/ui/nll/issue-54556-stephaneyfx.rs create mode 100644 src/test/ui/nll/issue-54556-stephaneyfx.stderr create mode 100644 src/test/ui/nll/issue-54556-temps-in-tail-diagnostic.nll.stderr create mode 100644 src/test/ui/nll/issue-54556-temps-in-tail-diagnostic.rs create mode 100644 src/test/ui/nll/issue-54556-temps-in-tail-diagnostic.stderr create mode 100644 src/test/ui/nll/issue-54556-used-vs-unused-tails.nll.stderr create mode 100644 src/test/ui/nll/issue-54556-used-vs-unused-tails.rs create mode 100644 src/test/ui/nll/issue-54556-used-vs-unused-tails.stderr create mode 100644 src/test/ui/nll/issue-54556-wrap-it-up.nll.stderr create mode 100644 src/test/ui/nll/issue-54556-wrap-it-up.rs create mode 100644 src/test/ui/nll/issue-54556-wrap-it-up.stderr diff --git a/src/test/ui/nll/issue-21114-ebfull.rs b/src/test/ui/nll/issue-21114-ebfull.rs new file mode 100644 index 0000000000000..f5738968746ee --- /dev/null +++ b/src/test/ui/nll/issue-21114-ebfull.rs @@ -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>) -> Vec<(usize, usize)> { + let mut foo = foo.lock().unwrap(); + + foo.drain().collect() +} + +fn but_after_nightly_update_now_i_gotta(foo: &Mutex>) -> Vec<(usize, usize)> { + let mut foo = foo.lock().unwrap(); + + return foo.drain().collect(); +} + +fn main() {} diff --git a/src/test/ui/nll/issue-21114-kixunil.rs b/src/test/ui/nll/issue-21114-kixunil.rs new file mode 100644 index 0000000000000..2add951b70bc0 --- /dev/null +++ b/src/test/ui/nll/issue-21114-kixunil.rs @@ -0,0 +1,19 @@ +// (this works, but only in NLL) +// compile-pass +#![feature(nll)] + +fn from_stdin(min: u64) -> Vec { + 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() {} diff --git a/src/test/ui/nll/issue-54556-niconii.nll.stderr b/src/test/ui/nll/issue-54556-niconii.nll.stderr new file mode 100644 index 0000000000000..40cd04de5ecc1 --- /dev/null +++ b/src/test/ui/nll/issue-54556-niconii.nll.stderr @@ -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, ()>` + | + = 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`. diff --git a/src/test/ui/nll/issue-54556-niconii.rs b/src/test/ui/nll/issue-54556-niconii.rs new file mode 100644 index 0000000000000..49b063f44f427 --- /dev/null +++ b/src/test/ui/nll/issue-54556-niconii.rs @@ -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 { 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. +} diff --git a/src/test/ui/nll/issue-54556-niconii.stderr b/src/test/ui/nll/issue-54556-niconii.stderr new file mode 100644 index 0000000000000..2d0de26ab309a --- /dev/null +++ b/src/test/ui/nll/issue-54556-niconii.stderr @@ -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`. diff --git a/src/test/ui/nll/issue-54556-stephaneyfx.nll.stderr b/src/test/ui/nll/issue-54556-stephaneyfx.nll.stderr new file mode 100644 index 0000000000000..0bf76485eef2a --- /dev/null +++ b/src/test/ui/nll/issue-54556-stephaneyfx.nll.stderr @@ -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, [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`. diff --git a/src/test/ui/nll/issue-54556-stephaneyfx.rs b/src/test/ui/nll/issue-54556-stephaneyfx.rs new file mode 100644 index 0000000000000..10a4e21497c73 --- /dev/null +++ b/src/test/ui/nll/issue-54556-stephaneyfx.rs @@ -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 { + None + } +} + +fn get_names() -> Option { + 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() {} diff --git a/src/test/ui/nll/issue-54556-stephaneyfx.stderr b/src/test/ui/nll/issue-54556-stephaneyfx.stderr new file mode 100644 index 0000000000000..4e581a516b2d3 --- /dev/null +++ b/src/test/ui/nll/issue-54556-stephaneyfx.stderr @@ -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`. diff --git a/src/test/ui/nll/issue-54556-temps-in-tail-diagnostic.nll.stderr b/src/test/ui/nll/issue-54556-temps-in-tail-diagnostic.nll.stderr new file mode 100644 index 0000000000000..513dca7950af9 --- /dev/null +++ b/src/test/ui/nll/issue-54556-temps-in-tail-diagnostic.nll.stderr @@ -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`. diff --git a/src/test/ui/nll/issue-54556-temps-in-tail-diagnostic.rs b/src/test/ui/nll/issue-54556-temps-in-tail-diagnostic.rs new file mode 100644 index 0000000000000..63b04333de4be --- /dev/null +++ b/src/test/ui/nll/issue-54556-temps-in-tail-diagnostic.rs @@ -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); + +impl Drop for D { + fn drop(&mut self) { + println!("dropping {:?})", self); + } +} + +impl D { + fn next(&self, _other: U) -> D { D(_other) } + fn end(&self) { } +} diff --git a/src/test/ui/nll/issue-54556-temps-in-tail-diagnostic.stderr b/src/test/ui/nll/issue-54556-temps-in-tail-diagnostic.stderr new file mode 100644 index 0000000000000..a74970f71182a --- /dev/null +++ b/src/test/ui/nll/issue-54556-temps-in-tail-diagnostic.stderr @@ -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`. diff --git a/src/test/ui/nll/issue-54556-used-vs-unused-tails.nll.stderr b/src/test/ui/nll/issue-54556-used-vs-unused-tails.nll.stderr new file mode 100644 index 0000000000000..9911fc9729190 --- /dev/null +++ b/src/test/ui/nll/issue-54556-used-vs-unused-tails.nll.stderr @@ -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`. diff --git a/src/test/ui/nll/issue-54556-used-vs-unused-tails.rs b/src/test/ui/nll/issue-54556-used-vs-unused-tails.rs new file mode 100644 index 0000000000000..64e4f75724aad --- /dev/null +++ b/src/test/ui/nll/issue-54556-used-vs-unused-tails.rs @@ -0,0 +1,48 @@ +// Ths test case is exploring the space of how blocs with tail +// expressions and statements can be composed, trying to keep each +// case on one line so that we can compare them via a vertical scan +// with the human eye. + +// Each comment on the right side of the line is summarizing the +// expected suggestion from the diagnostic for issue #54556. + +fn main() { + { let mut _t1 = D(Box::new("t1")); D(&_t1).end() } ; // suggest `;` + + { { let mut _t1 = D(Box::new("t1")); D(&_t1).end() } } ; // suggest `;` + + { { let mut _t1 = D(Box::new("t1")); D(&_t1).end() }; } // suggest `;` + + let _ = { let mut _t1 = D(Box::new("t1")); D(&_t1).end() } ; // suggest `;` + + let _u = { let mut _t1 = D(Box::new("t1")); D(&_t1).unit() } ; // suggest `;` + + let _x = { let mut _t1 = D(Box::new("t1")); D(&_t1).end() } ; // `let x = ...; x` + let _x = { let mut _t1 = D(Box::new("t1")); let x = D(&_t1).end(); x } ; // no error + + let mut _y; + _y = { let mut _t1 = D(Box::new("t1")); D(&_t1).end() } ; // `let x = ...; x` + _y = { let mut _t1 = D(Box::new("t1")); let x = D(&_t1).end(); x } ; // no error +} + +fn f_param_ref(_t1: D>) { D(&_t1).unit() } // no error + +fn f_local_ref() { let mut _t1 = D(Box::new("t1")); D(&_t1).unit() } // suggest `;` + +fn f() -> String { let mut _t1 = D(Box::new("t1")); D(&_t1).end() } // `let x = ...; x` + + +#[derive(Debug)] +struct D(T); + +impl Drop for D { + fn drop(&mut self) { + println!("dropping {:?})", self); + } +} + +impl D { + fn next(&self, _other: U) -> D { D(_other) } + fn end(&self) -> String { format!("End({:?})", self.0) } + fn unit(&self) { } +} diff --git a/src/test/ui/nll/issue-54556-used-vs-unused-tails.stderr b/src/test/ui/nll/issue-54556-used-vs-unused-tails.stderr new file mode 100644 index 0000000000000..c75707b2aee17 --- /dev/null +++ b/src/test/ui/nll/issue-54556-used-vs-unused-tails.stderr @@ -0,0 +1,86 @@ +error[E0597]: `_t1` does not live long enough + --> $DIR/issue-54556-used-vs-unused-tails.rs:10:56 + | +LL | { let mut _t1 = D(Box::new("t1")); D(&_t1).end() } ; // suggest `;` + | ^^^ - - borrowed value needs to live until here + | | | + | | `_t1` dropped here while still borrowed + | borrowed value does not live long enough + +error[E0597]: `_t1` does not live long enough + --> $DIR/issue-54556-used-vs-unused-tails.rs:12:56 + | +LL | { { let mut _t1 = D(Box::new("t1")); D(&_t1).end() } } ; // suggest `;` + | ^^^ - - borrowed value needs to live until here + | | | + | | `_t1` dropped here while still borrowed + | borrowed value does not live long enough + +error[E0597]: `_t1` does not live long enough + --> $DIR/issue-54556-used-vs-unused-tails.rs:14:56 + | +LL | { { let mut _t1 = D(Box::new("t1")); D(&_t1).end() }; } // suggest `;` + | ^^^ -- borrowed value needs to live until here + | | | + | | `_t1` dropped here while still borrowed + | borrowed value does not live long enough + +error[E0597]: `_t1` does not live long enough + --> $DIR/issue-54556-used-vs-unused-tails.rs:16:56 + | +LL | let _ = { let mut _t1 = D(Box::new("t1")); D(&_t1).end() } ; // suggest `;` + | ^^^ - - borrowed value needs to live until here + | | | + | | `_t1` dropped here while still borrowed + | borrowed value does not live long enough + +error[E0597]: `_t1` does not live long enough + --> $DIR/issue-54556-used-vs-unused-tails.rs:18:56 + | +LL | let _u = { let mut _t1 = D(Box::new("t1")); D(&_t1).unit() } ; // suggest `;` + | ^^^ - - borrowed value needs to live until here + | | | + | | `_t1` dropped here while still borrowed + | borrowed value does not live long enough + +error[E0597]: `_t1` does not live long enough + --> $DIR/issue-54556-used-vs-unused-tails.rs:20:56 + | +LL | let _x = { let mut _t1 = D(Box::new("t1")); D(&_t1).end() } ; // `let x = ...; x` + | ^^^ - - borrowed value needs to live until here + | | | + | | `_t1` dropped here while still borrowed + | borrowed value does not live long enough + +error[E0597]: `_t1` does not live long enough + --> $DIR/issue-54556-used-vs-unused-tails.rs:24:56 + | +LL | _y = { let mut _t1 = D(Box::new("t1")); D(&_t1).end() } ; // `let x = ...; x` + | ^^^ - - borrowed value needs to live until here + | | | + | | `_t1` dropped here while still borrowed + | borrowed value does not live long enough + +error[E0597]: `_t1` does not live long enough + --> $DIR/issue-54556-used-vs-unused-tails.rs:30:56 + | +LL | fn f_local_ref() { let mut _t1 = D(Box::new("t1")); D(&_t1).unit() } // suggest `;` + | ^^^ - `_t1` dropped here while still borrowed + | | + | borrowed value does not live long enough + | + = note: values in a scope are dropped in the opposite order they are created + +error[E0597]: `_t1` does not live long enough + --> $DIR/issue-54556-used-vs-unused-tails.rs:32:56 + | +LL | fn f() -> String { let mut _t1 = D(Box::new("t1")); D(&_t1).end() } // `let x = ...; x` + | ^^^ - `_t1` dropped here while still borrowed + | | + | borrowed value does not live long enough + | + = note: values in a scope are dropped in the opposite order they are created + +error: aborting due to 9 previous errors + +For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/nll/issue-54556-wrap-it-up.nll.stderr b/src/test/ui/nll/issue-54556-wrap-it-up.nll.stderr new file mode 100644 index 0000000000000..a13e59fa48b5c --- /dev/null +++ b/src/test/ui/nll/issue-54556-wrap-it-up.nll.stderr @@ -0,0 +1,14 @@ +error[E0506]: cannot assign to `x` because it is borrowed + --> $DIR/issue-54556-wrap-it-up.rs:27:5 + | +LL | let wrap = Wrap { p: &mut x }; + | ------ borrow of `x` occurs here +... +LL | x = 1; //~ ERROR cannot assign to `x` because it is borrowed [E0506] + | ^^^^^ assignment to borrowed `x` occurs here +LL | } + | - borrow might be used here, when `foo` is dropped and runs the destructor for type `Foo<'_>` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0506`. diff --git a/src/test/ui/nll/issue-54556-wrap-it-up.rs b/src/test/ui/nll/issue-54556-wrap-it-up.rs new file mode 100644 index 0000000000000..11dbef0d86460 --- /dev/null +++ b/src/test/ui/nll/issue-54556-wrap-it-up.rs @@ -0,0 +1,28 @@ +// This is testing how the diagnostic from issue #54556 behaves when +// the destructor code is attached to a place held in a field of the +// temporary being dropped. +// +// Eventually it would be nice if the diagnostic would actually report +// that specific place and its type that implements the `Drop` trait. +// But for the short term, it is acceptable to just print out the +// whole type of the temporary. + +#![allow(warnings)] + +struct Wrap<'p> { p: &'p mut i32 } + +impl<'p> Drop for Wrap<'p> { + fn drop(&mut self) { + *self.p += 1; + } +} + +struct Foo<'p> { a: String, b: Wrap<'p> } + +fn main() { + let mut x = 0; + let wrap = Wrap { p: &mut x }; + let s = String::from("str"); + let foo = Foo { a: s, b: wrap }; + x = 1; //~ ERROR cannot assign to `x` because it is borrowed [E0506] +} diff --git a/src/test/ui/nll/issue-54556-wrap-it-up.stderr b/src/test/ui/nll/issue-54556-wrap-it-up.stderr new file mode 100644 index 0000000000000..a0c19b9638798 --- /dev/null +++ b/src/test/ui/nll/issue-54556-wrap-it-up.stderr @@ -0,0 +1,12 @@ +error[E0506]: cannot assign to `x` because it is borrowed + --> $DIR/issue-54556-wrap-it-up.rs:27:5 + | +LL | let wrap = Wrap { p: &mut x }; + | - borrow of `x` occurs here +... +LL | x = 1; //~ ERROR cannot assign to `x` because it is borrowed [E0506] + | ^^^^^ assignment to borrowed `x` occurs here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0506`.