Rollup merge of #142543 - Urgau:span-borrowck-semicolon, r=fmease
Suggest adding semicolon in user code rather than macro impl details This PR tries to find the right span (by peeling expansion) so that the suggestion for adding a semicolon is suggested in user code rather than in the expanded code (in the example a macro impl). Fixes rust-lang/rust#139049 r? `@fmease`
This commit is contained in:
commit
07048643dd
5 changed files with 166 additions and 3 deletions
|
|
@ -342,6 +342,10 @@ impl<'tcx> BorrowExplanation<'tcx> {
|
|||
}
|
||||
}
|
||||
} else if let LocalInfo::BlockTailTemp(info) = local_decl.local_info() {
|
||||
let sp = info
|
||||
.span
|
||||
.find_ancestor_in_same_ctxt(local_decl.source_info.span)
|
||||
.unwrap_or(info.span);
|
||||
if info.tail_result_is_ignored {
|
||||
// #85581: If the first mutable borrow's scope contains
|
||||
// the second borrow, this suggestion isn't helpful.
|
||||
|
|
@ -349,7 +353,7 @@ impl<'tcx> BorrowExplanation<'tcx> {
|
|||
old.to(info.span.shrink_to_hi()).contains(new)
|
||||
}) {
|
||||
err.span_suggestion_verbose(
|
||||
info.span.shrink_to_hi(),
|
||||
sp.shrink_to_hi(),
|
||||
"consider adding semicolon after the expression so its \
|
||||
temporaries are dropped sooner, before the local variables \
|
||||
declared by the block are dropped",
|
||||
|
|
@ -368,8 +372,8 @@ impl<'tcx> BorrowExplanation<'tcx> {
|
|||
local variable `x` and then make `x` be the expression at the \
|
||||
end of the block",
|
||||
vec![
|
||||
(info.span.shrink_to_lo(), "let x = ".to_string()),
|
||||
(info.span.shrink_to_hi(), "; x".to_string()),
|
||||
(sp.shrink_to_lo(), "let x = ".to_string()),
|
||||
(sp.shrink_to_hi(), "; x".to_string()),
|
||||
],
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
|
|
|
|||
52
tests/ui/borrowck/span-semicolon-issue-139049.fixed
Normal file
52
tests/ui/borrowck/span-semicolon-issue-139049.fixed
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
// Make sure the generated suggestion suggest editing the user
|
||||
// code instead of the std macro implementation
|
||||
|
||||
//@ run-rustfix
|
||||
|
||||
#![allow(dead_code)]
|
||||
|
||||
use std::fmt::{self, Display};
|
||||
|
||||
struct Mutex;
|
||||
|
||||
impl Mutex {
|
||||
fn lock(&self) -> MutexGuard<'_> {
|
||||
MutexGuard(self)
|
||||
}
|
||||
}
|
||||
|
||||
struct MutexGuard<'a>(&'a Mutex);
|
||||
|
||||
impl<'a> Drop for MutexGuard<'a> {
|
||||
fn drop(&mut self) {}
|
||||
}
|
||||
|
||||
struct Out;
|
||||
|
||||
impl Out {
|
||||
fn write_fmt(&self, _args: fmt::Arguments) {}
|
||||
}
|
||||
|
||||
impl<'a> Display for MutexGuard<'a> {
|
||||
fn fmt(&self, _formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let _write = {
|
||||
let mutex = Mutex;
|
||||
write!(Out, "{}", mutex.lock());
|
||||
//~^ ERROR `mutex` does not live long enough
|
||||
//~| SUGGESTION ;
|
||||
};
|
||||
|
||||
let _write = {
|
||||
use std::io::Write as _;
|
||||
|
||||
let mutex = Mutex;
|
||||
let x = write!(std::io::stdout(), "{}", mutex.lock()); x
|
||||
//~^ ERROR `mutex` does not live long enough
|
||||
//~| SUGGESTION let x
|
||||
};
|
||||
}
|
||||
52
tests/ui/borrowck/span-semicolon-issue-139049.rs
Normal file
52
tests/ui/borrowck/span-semicolon-issue-139049.rs
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
// Make sure the generated suggestion suggest editing the user
|
||||
// code instead of the std macro implementation
|
||||
|
||||
//@ run-rustfix
|
||||
|
||||
#![allow(dead_code)]
|
||||
|
||||
use std::fmt::{self, Display};
|
||||
|
||||
struct Mutex;
|
||||
|
||||
impl Mutex {
|
||||
fn lock(&self) -> MutexGuard<'_> {
|
||||
MutexGuard(self)
|
||||
}
|
||||
}
|
||||
|
||||
struct MutexGuard<'a>(&'a Mutex);
|
||||
|
||||
impl<'a> Drop for MutexGuard<'a> {
|
||||
fn drop(&mut self) {}
|
||||
}
|
||||
|
||||
struct Out;
|
||||
|
||||
impl Out {
|
||||
fn write_fmt(&self, _args: fmt::Arguments) {}
|
||||
}
|
||||
|
||||
impl<'a> Display for MutexGuard<'a> {
|
||||
fn fmt(&self, _formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let _write = {
|
||||
let mutex = Mutex;
|
||||
write!(Out, "{}", mutex.lock())
|
||||
//~^ ERROR `mutex` does not live long enough
|
||||
//~| SUGGESTION ;
|
||||
};
|
||||
|
||||
let _write = {
|
||||
use std::io::Write as _;
|
||||
|
||||
let mutex = Mutex;
|
||||
write!(std::io::stdout(), "{}", mutex.lock())
|
||||
//~^ ERROR `mutex` does not live long enough
|
||||
//~| SUGGESTION let x
|
||||
};
|
||||
}
|
||||
47
tests/ui/borrowck/span-semicolon-issue-139049.stderr
Normal file
47
tests/ui/borrowck/span-semicolon-issue-139049.stderr
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
error[E0597]: `mutex` does not live long enough
|
||||
--> $DIR/span-semicolon-issue-139049.rs:39:27
|
||||
|
|
||||
LL | let mutex = Mutex;
|
||||
| ----- binding `mutex` declared here
|
||||
LL | write!(Out, "{}", mutex.lock())
|
||||
| ^^^^^-------
|
||||
| |
|
||||
| borrowed value does not live long enough
|
||||
| a temporary with access to the borrow is created here ...
|
||||
...
|
||||
LL | };
|
||||
| -- ... and the borrow might be used here, when that temporary is dropped and runs the `Drop` code for type `MutexGuard`
|
||||
| |
|
||||
| `mutex` dropped here while still borrowed
|
||||
|
|
||||
help: consider adding semicolon after the expression so its temporaries are dropped sooner, before the local variables declared by the block are dropped
|
||||
|
|
||||
LL | write!(Out, "{}", mutex.lock());
|
||||
| +
|
||||
|
||||
error[E0597]: `mutex` does not live long enough
|
||||
--> $DIR/span-semicolon-issue-139049.rs:48:41
|
||||
|
|
||||
LL | let mutex = Mutex;
|
||||
| ----- binding `mutex` declared here
|
||||
LL | write!(std::io::stdout(), "{}", mutex.lock())
|
||||
| ^^^^^-------
|
||||
| |
|
||||
| borrowed value does not live long enough
|
||||
| a temporary with access to the borrow is created here ...
|
||||
...
|
||||
LL | };
|
||||
| -- ... and the borrow might be used here, when that temporary is dropped and runs the `Drop` code for type `MutexGuard`
|
||||
| |
|
||||
| `mutex` dropped here while still borrowed
|
||||
|
|
||||
= 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
|
||||
help: 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
|
||||
|
|
||||
LL | let x = write!(std::io::stdout(), "{}", mutex.lock()); x
|
||||
| +++++++ +++
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0597`.
|
||||
|
|
@ -14,6 +14,10 @@ LL | };
|
|||
| |
|
||||
| `mutex` dropped here while still borrowed
|
||||
|
|
||||
help: consider adding semicolon after the expression so its temporaries are dropped sooner, before the local variables declared by the block are dropped
|
||||
|
|
||||
LL | write!(Out, "{}", mutex.lock()); /* no semicolon */
|
||||
| +
|
||||
|
||||
error[E0597]: `mutex` does not live long enough
|
||||
--> $DIR/format-args-temporaries-in-write.rs:47:29
|
||||
|
|
@ -31,6 +35,10 @@ LL | };
|
|||
| |
|
||||
| `mutex` dropped here while still borrowed
|
||||
|
|
||||
help: consider adding semicolon after the expression so its temporaries are dropped sooner, before the local variables declared by the block are dropped
|
||||
|
|
||||
LL | writeln!(Out, "{}", mutex.lock()); /* no semicolon */
|
||||
| +
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue