Skip to content

Commit 7ea93ab

Browse files
committed
Auto merge of #21691 - edwardw:double-closure, r=nikomatsakis
It was considered to be impossible but actually it can happen for nested closures. Also, because there must be nested closures when this happens, we can use more targeted help message. Closes #21390 Closes #21600
2 parents 265a233 + 2c6440e commit 7ea93ab

File tree

2 files changed

+38
-11
lines changed

2 files changed

+38
-11
lines changed

src/librustc_borrowck/borrowck/mod.rs

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -770,16 +770,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
770770
MutabilityViolation => {
771771
"cannot assign to data"
772772
}
773-
BorrowViolation(euv::ClosureCapture(_)) => {
774-
// I don't think we can get aliasability violations
775-
// with closure captures, so no need to come up with a
776-
// good error message. The reason this cannot happen
777-
// is because we only capture local variables in
778-
// closures, and those are never aliasable.
779-
self.tcx.sess.span_bug(
780-
span,
781-
"aliasability violation with closure");
782-
}
773+
BorrowViolation(euv::ClosureCapture(_)) |
783774
BorrowViolation(euv::OverloadedOperator) |
784775
BorrowViolation(euv::AddrOf) |
785776
BorrowViolation(euv::AutoRef) |
@@ -809,8 +800,17 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
809800
self.tcx.sess.span_err(span,
810801
format!("{} in a captured outer \
811802
variable in an `Fn` closure", prefix).as_slice());
812-
span_help!(self.tcx.sess, self.tcx.map.span(id),
803+
if let BorrowViolation(euv::ClosureCapture(_)) = kind {
804+
// The aliasability violation with closure captures can
805+
// happen for nested closures, so we know the enclosing
806+
// closure incorrectly accepts an `Fn` while it needs to
807+
// be `FnMut`.
808+
span_help!(self.tcx.sess, self.tcx.map.span(id),
809+
"consider changing this to accept closures that implement `FnMut`");
810+
} else {
811+
span_help!(self.tcx.sess, self.tcx.map.span(id),
813812
"consider changing this closure to take self by mutable reference");
813+
}
814814
}
815815
mc::AliasableStatic(..) |
816816
mc::AliasableStaticMut(..) => {

src/test/compile-fail/issue-21600.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// Copyright 2015 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+
fn call_it<F>(f: F) where F: Fn() { f(); }
12+
13+
struct A;
14+
15+
impl A {
16+
fn gen(&self) {}
17+
fn gen_mut(&mut self) {}
18+
}
19+
20+
fn main() {
21+
let mut x = A;
22+
call_it(|| { //~ HELP consider changing this to accept closures that implement `FnMut`
23+
call_it(|| x.gen());
24+
call_it(|| x.gen_mut()); //~ ERROR cannot borrow data mutably in a captured outer
25+
//~^ ERROR cannot borrow data mutably in a captured outer
26+
});
27+
}

0 commit comments

Comments
 (0)