Skip to content

Commit 7245006

Browse files
committed
Auto merge of #46598 - davidtwco:issue-46471, r=arielb1
MIR borrowck: error message confuses locals and temporaries Fixes #46471 and fixes #46472 (see [this Gitter comment](https://gitter.im/rust-impl-period/WG-compiler-nll?at=5a2d5cb53ae2aa6b3facf0c2)). r? @arielb1
2 parents 3a0b652 + 3dbc11b commit 7245006

21 files changed

+297
-51
lines changed

src/librustc_mir/borrow_check/error_reporting.rs

+90-4
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,14 @@
99
// except according to those terms.
1010

1111
use syntax_pos::Span;
12+
use rustc::middle::region::ScopeTree;
1213
use rustc::mir::{BorrowKind, Field, Local, Location, Operand};
1314
use rustc::mir::{Place, ProjectionElem, Rvalue, StatementKind};
14-
use rustc::ty;
15+
use rustc::ty::{self, RegionKind};
1516
use rustc_data_structures::indexed_vec::Idx;
1617

18+
use std::rc::Rc;
19+
1720
use super::{MirBorrowckCtxt, Context};
1821
use super::{InitializationRequiringAction, PrefixSet};
1922
use dataflow::{BorrowData, Borrows, FlowAtLocation, MovingOutStatements};
@@ -324,6 +327,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
324327
borrows: &Borrows<'cx, 'gcx, 'tcx>
325328
) {
326329
let end_span = borrows.opt_region_end_span(&borrow.region);
330+
let scope_tree = borrows.scope_tree();
327331
let root_place = self.prefixes(&borrow.place, PrefixSet::All).last().unwrap();
328332

329333
match root_place {
@@ -347,21 +351,103 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
347351
unreachable!("root_place is an unreachable???")
348352
};
349353

354+
let borrow_span = self.mir.source_info(borrow.location).span;
350355
let proper_span = match *root_place {
351356
Place::Local(local) => self.mir.local_decls[local].source_info.span,
352357
_ => drop_span,
353358
};
354359

355-
let mut err = self.tcx
356-
.path_does_not_live_long_enough(drop_span, "borrowed value", Origin::Mir);
360+
match (borrow.region, &self.describe_place(&borrow.place)) {
361+
(RegionKind::ReScope(_), Some(name)) => {
362+
self.report_scoped_local_value_does_not_live_long_enough(
363+
name, &scope_tree, &borrow, drop_span, borrow_span, proper_span, end_span);
364+
},
365+
(RegionKind::ReScope(_), None) => {
366+
self.report_scoped_temporary_value_does_not_live_long_enough(
367+
&scope_tree, &borrow, drop_span, borrow_span, proper_span, end_span);
368+
},
369+
(RegionKind::ReEarlyBound(_), Some(name)) |
370+
(RegionKind::ReFree(_), Some(name)) |
371+
(RegionKind::ReStatic, Some(name)) |
372+
(RegionKind::ReEmpty, Some(name)) |
373+
(RegionKind::ReVar(_), Some(name)) => {
374+
self.report_unscoped_local_value_does_not_live_long_enough(
375+
name, &scope_tree, &borrow, drop_span, borrow_span, proper_span, end_span);
376+
},
377+
(RegionKind::ReEarlyBound(_), None) |
378+
(RegionKind::ReFree(_), None) |
379+
(RegionKind::ReStatic, None) |
380+
(RegionKind::ReEmpty, None) |
381+
(RegionKind::ReVar(_), None) => {
382+
self.report_unscoped_temporary_value_does_not_live_long_enough(
383+
&scope_tree, &borrow, drop_span, borrow_span, proper_span, end_span);
384+
},
385+
(RegionKind::ReLateBound(_, _), _) |
386+
(RegionKind::ReSkolemized(_, _), _) |
387+
(RegionKind::ReErased, _) => {
388+
span_bug!(drop_span, "region does not make sense in this context");
389+
},
390+
}
391+
}
392+
393+
fn report_scoped_local_value_does_not_live_long_enough(
394+
&mut self, name: &String, _scope_tree: &Rc<ScopeTree>, _borrow: &BorrowData<'tcx>,
395+
drop_span: Span, borrow_span: Span, _proper_span: Span, end_span: Option<Span>
396+
) {
397+
let mut err = self.tcx.path_does_not_live_long_enough(drop_span,
398+
&format!("`{}`", name),
399+
Origin::Mir);
400+
err.span_label(borrow_span, "borrow occurs here");
401+
err.span_label(drop_span, format!("`{}` dropped here while still borrowed", name));
402+
if let Some(end) = end_span {
403+
err.span_label(end, "borrowed value needs to live until here");
404+
}
405+
err.emit();
406+
}
407+
408+
fn report_scoped_temporary_value_does_not_live_long_enough(
409+
&mut self, _scope_tree: &Rc<ScopeTree>, _borrow: &BorrowData<'tcx>,
410+
drop_span: Span, borrow_span: Span, proper_span: Span, end_span: Option<Span>
411+
) {
412+
let mut err = self.tcx.path_does_not_live_long_enough(borrow_span,
413+
"borrowed value",
414+
Origin::Mir);
357415
err.span_label(proper_span, "temporary value created here");
358416
err.span_label(drop_span, "temporary value dropped here while still borrowed");
359417
err.note("consider using a `let` binding to increase its lifetime");
360-
361418
if let Some(end) = end_span {
362419
err.span_label(end, "temporary value needs to live until here");
363420
}
421+
err.emit();
422+
}
423+
424+
fn report_unscoped_local_value_does_not_live_long_enough(
425+
&mut self, name: &String, scope_tree: &Rc<ScopeTree>, borrow: &BorrowData<'tcx>,
426+
drop_span: Span, borrow_span: Span, _proper_span: Span, _end_span: Option<Span>
427+
) {
428+
let mut err = self.tcx.path_does_not_live_long_enough(borrow_span,
429+
&format!("`{}`", name),
430+
Origin::Mir);
431+
err.span_label(borrow_span, "does not live long enough");
432+
err.span_label(drop_span, "borrowed value only lives until here");
433+
self.tcx.note_and_explain_region(scope_tree, &mut err,
434+
"borrowed value must be valid for ",
435+
borrow.region, "...");
436+
err.emit();
437+
}
364438

439+
fn report_unscoped_temporary_value_does_not_live_long_enough(
440+
&mut self, scope_tree: &Rc<ScopeTree>, borrow: &BorrowData<'tcx>,
441+
drop_span: Span, _borrow_span: Span, proper_span: Span, _end_span: Option<Span>
442+
) {
443+
let mut err = self.tcx.path_does_not_live_long_enough(proper_span,
444+
"borrowed value",
445+
Origin::Mir);
446+
err.span_label(proper_span, "does not live long enough");
447+
err.span_label(drop_span, "temporary value only lives until here");
448+
self.tcx.note_and_explain_region(scope_tree, &mut err,
449+
"borrowed value must be valid for ",
450+
borrow.region, "...");
365451
err.emit();
366452
}
367453

src/librustc_mir/borrow_check/mod.rs

-1
Original file line numberDiff line numberDiff line change
@@ -1800,7 +1800,6 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
18001800
}
18011801
}
18021802

1803-
18041803
impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
18051804
// FIXME (#16118): function intended to allow the borrow checker
18061805
// to be less precise in its handling of Box while still allowing

src/librustc_mir/dataflow/impls/borrows.rs

+2
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,8 @@ impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> {
160160

161161
pub fn borrows(&self) -> &IndexVec<BorrowIndex, BorrowData<'tcx>> { &self.borrows }
162162

163+
pub fn scope_tree(&self) -> &Rc<region::ScopeTree> { &self.scope_tree }
164+
163165
pub fn location(&self, idx: BorrowIndex) -> &Location {
164166
&self.borrows[idx].location
165167
}

src/test/compile-fail/borrowck/borrowck-local-borrow-outlives-fn.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,9 @@
1212
//[mir]compile-flags: -Z borrowck=mir
1313

1414
fn cplusplus_mode(x: isize) -> &'static isize {
15-
&x //[ast]~ ERROR `x` does not live long enough
15+
&x
16+
//[ast]~^ ERROR `x` does not live long enough [E0597]
17+
//[mir]~^^ ERROR `x` does not live long enough [E0597]
1618
}
17-
//[mir]~^ ERROR borrowed value does not live long enough
1819

1920
fn main() {}

src/test/compile-fail/borrowck/borrowck-local-borrow-with-panic-outlives-fn.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,11 @@
1313

1414
fn cplusplus_mode_exceptionally_unsafe(x: &mut Option<&'static mut isize>) {
1515
let mut z = (0, 0);
16-
*x = Some(&mut z.1); //[ast]~ ERROR [E0597]
16+
*x = Some(&mut z.1);
17+
//[ast]~^ ERROR `z.1` does not live long enough [E0597]
18+
//[mir]~^^ ERROR `z.1` does not live long enough [E0597]
1719
panic!("catch me for a dangling pointer!")
1820
}
19-
//[mir]~^ ERROR [E0597]
2021

2122
fn main() {
2223
cplusplus_mode_exceptionally_unsafe(&mut None);

src/test/compile-fail/issue-17954.rs

+7-3
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,16 @@ static FOO: u8 = 3;
1818

1919
fn main() {
2020
let a = &FOO;
21-
//[ast]~^ ERROR borrowed value does not live long enough
21+
//[mir]~^ ERROR `FOO` does not live long enough [E0597]
22+
//[mir]~| does not live long enough
23+
//[mir]~| NOTE borrowed value must be valid for the static lifetime
24+
//[ast]~^^^^ ERROR borrowed value does not live long enough
2225
//[ast]~| does not live long enough
2326
//[ast]~| NOTE borrowed value must be valid for the static lifetime
2427

2528
std::thread::spawn(move || {
2629
println!("{}", a);
2730
});
28-
} //[ast]~ temporary value only lives until here
29-
//[mir]~^ ERROR borrowed value does not live long enough
31+
}
32+
//[mir]~^ borrowed value only lives until here
33+
//[ast]~^^ temporary value only lives until here

src/test/compile-fail/region-borrow-params-issue-29793-big.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -82,8 +82,8 @@ fn main() {
8282
//[ast]~^ ERROR `x` does not live long enough
8383
//[ast]~| ERROR `y` does not live long enough
8484
});
85-
//[mir]~^ ERROR borrowed value does not live long enough
86-
//[mir]~| ERROR borrowed value does not live long enough
85+
//[mir]~^ ERROR `x` does not live long enough
86+
//[mir]~| ERROR `y` does not live long enough
8787

8888
w.handle(); // This works
8989
// w.handle_ref(); // This doesn't

src/test/ui/issue-46471-1.rs

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// compile-flags: -Z emit-end-regions -Z borrowck=compare
12+
13+
fn main() {
14+
let y = {
15+
let mut z = 0;
16+
&mut z
17+
};
18+
//~^ ERROR `z` does not live long enough (Ast) [E0597]
19+
//~| ERROR `z` does not live long enough (Mir) [E0597]
20+
println!("{}", y);
21+
}

src/test/ui/issue-46471-1.stderr

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
error[E0597]: `z` does not live long enough (Ast)
2+
--> $DIR/issue-46471-1.rs:17:5
3+
|
4+
16 | &mut z
5+
| - borrow occurs here
6+
17 | };
7+
| ^ `z` dropped here while still borrowed
8+
...
9+
21 | }
10+
| - borrowed value needs to live until here
11+
12+
error[E0597]: `z` does not live long enough (Mir)
13+
--> $DIR/issue-46471-1.rs:17:6
14+
|
15+
16 | &mut z
16+
| ------ borrow occurs here
17+
17 | };
18+
| ^ `z` dropped here while still borrowed
19+
...
20+
21 | }
21+
| - borrowed value needs to live until here
22+
23+
error: aborting due to 2 previous errors
24+

src/test/ui/issue-46471.rs

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// compile-flags: -Z emit-end-regions -Z borrowck=compare
12+
13+
fn foo() -> &'static u32 {
14+
let x = 0;
15+
&x
16+
//~^ ERROR `x` does not live long enough (Ast) [E0597]
17+
//~| ERROR `x` does not live long enough (Mir) [E0597]
18+
}
19+
20+
fn main() { }

src/test/ui/issue-46471.stderr

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
error[E0597]: `x` does not live long enough (Ast)
2+
--> $DIR/issue-46471.rs:15:6
3+
|
4+
15 | &x
5+
| ^ does not live long enough
6+
...
7+
18 | }
8+
| - borrowed value only lives until here
9+
|
10+
= note: borrowed value must be valid for the static lifetime...
11+
12+
error[E0597]: `x` does not live long enough (Mir)
13+
--> $DIR/issue-46471.rs:15:5
14+
|
15+
15 | &x
16+
| ^^ does not live long enough
17+
...
18+
18 | }
19+
| - borrowed value only lives until here
20+
|
21+
= note: borrowed value must be valid for the static lifetime...
22+
23+
error: aborting due to 2 previous errors
24+

src/test/ui/issue-46472.rs

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// compile-flags: -Z emit-end-regions -Z borrowck=compare
12+
13+
fn bar<'a>() -> &'a mut u32 {
14+
&mut 4
15+
//~^ ERROR borrowed value does not live long enough (Ast) [E0597]
16+
//~| ERROR borrowed value does not live long enough (Mir) [E0597]
17+
}
18+
19+
fn main() { }

src/test/ui/issue-46472.stderr

+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
error[E0597]: borrowed value does not live long enough (Ast)
2+
--> $DIR/issue-46472.rs:14:10
3+
|
4+
14 | &mut 4
5+
| ^ does not live long enough
6+
...
7+
17 | }
8+
| - temporary value only lives until here
9+
|
10+
note: borrowed value must be valid for the lifetime 'a as defined on the function body at 13:1...
11+
--> $DIR/issue-46472.rs:13:1
12+
|
13+
13 | / fn bar<'a>() -> &'a mut u32 {
14+
14 | | &mut 4
15+
15 | | //~^ ERROR borrowed value does not live long enough (Ast) [E0597]
16+
16 | | //~| ERROR borrowed value does not live long enough (Mir) [E0597]
17+
17 | | }
18+
| |_^
19+
20+
error[E0597]: borrowed value does not live long enough (Mir)
21+
--> $DIR/issue-46472.rs:14:10
22+
|
23+
14 | &mut 4
24+
| ^ does not live long enough
25+
...
26+
17 | }
27+
| - temporary value only lives until here
28+
|
29+
note: borrowed value must be valid for the lifetime 'a as defined on the function body at 13:1...
30+
--> $DIR/issue-46472.rs:13:1
31+
|
32+
13 | / fn bar<'a>() -> &'a mut u32 {
33+
14 | | &mut 4
34+
15 | | //~^ ERROR borrowed value does not live long enough (Ast) [E0597]
35+
16 | | //~| ERROR borrowed value does not live long enough (Mir) [E0597]
36+
17 | | }
37+
| |_^
38+
39+
error: aborting due to 2 previous errors
40+

src/test/ui/nll/capture-ref-in-struct.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,11 @@ fn test() {
3030
let closure = SomeStruct {
3131
p: &mut p,
3232
y: &y,
33+
//~^ ERROR `y` does not live long enough [E0597]
3334
};
3435

3536
closure.invoke();
3637
}
37-
//~^ ERROR borrowed value does not live long enough [E0597]
3838

3939
deref(p);
4040
}
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
1-
error[E0597]: borrowed value does not live long enough
2-
--> $DIR/capture-ref-in-struct.rs:36:6
1+
error[E0597]: `y` does not live long enough
2+
--> $DIR/capture-ref-in-struct.rs:32:16
33
|
4-
28 | let y = 22;
5-
| - temporary value created here
4+
32 | y: &y,
5+
| ^^ does not live long enough
66
...
7-
36 | }
8-
| ^ temporary value dropped here while still borrowed
7+
37 | }
8+
| - borrowed value only lives until here
99
|
10-
= note: consider using a `let` binding to increase its lifetime
10+
= note: borrowed value must be valid for lifetime '_#4r...
1111

1212
error: aborting due to previous error
1313

0 commit comments

Comments
 (0)