Skip to content

Commit

Permalink
Rollup merge of rust-lang#36171 - jonathandturner:temporary_value, r=…
Browse files Browse the repository at this point in the history
…nikomatsakis

Update lifetime errors to specifically note temporaries

This PR updates the error message we give in the case of a temporary value not living long enough.

Before:

<img width="497" alt="screen shot 2016-08-31 at 10 02 47 am" src="https://cloud.githubusercontent.com/assets/547158/18138551/27a06794-6f62-11e6-9ee2-bdf8bed75ca7.png">

Now:

<img width="488" alt="screen shot 2016-08-31 at 10 03 01 am" src="https://cloud.githubusercontent.com/assets/547158/18138557/2e5cf322-6f62-11e6-9047-4a78abf3d78c.png">

Specifically, it makes the following changes:

* Detects if a temporary is being used.  If so, it changes the labels to mention that a temporary value specifically is in question
* Simplifies wording of the existing labels to focus on lifetimes rather than values being valid
* Changes the help to a note, since the help+span wasn't as helpful (and sometimes more confusing) than just a note.

r? @nikomatsakis
  • Loading branch information
Jonathan Turner authored Sep 2, 2016
2 parents 9327edd + 439afcd commit 59c0ff6
Show file tree
Hide file tree
Showing 6 changed files with 44 additions and 29 deletions.
22 changes: 14 additions & 8 deletions src/librustc_borrowck/borrowck/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1028,6 +1028,12 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
}

err_out_of_scope(super_scope, sub_scope, cause) => {
let (value_kind, value_msg) = match err.cmt.cat {
mc::Categorization::Rvalue(_) =>
("temporary value", "temporary value created here"),
_ =>
("borrowed value", "does not live long enough")
};
match cause {
euv::ClosureCapture(s) => {
// The primary span starts out as the closure creation point.
Expand All @@ -1038,13 +1044,13 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
Some(primary) => {
db.span = MultiSpan::from_span(s);
db.span_label(primary, &format!("capture occurs here"));
db.span_label(s, &format!("does not live long enough"));
db.span_label(s, &value_msg);
}
None => ()
}
}
_ => {
db.span_label(error_span, &format!("does not live long enough"));
db.span_label(error_span, &value_msg);
}
}

Expand All @@ -1053,14 +1059,15 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {

match (sub_span, super_span) {
(Some(s1), Some(s2)) if s1 == s2 => {
db.span_label(s1, &"borrowed value dropped before borrower");
db.span_label(s1, &format!("{} dropped before borrower", value_kind));
db.note("values in a scope are dropped in the opposite order \
they are created");
}
_ => {
match sub_span {
Some(s) => {
db.span_label(s, &"borrowed value must be valid until here");
db.span_label(s, &format!("{} needs to live until here",
value_kind));
}
None => {
self.tcx.note_and_explain_region(
Expand All @@ -1072,7 +1079,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
}
match super_span {
Some(s) => {
db.span_label(s, &"borrowed value only valid until here");
db.span_label(s, &format!("{} only lives until here", value_kind));
}
None => {
self.tcx.note_and_explain_region(
Expand All @@ -1085,9 +1092,8 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
}
}

if let Some(span) = statement_scope_span(self.tcx, super_scope) {
db.span_help(span,
"consider using a `let` binding to increase its lifetime");
if let Some(_) = statement_scope_span(self.tcx, super_scope) {
db.note("consider using a `let` binding to increase its lifetime");
}
}

Expand Down
24 changes: 12 additions & 12 deletions src/test/compile-fail/borrowck/borrowck-let-suggestion-suffixes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,36 +25,36 @@ fn f() {

v3.push(&'x'); // statement 6
//~^ ERROR borrowed value does not live long enough
//~| NOTE does not live long enough
//~| NOTE borrowed value only valid until here
//~| HELP consider using a `let` binding to increase its lifetime
//~| NOTE temporary value created here
//~| NOTE temporary value only lives until here
//~| NOTE consider using a `let` binding to increase its lifetime

{

let mut v4 = Vec::new(); // (sub) statement 0

v4.push(&'y');
//~^ ERROR borrowed value does not live long enough
//~| NOTE does not live long enough
//~| NOTE borrowed value only valid until here
//~| HELP consider using a `let` binding to increase its lifetime
//~| NOTE temporary value created here
//~| NOTE temporary value only lives until here
//~| NOTE consider using a `let` binding to increase its lifetime

} // (statement 7)
//~^ NOTE borrowed value must be valid until here
//~^ NOTE temporary value needs to live until here

let mut v5 = Vec::new(); // statement 8

v5.push(&'z');
//~^ ERROR borrowed value does not live long enough
//~| NOTE does not live long enough
//~| NOTE borrowed value only valid until here
//~| HELP consider using a `let` binding to increase its lifetime
//~| NOTE temporary value created here
//~| NOTE temporary value only lives until here
//~| NOTE consider using a `let` binding to increase its lifetime

v1.push(&old[0]);
}
//~^ NOTE borrowed value dropped before borrower
//~| NOTE borrowed value must be valid until here
//~| NOTE borrowed value must be valid until here
//~| NOTE temporary value needs to live until here
//~| NOTE temporary value needs to live until here

fn main() {
f();
Expand Down
4 changes: 2 additions & 2 deletions src/test/compile-fail/regions-escape-loop-via-vec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ fn broken() {
x += 1; //~ ERROR cannot assign
//~^ NOTE assignment to borrowed `x` occurs here
}
//~^ NOTE borrowed value only valid until here
//~^ NOTE borrowed value only lives until here
}
//~^ NOTE borrowed value must be valid until here
//~^ NOTE borrowed value needs to live until here

fn main() { }
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,7 @@

fn f() {
let x = [1].iter();
//~^ ERROR borrowed value does not live long enough
//~| NOTE does not live long enough
//~| NOTE borrowed value only valid until here
//~| HELP consider using a `let` binding to increase its lifetime
}
//~^ borrowed value must be valid until here

fn main() {
f();
Expand Down
14 changes: 14 additions & 0 deletions src/test/ui/lifetimes/borrowck-let-suggestion.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
error: borrowed value does not live long enough
--> $DIR/borrowck-let-suggestion.rs:12:13
|
12 | let x = [1].iter();
| ^^^ - temporary value only lives until here
| |
| temporary value created here
13 | }
| - temporary value needs to live until here
|
= note: consider using a `let` binding to increase its lifetime

error: aborting due to previous error

4 changes: 2 additions & 2 deletions src/test/ui/span/issue-11925.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ error: `x` does not live long enough
| ^
| |
| does not live long enough
| borrowed value only valid until here
| borrowed value only lives until here
...
23 | }
| - borrowed value must be valid until here
| - borrowed value needs to live until here

error: aborting due to previous error

0 comments on commit 59c0ff6

Please sign in to comment.