]> git.lizzy.rs Git - rust.git/commitdiff
Move 'doesn't live long enough' errors to labels
authorJonathan Turner <jturner@mozilla.com>
Tue, 16 Aug 2016 22:02:20 +0000 (15:02 -0700)
committerJonathan Turner <jturner@mozilla.com>
Wed, 17 Aug 2016 22:24:42 +0000 (15:24 -0700)
src/librustc_borrowck/borrowck/gather_loans/lifetime.rs
src/librustc_borrowck/borrowck/mod.rs
src/test/compile-fail/borrowck/borrowck-let-suggestion-suffixes.rs
src/test/compile-fail/borrowck/borrowck-let-suggestion.rs
src/test/compile-fail/impl-trait/loan-extend.rs
src/test/compile-fail/issue-11925.rs [deleted file]
src/test/compile-fail/region-borrow-params-issue-29793-small.rs
src/test/compile-fail/send-is-not-static-ensures-scoping.rs
src/test/compile-fail/unboxed-closures-failed-recursive-fn-1.rs
src/test/ui/span/issue-11925.rs [new file with mode: 0644]
src/test/ui/span/issue-11925.stderr [new file with mode: 0644]

index e34c6e567bd8ece197adcf425ef455f1e2d9eb22..667bf16874ec4df7165acfc0d41da0076e67334e 100644 (file)
@@ -96,7 +96,7 @@ fn check_scope(&self, max_scope: ty::Region) -> R {
         //! 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(())
         }
index e0cbd972bd37f9f3c62fc9d65e26b18bb47915af..7e3466c1ad84ad97d16e3ed86f5b8fe47790e719 100644 (file)
@@ -43,7 +43,7 @@
 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;
@@ -566,7 +566,7 @@ pub fn opt_loan_path<'tcx>(cmt: &mc::cmt<'tcx>) -> Option<Rc<LoanPath<'tcx>>> {
 #[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
 }
 
@@ -614,9 +614,9 @@ pub fn is_subregion_of(&self, r_sub: ty::Region, r_sup: ty::Region)
     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);
             }
@@ -963,6 +963,24 @@ fn report_out_of_scope_escaping_closure_capture(&self,
             .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;
@@ -1003,19 +1021,61 @@ pub fn note_and_explain_bckerr(&self, db: &mut DiagnosticBuilder, err: BckError<
                 }
             }
 
-            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");
                 }
index 02aa771c787897209d1f19a37f893ea4bb93597f..6c9f67b2b33d45151aba71dce7f1c157f940fdca 100644 (file)
@@ -13,47 +13,48 @@ fn f() {
     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();
index 866e72f1a525844100150b59f13b62f96697a7f1..ef8f44c1df78978c1d0974c6704e33f714ca7c8a 100644 (file)
 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();
index ceaa8f4eed72348dfa1e34e2db89c42b261c22eb..8dfcb08cff339b4153037ec430e0aa462a871b78 100644 (file)
 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
diff --git a/src/test/compile-fail/issue-11925.rs b/src/test/compile-fail/issue-11925.rs
deleted file mode 100644 (file)
index 7bd072c..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-// 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);
-}
index 6be2adbe2a0d1ac0eb200159b11af647bc1f875b..196c233a0b5c3b0ed178d91be611d2894748b2da 100644 (file)
 
 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
@@ -35,15 +39,19 @@ fn escaping_borrow_of_closure_params_1() {
 
 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)
 }
index 2e401ba6e9085929d1621640eee1214b74798667..1b7718d2283a7bfd6a617c112f8a5d19bdd209a6 100644 (file)
@@ -26,8 +26,8 @@ fn main() {
         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
         })
     };
 
index f73b06653012afd294d024861c13acbc9ca49975..ce60521034ee7cc89b8dc89bbda548497297de34 100644 (file)
@@ -22,8 +22,8 @@ fn a() {
     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)}
     };
 
diff --git a/src/test/ui/span/issue-11925.rs b/src/test/ui/span/issue-11925.rs
new file mode 100644 (file)
index 0000000..7bea864
--- /dev/null
@@ -0,0 +1,23 @@
+// 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);
+}
diff --git a/src/test/ui/span/issue-11925.stderr b/src/test/ui/span/issue-11925.stderr
new file mode 100644 (file)
index 0000000..d379cfc
--- /dev/null
@@ -0,0 +1,14 @@
+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
+