Skip to content

Commit 9d188e6

Browse files
committed
Better closure error message
Use tracked data introduced in #42196 to provide a better closure error message by showing why a closure implements `FnOnce`. ``` error[E0525]: expected a closure that implements the `Fn` trait, but this closure only implements `FnOnce` --> $DIR/issue_26046.rs:4:19 | 4 | let closure = move || { | ___________________^ 5 | | vec 6 | | }; | |_____^ | note: closure is `FnOnce` because it moves the variable `vec` out of its environment --> $DIR/issue_26046.rs:5:9 | 5 | vec | ^^^ error: aborting due to previous error(s) ``` Fixes #26046
1 parent c94a9ac commit 9d188e6

File tree

1 file changed

+27
-5
lines changed

1 file changed

+27
-5
lines changed

src/librustc/traits/error_reporting.rs

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ use hir::{self, intravisit, Local, Pat, Body};
2929
use hir::intravisit::{Visitor, NestedVisitorMap};
3030
use hir::map::NodeExpr;
3131
use hir::def_id::DefId;
32-
use infer::{self, InferCtxt};
32+
use infer::{self, InferCtxt, InferTables, InferTablesRef};
3333
use infer::type_variable::TypeVariableOrigin;
3434
use rustc::lint::builtin::EXTRA_REQUIREMENT_IN_IMPL;
3535
use std::fmt;
@@ -640,16 +640,38 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
640640
ty::Predicate::ClosureKind(closure_def_id, kind) => {
641641
let found_kind = self.closure_kind(closure_def_id).unwrap();
642642
let closure_span = self.tcx.hir.span_if_local(closure_def_id).unwrap();
643+
let node_id = self.tcx.hir.as_local_node_id(closure_def_id).unwrap();
643644
let mut err = struct_span_err!(
644645
self.tcx.sess, closure_span, E0525,
645646
"expected a closure that implements the `{}` trait, \
646647
but this closure only implements `{}`",
647648
kind,
648649
found_kind);
649-
err.span_note(
650-
obligation.cause.span,
651-
&format!("the requirement to implement \
652-
`{}` derives from here", kind));
650+
651+
let infer_tables = match self.tables {
652+
InferTables::Interned(tables) =>
653+
Some(InferTablesRef::Interned(tables)),
654+
InferTables::InProgress(tables) =>
655+
Some(InferTablesRef::InProgress(tables.borrow())),
656+
InferTables::Missing => None,
657+
};
658+
659+
if let Some(tables) = infer_tables {
660+
if let Some(&(ty::ClosureKind::FnOnce, Some((span, name)))) =
661+
tables.closure_kinds.get(&node_id)
662+
{
663+
err.span_note(
664+
span,
665+
&format!("closure is `FnOnce` because it moves the \
666+
variable `{}` out of its environment", name));
667+
}
668+
} else {
669+
err.span_note(
670+
obligation.cause.span,
671+
&format!("the requirement to implement `{}` \
672+
derives from here", kind));
673+
}
674+
653675
err.emit();
654676
return;
655677
}

0 commit comments

Comments
 (0)