-
Notifications
You must be signed in to change notification settings - Fork 12.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Suggest move for closures and async blocks in more cases. #70906
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -760,47 +760,26 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { | |
( | ||
Some(ref name), | ||
BorrowExplanation::MustBeValidFor { | ||
category: category @ ConstraintCategory::Return, | ||
category: | ||
category | ||
@ | ||
(ConstraintCategory::Return | ||
| ConstraintCategory::CallArgument | ||
| ConstraintCategory::OpaqueType), | ||
from_closure: false, | ||
ref region_name, | ||
span, | ||
.. | ||
}, | ||
) | ||
| ( | ||
Some(ref name), | ||
BorrowExplanation::MustBeValidFor { | ||
category: category @ ConstraintCategory::CallArgument, | ||
from_closure: false, | ||
ref region_name, | ||
span, | ||
.. | ||
}, | ||
) if borrow_spans.for_closure() => self.report_escaping_closure_capture( | ||
borrow_spans, | ||
borrow_span, | ||
region_name, | ||
category, | ||
span, | ||
&format!("`{}`", name), | ||
), | ||
( | ||
Some(ref name), | ||
BorrowExplanation::MustBeValidFor { | ||
category: category @ ConstraintCategory::OpaqueType, | ||
from_closure: false, | ||
ref region_name, | ||
) if borrow_spans.for_generator() | borrow_spans.for_closure() => self | ||
.report_escaping_closure_capture( | ||
borrow_spans, | ||
borrow_span, | ||
region_name, | ||
category, | ||
span, | ||
.. | ||
}, | ||
) if borrow_spans.for_generator() => self.report_escaping_closure_capture( | ||
borrow_spans, | ||
borrow_span, | ||
region_name, | ||
category, | ||
span, | ||
&format!("`{}`", name), | ||
), | ||
&format!("`{}`", name), | ||
), | ||
( | ||
ref name, | ||
BorrowExplanation::MustBeValidFor { | ||
|
@@ -1187,7 +1166,6 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { | |
) -> DiagnosticBuilder<'cx> { | ||
let tcx = self.infcx.tcx; | ||
let args_span = use_span.args_or_use(); | ||
let mut err = self.cannot_capture_in_long_lived_closure(args_span, captured_var, var_span); | ||
|
||
let suggestion = match tcx.sess.source_map().span_to_snippet(args_span) { | ||
Ok(mut string) => { | ||
|
@@ -1213,6 +1191,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { | |
}, | ||
None => "closure", | ||
}; | ||
|
||
let mut err = | ||
self.cannot_capture_in_long_lived_closure(args_span, kind, captured_var, var_span); | ||
err.span_suggestion( | ||
args_span, | ||
&format!( | ||
|
@@ -1225,8 +1206,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { | |
); | ||
|
||
let msg = match category { | ||
ConstraintCategory::Return => "closure is returned here".to_string(), | ||
ConstraintCategory::OpaqueType => "generator is returned here".to_string(), | ||
ConstraintCategory::Return | ConstraintCategory::OpaqueType => { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I feel the existing behavior is wrong, users of async should not see There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think that we'll 1) need to be able to differentiate between closures and generators here in the first place and 2) in the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Agreed that saying generators in an error message is basically never right, regardless. |
||
format!("{} is returned here", kind) | ||
} | ||
ConstraintCategory::CallArgument => { | ||
fr_name.highlight_region_name(&mut err); | ||
format!("function requires argument type to outlive `{}`", fr_name) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,12 +1,18 @@ | ||
// edition:2018 | ||
// run-rustfix | ||
|
||
fn foo() -> Box<impl std::future::Future<Output = u32>> { | ||
fn test_boxed() -> Box<impl std::future::Future<Output = u32>> { | ||
let x = 0u32; | ||
Box::new(async move { x } ) | ||
//~^ ERROR E0373 | ||
} | ||
|
||
fn test_ref(x: &u32) -> impl std::future::Future<Output = u32> + '_ { | ||
async move { *x } | ||
//~^ ERROR E0373 | ||
} | ||
|
||
fn main() { | ||
let _foo = foo(); | ||
let _ = test_boxed(); | ||
let _ = test_ref(&0u32); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,12 +1,18 @@ | ||
// edition:2018 | ||
// run-rustfix | ||
|
||
fn foo() -> Box<impl std::future::Future<Output = u32>> { | ||
fn test_boxed() -> Box<impl std::future::Future<Output = u32>> { | ||
let x = 0u32; | ||
Box::new(async { x } ) | ||
//~^ ERROR E0373 | ||
} | ||
|
||
fn test_ref(x: &u32) -> impl std::future::Future<Output = u32> + '_ { | ||
async { *x } | ||
//~^ ERROR E0373 | ||
} | ||
|
||
fn main() { | ||
let _foo = foo(); | ||
let _ = test_boxed(); | ||
let _ = test_ref(&0u32); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,21 +1,21 @@ | ||
error[E0597]: `prefix` does not live long enough | ||
--> $DIR/does-not-live-long-enough.rs:6:51 | ||
error[E0373]: closure may outlive the current function, but it borrows `prefix`, which is owned by the current function | ||
--> $DIR/does-not-live-long-enough.rs:6:33 | ||
| | ||
LL | fn started_with<'a>(&'a self, prefix: &'a str) -> impl Iterator<Item=&'a str> { | ||
| -- lifetime `'a` defined here --------------------------- opaque type requires that `prefix` is borrowed for `'a` | ||
LL | self.data.iter().filter(|s| s.starts_with(prefix)).map(|s| s.as_ref()) | ||
| --- ^^^^^^ borrowed value does not live long enough | ||
| ^^^ ------ `prefix` is borrowed here | ||
| | | ||
| value captured here | ||
LL | | ||
LL | } | ||
| - `prefix` dropped here while still borrowed | ||
| may outlive borrowed value `prefix` | ||
| | ||
note: closure is returned here | ||
--> $DIR/does-not-live-long-enough.rs:5:55 | ||
| | ||
help: you can add a bound to the opaque type to make it last less than `'static` and match `'a` | ||
LL | fn started_with<'a>(&'a self, prefix: &'a str) -> impl Iterator<Item=&'a str> { | ||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||
help: to force the closure to take ownership of `prefix` (and any other referenced variables), use the `move` keyword | ||
| | ||
LL | fn started_with<'a>(&'a self, prefix: &'a str) -> impl Iterator<Item=&'a str> + 'a { | ||
| ^^^^ | ||
LL | self.data.iter().filter(move |s| s.starts_with(prefix)).map(|s| s.as_ref()) | ||
| ^^^^^^^^ | ||
|
||
error: aborting due to previous error | ||
|
||
For more information about this error, try `rustc --explain E0597`. | ||
For more information about this error, try `rustc --explain E0373`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Highlighting this for a rustfmt issue (rust-lang/rustfmt#4110) I'm filing (no need to do anything about it in this PR).