if let mc::NoteClosureEnv(upvar_id) = err.cmt.note {
let node_id = self.tcx.hir.hir_to_node_id(upvar_id.var_id);
let sp = self.tcx.hir.span(node_id);
- match self.tcx.sess.codemap().span_to_snippet(sp) {
- Ok(snippet) => {
+ let fn_closure_msg = "`Fn` closures cannot capture their enclosing \
+ environment for modifications";
+ match (self.tcx.sess.codemap().span_to_snippet(sp), &err.cmt.cat) {
+ (_, &Categorization::Upvar(mc::Upvar {
+ kind: ty::ClosureKind::Fn, ..
+ })) => {
+ db.note(fn_closure_msg);
+ // we should point at the cause for this closure being
+ // identified as `Fn` (like in signature of method this
+ // closure was passed into)
+ }
+ (Ok(ref snippet), ref cat) => {
let msg = &format!("consider making `{}` mutable", snippet);
- db.span_suggestion(sp, msg, format!("mut {}", snippet));
+ let suggestion = format!("mut {}", snippet);
+
+ if let &Categorization::Deref(ref cmt, _) = cat {
+ if let Categorization::Upvar(mc::Upvar {
+ kind: ty::ClosureKind::Fn, ..
+ }) = cmt.cat {
+ db.note(fn_closure_msg);
+ } else {
+ db.span_suggestion(sp, msg, suggestion);
+ }
+ } else {
+ db.span_suggestion(sp, msg, suggestion);
+ }
}
_ => {
db.span_help(sp, "consider making this binding mutable");
--- /dev/null
+// 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.
+
+pub fn bar<F: Fn()>(_f: F) {}
+
+pub fn foo() {
+ let mut x = 0;
+ bar(move || x = 1);
+ //~^ ERROR cannot assign to captured outer variable in an `Fn` closure
+ //~| NOTE `Fn` closures cannot capture their enclosing environment for modifications
+}
+
+fn main() {}
--- /dev/null
+error[E0594]: cannot assign to captured outer variable in an `Fn` closure
+ --> $DIR/fn-closure-mutable-capture.rs:15:17
+ |
+15 | bar(move || x = 1);
+ | ^^^^^
+ |
+ = note: `Fn` closures cannot capture their enclosing environment for modifications
+help: consider changing this closure to take self by mutable reference
+ --> $DIR/fn-closure-mutable-capture.rs:15:9
+ |
+15 | bar(move || x = 1);
+ | ^^^^^^^^^^^^^
+
+error: aborting due to previous error
+