Skip to content

Commit ee88a87

Browse files
committed
Explain why closure is moved in error message
1 parent bf25b5e commit ee88a87

File tree

3 files changed

+38
-29
lines changed

3 files changed

+38
-29
lines changed

Diff for: src/librustc/ty/context.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -230,9 +230,9 @@ pub struct TypeckTables<'tcx> {
230230
/// Records the type of each closure.
231231
pub closure_tys: NodeMap<ty::PolyFnSig<'tcx>>,
232232

233-
/// Records the kind of each closure and the span of the variable that
234-
/// cause the closure to be this kind.
235-
pub closure_kinds: NodeMap<(ty::ClosureKind, Option<Span>)>,
233+
/// Records the kind of each closure and the span and name of the variable
234+
/// that caused the closure to be this kind.
235+
pub closure_kinds: NodeMap<(ty::ClosureKind, Option<(Span, ast::Name)>)>,
236236

237237
/// For each fn, records the "liberated" types of its arguments
238238
/// and return type. Liberated means that all bound regions

Diff for: src/librustc_borrowck/borrowck/mod.rs

+8-8
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,6 @@ use rustc::middle::free_region::RegionRelations;
3939
use rustc::ty::{self, TyCtxt};
4040
use rustc::ty::maps::Providers;
4141

42-
use syntax_pos::DUMMY_SP;
43-
4442
use std::fmt;
4543
use std::rc::Rc;
4644
use std::hash::{Hash, Hasher};
@@ -594,12 +592,14 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
594592
verb, msg, nl);
595593
let need_note = match lp.ty.sty {
596594
ty::TypeVariants::TyClosure(id, _) => {
597-
if let Ok(ty::ClosureKind::FnOnce) =
598-
ty::queries::closure_kind::try_get(self.tcx, DUMMY_SP, id) {
599-
err.help("closure was moved because it only implements `FnOnce`");
600-
if let Some(&(_kind, Some(span))) = self.tables.closure_kinds.get( ) {
601-
err.span_label(span, "move occured here");
602-
}
595+
let node_id = self.tcx.hir.as_local_node_id(id).unwrap();
596+
if let Some(&(ty::ClosureKind::FnOnce, Some((span, name)))) =
597+
self.tables.closure_kinds.get(&node_id)
598+
{
599+
err.help(&format!("closure cannot be invoked more than once because \
600+
it moves the variable `{}` out of its environment",
601+
name));
602+
err.span_label(span, format!("{} moved here", name));
603603
false
604604
} else {
605605
true

Diff for: src/librustc_typeck/check/upvar.rs

+27-18
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
7474

7575
struct SeedBorrowKind<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
7676
fcx: &'a FnCtxt<'a, 'gcx, 'tcx>,
77-
temp_closure_kinds: NodeMap<(ty::ClosureKind, Option<Span>)>,
77+
temp_closure_kinds: NodeMap<(ty::ClosureKind, Option<(Span, ast::Name)>)>,
7878
}
7979

8080
impl<'a, 'gcx, 'tcx> Visitor<'gcx> for SeedBorrowKind<'a, 'gcx, 'tcx> {
@@ -143,12 +143,12 @@ impl<'a, 'gcx, 'tcx> SeedBorrowKind<'a, 'gcx, 'tcx> {
143143

144144
struct AdjustBorrowKind<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
145145
fcx: &'a FnCtxt<'a, 'gcx, 'tcx>,
146-
temp_closure_kinds: NodeMap<(ty::ClosureKind, Option<Span>)>,
146+
temp_closure_kinds: NodeMap<(ty::ClosureKind, Option<(Span, ast::Name)>)>,
147147
}
148148

149149
impl<'a, 'gcx, 'tcx> AdjustBorrowKind<'a, 'gcx, 'tcx> {
150150
fn new(fcx: &'a FnCtxt<'a, 'gcx, 'tcx>,
151-
temp_closure_kinds: NodeMap<(ty::ClosureKind, Option<Span>)>)
151+
temp_closure_kinds: NodeMap<(ty::ClosureKind, Option<(Span, ast::Name)>)>)
152152
-> AdjustBorrowKind<'a, 'gcx, 'tcx> {
153153
AdjustBorrowKind { fcx: fcx, temp_closure_kinds: temp_closure_kinds }
154154
}
@@ -211,8 +211,8 @@ impl<'a, 'gcx, 'tcx> AdjustBorrowKind<'a, 'gcx, 'tcx> {
211211

212212
// If we are also inferred the closure kind here, update the
213213
// main table and process any deferred resolutions.
214-
if let Some(&(kind, span)) = self.temp_closure_kinds.get(&id) {
215-
self.fcx.tables.borrow_mut().closure_kinds.insert(id, (kind, span));
214+
if let Some(&(kind, context)) = self.temp_closure_kinds.get(&id) {
215+
self.fcx.tables.borrow_mut().closure_kinds.insert(id, (kind, context));
216216
let closure_def_id = self.fcx.tcx.hir.local_def_id(id);
217217
debug!("closure_kind({:?}) = {:?}", closure_def_id, kind);
218218

@@ -272,11 +272,12 @@ impl<'a, 'gcx, 'tcx> AdjustBorrowKind<'a, 'gcx, 'tcx> {
272272
euv::Move(_) => { }
273273
}
274274

275+
let tcx = self.fcx.tcx;
276+
275277
// watch out for a move of the deref of a borrowed pointer;
276278
// for that to be legal, the upvar would have to be borrowed
277279
// by value instead
278280
let guarantor = cmt.guarantor();
279-
let tcx = self.fcx.tcx;
280281
debug!("adjust_upvar_borrow_kind_for_consume: guarantor={:?}",
281282
guarantor);
282283
match guarantor.cat {
@@ -291,7 +292,8 @@ impl<'a, 'gcx, 'tcx> AdjustBorrowKind<'a, 'gcx, 'tcx> {
291292
// to move out of an upvar, this must be a FnOnce closure
292293
self.adjust_closure_kind(upvar_id.closure_expr_id,
293294
ty::ClosureKind::FnOnce,
294-
tcx.hir.span(upvar_id.var_id));
295+
guarantor.span,
296+
tcx.hir.name(upvar_id.var_id));
295297

296298
let upvar_capture_map =
297299
&mut self.fcx.tables.borrow_mut().upvar_capture_map;
@@ -306,7 +308,8 @@ impl<'a, 'gcx, 'tcx> AdjustBorrowKind<'a, 'gcx, 'tcx> {
306308
// of the environment.
307309
self.adjust_closure_kind(upvar_id.closure_expr_id,
308310
ty::ClosureKind::FnOnce,
309-
tcx.hir.span(upvar_id.var_id));
311+
guarantor.span,
312+
tcx.hir.name(upvar_id.var_id));
310313
}
311314
mc::NoteNone => {
312315
}
@@ -334,7 +337,7 @@ impl<'a, 'gcx, 'tcx> AdjustBorrowKind<'a, 'gcx, 'tcx> {
334337

335338
Categorization::Deref(base, _, mc::BorrowedPtr(..)) |
336339
Categorization::Deref(base, _, mc::Implicit(..)) => {
337-
if !self.try_adjust_upvar_deref(&cmt.note, ty::MutBorrow) {
340+
if !self.try_adjust_upvar_deref(cmt, ty::MutBorrow) {
338341
// assignment to deref of an `&mut`
339342
// borrowed pointer implies that the
340343
// pointer itself must be unique, but not
@@ -368,7 +371,7 @@ impl<'a, 'gcx, 'tcx> AdjustBorrowKind<'a, 'gcx, 'tcx> {
368371

369372
Categorization::Deref(base, _, mc::BorrowedPtr(..)) |
370373
Categorization::Deref(base, _, mc::Implicit(..)) => {
371-
if !self.try_adjust_upvar_deref(&cmt.note, ty::UniqueImmBorrow) {
374+
if !self.try_adjust_upvar_deref(cmt, ty::UniqueImmBorrow) {
372375
// for a borrowed pointer to be unique, its
373376
// base must be unique
374377
self.adjust_upvar_borrow_kind_for_unique(base);
@@ -385,7 +388,7 @@ impl<'a, 'gcx, 'tcx> AdjustBorrowKind<'a, 'gcx, 'tcx> {
385388
}
386389

387390
fn try_adjust_upvar_deref(&mut self,
388-
note: &mc::Note,
391+
cmt: mc::cmt<'tcx>,
389392
borrow_kind: ty::BorrowKind)
390393
-> bool
391394
{
@@ -399,7 +402,7 @@ impl<'a, 'gcx, 'tcx> AdjustBorrowKind<'a, 'gcx, 'tcx> {
399402

400403
let tcx = self.fcx.tcx;
401404

402-
match *note {
405+
match cmt.note {
403406
mc::NoteUpvarRef(upvar_id) => {
404407
// if this is an implicit deref of an
405408
// upvar, then we need to modify the
@@ -414,7 +417,8 @@ impl<'a, 'gcx, 'tcx> AdjustBorrowKind<'a, 'gcx, 'tcx> {
414417
// also need to be in an FnMut closure since this is not an ImmBorrow
415418
self.adjust_closure_kind(upvar_id.closure_expr_id,
416419
ty::ClosureKind::FnMut,
417-
tcx.hir.span(upvar_id.var_id));
420+
cmt.span,
421+
tcx.hir.name(upvar_id.var_id));
418422

419423
true
420424
}
@@ -424,7 +428,8 @@ impl<'a, 'gcx, 'tcx> AdjustBorrowKind<'a, 'gcx, 'tcx> {
424428
// upvar, we need to be an FnMut closure
425429
self.adjust_closure_kind(upvar_id.closure_expr_id,
426430
ty::ClosureKind::FnMut,
427-
tcx.hir.span(upvar_id.var_id));
431+
cmt.span,
432+
tcx.hir.name(upvar_id.var_id));
428433

429434
true
430435
}
@@ -472,9 +477,10 @@ impl<'a, 'gcx, 'tcx> AdjustBorrowKind<'a, 'gcx, 'tcx> {
472477
fn adjust_closure_kind(&mut self,
473478
closure_id: ast::NodeId,
474479
new_kind: ty::ClosureKind,
475-
upvar_span: Span) {
476-
debug!("adjust_closure_kind(closure_id={}, new_kind={:?})",
477-
closure_id, new_kind);
480+
upvar_span: Span,
481+
var_name: ast::Name) {
482+
debug!("adjust_closure_kind(closure_id={}, new_kind={:?}, upvar_span={:?}, var_name={})",
483+
closure_id, new_kind, upvar_span, var_name);
478484

479485
if let Some(&(existing_kind, _)) = self.temp_closure_kinds.get(&closure_id) {
480486
debug!("adjust_closure_kind: closure_id={}, existing_kind={:?}, new_kind={:?}",
@@ -492,7 +498,10 @@ impl<'a, 'gcx, 'tcx> AdjustBorrowKind<'a, 'gcx, 'tcx> {
492498
(ty::ClosureKind::Fn, ty::ClosureKind::FnOnce) |
493499
(ty::ClosureKind::FnMut, ty::ClosureKind::FnOnce) => {
494500
// new kind is stronger than the old kind
495-
self.temp_closure_kinds.insert(closure_id, (new_kind, Some(upvar_span)));
501+
self.temp_closure_kinds.insert(
502+
closure_id,
503+
(new_kind, Some((upvar_span, var_name)))
504+
);
496505
}
497506
}
498507
}

0 commit comments

Comments
 (0)