-
Notifications
You must be signed in to change notification settings - Fork 13.4k
Explain why a closure is FnOnce
in closure errors.
#42196
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
Changes from 2 commits
7748bc6
bf25b5e
ee88a87
31bfdd7
c2f7e94
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 |
---|---|---|
|
@@ -597,6 +597,9 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { | |
if let Ok(ty::ClosureKind::FnOnce) = | ||
ty::queries::closure_kind::try_get(self.tcx, DUMMY_SP, id) { | ||
err.help("closure was moved because it only implements `FnOnce`"); | ||
if let Some(&(_kind, Some(span))) = self.tables.closure_kinds.get( ) { | ||
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. How do you find the node_id here? 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. This would be the result of 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. (Also, @eddyb, why is this |
||
err.span_label(span, "move occured here"); | ||
} | ||
false | ||
} else { | ||
true | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -74,7 +74,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { | |
|
||
struct SeedBorrowKind<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { | ||
fcx: &'a FnCtxt<'a, 'gcx, 'tcx>, | ||
temp_closure_kinds: NodeMap<ty::ClosureKind>, | ||
temp_closure_kinds: NodeMap<(ty::ClosureKind, Option<Span>)>, | ||
} | ||
|
||
impl<'a, 'gcx, 'tcx> Visitor<'gcx> for SeedBorrowKind<'a, 'gcx, 'tcx> { | ||
|
@@ -107,7 +107,7 @@ impl<'a, 'gcx, 'tcx> SeedBorrowKind<'a, 'gcx, 'tcx> { | |
capture_clause: hir::CaptureClause) | ||
{ | ||
if !self.fcx.tables.borrow().closure_kinds.contains_key(&expr.id) { | ||
self.temp_closure_kinds.insert(expr.id, ty::ClosureKind::Fn); | ||
self.temp_closure_kinds.insert(expr.id, (ty::ClosureKind::Fn, None)); | ||
debug!("check_closure: adding closure {:?} as Fn", expr.id); | ||
} | ||
|
||
|
@@ -143,12 +143,12 @@ impl<'a, 'gcx, 'tcx> SeedBorrowKind<'a, 'gcx, 'tcx> { | |
|
||
struct AdjustBorrowKind<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { | ||
fcx: &'a FnCtxt<'a, 'gcx, 'tcx>, | ||
temp_closure_kinds: NodeMap<ty::ClosureKind>, | ||
temp_closure_kinds: NodeMap<(ty::ClosureKind, Option<Span>)>, | ||
} | ||
|
||
impl<'a, 'gcx, 'tcx> AdjustBorrowKind<'a, 'gcx, 'tcx> { | ||
fn new(fcx: &'a FnCtxt<'a, 'gcx, 'tcx>, | ||
temp_closure_kinds: NodeMap<ty::ClosureKind>) | ||
temp_closure_kinds: NodeMap<(ty::ClosureKind, Option<Span>)>) | ||
-> AdjustBorrowKind<'a, 'gcx, 'tcx> { | ||
AdjustBorrowKind { fcx: fcx, temp_closure_kinds: temp_closure_kinds } | ||
} | ||
|
@@ -211,8 +211,8 @@ impl<'a, 'gcx, 'tcx> AdjustBorrowKind<'a, 'gcx, 'tcx> { | |
|
||
// If we are also inferred the closure kind here, update the | ||
// main table and process any deferred resolutions. | ||
if let Some(&kind) = self.temp_closure_kinds.get(&id) { | ||
self.fcx.tables.borrow_mut().closure_kinds.insert(id, kind); | ||
if let Some(&(kind, span)) = self.temp_closure_kinds.get(&id) { | ||
self.fcx.tables.borrow_mut().closure_kinds.insert(id, (kind, span)); | ||
let closure_def_id = self.fcx.tcx.hir.local_def_id(id); | ||
debug!("closure_kind({:?}) = {:?}", closure_def_id, kind); | ||
|
||
|
@@ -276,6 +276,7 @@ impl<'a, 'gcx, 'tcx> AdjustBorrowKind<'a, 'gcx, 'tcx> { | |
// for that to be legal, the upvar would have to be borrowed | ||
// by value instead | ||
let guarantor = cmt.guarantor(); | ||
let tcx = self.fcx.tcx; | ||
debug!("adjust_upvar_borrow_kind_for_consume: guarantor={:?}", | ||
guarantor); | ||
match guarantor.cat { | ||
|
@@ -289,7 +290,8 @@ impl<'a, 'gcx, 'tcx> AdjustBorrowKind<'a, 'gcx, 'tcx> { | |
|
||
// to move out of an upvar, this must be a FnOnce closure | ||
self.adjust_closure_kind(upvar_id.closure_expr_id, | ||
ty::ClosureKind::FnOnce); | ||
ty::ClosureKind::FnOnce, | ||
tcx.hir.span(upvar_id.var_id)); | ||
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 I would just use |
||
|
||
let upvar_capture_map = | ||
&mut self.fcx.tables.borrow_mut().upvar_capture_map; | ||
|
@@ -303,7 +305,8 @@ impl<'a, 'gcx, 'tcx> AdjustBorrowKind<'a, 'gcx, 'tcx> { | |
// to be a FnOnce closure to permit moves out | ||
// of the environment. | ||
self.adjust_closure_kind(upvar_id.closure_expr_id, | ||
ty::ClosureKind::FnOnce); | ||
ty::ClosureKind::FnOnce, | ||
tcx.hir.span(upvar_id.var_id)); | ||
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. Also here, |
||
} | ||
mc::NoteNone => { | ||
} | ||
|
@@ -394,6 +397,8 @@ impl<'a, 'gcx, 'tcx> AdjustBorrowKind<'a, 'gcx, 'tcx> { | |
ty::ImmBorrow => false, | ||
}); | ||
|
||
let tcx = self.fcx.tcx; | ||
|
||
match *note { | ||
mc::NoteUpvarRef(upvar_id) => { | ||
// if this is an implicit deref of an | ||
|
@@ -407,15 +412,19 @@ impl<'a, 'gcx, 'tcx> AdjustBorrowKind<'a, 'gcx, 'tcx> { | |
} | ||
|
||
// also need to be in an FnMut closure since this is not an ImmBorrow | ||
self.adjust_closure_kind(upvar_id.closure_expr_id, ty::ClosureKind::FnMut); | ||
self.adjust_closure_kind(upvar_id.closure_expr_id, | ||
ty::ClosureKind::FnMut, | ||
tcx.hir.span(upvar_id.var_id)); | ||
|
||
true | ||
} | ||
mc::NoteClosureEnv(upvar_id) => { | ||
// this kind of deref occurs in a `move` closure, or | ||
// for a by-value upvar; in either case, to mutate an | ||
// upvar, we need to be an FnMut closure | ||
self.adjust_closure_kind(upvar_id.closure_expr_id, ty::ClosureKind::FnMut); | ||
self.adjust_closure_kind(upvar_id.closure_expr_id, | ||
ty::ClosureKind::FnMut, | ||
tcx.hir.span(upvar_id.var_id)); | ||
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. here, in addition to passing in the |
||
|
||
true | ||
} | ||
|
@@ -462,11 +471,12 @@ impl<'a, 'gcx, 'tcx> AdjustBorrowKind<'a, 'gcx, 'tcx> { | |
|
||
fn adjust_closure_kind(&mut self, | ||
closure_id: ast::NodeId, | ||
new_kind: ty::ClosureKind) { | ||
new_kind: ty::ClosureKind, | ||
upvar_span: Span) { | ||
debug!("adjust_closure_kind(closure_id={}, new_kind={:?})", | ||
closure_id, new_kind); | ||
|
||
if let Some(&existing_kind) = self.temp_closure_kinds.get(&closure_id) { | ||
if let Some(&(existing_kind, _)) = self.temp_closure_kinds.get(&closure_id) { | ||
debug!("adjust_closure_kind: closure_id={}, existing_kind={:?}, new_kind={:?}", | ||
closure_id, existing_kind, new_kind); | ||
|
||
|
@@ -482,7 +492,7 @@ impl<'a, 'gcx, 'tcx> AdjustBorrowKind<'a, 'gcx, 'tcx> { | |
(ty::ClosureKind::Fn, ty::ClosureKind::FnOnce) | | ||
(ty::ClosureKind::FnMut, ty::ClosureKind::FnOnce) => { | ||
// new kind is stronger than the old kind | ||
self.temp_closure_kinds.insert(closure_id, new_kind); | ||
self.temp_closure_kinds.insert(closure_id, (new_kind, Some(upvar_span))); | ||
} | ||
} | ||
} | ||
|
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.
Nit: I think what we want is to include the span of a variable, but perhaps more than that we would prefer to include the name as well, for later use in the error message (including just the node-id of the reference could suffice, but I'm a bit wary of including a node-id in this value, since it will make life harder later as we handle incremental etc).