Migrate multiple mut borrows diagnostic

This commit is contained in:
TheOddGarlic 2022-08-30 20:38:10 +03:00 committed by mejrs
parent 3a9a06311d
commit e71a722fa6
3 changed files with 47 additions and 7 deletions

View File

@ -293,3 +293,9 @@ mir_build_borrow_of_moved_value = borrow of moved value
.occurs_because_label = move occurs because `{$name}` has type `{$ty}` which does not implement the `Copy` trait
.value_borrowed_label = value borrowed here after move
.suggest_borrowing = borrow this binding in the pattern to avoid moving the value
mir_build_multiple_mut_borrows = cannot borrow value as mutable more than once at a time
.label = first mutable borrow, by `{$name}`, occurs here
.mutable_borrow = another mutable borrow, by `{$name_mut}`, occurs here
.immutable_borrow = also borrowed as immutable, by `{$name_immut}`, here
.moved = also moved into `{$name_moved}` here

View File

@ -578,3 +578,37 @@ pub struct BorrowOfMovedValue<'tcx> {
#[suggestion(code = "ref ", applicability = "machine-applicable")]
pub suggest_borrowing: Option<Span>,
}
#[derive(SessionDiagnostic)]
#[diag(mir_build::multiple_mut_borrows)]
pub struct MultipleMutBorrows {
#[primary_span]
pub span: Span,
#[label]
pub binding_span: Span,
#[subdiagnostic]
pub occurences: Vec<MultipleMutBorrowOccurence>,
pub name: Ident,
}
#[derive(SessionSubdiagnostic)]
pub enum MultipleMutBorrowOccurence {
#[label(mir_build::mutable_borrow)]
Mutable {
#[primary_span]
span: Span,
name_mut: Ident,
},
#[label(mir_build::immutable_borrow)]
Immutable {
#[primary_span]
span: Span,
name_immut: Ident,
},
#[label(mir_build::moved)]
Moved {
#[primary_span]
span: Span,
name_moved: Ident,
},
}

View File

@ -999,19 +999,19 @@ fn check_borrow_conflicts_in_at_patterns(cx: &MatchVisitor<'_, '_, '_>, pat: &Pa
// Report errors if any.
if !conflicts_mut_mut.is_empty() {
// Report mutability conflicts for e.g. `ref mut x @ Some(ref mut y)`.
let mut err = sess
.struct_span_err(pat.span, "cannot borrow value as mutable more than once at a time");
err.span_label(binding_span, format!("first mutable borrow, by `{}`, occurs here", name));
let mut occurences = vec![];
for (span, name) in conflicts_mut_mut {
err.span_label(span, format!("another mutable borrow, by `{}`, occurs here", name));
occurences.push(MultipleMutBorrowOccurence::Mutable { span, name_mut: name });
}
for (span, name) in conflicts_mut_ref {
err.span_label(span, format!("also borrowed as immutable, by `{}`, here", name));
occurences.push(MultipleMutBorrowOccurence::Immutable { span, name_immut: name });
}
for (span, name) in conflicts_move {
err.span_label(span, format!("also moved into `{}` here", name));
occurences.push(MultipleMutBorrowOccurence::Moved { span, name_moved: name });
}
err.emit();
sess.emit_err(MultipleMutBorrows { span: pat.span, binding_span, occurences, name });
} else if !conflicts_mut_ref.is_empty() {
// Report mutability conflicts for e.g. `ref x @ Some(ref mut y)` or the converse.
let (primary, also) = match mut_outer {