Skip to content

Commit b55bb2e

Browse files
committed
Better messages for errors from Shallow borrows
1 parent ced5c2d commit b55bb2e

File tree

4 files changed

+96
-9
lines changed

4 files changed

+96
-9
lines changed

src/librustc_mir/borrow_check/error_reporting.rs

Lines changed: 42 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,22 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
335335

336336
(BorrowKind::Mut { .. }, _, _, BorrowKind::Shallow, _, _)
337337
| (BorrowKind::Unique, _, _, BorrowKind::Shallow, _, _) => {
338+
let mut err = tcx.cannot_mutate_in_match_guard(
339+
span,
340+
issued_span,
341+
&desc_place,
342+
"mutably borrow",
343+
Origin::Mir,
344+
);
345+
borrow_spans.var_span_label(
346+
&mut err,
347+
format!(
348+
"borrow occurs due to use of `{}` in closure",
349+
desc_place
350+
),
351+
);
352+
err.buffer(&mut self.errors_buffer);
353+
338354
return;
339355
}
340356

@@ -373,7 +389,16 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
373389
Origin::Mir,
374390
),
375391

376-
(BorrowKind::Shared, _, _, BorrowKind::Shared, _, _) => unreachable!(),
392+
(BorrowKind::Shallow, _, _, BorrowKind::Unique, _, _)
393+
| (BorrowKind::Shallow, _, _, BorrowKind::Mut { .. }, _, _) => {
394+
// Shallow borrows are uses from the user's point of view.
395+
self.report_use_while_mutably_borrowed(context, (place, span), issued_borrow);
396+
return
397+
}
398+
(BorrowKind::Shared, _, _, BorrowKind::Shared, _, _)
399+
| (BorrowKind::Shared, _, _, BorrowKind::Shallow, _, _)
400+
| (BorrowKind::Shallow, _, _, BorrowKind::Shared, _, _)
401+
| (BorrowKind::Shallow, _, _, BorrowKind::Shallow, _, _) => unreachable!(),
377402
};
378403

379404
if issued_spans == borrow_spans {
@@ -785,12 +810,22 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
785810
let loan_span = loan_spans.args_or_use();
786811

787812
let tcx = self.infcx.tcx;
788-
let mut err = tcx.cannot_assign_to_borrowed(
789-
span,
790-
loan_span,
791-
&self.describe_place(place).unwrap_or("_".to_owned()),
792-
Origin::Mir,
793-
);
813+
let mut err = if loan.kind == BorrowKind::Shallow {
814+
tcx.cannot_mutate_in_match_guard(
815+
span,
816+
loan_span,
817+
&self.describe_place(place).unwrap_or("_".to_owned()),
818+
"assign",
819+
Origin::Mir,
820+
)
821+
} else {
822+
tcx.cannot_assign_to_borrowed(
823+
span,
824+
loan_span,
825+
&self.describe_place(place).unwrap_or("_".to_owned()),
826+
Origin::Mir,
827+
)
828+
};
794829

795830
loan_spans.var_span_label(&mut err, "borrow occurs due to use in closure");
796831

src/librustc_mir/borrow_check/mod.rs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -836,6 +836,7 @@ enum LocalMutationIsAllowed {
836836
enum InitializationRequiringAction {
837837
Update,
838838
Borrow,
839+
MatchOn,
839840
Use,
840841
Assignment,
841842
}
@@ -850,6 +851,7 @@ impl InitializationRequiringAction {
850851
match self {
851852
InitializationRequiringAction::Update => "update",
852853
InitializationRequiringAction::Borrow => "borrow",
854+
InitializationRequiringAction::MatchOn => "use", // no good noun
853855
InitializationRequiringAction::Use => "use",
854856
InitializationRequiringAction::Assignment => "assign",
855857
}
@@ -859,6 +861,7 @@ impl InitializationRequiringAction {
859861
match self {
860862
InitializationRequiringAction::Update => "updated",
861863
InitializationRequiringAction::Borrow => "borrowed",
864+
InitializationRequiringAction::MatchOn => "matched on",
862865
InitializationRequiringAction::Use => "used",
863866
InitializationRequiringAction::Assignment => "assigned",
864867
}
@@ -991,7 +994,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
991994
}
992995

993996
match kind {
994-
ReadKind::Copy => {
997+
ReadKind::Copy => {
995998
error_reported = true;
996999
this.report_use_while_mutably_borrowed(context, place_span, borrow)
9971000
}
@@ -1137,9 +1140,15 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
11371140
flow_state,
11381141
);
11391142

1143+
let action = if bk == BorrowKind::Shallow {
1144+
InitializationRequiringAction::MatchOn
1145+
} else {
1146+
InitializationRequiringAction::Borrow
1147+
};
1148+
11401149
self.check_if_path_or_subpath_is_moved(
11411150
context,
1142-
InitializationRequiringAction::Borrow,
1151+
action,
11431152
(place, span),
11441153
flow_state,
11451154
);

src/librustc_mir/diagnostics.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1991,6 +1991,26 @@ fn main() {
19911991
```
19921992
"##,
19931993

1994+
E0510: r##"
1995+
Cannot mutate place in this match guard.
1996+
1997+
When matching on a variable it cannot be mutated in the match guards, as this
1998+
could cause the match to be non-exhaustive:
1999+
2000+
```compile_fail,E0510
2001+
#![feature(nll, bind_by_move_pattern_guards)]
2002+
let mut x = Some(0);
2003+
match x {
2004+
None => (),
2005+
Some(v) if { x = None; false } => (),
2006+
Some(_) => (), // No longer matches
2007+
}
2008+
```
2009+
2010+
Here executing `x = None` would modify the value being matched and require us
2011+
to go "back in time" to the `None` arm.
2012+
"##,
2013+
19942014
E0579: r##"
19952015
When matching against an exclusive range, the compiler verifies that the range
19962016
is non-empty. Exclusive range patterns include the start point but not the end

src/librustc_mir/util/borrowck_errors.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -555,6 +555,29 @@ pub trait BorrowckErrors<'cx>: Sized + Copy {
555555
self.cannot_borrow_path_as_mutable_because(span, path, "", o)
556556
}
557557

558+
fn cannot_mutate_in_match_guard(
559+
self,
560+
mutate_span: Span,
561+
match_span: Span,
562+
match_place: &str,
563+
action: &str,
564+
o: Origin,
565+
) -> DiagnosticBuilder<'cx> {
566+
let mut err = struct_span_err!(
567+
self,
568+
mutate_span,
569+
E0510,
570+
"cannot {} `{}` in match guard{OGN}",
571+
action,
572+
match_place,
573+
OGN = o
574+
);
575+
err.span_label(mutate_span, format!("cannot {}", action));
576+
err.span_label(match_span, format!("value is immutable in match guard"));
577+
578+
self.cancel_if_wrong_origin(err, o)
579+
}
580+
558581
fn cannot_borrow_across_generator_yield(
559582
self,
560583
span: Span,

0 commit comments

Comments
 (0)