Skip to content

Commit 43c090e

Browse files
authored
Auto merge of #35732 - jonathandturner:region_error_labels, r=nikomatsakis
Move 'doesn't live long enough' errors to labels This patch moves the "doesn't live long enough" region-style errors to instead use labels. An example follows. Before: ``` error: `x` does not live long enough --> src/test/compile-fail/send-is-not-static-ensures-scoping.rs:26:18 | 26 | let y = &x; | ^ | note: reference must be valid for the block at 23:10... --> src/test/compile-fail/send-is-not-static-ensures-scoping.rs:23:11 | 23 | fn main() { | ^ note: ...but borrowed value is only valid for the block suffix following statement 0 at 25:18 --> src/test/compile-fail/send-is-not-static-ensures-scoping.rs:25:19 | 25 | let x = 1; | ^ ``` After: ``` error: `x` does not live long enough --> src/test/compile-fail/send-is-not-static-ensures-scoping.rs:26:18 | 26 | let y = &x; | ^ does not live long enough ... 32 | }; | - borrowed value only valid until here ... 35 | } | - borrowed value must be valid until here ``` r? @nikomatsakis
2 parents 9d6520f + 864b3ef commit 43c090e

10 files changed

+129
-44
lines changed

src/librustc_borrowck/borrowck/gather_loans/lifetime.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ impl<'a, 'tcx> GuaranteeLifetimeContext<'a, 'tcx> {
9696
//! Reports an error if `loan_region` is larger than `max_scope`
9797
9898
if !self.bccx.is_subregion_of(self.loan_region, max_scope) {
99-
Err(self.report_error(err_out_of_scope(max_scope, self.loan_region)))
99+
Err(self.report_error(err_out_of_scope(max_scope, self.loan_region, self.cause)))
100100
} else {
101101
Ok(())
102102
}

src/librustc_borrowck/borrowck/mod.rs

+77-15
Original file line numberDiff line numberDiff line change
@@ -566,7 +566,7 @@ pub fn opt_loan_path<'tcx>(cmt: &mc::cmt<'tcx>) -> Option<Rc<LoanPath<'tcx>>> {
566566
#[derive(PartialEq)]
567567
pub enum bckerr_code {
568568
err_mutbl,
569-
err_out_of_scope(ty::Region, ty::Region), // superscope, subscope
569+
err_out_of_scope(ty::Region, ty::Region, euv::LoanCause), // superscope, subscope, loan cause
570570
err_borrowed_pointer_too_short(ty::Region, ty::Region), // loan, ptr
571571
}
572572

@@ -614,9 +614,9 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
614614
pub fn report(&self, err: BckError<'tcx>) {
615615
// Catch and handle some particular cases.
616616
match (&err.code, &err.cause) {
617-
(&err_out_of_scope(ty::ReScope(_), ty::ReStatic),
617+
(&err_out_of_scope(ty::ReScope(_), ty::ReStatic, _),
618618
&BorrowViolation(euv::ClosureCapture(span))) |
619-
(&err_out_of_scope(ty::ReScope(_), ty::ReFree(..)),
619+
(&err_out_of_scope(ty::ReScope(_), ty::ReFree(..), _),
620620
&BorrowViolation(euv::ClosureCapture(span))) => {
621621
return self.report_out_of_scope_escaping_closure_capture(&err, span);
622622
}
@@ -963,6 +963,22 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
963963
.emit();
964964
}
965965

966+
fn region_end_span(&self, region: ty::Region) -> Option<Span> {
967+
match region {
968+
ty::ReScope(scope) => {
969+
match scope.span(&self.tcx.region_maps, &self.tcx.map) {
970+
Some(s) => {
971+
Some(s.end_point())
972+
}
973+
None => {
974+
None
975+
}
976+
}
977+
}
978+
_ => None
979+
}
980+
}
981+
966982
pub fn note_and_explain_bckerr(&self, db: &mut DiagnosticBuilder, err: BckError<'tcx>,
967983
error_span: Span) {
968984
let code = err.code;
@@ -1003,19 +1019,65 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
10031019
}
10041020
}
10051021

1006-
err_out_of_scope(super_scope, sub_scope) => {
1007-
self.tcx.note_and_explain_region(
1008-
db,
1009-
"reference must be valid for ",
1010-
sub_scope,
1011-
"...");
1012-
self.tcx.note_and_explain_region(
1013-
db,
1014-
"...but borrowed value is only valid for ",
1015-
super_scope,
1016-
"");
1022+
err_out_of_scope(super_scope, sub_scope, cause) => {
1023+
match cause {
1024+
euv::ClosureCapture(s) => {
1025+
// The primary span starts out as the closure creation point.
1026+
// Change the primary span here to highlight the use of the variable
1027+
// in the closure, because it seems more natural. Highlight
1028+
// closure creation point as a secondary span.
1029+
match db.span.primary_span() {
1030+
Some(primary) => {
1031+
db.span = MultiSpan::from_span(s);
1032+
db.span_label(primary, &format!("capture occurs here"));
1033+
db.span_label(s, &format!("does not live long enough"));
1034+
}
1035+
None => ()
1036+
}
1037+
}
1038+
_ => {
1039+
db.span_label(error_span, &format!("does not live long enough"));
1040+
}
1041+
}
1042+
1043+
let sub_span = self.region_end_span(sub_scope);
1044+
let super_span = self.region_end_span(super_scope);
1045+
1046+
match (sub_span, super_span) {
1047+
(Some(s1), Some(s2)) if s1 == s2 => {
1048+
db.span_label(s1, &"borrowed value dropped before borrower");
1049+
db.note("values in a scope are dropped in the opposite order \
1050+
they are created");
1051+
}
1052+
_ => {
1053+
match sub_span {
1054+
Some(s) => {
1055+
db.span_label(s, &"borrowed value must be valid until here");
1056+
}
1057+
None => {
1058+
self.tcx.note_and_explain_region(
1059+
db,
1060+
"borrowed value must be valid for ",
1061+
sub_scope,
1062+
"...");
1063+
}
1064+
}
1065+
match super_span {
1066+
Some(s) => {
1067+
db.span_label(s, &"borrowed value only valid until here");
1068+
}
1069+
None => {
1070+
self.tcx.note_and_explain_region(
1071+
db,
1072+
"...but borrowed value is only valid for ",
1073+
super_scope,
1074+
"");
1075+
}
1076+
}
1077+
}
1078+
}
1079+
10171080
if let Some(span) = statement_scope_span(self.tcx, super_scope) {
1018-
db.span_label(error_span, &format!("does not live long enough"));
10191081
db.span_help(span,
10201082
"consider using a `let` binding to increase its lifetime");
10211083
}

src/test/compile-fail/borrowck/borrowck-let-suggestion-suffixes.rs

+12-11
Original file line numberDiff line numberDiff line change
@@ -13,47 +13,48 @@ fn f() {
1313
let mut v1 = Vec::new(); // statement 1
1414

1515
let mut v2 = Vec::new(); // statement 2
16-
//~^ NOTE reference must be valid for the block suffix following statement 2
1716

1817
let young = ['y']; // statement 3
19-
//~^ NOTE ...but borrowed value is only valid for the block suffix following statement 3
2018

2119
v2.push(&young[0]); // statement 4
2220
//~^ ERROR `young[..]` does not live long enough
21+
//~| NOTE does not live long enough
22+
//~| NOTE values in a scope are dropped in the opposite order they are created
2323

2424
let mut v3 = Vec::new(); // statement 5
25-
//~^ NOTE reference must be valid for the block suffix following statement 5
2625

2726
v3.push(&'x'); // statement 6
2827
//~^ ERROR borrowed value does not live long enough
29-
//~| does not live long enough
30-
//~| NOTE ...but borrowed value is only valid for the statement
28+
//~| NOTE does not live long enough
29+
//~| NOTE borrowed value only valid until here
3130
//~| HELP consider using a `let` binding to increase its lifetime
3231

3332
{
3433

3534
let mut v4 = Vec::new(); // (sub) statement 0
36-
//~^ NOTE reference must be valid for the block suffix following statement 0
3735

3836
v4.push(&'y');
3937
//~^ ERROR borrowed value does not live long enough
40-
//~| does not live long enough
41-
//~| NOTE ...but borrowed value is only valid for the statement
38+
//~| NOTE does not live long enough
39+
//~| NOTE borrowed value only valid until here
4240
//~| HELP consider using a `let` binding to increase its lifetime
4341

4442
} // (statement 7)
43+
//~^ NOTE borrowed value must be valid until here
4544

4645
let mut v5 = Vec::new(); // statement 8
47-
//~^ NOTE reference must be valid for the block suffix following statement 8
4846

4947
v5.push(&'z');
5048
//~^ ERROR borrowed value does not live long enough
51-
//~| does not live long enough
52-
//~| NOTE ...but borrowed value is only valid for the statement
49+
//~| NOTE does not live long enough
50+
//~| NOTE borrowed value only valid until here
5351
//~| HELP consider using a `let` binding to increase its lifetime
5452

5553
v1.push(&old[0]);
5654
}
55+
//~^ NOTE borrowed value dropped before borrower
56+
//~| NOTE borrowed value must be valid until here
57+
//~| NOTE borrowed value must be valid until here
5758

5859
fn main() {
5960
f();

src/test/compile-fail/borrowck/borrowck-let-suggestion.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,11 @@
1111
fn f() {
1212
let x = [1].iter();
1313
//~^ ERROR borrowed value does not live long enough
14-
//~|does not live long enough
15-
//~| NOTE reference must be valid for the block suffix following statement
14+
//~| NOTE does not live long enough
15+
//~| NOTE borrowed value only valid until here
1616
//~| HELP consider using a `let` binding to increase its lifetime
17-
//~| NOTE ...but borrowed value is only valid for the statement at 12:4
1817
}
18+
//~^ borrowed value must be valid until here
1919

2020
fn main() {
2121
f();

src/test/compile-fail/impl-trait/loan-extend.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,10 @@
1414
fn borrow<'a, T>(_: &'a mut T) -> impl Copy { () }
1515

1616
fn main() {
17-
//~^ NOTE reference must be valid for the block
1817
let long;
1918
let mut short = 0;
20-
//~^ NOTE but borrowed value is only valid for the block suffix following statement 1
2119
long = borrow(&mut short);
2220
//~^ ERROR `short` does not live long enough
23-
}
21+
//~| NOTE does not live long enough
22+
//~| NOTE values in a scope are dropped in the opposite order they are created
23+
} //~ borrowed value dropped before borrower

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

+16-8
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,19 @@
1616

1717
fn escaping_borrow_of_closure_params_1() {
1818
let g = |x: usize, y:usize| {
19-
//~^ NOTE reference must be valid for the scope of call-site for function
20-
//~| NOTE ...but borrowed value is only valid for the scope of function body
21-
//~| NOTE reference must be valid for the scope of call-site for function
22-
//~| NOTE ...but borrowed value is only valid for the scope of function body
2319
let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
2420
//~^ ERROR `x` does not live long enough
2521
//~| ERROR `y` does not live long enough
22+
//~| NOTE capture occurs here
23+
//~| NOTE capture occurs here
24+
//~| NOTE does not live long enough
25+
//~| NOTE does not live long enough
26+
//~| NOTE values in a scope are dropped in the opposite order they are created
27+
//~| NOTE values in a scope are dropped in the opposite order they are created
2628
return f;
2729
};
30+
//~^ NOTE borrowed value dropped before borrower
31+
//~| NOTE borrowed value dropped before borrower
2832

2933
// We delberately do not call `g`; this small version of the test,
3034
// after adding such a call, was (properly) rejected even when the
@@ -35,15 +39,19 @@ fn escaping_borrow_of_closure_params_1() {
3539

3640
fn escaping_borrow_of_closure_params_2() {
3741
let g = |x: usize, y:usize| {
38-
//~^ NOTE reference must be valid for the scope of call-site for function
39-
//~| NOTE ...but borrowed value is only valid for the scope of function body
40-
//~| NOTE reference must be valid for the scope of call-site for function
41-
//~| NOTE ...but borrowed value is only valid for the scope of function body
4242
let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
4343
//~^ ERROR `x` does not live long enough
4444
//~| ERROR `y` does not live long enough
45+
//~| NOTE capture occurs here
46+
//~| NOTE capture occurs here
47+
//~| NOTE does not live long enough
48+
//~| NOTE does not live long enough
49+
//~| NOTE values in a scope are dropped in the opposite order they are created
50+
//~| NOTE values in a scope are dropped in the opposite order they are created
4551
f
4652
};
53+
//~^ NOTE borrowed value dropped before borrower
54+
//~| NOTE borrowed value dropped before borrower
4755

4856
// (we don't call `g`; see above)
4957
}

src/test/compile-fail/send-is-not-static-ensures-scoping.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@ fn main() {
2626
let y = &x; //~ ERROR `x` does not live long enough
2727

2828
scoped(|| {
29-
//~^ ERROR `y` does not live long enough
3029
let _z = y;
30+
//~^ ERROR `y` does not live long enough
3131
})
3232
};
3333

src/test/compile-fail/unboxed-closures-failed-recursive-fn-1.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@ fn a() {
2222
let mut factorial: Option<Box<Fn(u32) -> u32>> = None;
2323

2424
let f = |x: u32| -> u32 {
25-
//~^ ERROR `factorial` does not live long enough
2625
let g = factorial.as_ref().unwrap();
26+
//~^ ERROR `factorial` does not live long enough
2727
if x == 0 {1} else {x * g(x-1)}
2828
};
2929

src/test/compile-fail/issue-11925.rs renamed to src/test/ui/span/issue-11925.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ fn to_fn_once<A,F:FnOnce<A>>(f: F) -> F { f }
1515
fn main() {
1616
let r = {
1717
let x: Box<_> = box 42;
18-
let f = to_fn_once(move|| &x); //~ ERROR: `x` does not live long enough
18+
let f = to_fn_once(move|| &x);
1919
f()
2020
};
2121

src/test/ui/span/issue-11925.stderr

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
error: `x` does not live long enough
2+
--> $DIR/issue-11925.rs:18:36
3+
|
4+
18 | let f = to_fn_once(move|| &x);
5+
| ^
6+
| |
7+
| does not live long enough
8+
| borrowed value only valid until here
9+
...
10+
23 | }
11+
| - borrowed value must be valid until here
12+
13+
error: aborting due to previous error
14+

0 commit comments

Comments
 (0)