Rollup merge of #68816 - estebank:fn-mut-closure, r=varkor

Tweak borrow error on `FnMut` when `Fn` is expected

Fix #31701, fix #66097.
This commit is contained in:
Dylan DPC 2020-02-11 16:36:55 +01:00 committed by GitHub
commit b6024c4766
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 366 additions and 237 deletions

View File

@ -10,7 +10,7 @@ use rustc_span::Span;
use crate::borrow_check::diagnostics::BorrowedContentSource; use crate::borrow_check::diagnostics::BorrowedContentSource;
use crate::borrow_check::MirBorrowckCtxt; use crate::borrow_check::MirBorrowckCtxt;
use crate::util::collect_writes::FindAssignments; use crate::util::collect_writes::FindAssignments;
use rustc_errors::Applicability; use rustc_errors::{Applicability, DiagnosticBuilder};
#[derive(Copy, Clone, Debug, Eq, PartialEq)] #[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub(crate) enum AccessKind { pub(crate) enum AccessKind {
@ -412,11 +412,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
projection: [ProjectionElem::Deref], projection: [ProjectionElem::Deref],
// FIXME document what is this 1 magic number about // FIXME document what is this 1 magic number about
} if local == Local::new(1) && !self.upvars.is_empty() => { } if local == Local::new(1) && !self.upvars.is_empty() => {
err.span_label(span, format!("cannot {ACT}", ACT = act)); self.expected_fn_found_fn_mut_call(&mut err, span, act);
err.span_help(
self.body.span,
"consider changing this to accept closures that implement `FnMut`",
);
} }
PlaceRef { local: _, projection: [.., ProjectionElem::Deref] } => { PlaceRef { local: _, projection: [.., ProjectionElem::Deref] } => {
@ -448,6 +444,101 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
err.buffer(&mut self.errors_buffer); err.buffer(&mut self.errors_buffer);
} }
/// Targetted error when encountering an `FnMut` closure where an `Fn` closure was expected.
fn expected_fn_found_fn_mut_call(&self, err: &mut DiagnosticBuilder<'_>, sp: Span, act: &str) {
err.span_label(sp, format!("cannot {}", act));
let hir = self.infcx.tcx.hir();
let closure_id = hir.as_local_hir_id(self.mir_def_id).unwrap();
let fn_call_id = hir.get_parent_node(closure_id);
let node = hir.get(fn_call_id);
let item_id = hir.get_parent_item(fn_call_id);
let mut look_at_return = true;
// If we can detect the expression to be an `fn` call where the closure was an argument,
// we point at the `fn` definition argument...
match node {
hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Call(func, args), .. }) => {
let arg_pos = args
.iter()
.enumerate()
.filter(|(_, arg)| arg.span == self.body.span)
.map(|(pos, _)| pos)
.next();
let def_id = hir.local_def_id(item_id);
let tables = self.infcx.tcx.typeck_tables_of(def_id);
if let Some(ty::FnDef(def_id, _)) =
tables.node_type_opt(func.hir_id).as_ref().map(|ty| &ty.kind)
{
let arg = match hir.get_if_local(*def_id) {
Some(hir::Node::Item(hir::Item {
ident,
kind: hir::ItemKind::Fn(sig, ..),
..
}))
| Some(hir::Node::TraitItem(hir::TraitItem {
ident,
kind: hir::TraitItemKind::Method(sig, _),
..
}))
| Some(hir::Node::ImplItem(hir::ImplItem {
ident,
kind: hir::ImplItemKind::Method(sig, _),
..
})) => Some(
arg_pos
.and_then(|pos| {
sig.decl.inputs.get(
pos + if sig.decl.implicit_self.has_implicit_self() {
1
} else {
0
},
)
})
.map(|arg| arg.span)
.unwrap_or(ident.span),
),
_ => None,
};
if let Some(span) = arg {
err.span_label(span, "change this to accept `FnMut` instead of `Fn`");
err.span_label(func.span, "expects `Fn` instead of `FnMut`");
if self.infcx.tcx.sess.source_map().is_multiline(self.body.span) {
err.span_label(self.body.span, "in this closure");
}
look_at_return = false;
}
}
}
_ => {}
}
if look_at_return && hir.get_return_block(closure_id).is_some() {
// ...otherwise we are probably in the tail expression of the function, point at the
// return type.
match hir.get(hir.get_parent_item(fn_call_id)) {
hir::Node::Item(hir::Item { ident, kind: hir::ItemKind::Fn(sig, ..), .. })
| hir::Node::TraitItem(hir::TraitItem {
ident,
kind: hir::TraitItemKind::Method(sig, _),
..
})
| hir::Node::ImplItem(hir::ImplItem {
ident,
kind: hir::ImplItemKind::Method(sig, _),
..
}) => {
err.span_label(ident.span, "");
err.span_label(
sig.decl.output.span(),
"change this to return `FnMut` instead of `Fn`",
);
err.span_label(self.body.span, "in this closure");
}
_ => {}
}
}
}
} }
fn suggest_ampmut_self<'tcx>( fn suggest_ampmut_self<'tcx>(

View File

@ -18,7 +18,10 @@ fn main() {
let _g = to_fn(|| set(&mut y)); //~ ERROR cannot borrow let _g = to_fn(|| set(&mut y)); //~ ERROR cannot borrow
let mut z = 0; let mut z = 0;
let _h = to_fn_mut(|| { set(&mut z); to_fn(|| z = 42); }); //~ ERROR cannot assign let _h = to_fn_mut(|| {
set(&mut z);
to_fn(|| z = 42); //~ ERROR cannot assign
});
} }
// By-value captures // By-value captures
@ -33,3 +36,19 @@ fn main() {
let _h = to_fn_mut(move || { set(&mut z); to_fn(move || z = 42); }); //~ ERROR cannot assign let _h = to_fn_mut(move || { set(&mut z); to_fn(move || z = 42); }); //~ ERROR cannot assign
} }
} }
fn foo() -> Box<dyn Fn() -> usize> {
let mut x = 0;
Box::new(move || {
x += 1; //~ ERROR cannot assign
x
})
}
fn bar() -> impl Fn() -> usize {
let mut x = 0;
move || {
x += 1; //~ ERROR cannot assign
x
}
}

View File

@ -1,76 +1,97 @@
error[E0594]: cannot assign to `x`, as it is a captured variable in a `Fn` closure error[E0594]: cannot assign to `x`, as it is a captured variable in a `Fn` closure
--> $DIR/borrow-immutable-upvar-mutation.rs:15:27 --> $DIR/borrow-immutable-upvar-mutation.rs:15:27
| |
LL | fn to_fn<A,F:Fn<A>>(f: F) -> F { f }
| - change this to accept `FnMut` instead of `Fn`
...
LL | let _f = to_fn(|| x = 42); LL | let _f = to_fn(|| x = 42);
| ^^^^^^ cannot assign | ----- ^^^^^^ cannot assign
| | |
help: consider changing this to accept closures that implement `FnMut` | expects `Fn` instead of `FnMut`
--> $DIR/borrow-immutable-upvar-mutation.rs:15:24
|
LL | let _f = to_fn(|| x = 42);
| ^^^^^^^^^
error[E0596]: cannot borrow `y` as mutable, as it is a captured variable in a `Fn` closure error[E0596]: cannot borrow `y` as mutable, as it is a captured variable in a `Fn` closure
--> $DIR/borrow-immutable-upvar-mutation.rs:18:31 --> $DIR/borrow-immutable-upvar-mutation.rs:18:31
| |
LL | fn to_fn<A,F:Fn<A>>(f: F) -> F { f }
| - change this to accept `FnMut` instead of `Fn`
...
LL | let _g = to_fn(|| set(&mut y)); LL | let _g = to_fn(|| set(&mut y));
| ^^^^^^ cannot borrow as mutable | ----- ^^^^^^ cannot borrow as mutable
| | |
help: consider changing this to accept closures that implement `FnMut` | expects `Fn` instead of `FnMut`
--> $DIR/borrow-immutable-upvar-mutation.rs:18:24
|
LL | let _g = to_fn(|| set(&mut y));
| ^^^^^^^^^^^^^^
error[E0594]: cannot assign to `z`, as it is a captured variable in a `Fn` closure error[E0594]: cannot assign to `z`, as it is a captured variable in a `Fn` closure
--> $DIR/borrow-immutable-upvar-mutation.rs:21:55 --> $DIR/borrow-immutable-upvar-mutation.rs:23:22
| |
LL | let _h = to_fn_mut(|| { set(&mut z); to_fn(|| z = 42); }); LL | fn to_fn<A,F:Fn<A>>(f: F) -> F { f }
| ^^^^^^ cannot assign | - change this to accept `FnMut` instead of `Fn`
| ...
help: consider changing this to accept closures that implement `FnMut` LL | to_fn(|| z = 42);
--> $DIR/borrow-immutable-upvar-mutation.rs:21:52 | ----- ^^^^^^ cannot assign
| | |
LL | let _h = to_fn_mut(|| { set(&mut z); to_fn(|| z = 42); }); | expects `Fn` instead of `FnMut`
| ^^^^^^^^^
error[E0594]: cannot assign to `x`, as it is a captured variable in a `Fn` closure error[E0594]: cannot assign to `x`, as it is a captured variable in a `Fn` closure
--> $DIR/borrow-immutable-upvar-mutation.rs:27:32 --> $DIR/borrow-immutable-upvar-mutation.rs:30:32
| |
LL | fn to_fn<A,F:Fn<A>>(f: F) -> F { f }
| - change this to accept `FnMut` instead of `Fn`
...
LL | let _f = to_fn(move || x = 42); LL | let _f = to_fn(move || x = 42);
| ^^^^^^ cannot assign | ----- ^^^^^^ cannot assign
| | |
help: consider changing this to accept closures that implement `FnMut` | expects `Fn` instead of `FnMut`
--> $DIR/borrow-immutable-upvar-mutation.rs:27:24
|
LL | let _f = to_fn(move || x = 42);
| ^^^^^^^^^^^^^^
error[E0596]: cannot borrow `y` as mutable, as it is a captured variable in a `Fn` closure error[E0596]: cannot borrow `y` as mutable, as it is a captured variable in a `Fn` closure
--> $DIR/borrow-immutable-upvar-mutation.rs:30:36 --> $DIR/borrow-immutable-upvar-mutation.rs:33:36
| |
LL | fn to_fn<A,F:Fn<A>>(f: F) -> F { f }
| - change this to accept `FnMut` instead of `Fn`
...
LL | let _g = to_fn(move || set(&mut y)); LL | let _g = to_fn(move || set(&mut y));
| ^^^^^^ cannot borrow as mutable | ----- ^^^^^^ cannot borrow as mutable
| | |
help: consider changing this to accept closures that implement `FnMut` | expects `Fn` instead of `FnMut`
--> $DIR/borrow-immutable-upvar-mutation.rs:30:24
|
LL | let _g = to_fn(move || set(&mut y));
| ^^^^^^^^^^^^^^^^^^^
error[E0594]: cannot assign to `z`, as it is a captured variable in a `Fn` closure error[E0594]: cannot assign to `z`, as it is a captured variable in a `Fn` closure
--> $DIR/borrow-immutable-upvar-mutation.rs:33:65 --> $DIR/borrow-immutable-upvar-mutation.rs:36:65
| |
LL | fn to_fn<A,F:Fn<A>>(f: F) -> F { f }
| - change this to accept `FnMut` instead of `Fn`
...
LL | let _h = to_fn_mut(move || { set(&mut z); to_fn(move || z = 42); }); LL | let _h = to_fn_mut(move || { set(&mut z); to_fn(move || z = 42); });
| ^^^^^^ cannot assign | ----- ^^^^^^ cannot assign
| | |
help: consider changing this to accept closures that implement `FnMut` | expects `Fn` instead of `FnMut`
--> $DIR/borrow-immutable-upvar-mutation.rs:33:57
|
LL | let _h = to_fn_mut(move || { set(&mut z); to_fn(move || z = 42); });
| ^^^^^^^^^^^^^^
error: aborting due to 6 previous errors error[E0594]: cannot assign to `x`, as it is a captured variable in a `Fn` closure
--> $DIR/borrow-immutable-upvar-mutation.rs:43:9
|
LL | fn foo() -> Box<dyn Fn() -> usize> {
| --- ---------------------- change this to return `FnMut` instead of `Fn`
LL | let mut x = 0;
LL | Box::new(move || {
| ______________-
LL | | x += 1;
| | ^^^^^^ cannot assign
LL | | x
LL | | })
| |_____- in this closure
error[E0594]: cannot assign to `x`, as it is a captured variable in a `Fn` closure
--> $DIR/borrow-immutable-upvar-mutation.rs:51:9
|
LL | fn bar() -> impl Fn() -> usize {
| --- ------------------ change this to return `FnMut` instead of `Fn`
LL | let mut x = 0;
LL | / move || {
LL | | x += 1;
| | ^^^^^^ cannot assign
LL | | x
LL | | }
| |_____- in this closure
error: aborting due to 8 previous errors
Some errors have detailed explanations: E0594, E0596. Some errors have detailed explanations: E0594, E0596.
For more information about an error, try `rustc --explain E0594`. For more information about an error, try `rustc --explain E0594`.

View File

@ -27,32 +27,32 @@ LL | f();
error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure
--> $DIR/borrow-raw-address-of-mutability.rs:29:17 --> $DIR/borrow-raw-address-of-mutability.rs:29:17
| |
LL | let y = &raw mut x; LL | fn make_fn<F: Fn()>(f: F) -> F { f }
| ^^^^^^^^^^ cannot borrow as mutable | - change this to accept `FnMut` instead of `Fn`
| ...
help: consider changing this to accept closures that implement `FnMut`
--> $DIR/borrow-raw-address-of-mutability.rs:28:21
|
LL | let f = make_fn(|| { LL | let f = make_fn(|| {
| _____________________^ | _____________-------_-
| | |
| | expects `Fn` instead of `FnMut`
LL | | let y = &raw mut x; LL | | let y = &raw mut x;
| | ^^^^^^^^^^ cannot borrow as mutable
LL | | }); LL | | });
| |_____^ | |_____- in this closure
error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure
--> $DIR/borrow-raw-address-of-mutability.rs:37:17 --> $DIR/borrow-raw-address-of-mutability.rs:37:17
| |
LL | let y = &raw mut x; LL | fn make_fn<F: Fn()>(f: F) -> F { f }
| ^^^^^^^^^^ cannot borrow as mutable | - change this to accept `FnMut` instead of `Fn`
| ...
help: consider changing this to accept closures that implement `FnMut`
--> $DIR/borrow-raw-address-of-mutability.rs:36:21
|
LL | let f = make_fn(move || { LL | let f = make_fn(move || {
| _____________________^ | _____________-------_-
| | |
| | expects `Fn` instead of `FnMut`
LL | | let y = &raw mut x; LL | | let y = &raw mut x;
| | ^^^^^^^^^^ cannot borrow as mutable
LL | | }); LL | | });
| |_____^ | |_____- in this closure
error: aborting due to 5 previous errors error: aborting due to 5 previous errors

View File

@ -119,146 +119,146 @@ LL | &mut (*f()).0;
error[E0594]: cannot assign to `x`, as it is a captured variable in a `Fn` closure error[E0594]: cannot assign to `x`, as it is a captured variable in a `Fn` closure
--> $DIR/mutability-errors.rs:40:9 --> $DIR/mutability-errors.rs:40:9
| |
LL | x = (1,); LL | fn fn_ref<F: Fn()>(f: F) -> F { f }
| ^^^^^^^^ cannot assign | - change this to accept `FnMut` instead of `Fn`
| ...
help: consider changing this to accept closures that implement `FnMut`
--> $DIR/mutability-errors.rs:39:12
|
LL | fn_ref(|| { LL | fn_ref(|| {
| ____________^ | _____------_-
| | |
| | expects `Fn` instead of `FnMut`
LL | | x = (1,); LL | | x = (1,);
| | ^^^^^^^^ cannot assign
LL | | x.0 = 1; LL | | x.0 = 1;
LL | | &mut x; LL | | &mut x;
LL | | &mut x.0; LL | | &mut x.0;
LL | | }); LL | | });
| |_____^ | |_____- in this closure
error[E0594]: cannot assign to `x.0`, as `Fn` closures cannot mutate their captured variables error[E0594]: cannot assign to `x.0`, as `Fn` closures cannot mutate their captured variables
--> $DIR/mutability-errors.rs:41:9 --> $DIR/mutability-errors.rs:41:9
| |
LL | x.0 = 1; LL | fn fn_ref<F: Fn()>(f: F) -> F { f }
| ^^^^^^^ cannot assign | - change this to accept `FnMut` instead of `Fn`
| ...
help: consider changing this to accept closures that implement `FnMut`
--> $DIR/mutability-errors.rs:39:12
|
LL | fn_ref(|| { LL | fn_ref(|| {
| ____________^ | _____------_-
| | |
| | expects `Fn` instead of `FnMut`
LL | | x = (1,); LL | | x = (1,);
LL | | x.0 = 1; LL | | x.0 = 1;
| | ^^^^^^^ cannot assign
LL | | &mut x; LL | | &mut x;
LL | | &mut x.0; LL | | &mut x.0;
LL | | }); LL | | });
| |_____^ | |_____- in this closure
error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure
--> $DIR/mutability-errors.rs:42:9 --> $DIR/mutability-errors.rs:42:9
| |
LL | &mut x; LL | fn fn_ref<F: Fn()>(f: F) -> F { f }
| ^^^^^^ cannot borrow as mutable | - change this to accept `FnMut` instead of `Fn`
| ...
help: consider changing this to accept closures that implement `FnMut`
--> $DIR/mutability-errors.rs:39:12
|
LL | fn_ref(|| { LL | fn_ref(|| {
| ____________^ | _____------_-
| | |
| | expects `Fn` instead of `FnMut`
LL | | x = (1,); LL | | x = (1,);
LL | | x.0 = 1; LL | | x.0 = 1;
LL | | &mut x; LL | | &mut x;
| | ^^^^^^ cannot borrow as mutable
LL | | &mut x.0; LL | | &mut x.0;
LL | | }); LL | | });
| |_____^ | |_____- in this closure
error[E0596]: cannot borrow `x.0` as mutable, as `Fn` closures cannot mutate their captured variables error[E0596]: cannot borrow `x.0` as mutable, as `Fn` closures cannot mutate their captured variables
--> $DIR/mutability-errors.rs:43:9 --> $DIR/mutability-errors.rs:43:9
| |
LL | &mut x.0; LL | fn fn_ref<F: Fn()>(f: F) -> F { f }
| ^^^^^^^^ cannot borrow as mutable | - change this to accept `FnMut` instead of `Fn`
| ...
help: consider changing this to accept closures that implement `FnMut`
--> $DIR/mutability-errors.rs:39:12
|
LL | fn_ref(|| { LL | fn_ref(|| {
| ____________^ | _____------_-
| | |
| | expects `Fn` instead of `FnMut`
LL | | x = (1,); LL | | x = (1,);
LL | | x.0 = 1; LL | | x.0 = 1;
LL | | &mut x; LL | | &mut x;
LL | | &mut x.0; LL | | &mut x.0;
| | ^^^^^^^^ cannot borrow as mutable
LL | | }); LL | | });
| |_____^ | |_____- in this closure
error[E0594]: cannot assign to `x`, as it is a captured variable in a `Fn` closure error[E0594]: cannot assign to `x`, as it is a captured variable in a `Fn` closure
--> $DIR/mutability-errors.rs:46:9 --> $DIR/mutability-errors.rs:46:9
| |
LL | x = (1,); LL | fn fn_ref<F: Fn()>(f: F) -> F { f }
| ^^^^^^^^ cannot assign | - change this to accept `FnMut` instead of `Fn`
| ...
help: consider changing this to accept closures that implement `FnMut`
--> $DIR/mutability-errors.rs:45:12
|
LL | fn_ref(move || { LL | fn_ref(move || {
| ____________^ | _____------_-
| | |
| | expects `Fn` instead of `FnMut`
LL | | x = (1,); LL | | x = (1,);
| | ^^^^^^^^ cannot assign
LL | | x.0 = 1; LL | | x.0 = 1;
LL | | &mut x; LL | | &mut x;
LL | | &mut x.0; LL | | &mut x.0;
LL | | }); LL | | });
| |_____^ | |_____- in this closure
error[E0594]: cannot assign to `x.0`, as `Fn` closures cannot mutate their captured variables error[E0594]: cannot assign to `x.0`, as `Fn` closures cannot mutate their captured variables
--> $DIR/mutability-errors.rs:47:9 --> $DIR/mutability-errors.rs:47:9
| |
LL | x.0 = 1; LL | fn fn_ref<F: Fn()>(f: F) -> F { f }
| ^^^^^^^ cannot assign | - change this to accept `FnMut` instead of `Fn`
| ...
help: consider changing this to accept closures that implement `FnMut`
--> $DIR/mutability-errors.rs:45:12
|
LL | fn_ref(move || { LL | fn_ref(move || {
| ____________^ | _____------_-
| | |
| | expects `Fn` instead of `FnMut`
LL | | x = (1,); LL | | x = (1,);
LL | | x.0 = 1; LL | | x.0 = 1;
| | ^^^^^^^ cannot assign
LL | | &mut x; LL | | &mut x;
LL | | &mut x.0; LL | | &mut x.0;
LL | | }); LL | | });
| |_____^ | |_____- in this closure
error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure
--> $DIR/mutability-errors.rs:48:9 --> $DIR/mutability-errors.rs:48:9
| |
LL | &mut x; LL | fn fn_ref<F: Fn()>(f: F) -> F { f }
| ^^^^^^ cannot borrow as mutable | - change this to accept `FnMut` instead of `Fn`
| ...
help: consider changing this to accept closures that implement `FnMut`
--> $DIR/mutability-errors.rs:45:12
|
LL | fn_ref(move || { LL | fn_ref(move || {
| ____________^ | _____------_-
| | |
| | expects `Fn` instead of `FnMut`
LL | | x = (1,); LL | | x = (1,);
LL | | x.0 = 1; LL | | x.0 = 1;
LL | | &mut x; LL | | &mut x;
| | ^^^^^^ cannot borrow as mutable
LL | | &mut x.0; LL | | &mut x.0;
LL | | }); LL | | });
| |_____^ | |_____- in this closure
error[E0596]: cannot borrow `x.0` as mutable, as `Fn` closures cannot mutate their captured variables error[E0596]: cannot borrow `x.0` as mutable, as `Fn` closures cannot mutate their captured variables
--> $DIR/mutability-errors.rs:49:9 --> $DIR/mutability-errors.rs:49:9
| |
LL | &mut x.0; LL | fn fn_ref<F: Fn()>(f: F) -> F { f }
| ^^^^^^^^ cannot borrow as mutable | - change this to accept `FnMut` instead of `Fn`
| ...
help: consider changing this to accept closures that implement `FnMut`
--> $DIR/mutability-errors.rs:45:12
|
LL | fn_ref(move || { LL | fn_ref(move || {
| ____________^ | _____------_-
| | |
| | expects `Fn` instead of `FnMut`
LL | | x = (1,); LL | | x = (1,);
LL | | x.0 = 1; LL | | x.0 = 1;
LL | | &mut x; LL | | &mut x;
LL | | &mut x.0; LL | | &mut x.0;
| | ^^^^^^^^ cannot borrow as mutable
LL | | }); LL | | });
| |_____^ | |_____- in this closure
error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable
--> $DIR/mutability-errors.rs:54:5 --> $DIR/mutability-errors.rs:54:5

View File

@ -1,11 +1,11 @@
pub fn bar<F: Fn()>(_f: F) {} pub fn bar<F: Fn()>(_f: F) {} //~ NOTE change this to accept `FnMut` instead of `Fn`
pub fn foo() { pub fn foo() {
let mut x = 0; let mut x = 0;
bar(move || x = 1); bar(move || x = 1);
//~^ ERROR cannot assign to `x`, as it is a captured variable in a `Fn` closure //~^ ERROR cannot assign to `x`, as it is a captured variable in a `Fn` closure
//~| NOTE cannot assign //~| NOTE cannot assign
//~| HELP consider changing this to accept closures that implement `FnMut` //~| NOTE expects `Fn` instead of `FnMut`
} }
fn main() {} fn main() {}

View File

@ -1,14 +1,13 @@
error[E0594]: cannot assign to `x`, as it is a captured variable in a `Fn` closure error[E0594]: cannot assign to `x`, as it is a captured variable in a `Fn` closure
--> $DIR/fn-closure-mutable-capture.rs:5:17 --> $DIR/fn-closure-mutable-capture.rs:5:17
| |
LL | pub fn bar<F: Fn()>(_f: F) {}
| - change this to accept `FnMut` instead of `Fn`
...
LL | bar(move || x = 1); LL | bar(move || x = 1);
| ^^^^^ cannot assign | --- ^^^^^ cannot assign
| | |
help: consider changing this to accept closures that implement `FnMut` | expects `Fn` instead of `FnMut`
--> $DIR/fn-closure-mutable-capture.rs:5:9
|
LL | bar(move || x = 1);
| ^^^^^^^^^^^^^
error: aborting due to previous error error: aborting due to previous error

View File

@ -1,34 +1,33 @@
error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure
--> $DIR/issue-21600.rs:14:20 --> $DIR/issue-21600.rs:14:20
| |
LL | fn call_it<F>(f: F) where F: Fn() { f(); }
| - change this to accept `FnMut` instead of `Fn`
...
LL | call_it(|| x.gen_mut()); LL | call_it(|| x.gen_mut());
| ^ cannot borrow as mutable | ------- ^ cannot borrow as mutable
| | |
help: consider changing this to accept closures that implement `FnMut` | expects `Fn` instead of `FnMut`
--> $DIR/issue-21600.rs:14:17
|
LL | call_it(|| x.gen_mut());
| ^^^^^^^^^^^^^^
error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure
--> $DIR/issue-21600.rs:14:17 --> $DIR/issue-21600.rs:14:17
| |
LL | call_it(|| x.gen_mut()); LL | fn call_it<F>(f: F) where F: Fn() { f(); }
| ^^ - mutable borrow occurs due to use of `x` in closure | - change this to accept `FnMut` instead of `Fn`
| | ...
| cannot borrow as mutable
|
help: consider changing this to accept closures that implement `FnMut`
--> $DIR/issue-21600.rs:12:13
|
LL | call_it(|| { LL | call_it(|| {
| _____________^ | _____-------_-
| | |
| | expects `Fn` instead of `FnMut`
LL | | call_it(|| x.gen()); LL | | call_it(|| x.gen());
LL | | call_it(|| x.gen_mut()); LL | | call_it(|| x.gen_mut());
| | ^^ - mutable borrow occurs due to use of `x` in closure
| | |
| | cannot borrow as mutable
LL | | LL | |
LL | | LL | |
LL | | }); LL | | });
| |_____^ | |_____- in this closure
error: aborting due to 2 previous errors error: aborting due to 2 previous errors

View File

@ -37,36 +37,36 @@ LL | x = 1;
error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure
--> $DIR/closure-captures.rs:27:9 --> $DIR/closure-captures.rs:27:9
| |
LL | || LL | fn fn_ref<F: Fn()>(f: F) -> F { f }
| ^^ cannot borrow as mutable | - change this to accept `FnMut` instead of `Fn`
LL | x = 1;} ...
| - mutable borrow occurs due to use of `x` in closure
|
help: consider changing this to accept closures that implement `FnMut`
--> $DIR/closure-captures.rs:26:12
|
LL | fn_ref(|| { LL | fn_ref(|| {
| ____________^ | _____------_-
| | |
| | expects `Fn` instead of `FnMut`
LL | | || LL | | ||
| | ^^ cannot borrow as mutable
LL | | x = 1;} LL | | x = 1;}
| |________________^ | |__________-_____- in this closure
| |
| mutable borrow occurs due to use of `x` in closure
error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure
--> $DIR/closure-captures.rs:31:9 --> $DIR/closure-captures.rs:31:9
| |
LL | || LL | fn fn_ref<F: Fn()>(f: F) -> F { f }
| ^^ cannot borrow as mutable | - change this to accept `FnMut` instead of `Fn`
LL | x = 1;}); ...
| - mutable borrow occurs due to use of `x` in closure
|
help: consider changing this to accept closures that implement `FnMut`
--> $DIR/closure-captures.rs:30:12
|
LL | fn_ref(move || { LL | fn_ref(move || {
| ____________^ | _____------_-
| | |
| | expects `Fn` instead of `FnMut`
LL | | || LL | | ||
| | ^^ cannot borrow as mutable
LL | | x = 1;}); LL | | x = 1;});
| |___________^ | |_____-_____- in this closure
| |
| mutable borrow occurs due to use of `x` in closure
error[E0594]: cannot assign to `x`, as it is not declared as mutable error[E0594]: cannot assign to `x`, as it is not declared as mutable
--> $DIR/closure-captures.rs:39:10 --> $DIR/closure-captures.rs:39:10
@ -80,19 +80,19 @@ LL | x = 1;}
error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure
--> $DIR/closure-captures.rs:38:9 --> $DIR/closure-captures.rs:38:9
| |
LL | || LL | fn fn_ref<F: Fn()>(f: F) -> F { f }
| ^^ cannot borrow as mutable | - change this to accept `FnMut` instead of `Fn`
LL | x = 1;} ...
| - mutable borrow occurs due to use of `x` in closure
|
help: consider changing this to accept closures that implement `FnMut`
--> $DIR/closure-captures.rs:37:12
|
LL | fn_ref(|| { LL | fn_ref(|| {
| ____________^ | _____------_-
| | |
| | expects `Fn` instead of `FnMut`
LL | | || LL | | ||
| | ^^ cannot borrow as mutable
LL | | x = 1;} LL | | x = 1;}
| |________________^ | |__________-_____- in this closure
| |
| mutable borrow occurs due to use of `x` in closure
error[E0594]: cannot assign to `x`, as it is not declared as mutable error[E0594]: cannot assign to `x`, as it is not declared as mutable
--> $DIR/closure-captures.rs:43:5 --> $DIR/closure-captures.rs:43:5
@ -106,53 +106,53 @@ LL | x = 1;});
error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure
--> $DIR/closure-captures.rs:42:9 --> $DIR/closure-captures.rs:42:9
| |
LL | || LL | fn fn_ref<F: Fn()>(f: F) -> F { f }
| ^^ cannot borrow as mutable | - change this to accept `FnMut` instead of `Fn`
LL | x = 1;}); ...
| - mutable borrow occurs due to use of `x` in closure
|
help: consider changing this to accept closures that implement `FnMut`
--> $DIR/closure-captures.rs:41:12
|
LL | fn_ref(move || { LL | fn_ref(move || {
| ____________^ | _____------_-
| | |
| | expects `Fn` instead of `FnMut`
LL | | || LL | | ||
| | ^^ cannot borrow as mutable
LL | | x = 1;}); LL | | x = 1;});
| |___________^ | |_____-_____- in this closure
| |
| mutable borrow occurs due to use of `x` in closure
error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure
--> $DIR/closure-captures.rs:48:9 --> $DIR/closure-captures.rs:48:9
| |
LL | || LL | fn fn_ref<F: Fn()>(f: F) -> F { f }
| ^^ cannot borrow as mutable | - change this to accept `FnMut` instead of `Fn`
LL | *x = 1;}); ...
| - mutable borrow occurs due to use of `x` in closure
|
help: consider changing this to accept closures that implement `FnMut`
--> $DIR/closure-captures.rs:47:12
|
LL | fn_ref(|| { LL | fn_ref(|| {
| ____________^ | _____------_-
| | |
| | expects `Fn` instead of `FnMut`
LL | | || LL | | ||
| | ^^ cannot borrow as mutable
LL | | *x = 1;}); LL | | *x = 1;});
| |________________^ | |__________-_____- in this closure
| |
| mutable borrow occurs due to use of `x` in closure
error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure
--> $DIR/closure-captures.rs:51:9 --> $DIR/closure-captures.rs:51:9
| |
LL | || LL | fn fn_ref<F: Fn()>(f: F) -> F { f }
| ^^ cannot borrow as mutable | - change this to accept `FnMut` instead of `Fn`
LL | *x = 1;}); ...
| - mutable borrow occurs due to use of `x` in closure
|
help: consider changing this to accept closures that implement `FnMut`
--> $DIR/closure-captures.rs:50:12
|
LL | fn_ref(move || { LL | fn_ref(move || {
| ____________^ | _____------_-
| | |
| | expects `Fn` instead of `FnMut`
LL | | || LL | | ||
| | ^^ cannot borrow as mutable
LL | | *x = 1;}); LL | | *x = 1;});
| |________________^ | |__________-_____- in this closure
| |
| mutable borrow occurs due to use of `x` in closure
error: aborting due to 12 previous errors error: aborting due to 12 previous errors

View File

@ -28,17 +28,17 @@ LL | n += 1;
error[E0594]: cannot assign to `n`, as it is a captured variable in a `Fn` closure error[E0594]: cannot assign to `n`, as it is a captured variable in a `Fn` closure
--> $DIR/unboxed-closures-mutate-upvar.rs:53:9 --> $DIR/unboxed-closures-mutate-upvar.rs:53:9
| |
LL | n += 1; LL | fn to_fn<A,F:Fn<A>>(f: F) -> F { f }
| ^^^^^^ cannot assign | - change this to accept `FnMut` instead of `Fn`
| ...
help: consider changing this to accept closures that implement `FnMut`
--> $DIR/unboxed-closures-mutate-upvar.rs:52:23
|
LL | let mut f = to_fn(move || { LL | let mut f = to_fn(move || {
| _______________________^ | _________________-----_-
| | |
| | expects `Fn` instead of `FnMut`
LL | | n += 1; LL | | n += 1;
| | ^^^^^^ cannot assign
LL | | }); LL | | });
| |_____^ | |_____- in this closure
error: aborting due to 4 previous errors error: aborting due to 4 previous errors

View File

@ -1,18 +1,18 @@
error[E0594]: cannot assign to `counter`, as it is a captured variable in a `Fn` closure error[E0594]: cannot assign to `counter`, as it is a captured variable in a `Fn` closure
--> $DIR/unboxed-closures-mutated-upvar-from-fn-closure.rs:11:9 --> $DIR/unboxed-closures-mutated-upvar-from-fn-closure.rs:11:9
| |
LL | counter += 1; LL | fn call<F>(f: F) where F : Fn() {
| ^^^^^^^^^^^^ cannot assign | - change this to accept `FnMut` instead of `Fn`
| ...
help: consider changing this to accept closures that implement `FnMut`
--> $DIR/unboxed-closures-mutated-upvar-from-fn-closure.rs:10:10
|
LL | call(|| { LL | call(|| {
| __________^ | _____----_-
| | |
| | expects `Fn` instead of `FnMut`
LL | | counter += 1; LL | | counter += 1;
| | ^^^^^^^^^^^^ cannot assign
LL | | LL | |
LL | | }); LL | | });
| |_____^ | |_____- in this closure
error: aborting due to previous error error: aborting due to previous error