Skip to content

Commit 2564c6a

Browse files
committed
Better messages for errors from Shallow borrows
1 parent b42a49e commit 2564c6a

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
@@ -840,6 +840,7 @@ enum LocalMutationIsAllowed {
840840
enum InitializationRequiringAction {
841841
Update,
842842
Borrow,
843+
MatchOn,
843844
Use,
844845
Assignment,
845846
}
@@ -854,6 +855,7 @@ impl InitializationRequiringAction {
854855
match self {
855856
InitializationRequiringAction::Update => "update",
856857
InitializationRequiringAction::Borrow => "borrow",
858+
InitializationRequiringAction::MatchOn => "use", // no good noun
857859
InitializationRequiringAction::Use => "use",
858860
InitializationRequiringAction::Assignment => "assign",
859861
}
@@ -863,6 +865,7 @@ impl InitializationRequiringAction {
863865
match self {
864866
InitializationRequiringAction::Update => "updated",
865867
InitializationRequiringAction::Borrow => "borrowed",
868+
InitializationRequiringAction::MatchOn => "matched on",
866869
InitializationRequiringAction::Use => "used",
867870
InitializationRequiringAction::Assignment => "assigned",
868871
}
@@ -1219,7 +1222,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
12191222
}
12201223

12211224
match kind {
1222-
ReadKind::Copy => {
1225+
ReadKind::Copy => {
12231226
error_reported = true;
12241227
this.report_use_while_mutably_borrowed(context, place_span, borrow)
12251228
}
@@ -1365,9 +1368,15 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
13651368
flow_state,
13661369
);
13671370

1371+
let action = if bk == BorrowKind::Shallow {
1372+
InitializationRequiringAction::MatchOn
1373+
} else {
1374+
InitializationRequiringAction::Borrow
1375+
};
1376+
13681377
self.check_if_path_or_subpath_is_moved(
13691378
context,
1370-
InitializationRequiringAction::Borrow,
1379+
action,
13711380
(place, span),
13721381
flow_state,
13731382
);

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)