forked from rust-lang/rust
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Auto merge of rust-lang#47144 - estebank:moved-closure-arg, r=nikomat…
…sakis Custom error when moving arg outside of its closure When given the following code: ```rust fn give_any<F: for<'r> FnOnce(&'r ())>(f: F) { f(&()); } fn main() { let mut x = None; give_any(|y| x = Some(y)); } ``` provide a custom error: ``` error: borrowed data cannot be moved outside of its closure --> file.rs:7:27 | 6 | let mut x = None; | ----- borrowed data cannot be moved into here... 7 | give_any(|y| x = Some(y)); | --- ^ cannot be moved outside of its closure | | | ...because it cannot outlive this closure ``` instead of the generic lifetime error: ``` error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements --> file.rs:7:27 | 7 | give_any(|y| x = Some(y)); | ^ | note: first, the lifetime cannot outlive the anonymous lifetime rust-lang#2 defined on the body at 7:14... --> file.rs:7:14 | 7 | give_any(|y| x = Some(y)); | ^^^^^^^^^^^^^^^ note: ...so that expression is assignable (expected &(), found &()) --> file.rs:7:27 | 7 | give_any(|y| x = Some(y)); | ^ note: but, the lifetime must be valid for the block suffix following statement 0 at 6:5... --> file.rs:6:5 | 6 | / let mut x = None; 7 | | give_any(|y| x = Some(y)); 8 | | } | |_^ note: ...so that variable is valid at time of its declaration --> file.rs:6:9 | 6 | let mut x = None; | ^^^^^ ``` Fix rust-lang#45983.
- Loading branch information
Showing
18 changed files
with
352 additions
and
21 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
124 changes: 124 additions & 0 deletions
124
src/librustc/infer/error_reporting/nice_region_error/outlives_closure.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,124 @@ | ||
// Copyright 2018 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. | ||
|
||
//! Error Reporting for Anonymous Region Lifetime Errors | ||
//! where both the regions are anonymous. | ||
use infer::error_reporting::nice_region_error::NiceRegionError; | ||
use infer::SubregionOrigin; | ||
use ty::RegionKind; | ||
use hir::{Expr, ExprClosure}; | ||
use hir::map::NodeExpr; | ||
use util::common::ErrorReported; | ||
use infer::lexical_region_resolve::RegionResolutionError::SubSupConflict; | ||
|
||
impl<'a, 'gcx, 'tcx> NiceRegionError<'a, 'gcx, 'tcx> { | ||
/// Print the error message for lifetime errors when binding excapes a closure. | ||
/// | ||
/// Consider a case where we have | ||
/// | ||
/// ```no_run | ||
/// fn with_int<F>(f: F) where F: FnOnce(&isize) { | ||
/// let x = 3; | ||
/// f(&x); | ||
/// } | ||
/// fn main() { | ||
/// let mut x = None; | ||
/// with_int(|y| x = Some(y)); | ||
/// } | ||
/// ``` | ||
/// | ||
/// the output will be | ||
/// | ||
/// ```text | ||
/// let mut x = None; | ||
/// ----- borrowed data cannot be stored into here... | ||
/// with_int(|y| x = Some(y)); | ||
/// --- ^ cannot be stored outside of its closure | ||
/// | | ||
/// ...because it cannot outlive this closure | ||
/// ``` | ||
pub(super) fn try_report_outlives_closure(&self) -> Option<ErrorReported> { | ||
if let Some(SubSupConflict(origin, | ||
ref sub_origin, | ||
_, | ||
ref sup_origin, | ||
sup_region)) = self.error { | ||
|
||
// #45983: when trying to assign the contents of an argument to a binding outside of a | ||
// closure, provide a specific message pointing this out. | ||
if let (&SubregionOrigin::BindingTypeIsNotValidAtDecl(ref external_span), | ||
&RegionKind::ReFree(ref free_region)) = (&sub_origin, sup_region) { | ||
let hir = &self.tcx.hir; | ||
if let Some(node_id) = hir.as_local_node_id(free_region.scope) { | ||
match hir.get(node_id) { | ||
NodeExpr(Expr { | ||
node: ExprClosure(_, _, _, closure_span, false), | ||
.. | ||
}) => { | ||
let sup_sp = sup_origin.span(); | ||
let origin_sp = origin.span(); | ||
let mut err = self.tcx.sess.struct_span_err( | ||
sup_sp, | ||
"borrowed data cannot be stored outside of its closure"); | ||
err.span_label(sup_sp, "cannot be stored outside of its closure"); | ||
if origin_sp == sup_sp || origin_sp.contains(sup_sp) { | ||
// // sup_sp == origin.span(): | ||
// | ||
// let mut x = None; | ||
// ----- borrowed data cannot be stored into here... | ||
// with_int(|y| x = Some(y)); | ||
// --- ^ cannot be stored outside of its closure | ||
// | | ||
// ...because it cannot outlive this closure | ||
// | ||
// // origin.contains(&sup_sp): | ||
// | ||
// let mut f: Option<&u32> = None; | ||
// ----- borrowed data cannot be stored into here... | ||
// closure_expecting_bound(|x: &'x u32| { | ||
// ------------ ... because it cannot outlive this closure | ||
// f = Some(x); | ||
// ^ cannot be stored outside of its closure | ||
err.span_label(*external_span, | ||
"borrowed data cannot be stored into here..."); | ||
err.span_label(*closure_span, | ||
"...because it cannot outlive this closure"); | ||
} else { | ||
// FIXME: the wording for this case could be much improved | ||
// | ||
// let mut lines_to_use: Vec<&CrateId> = Vec::new(); | ||
// - cannot infer an appropriate lifetime... | ||
// let push_id = |installed_id: &CrateId| { | ||
// ------- ------------------------ borrowed data cannot outlive this closure | ||
// | | ||
// ...so that variable is valid at time of its declaration | ||
// lines_to_use.push(installed_id); | ||
// ^^^^^^^^^^^^ cannot be stored outside of its closure | ||
err.span_label(origin_sp, | ||
"cannot infer an appropriate lifetime..."); | ||
err.span_label(*external_span, | ||
"...so that variable is valid at time of its \ | ||
declaration"); | ||
err.span_label(*closure_span, | ||
"borrowed data cannot outlive this closure"); | ||
} | ||
err.emit(); | ||
return Some(ErrorReported); | ||
} | ||
_ => {} | ||
} | ||
} | ||
} | ||
} | ||
None | ||
} | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
// Copyright 2018 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. | ||
|
||
fn give_any<F: for<'r> FnOnce(&'r ())>(f: F) { | ||
f(&()); | ||
} | ||
|
||
fn main() { | ||
let x = None; | ||
give_any(|y| x = Some(y)); | ||
//~^ ERROR borrowed data cannot be stored outside of its closure | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
error: borrowed data cannot be stored outside of its closure | ||
--> $DIR/issue-45983.rs:17:27 | ||
| | ||
16 | let x = None; | ||
| - borrowed data cannot be stored into here... | ||
17 | give_any(|y| x = Some(y)); | ||
| --- ^ cannot be stored outside of its closure | ||
| | | ||
| ...because it cannot outlive this closure | ||
|
||
error: aborting due to previous error | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
error: borrowed data cannot be stored outside of its closure | ||
--> $DIR/issue-7573.rs:32:27 | ||
| | ||
27 | let mut lines_to_use: Vec<&CrateId> = Vec::new(); | ||
| - cannot infer an appropriate lifetime... | ||
28 | //~^ NOTE cannot infer an appropriate lifetime | ||
29 | let push_id = |installed_id: &CrateId| { | ||
| ------- ------------------------ borrowed data cannot outlive this closure | ||
| | | ||
| ...so that variable is valid at time of its declaration | ||
... | ||
32 | lines_to_use.push(installed_id); | ||
| ^^^^^^^^^^^^ cannot be stored outside of its closure | ||
|
||
error: aborting due to previous error | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
error: borrowed data cannot be stored outside of its closure | ||
--> $DIR/regions-escape-bound-fn-2.rs:18:27 | ||
| | ||
17 | let mut x = None; | ||
| ----- borrowed data cannot be stored into here... | ||
18 | with_int(|y| x = Some(y)); | ||
| --- ^ cannot be stored outside of its closure | ||
| | | ||
| ...because it cannot outlive this closure | ||
|
||
error: aborting due to previous error | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
error: borrowed data cannot be stored outside of its closure | ||
--> $DIR/regions-escape-bound-fn.rs:18:27 | ||
| | ||
17 | let mut x: Option<&isize> = None; | ||
| ----- borrowed data cannot be stored into here... | ||
18 | with_int(|y| x = Some(y)); | ||
| --- ^ cannot be stored outside of its closure | ||
| | | ||
| ...because it cannot outlive this closure | ||
|
||
error: aborting due to previous error | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
12 changes: 12 additions & 0 deletions
12
src/test/ui/borrowck/regions-escape-unboxed-closure.stderr
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
error: borrowed data cannot be stored outside of its closure | ||
--> $DIR/regions-escape-unboxed-closure.rs:16:32 | ||
| | ||
15 | let mut x: Option<&isize> = None; | ||
| ----- borrowed data cannot be stored into here... | ||
16 | with_int(&mut |y| x = Some(y)); | ||
| --- ^ cannot be stored outside of its closure | ||
| | | ||
| ...because it cannot outlive this closure | ||
|
||
error: aborting due to previous error | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.