Skip to content

Commit 7129f17

Browse files
committed
Improve diagnostics that result from the fix for #18335
1 parent 1062955 commit 7129f17

File tree

2 files changed

+37
-13
lines changed

2 files changed

+37
-13
lines changed

src/librustc/middle/borrowck/check_loans.rs

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -777,13 +777,28 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
777777
// Otherwise, just a plain error.
778778
match assignee_cmt.note {
779779
mc::NoteClosureEnv(upvar_id) => {
780-
self.bccx.span_err(
781-
assignment_span,
782-
format!("cannot assign to {}",
783-
self.bccx.cmt_to_string(&*assignee_cmt)).as_slice());
784-
self.bccx.span_note(
785-
self.tcx().map.span(upvar_id.closure_expr_id),
786-
"consider changing this closure to take self by mutable reference");
780+
// If this is an `Fn` closure, it simply can't mutate upvars.
781+
// If it's an `FnMut` closure, the original variable was declared immutable.
782+
// We need to determine which is the case here.
783+
let kind = match assignee_cmt.upvar().unwrap().cat {
784+
mc::cat_upvar(mc::Upvar { kind, .. }) => kind,
785+
_ => unreachable!()
786+
};
787+
if kind == ty::FnUnboxedClosureKind {
788+
self.bccx.span_err(
789+
assignment_span,
790+
format!("cannot assign to {}",
791+
self.bccx.cmt_to_string(&*assignee_cmt)).as_slice());
792+
self.bccx.span_note(
793+
self.tcx().map.span(upvar_id.closure_expr_id),
794+
"consider changing this closure to take self by mutable reference");
795+
} else {
796+
self.bccx.span_err(
797+
assignment_span,
798+
format!("cannot assign to {} {}",
799+
assignee_cmt.mutbl.to_user_str(),
800+
self.bccx.cmt_to_string(&*assignee_cmt)).as_slice());
801+
}
787802
}
788803
_ => match opt_loan_path(&assignee_cmt) {
789804
Some(lp) => {

src/librustc/middle/borrowck/mod.rs

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -626,7 +626,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
626626
match err.code {
627627
err_mutbl => {
628628
let descr = match err.cmt.note {
629-
mc::NoteClosureEnv(_) => {
629+
mc::NoteClosureEnv(_) | mc::NoteUpvarRef(_) => {
630630
self.cmt_to_string(&*err.cmt)
631631
}
632632
_ => match opt_loan_path(&err.cmt) {
@@ -762,11 +762,20 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
762762
match code {
763763
err_mutbl(..) => {
764764
match err.cmt.note {
765-
mc::NoteClosureEnv(upvar_id) => {
766-
self.tcx.sess.span_note(
767-
self.tcx.map.span(upvar_id.closure_expr_id),
768-
"consider changing this closure to take \
769-
self by mutable reference");
765+
mc::NoteClosureEnv(upvar_id) | mc::NoteUpvarRef(upvar_id) => {
766+
// If this is an `Fn` closure, it simply can't mutate upvars.
767+
// If it's an `FnMut` closure, the original variable was declared immutable.
768+
// We need to determine which is the case here.
769+
let kind = match err.cmt.upvar().unwrap().cat {
770+
mc::cat_upvar(mc::Upvar { kind, .. }) => kind,
771+
_ => unreachable!()
772+
};
773+
if kind == ty::FnUnboxedClosureKind {
774+
self.tcx.sess.span_note(
775+
self.tcx.map.span(upvar_id.closure_expr_id),
776+
"consider changing this closure to take \
777+
self by mutable reference");
778+
}
770779
}
771780
_ => {}
772781
}

0 commit comments

Comments
 (0)