Skip to content

Commit 4283623

Browse files
authored
Rollup merge of #81158 - 1000teslas:issue-80313-fix, r=Aaron1011
Point to span of upvar making closure FnMut For #80313.
2 parents a3c060c + 26b4baf commit 4283623

13 files changed

+152
-4
lines changed

compiler/rustc_mir/src/borrow_check/diagnostics/mutability_errors.rs

+55-1
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
use rustc_hir as hir;
22
use rustc_hir::Node;
33
use rustc_index::vec::Idx;
4-
use rustc_middle::mir::{self, ClearCrossCrate, Local, LocalDecl, LocalInfo, Location};
54
use rustc_middle::mir::{Mutability, Place, PlaceRef, ProjectionElem};
65
use rustc_middle::ty::{self, Ty, TyCtxt};
6+
use rustc_middle::{
7+
hir::place::PlaceBase,
8+
mir::{self, ClearCrossCrate, Local, LocalDecl, LocalInfo, Location},
9+
};
710
use rustc_span::source_map::DesugaringKind;
811
use rustc_span::symbol::{kw, Symbol};
912
use rustc_span::Span;
@@ -241,6 +244,10 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
241244
format!("mut {}", self.local_names[local].unwrap()),
242245
Applicability::MachineApplicable,
243246
);
247+
let tcx = self.infcx.tcx;
248+
if let ty::Closure(id, _) = the_place_err.ty(self.body, tcx).ty.kind() {
249+
self.show_mutating_upvar(tcx, id, the_place_err, &mut err);
250+
}
244251
}
245252

246253
// Also suggest adding mut for upvars
@@ -271,6 +278,14 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
271278
);
272279
}
273280
}
281+
282+
let tcx = self.infcx.tcx;
283+
if let ty::Ref(_, ty, Mutability::Mut) = the_place_err.ty(self.body, tcx).ty.kind()
284+
{
285+
if let ty::Closure(id, _) = ty.kind() {
286+
self.show_mutating_upvar(tcx, id, the_place_err, &mut err);
287+
}
288+
}
274289
}
275290

276291
// complete hack to approximate old AST-borrowck
@@ -463,6 +478,45 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
463478
err.buffer(&mut self.errors_buffer);
464479
}
465480

481+
// point to span of upvar making closure call require mutable borrow
482+
fn show_mutating_upvar(
483+
&self,
484+
tcx: TyCtxt<'_>,
485+
id: &hir::def_id::DefId,
486+
the_place_err: PlaceRef<'tcx>,
487+
err: &mut DiagnosticBuilder<'_>,
488+
) {
489+
let id = id.expect_local();
490+
let tables = tcx.typeck(id);
491+
let hir_id = tcx.hir().local_def_id_to_hir_id(id);
492+
let (span, place) = &tables.closure_kind_origins()[hir_id];
493+
let reason = if let PlaceBase::Upvar(upvar_id) = place.base {
494+
let upvar = ty::place_to_string_for_capture(tcx, place);
495+
match tables.upvar_capture(upvar_id) {
496+
ty::UpvarCapture::ByRef(ty::UpvarBorrow {
497+
kind: ty::BorrowKind::MutBorrow,
498+
..
499+
}) => {
500+
format!("mutable borrow of `{}`", upvar)
501+
}
502+
ty::UpvarCapture::ByValue(_) => {
503+
format!("possible mutation of `{}`", upvar)
504+
}
505+
_ => bug!("upvar `{}` borrowed, but not mutably", upvar),
506+
}
507+
} else {
508+
bug!("not an upvar")
509+
};
510+
err.span_label(
511+
*span,
512+
format!(
513+
"calling `{}` requires mutable binding due to {}",
514+
self.describe_place(the_place_err).unwrap(),
515+
reason
516+
),
517+
);
518+
}
519+
466520
/// Targeted error when encountering an `FnMut` closure where an `Fn` closure was expected.
467521
fn expected_fn_found_fn_mut_call(&self, err: &mut DiagnosticBuilder<'_>, sp: Span, act: &str) {
468522
err.span_label(sp, format!("cannot {}", act));

src/test/ui/borrowck/borrow-raw-address-of-mutability.stderr

+3-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,9 @@ error[E0596]: cannot borrow `f` as mutable, as it is not declared as mutable
2020
|
2121
LL | let f = || {
2222
| - help: consider changing this to be mutable: `mut f`
23-
...
23+
LL | let y = &raw mut x;
24+
| - calling `f` requires mutable binding due to mutable borrow of `x`
25+
LL | };
2426
LL | f();
2527
| ^ cannot borrow as mutable
2628

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
fn main() {
2+
let mut my_var = false;
3+
let callback = || {
4+
&mut my_var;
5+
};
6+
callback(); //~ ERROR E0596
7+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
error[E0596]: cannot borrow `callback` as mutable, as it is not declared as mutable
2+
--> $DIR/issue-80313-mutable-borrow-in-closure.rs:6:5
3+
|
4+
LL | let callback = || {
5+
| -------- help: consider changing this to be mutable: `mut callback`
6+
LL | &mut my_var;
7+
| ------ calling `callback` requires mutable binding due to mutable borrow of `my_var`
8+
LL | };
9+
LL | callback();
10+
| ^^^^^^^^ cannot borrow as mutable
11+
12+
error: aborting due to previous error
13+
14+
For more information about this error, try `rustc --explain E0596`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
fn main() {
2+
let mut my_var = false;
3+
let callback = move || {
4+
&mut my_var;
5+
};
6+
callback(); //~ ERROR E0596
7+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
error[E0596]: cannot borrow `callback` as mutable, as it is not declared as mutable
2+
--> $DIR/issue-80313-mutable-borrow-in-move-closure.rs:6:5
3+
|
4+
LL | let callback = move || {
5+
| -------- help: consider changing this to be mutable: `mut callback`
6+
LL | &mut my_var;
7+
| ------ calling `callback` requires mutable binding due to possible mutation of `my_var`
8+
LL | };
9+
LL | callback();
10+
| ^^^^^^^^ cannot borrow as mutable
11+
12+
error: aborting due to previous error
13+
14+
For more information about this error, try `rustc --explain E0596`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
fn main() {
2+
let mut my_var = false;
3+
let callback = || {
4+
my_var = true;
5+
};
6+
callback(); //~ ERROR E0596
7+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
error[E0596]: cannot borrow `callback` as mutable, as it is not declared as mutable
2+
--> $DIR/issue-80313-mutation-in-closure.rs:6:5
3+
|
4+
LL | let callback = || {
5+
| -------- help: consider changing this to be mutable: `mut callback`
6+
LL | my_var = true;
7+
| ------ calling `callback` requires mutable binding due to mutable borrow of `my_var`
8+
LL | };
9+
LL | callback();
10+
| ^^^^^^^^ cannot borrow as mutable
11+
12+
error: aborting due to previous error
13+
14+
For more information about this error, try `rustc --explain E0596`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
fn main() {
2+
let mut my_var = false;
3+
let callback = move || {
4+
my_var = true;
5+
};
6+
callback(); //~ ERROR E0596
7+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
error[E0596]: cannot borrow `callback` as mutable, as it is not declared as mutable
2+
--> $DIR/issue-80313-mutation-in-move-closure.rs:6:5
3+
|
4+
LL | let callback = move || {
5+
| -------- help: consider changing this to be mutable: `mut callback`
6+
LL | my_var = true;
7+
| ------ calling `callback` requires mutable binding due to possible mutation of `my_var`
8+
LL | };
9+
LL | callback();
10+
| ^^^^^^^^ cannot borrow as mutable
11+
12+
error: aborting due to previous error
13+
14+
For more information about this error, try `rustc --explain E0596`.

src/test/ui/unboxed-closures/unboxed-closures-infer-fnmut-calling-fnmut-no-mut.stderr

+4
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ error[E0596]: cannot borrow `tick1` as mutable, as it is not declared as mutable
33
|
44
LL | let tick1 = || {
55
| ----- help: consider changing this to be mutable: `mut tick1`
6+
LL | counter += 1;
7+
| ------- calling `tick1` requires mutable binding due to mutable borrow of `counter`
68
...
79
LL | tick1();
810
| ^^^^^ cannot borrow as mutable
@@ -12,6 +14,8 @@ error[E0596]: cannot borrow `tick2` as mutable, as it is not declared as mutable
1214
|
1315
LL | let tick2 = || {
1416
| ----- help: consider changing this to be mutable: `mut tick2`
17+
LL | tick1();
18+
| ----- calling `tick2` requires mutable binding due to mutable borrow of `tick1`
1519
...
1620
LL | tick2();
1721
| ^^^^^ cannot borrow as mutable

src/test/ui/unboxed-closures/unboxed-closures-infer-fnmut-missing-mut.stderr

+3-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@ error[E0596]: cannot borrow `tick` as mutable, as it is not declared as mutable
22
--> $DIR/unboxed-closures-infer-fnmut-missing-mut.rs:7:5
33
|
44
LL | let tick = || counter += 1;
5-
| ---- help: consider changing this to be mutable: `mut tick`
5+
| ---- ------- calling `tick` requires mutable binding due to mutable borrow of `counter`
6+
| |
7+
| help: consider changing this to be mutable: `mut tick`
68
LL | tick();
79
| ^^^^ cannot borrow as mutable
810

src/test/ui/unboxed-closures/unboxed-closures-infer-fnmut-move-missing-mut.stderr

+3-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@ error[E0596]: cannot borrow `tick` as mutable, as it is not declared as mutable
22
--> $DIR/unboxed-closures-infer-fnmut-move-missing-mut.rs:7:5
33
|
44
LL | let tick = move || counter += 1;
5-
| ---- help: consider changing this to be mutable: `mut tick`
5+
| ---- ------- calling `tick` requires mutable binding due to possible mutation of `counter`
6+
| |
7+
| help: consider changing this to be mutable: `mut tick`
68
LL | tick();
79
| ^^^^ cannot borrow as mutable
810

0 commit comments

Comments
 (0)