Skip to content

Commit fab6a10

Browse files
committed
Point at immutable outer variable
When attempting to mutate an immutable outer variable from a closure, point at the outer variable and suggest making it mutable.
1 parent ec016f8 commit fab6a10

File tree

3 files changed

+45
-1
lines changed

3 files changed

+45
-1
lines changed

src/librustc_borrowck/borrowck/mod.rs

+15-1
Original file line numberDiff line numberDiff line change
@@ -759,7 +759,21 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
759759

760760
let mut db = match err.cause {
761761
MutabilityViolation => {
762-
self.cannot_assign(error_span, &descr, Origin::Ast)
762+
let mut db = self.cannot_assign(error_span, &descr, Origin::Ast);
763+
if let mc::NoteClosureEnv(upvar_id) = err.cmt.note {
764+
let node_id = self.tcx.hir.hir_to_node_id(upvar_id.var_id);
765+
let sp = self.tcx.hir.span(node_id);
766+
match self.tcx.sess.codemap().span_to_snippet(sp) {
767+
Ok(snippet) => {
768+
let msg = &format!("consider making `{}` mutable", snippet);
769+
db.span_suggestion(sp, msg, format!("mut {}", snippet));
770+
}
771+
_ => {
772+
db.span_help(sp, "consider making this binding mutable");
773+
}
774+
}
775+
}
776+
db
763777
}
764778
BorrowViolation(euv::ClosureCapture(_)) => {
765779
struct_span_err!(self.tcx.sess, error_span, E0595,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// Point at the captured immutable outer variable
12+
13+
fn foo(mut f: Box<FnMut()>) {
14+
f();
15+
}
16+
17+
fn main() {
18+
let y = true;
19+
foo(Box::new(move || y = false) as Box<_>);
20+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
error[E0594]: cannot assign to captured outer variable in an `FnMut` closure
2+
--> $DIR/closure-immutable-outer-variable.rs:19:26
3+
|
4+
18 | let y = true;
5+
| - help: consider making `y` mutable: `mut y`
6+
19 | foo(Box::new(move || y = false) as Box<_>);
7+
| ^^^^^^^^^
8+
9+
error: aborting due to previous error
10+

0 commit comments

Comments
 (0)