Skip to content

Commit c79a6c0

Browse files
Rollup merge of #142584 - Urgau:span-borrowck-139049, r=fmease
Handle same-crate macro for borrowck semicolon suggestion Handles #142543 (comment) cc ```@m-ou-se``` r? ```@fmease```
2 parents 0945b2b + 994794a commit c79a6c0

File tree

4 files changed

+65
-120
lines changed

4 files changed

+65
-120
lines changed

compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -342,10 +342,7 @@ impl<'tcx> BorrowExplanation<'tcx> {
342342
}
343343
}
344344
} else if let LocalInfo::BlockTailTemp(info) = local_decl.local_info() {
345-
let sp = info
346-
.span
347-
.find_ancestor_in_same_ctxt(local_decl.source_info.span)
348-
.unwrap_or(info.span);
345+
let sp = info.span.find_oldest_ancestor_in_same_ctxt();
349346
if info.tail_result_is_ignored {
350347
// #85581: If the first mutable borrow's scope contains
351348
// the second borrow, this suggestion isn't helpful.
Lines changed: 16 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,52 +1,25 @@
1-
// Make sure the generated suggestion suggest editing the user
2-
// code instead of the std macro implementation
1+
// Make sure the generated suggestion suggest editing the user code instead of
2+
// the macro implementation (which might come from an external crate).
3+
// issue: <https://github.com/rust-lang/rust/issues/139049>
34

45
//@ run-rustfix
56

67
#![allow(dead_code)]
78

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-
}
9+
// You could assume that this comes from an extern crate (it doesn't
10+
// because an aux crate would be overkill for this test).
11+
macro_rules! perform { ($e:expr) => { D(&$e).end() } }
12+
//~^ ERROR does not live long enough
13+
//~| ERROR does not live long enough
3514

3615
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-
44-
let _write = {
45-
use std::io::Write as _;
16+
{ let l = (); perform!(l); };
17+
//~^ SUGGESTION ;
4618

47-
let mutex = Mutex;
48-
let x = write!(std::io::stdout(), "{}", mutex.lock()); x
49-
//~^ ERROR `mutex` does not live long enough
50-
//~| SUGGESTION let x
51-
};
19+
let _x = { let l = (); let x = perform!(l); x };
20+
//~^ SUGGESTION let x
5221
}
22+
23+
struct D<T>(T);
24+
impl<T> Drop for D<T> { fn drop(&mut self) {} }
25+
impl<T> D<T> { fn end(&self) -> String { String::new() } }
Lines changed: 16 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,52 +1,25 @@
1-
// Make sure the generated suggestion suggest editing the user
2-
// code instead of the std macro implementation
1+
// Make sure the generated suggestion suggest editing the user code instead of
2+
// the macro implementation (which might come from an external crate).
3+
// issue: <https://github.com/rust-lang/rust/issues/139049>
34

45
//@ run-rustfix
56

67
#![allow(dead_code)]
78

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-
}
9+
// You could assume that this comes from an extern crate (it doesn't
10+
// because an aux crate would be overkill for this test).
11+
macro_rules! perform { ($e:expr) => { D(&$e).end() } }
12+
//~^ ERROR does not live long enough
13+
//~| ERROR does not live long enough
3514

3615
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-
44-
let _write = {
45-
use std::io::Write as _;
16+
{ let l = (); perform!(l) };
17+
//~^ SUGGESTION ;
4618

47-
let mutex = Mutex;
48-
write!(std::io::stdout(), "{}", mutex.lock())
49-
//~^ ERROR `mutex` does not live long enough
50-
//~| SUGGESTION let x
51-
};
19+
let _x = { let l = (); perform!(l) };
20+
//~^ SUGGESTION let x
5221
}
22+
23+
struct D<T>(T);
24+
impl<T> Drop for D<T> { fn drop(&mut self) {} }
25+
impl<T> D<T> { fn end(&self) -> String { String::new() } }

tests/ui/borrowck/span-semicolon-issue-139049.stderr

Lines changed: 32 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,48 @@
1-
error[E0597]: `mutex` does not live long enough
2-
--> $DIR/span-semicolon-issue-139049.rs:39:27
1+
error[E0597]: `l` does not live long enough
2+
--> $DIR/span-semicolon-issue-139049.rs:11:41
33
|
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 ...
4+
LL | macro_rules! perform { ($e:expr) => { D(&$e).end() } }
5+
| --^^^-
6+
| | |
7+
| | borrowed value does not live long enough
8+
| a temporary with access to the borrow is created here ...
119
...
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
10+
LL | { let l = (); perform!(l) };
11+
| - ----------- -- ... and the borrow might be used here, when that temporary is dropped and runs the `Drop` code for type `D`
12+
| | | |
13+
| | | `l` dropped here while still borrowed
14+
| | in this macro invocation
15+
| binding `l` declared here
1616
|
17+
= note: this error originates in the macro `perform` (in Nightly builds, run with -Z macro-backtrace for more info)
1718
help: consider adding semicolon after the expression so its temporaries are dropped sooner, before the local variables declared by the block are dropped
1819
|
19-
LL | write!(Out, "{}", mutex.lock());
20-
| +
20+
LL | { let l = (); perform!(l); };
21+
| +
2122

22-
error[E0597]: `mutex` does not live long enough
23-
--> $DIR/span-semicolon-issue-139049.rs:48:41
23+
error[E0597]: `l` does not live long enough
24+
--> $DIR/span-semicolon-issue-139049.rs:11:41
2425
|
25-
LL | let mutex = Mutex;
26-
| ----- binding `mutex` declared here
27-
LL | write!(std::io::stdout(), "{}", mutex.lock())
28-
| ^^^^^-------
29-
| |
30-
| borrowed value does not live long enough
31-
| a temporary with access to the borrow is created here ...
26+
LL | macro_rules! perform { ($e:expr) => { D(&$e).end() } }
27+
| --^^^-
28+
| | |
29+
| | borrowed value does not live long enough
30+
| a temporary with access to the borrow is created here ...
3231
...
33-
LL | };
34-
| -- ... and the borrow might be used here, when that temporary is dropped and runs the `Drop` code for type `MutexGuard`
35-
| |
36-
| `mutex` dropped here while still borrowed
32+
LL | let _x = { let l = (); perform!(l) };
33+
| - ----------- -- ... and the borrow might be used here, when that temporary is dropped and runs the `Drop` code for type `D`
34+
| | | |
35+
| | | `l` dropped here while still borrowed
36+
| | in this macro invocation
37+
| binding `l` declared here
3738
|
3839
= note: the temporary is part of an expression at the end of a block;
3940
consider forcing this temporary to be dropped sooner, before the block's local variables are dropped
41+
= note: this error originates in the macro `perform` (in Nightly builds, run with -Z macro-backtrace for more info)
4042
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
4143
|
42-
LL | let x = write!(std::io::stdout(), "{}", mutex.lock()); x
43-
| +++++++ +++
44+
LL | let _x = { let l = (); let x = perform!(l); x };
45+
| +++++++ +++
4446

4547
error: aborting due to 2 previous errors
4648

0 commit comments

Comments
 (0)