Skip to content

Commit ac875a1

Browse files
committed
Suggest adding semicolon in user code rather than macro impl details
1 parent 6c8138d commit ac875a1

File tree

4 files changed

+114
-1
lines changed

4 files changed

+114
-1
lines changed

compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -349,7 +349,10 @@ impl<'tcx> BorrowExplanation<'tcx> {
349349
old.to(info.span.shrink_to_hi()).contains(new)
350350
}) {
351351
err.span_suggestion_verbose(
352-
info.span.shrink_to_hi(),
352+
info.span
353+
.find_ancestor_in_same_ctxt(local_decl.source_info.span)
354+
.unwrap_or(info.span)
355+
.shrink_to_hi(),
353356
"consider adding semicolon after the expression so its \
354357
temporaries are dropped sooner, before the local variables \
355358
declared by the block are dropped",
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// Make sure the generated suggestion suggest editing the user
2+
// code instead of the std macro implementation
3+
4+
//@ run-rustfix
5+
6+
#![allow(dead_code)]
7+
8+
use std::fmt::{self, Display};
9+
10+
struct Mutex;
11+
12+
impl Mutex {
13+
fn lock(&self) -> MutexGuard<'_> {
14+
MutexGuard(self)
15+
}
16+
}
17+
18+
struct MutexGuard<'a>(&'a Mutex);
19+
20+
impl<'a> Drop for MutexGuard<'a> {
21+
fn drop(&mut self) {}
22+
}
23+
24+
struct Out;
25+
26+
impl Out {
27+
fn write_fmt(&self, _args: fmt::Arguments) {}
28+
}
29+
30+
impl<'a> Display for MutexGuard<'a> {
31+
fn fmt(&self, _formatter: &mut fmt::Formatter) -> fmt::Result {
32+
Ok(())
33+
}
34+
}
35+
36+
fn main() {
37+
let _write = {
38+
let mutex = Mutex;
39+
write!(Out, "{}", mutex.lock());
40+
//~^ ERROR `mutex` does not live long enough
41+
//~| SUGGESTION ;
42+
};
43+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// Make sure the generated suggestion suggest editing the user
2+
// code instead of the std macro implementation
3+
4+
//@ run-rustfix
5+
6+
#![allow(dead_code)]
7+
8+
use std::fmt::{self, Display};
9+
10+
struct Mutex;
11+
12+
impl Mutex {
13+
fn lock(&self) -> MutexGuard<'_> {
14+
MutexGuard(self)
15+
}
16+
}
17+
18+
struct MutexGuard<'a>(&'a Mutex);
19+
20+
impl<'a> Drop for MutexGuard<'a> {
21+
fn drop(&mut self) {}
22+
}
23+
24+
struct Out;
25+
26+
impl Out {
27+
fn write_fmt(&self, _args: fmt::Arguments) {}
28+
}
29+
30+
impl<'a> Display for MutexGuard<'a> {
31+
fn fmt(&self, _formatter: &mut fmt::Formatter) -> fmt::Result {
32+
Ok(())
33+
}
34+
}
35+
36+
fn main() {
37+
let _write = {
38+
let mutex = Mutex;
39+
write!(Out, "{}", mutex.lock())
40+
//~^ ERROR `mutex` does not live long enough
41+
//~| SUGGESTION ;
42+
};
43+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
error[E0597]: `mutex` does not live long enough
2+
--> $DIR/span-semicolon-issue-139049.rs:39:27
3+
|
4+
LL | let mutex = Mutex;
5+
| ----- binding `mutex` declared here
6+
LL | write!(Out, "{}", mutex.lock())
7+
| ^^^^^-------
8+
| |
9+
| borrowed value does not live long enough
10+
| a temporary with access to the borrow is created here ...
11+
...
12+
LL | };
13+
| -- ... and the borrow might be used here, when that temporary is dropped and runs the `Drop` code for type `MutexGuard`
14+
| |
15+
| `mutex` dropped here while still borrowed
16+
|
17+
help: consider adding semicolon after the expression so its temporaries are dropped sooner, before the local variables declared by the block are dropped
18+
|
19+
LL | write!(Out, "{}", mutex.lock());
20+
| +
21+
22+
error: aborting due to 1 previous error
23+
24+
For more information about this error, try `rustc --explain E0597`.

0 commit comments

Comments
 (0)