//! Reports an error if `loan_region` is larger than `max_scope`
if !self.bccx.is_subregion_of(self.loan_region, max_scope) {
- Err(self.report_error(err_out_of_scope(max_scope, self.loan_region)))
+ Err(self.report_error(err_out_of_scope(max_scope, self.loan_region, self.cause)))
} else {
Ok(())
}
use std::rc::Rc;
use syntax::ast;
use syntax::attr::AttrMetaMethods;
-use syntax_pos::{MultiSpan, Span};
+use syntax_pos::{MultiSpan, Span, BytePos};
use errors::DiagnosticBuilder;
use rustc::hir;
#[derive(PartialEq)]
pub enum bckerr_code {
err_mutbl,
- err_out_of_scope(ty::Region, ty::Region), // superscope, subscope
+ err_out_of_scope(ty::Region, ty::Region, euv::LoanCause), // superscope, subscope, loan cause
err_borrowed_pointer_too_short(ty::Region, ty::Region), // loan, ptr
}
pub fn report(&self, err: BckError<'tcx>) {
// Catch and handle some particular cases.
match (&err.code, &err.cause) {
- (&err_out_of_scope(ty::ReScope(_), ty::ReStatic),
+ (&err_out_of_scope(ty::ReScope(_), ty::ReStatic, _),
&BorrowViolation(euv::ClosureCapture(span))) |
- (&err_out_of_scope(ty::ReScope(_), ty::ReFree(..)),
+ (&err_out_of_scope(ty::ReScope(_), ty::ReFree(..), _),
&BorrowViolation(euv::ClosureCapture(span))) => {
return self.report_out_of_scope_escaping_closure_capture(&err, span);
}
.emit();
}
+ fn convert_region_to_span(&self, region: ty::Region) -> Option<Span> {
+ match region {
+ ty::ReScope(scope) => {
+ match scope.span(&self.tcx.region_maps, &self.tcx.map) {
+ Some(s) => {
+ let mut last_span = s;
+ last_span.lo = BytePos(last_span.hi.0 - 1);
+ Some(last_span)
+ }
+ None => {
+ None
+ }
+ }
+ }
+ _ => None
+ }
+ }
+
pub fn note_and_explain_bckerr(&self, db: &mut DiagnosticBuilder, err: BckError<'tcx>,
error_span: Span) {
let code = err.code;
}
}
- err_out_of_scope(super_scope, sub_scope) => {
- self.tcx.note_and_explain_region(
- db,
- "reference must be valid for ",
- sub_scope,
- "...");
- self.tcx.note_and_explain_region(
- db,
- "...but borrowed value is only valid for ",
- super_scope,
- "");
+ err_out_of_scope(super_scope, sub_scope, cause) => {
+ match cause {
+ euv::ClosureCapture(s) => {
+ match db.span.primary_span() {
+ 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"));
+ }
+ None => ()
+ }
+ }
+ _ => {
+ db.span_label(error_span, &format!("does not live long enough"));
+ }
+ }
+
+ let sub_span = self.convert_region_to_span(sub_scope);
+ let super_span = self.convert_region_to_span(super_scope);
+
+ match (sub_span, super_span) {
+ (Some(s1), Some(s2)) if s1 == s2 => {
+ db.span_label(s1, &"borrowed value dropped before borrower");
+ 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");
+ }
+ None => {
+ self.tcx.note_and_explain_region(
+ db,
+ "borrowed value must be valid for ",
+ sub_scope,
+ "...");
+ }
+ }
+ match super_span {
+ Some(s) => {
+ db.span_label(s, &"borrowed value only valid until here");
+ }
+ None => {
+ self.tcx.note_and_explain_region(
+ db,
+ "...but borrowed value is only valid for ",
+ super_scope,
+ "");
+ }
+ }
+ }
+ }
+
if let Some(span) = statement_scope_span(self.tcx, super_scope) {
- db.span_label(error_span, &format!("does not live long enough"));
db.span_help(span,
"consider using a `let` binding to increase its lifetime");
}
let mut v1 = Vec::new(); // statement 1
let mut v2 = Vec::new(); // statement 2
- //~^ NOTE reference must be valid for the block suffix following statement 2
let young = ['y']; // statement 3
- //~^ NOTE ...but borrowed value is only valid for the block suffix following statement 3
v2.push(&young[0]); // statement 4
//~^ ERROR `young[..]` does not live long enough
+ //~| NOTE does not live long enough
+ //~| NOTE values in a scope are dropped in the opposite order they are created
let mut v3 = Vec::new(); // statement 5
- //~^ NOTE reference must be valid for the block suffix following statement 5
v3.push(&'x'); // statement 6
//~^ ERROR borrowed value does not live long enough
- //~| does not live long enough
- //~| NOTE ...but borrowed value is only valid for the statement
+ //~| NOTE does not live long enough
+ //~| NOTE borrowed value only valid until here
//~| HELP consider using a `let` binding to increase its lifetime
{
let mut v4 = Vec::new(); // (sub) statement 0
- //~^ NOTE reference must be valid for the block suffix following statement 0
v4.push(&'y');
//~^ ERROR borrowed value does not live long enough
- //~| does not live long enough
- //~| NOTE ...but borrowed value is only valid for the statement
+ //~| NOTE does not live long enough
+ //~| NOTE borrowed value only valid until here
//~| HELP consider using a `let` binding to increase its lifetime
} // (statement 7)
+ //~^ NOTE borrowed value must be valid until here
let mut v5 = Vec::new(); // statement 8
- //~^ NOTE reference must be valid for the block suffix following statement 8
v5.push(&'z');
//~^ ERROR borrowed value does not live long enough
- //~| does not live long enough
- //~| NOTE ...but borrowed value is only valid for the statement
+ //~| NOTE does not live long enough
+ //~| NOTE borrowed value only valid until here
//~| HELP 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
fn main() {
f();
fn f() {
let x = [1].iter();
//~^ ERROR borrowed value does not live long enough
- //~|does not live long enough
- //~| NOTE reference must be valid for the block suffix following statement
+ //~| NOTE does not live long enough
+ //~| NOTE borrowed value only valid until here
//~| HELP consider using a `let` binding to increase its lifetime
- //~| NOTE ...but borrowed value is only valid for the statement at 12:4
}
+//~^ borrowed value must be valid until here
fn main() {
f();
fn borrow<'a, T>(_: &'a mut T) -> impl Copy { () }
fn main() {
- //~^ NOTE reference must be valid for the block
let long;
let mut short = 0;
- //~^ NOTE but borrowed value is only valid for the block suffix following statement 1
long = borrow(&mut short);
//~^ ERROR `short` does not live long enough
-}
+ //~| NOTE does not live long enough
+ //~| NOTE values in a scope are dropped in the opposite order they are created
+} //~ borrowed value dropped before borrower
+++ /dev/null
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-#![feature(box_syntax, unboxed_closures)]
-
-fn to_fn_once<A,F:FnOnce<A>>(f: F) -> F { f }
-
-fn main() {
- let r = {
- let x: Box<_> = box 42;
- let f = to_fn_once(move|| &x); //~ ERROR: `x` does not live long enough
- f()
- };
-
- drop(r);
-}
fn escaping_borrow_of_closure_params_1() {
let g = |x: usize, y:usize| {
- //~^ NOTE reference must be valid for the scope of call-site for function
- //~| NOTE ...but borrowed value is only valid for the scope of function body
- //~| NOTE reference must be valid for the scope of call-site for function
- //~| NOTE ...but borrowed value is only valid for the scope of function body
let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
//~^ ERROR `x` does not live long enough
//~| ERROR `y` does not live long enough
+ //~| NOTE capture occurs here
+ //~| NOTE capture occurs here
+ //~| NOTE does not live long enough
+ //~| NOTE does not live long enough
+ //~| NOTE values in a scope are dropped in the opposite order they are created
+ //~| NOTE values in a scope are dropped in the opposite order they are created
return f;
};
+ //~^ NOTE borrowed value dropped before borrower
+ //~| NOTE borrowed value dropped before borrower
// We delberately do not call `g`; this small version of the test,
// after adding such a call, was (properly) rejected even when the
fn escaping_borrow_of_closure_params_2() {
let g = |x: usize, y:usize| {
- //~^ NOTE reference must be valid for the scope of call-site for function
- //~| NOTE ...but borrowed value is only valid for the scope of function body
- //~| NOTE reference must be valid for the scope of call-site for function
- //~| NOTE ...but borrowed value is only valid for the scope of function body
let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
//~^ ERROR `x` does not live long enough
//~| ERROR `y` does not live long enough
+ //~| NOTE capture occurs here
+ //~| NOTE capture occurs here
+ //~| NOTE does not live long enough
+ //~| NOTE does not live long enough
+ //~| NOTE values in a scope are dropped in the opposite order they are created
+ //~| NOTE values in a scope are dropped in the opposite order they are created
f
};
+ //~^ NOTE borrowed value dropped before borrower
+ //~| NOTE borrowed value dropped before borrower
// (we don't call `g`; see above)
}
let y = &x; //~ ERROR `x` does not live long enough
scoped(|| {
- //~^ ERROR `y` does not live long enough
let _z = y;
+ //~^ ERROR `y` does not live long enough
})
};
let mut factorial: Option<Box<Fn(u32) -> u32>> = None;
let f = |x: u32| -> u32 {
- //~^ ERROR `factorial` does not live long enough
let g = factorial.as_ref().unwrap();
+ //~^ ERROR `factorial` does not live long enough
if x == 0 {1} else {x * g(x-1)}
};
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(box_syntax, unboxed_closures)]
+
+fn to_fn_once<A,F:FnOnce<A>>(f: F) -> F { f }
+
+fn main() {
+ let r = {
+ let x: Box<_> = box 42;
+ let f = to_fn_once(move|| &x);
+ f()
+ };
+
+ drop(r);
+}
--- /dev/null
+error: `x` does not live long enough
+ --> $DIR/issue-11925.rs:18:36
+ |
+18 | let f = to_fn_once(move|| &x);
+ | ^
+ | |
+ | does not live long enough
+ | borrowed value only valid until here
+...
+23 | }
+ | - borrowed value must be valid until here
+
+error: aborting due to previous error
+