Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Migrate mir_build's borrow conflicts #106978

Merged
merged 1 commit into from
Jan 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 12 additions & 4 deletions compiler/rustc_error_messages/locales/en-US/mir_build.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -299,10 +299,18 @@ mir_build_borrow_of_moved_value = borrow of moved value
.suggestion = 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

mir_build_already_borrowed = cannot borrow value as mutable because it is also borrowed as immutable

mir_build_already_mut_borrowed = cannot borrow value as immutable because it is also borrowed as mutable

mir_build_moved_while_borrowed = cannot move out of value because it is borrowed

mir_build_mutable_borrow = value is mutably borrowed by `{$name}` here

mir_build_borrow = value is borrowed by `{$name}` here

mir_build_moved = value is moved into `{$name}` here

mir_build_union_pattern = cannot use unions in constant patterns

Expand Down
50 changes: 37 additions & 13 deletions compiler/rustc_mir_build/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -600,32 +600,56 @@ pub struct BorrowOfMovedValue<'tcx> {
pub struct MultipleMutBorrows {
#[primary_span]
pub span: Span,
#[label]
pub binding_span: Span,
#[subdiagnostic]
pub occurences: Vec<MultipleMutBorrowOccurence>,
pub name: Ident,
pub occurences: Vec<Conflict>,
}

#[derive(Diagnostic)]
#[diag(mir_build_already_borrowed)]
pub struct AlreadyBorrowed {
#[primary_span]
pub span: Span,
#[subdiagnostic]
pub occurences: Vec<Conflict>,
}

#[derive(Diagnostic)]
#[diag(mir_build_already_mut_borrowed)]
pub struct AlreadyMutBorrowed {
#[primary_span]
pub span: Span,
#[subdiagnostic]
pub occurences: Vec<Conflict>,
}

#[derive(Diagnostic)]
#[diag(mir_build_moved_while_borrowed)]
pub struct MovedWhileBorrowed {
#[primary_span]
pub span: Span,
#[subdiagnostic]
pub occurences: Vec<Conflict>,
}

#[derive(Subdiagnostic)]
pub enum MultipleMutBorrowOccurence {
#[label(mutable_borrow)]
Mutable {
pub enum Conflict {
#[label(mir_build_mutable_borrow)]
Mut {
#[primary_span]
span: Span,
name_mut: Ident,
name: Ident,
},
#[label(immutable_borrow)]
Immutable {
#[label(mir_build_borrow)]
Ref {
#[primary_span]
span: Span,
name_immut: Ident,
name: Ident,
},
#[label(moved)]
#[label(mir_build_moved)]
Moved {
#[primary_span]
span: Span,
name_moved: Ident,
name: Ident,
},
}

Expand Down
77 changes: 37 additions & 40 deletions compiler/rustc_mir_build/src/thir/pattern/check_match.rs
Original file line number Diff line number Diff line change
Expand Up @@ -914,58 +914,55 @@ fn check_borrow_conflicts_in_at_patterns(cx: &MatchVisitor<'_, '_, '_>, pat: &Pa
sub.each_binding(|_, hir_id, span, name| {
match typeck_results.extract_binding_mode(sess, hir_id, span) {
Some(ty::BindByReference(mut_inner)) => match (mut_outer, mut_inner) {
(Mutability::Not, Mutability::Not) => {} // Both sides are `ref`.
(Mutability::Mut, Mutability::Mut) => conflicts_mut_mut.push((span, name)), // 2x `ref mut`.
_ => conflicts_mut_ref.push((span, name)), // `ref` + `ref mut` in either direction.
// Both sides are `ref`.
(Mutability::Not, Mutability::Not) => {}
// 2x `ref mut`.
(Mutability::Mut, Mutability::Mut) => {
conflicts_mut_mut.push(Conflict::Mut { span, name })
}
(Mutability::Not, Mutability::Mut) => {
conflicts_mut_ref.push(Conflict::Mut { span, name })
}
(Mutability::Mut, Mutability::Not) => {
conflicts_mut_ref.push(Conflict::Ref { span, name })
}
},
Some(ty::BindByValue(_)) if is_binding_by_move(cx, hir_id) => {
conflicts_move.push((span, name)) // `ref mut?` + by-move conflict.
conflicts_move.push(Conflict::Moved { span, name }) // `ref mut?` + by-move conflict.
}
Some(ty::BindByValue(_)) | None => {} // `ref mut?` + by-copy is fine.
}
});

let report_mut_mut = !conflicts_mut_mut.is_empty();
let report_mut_ref = !conflicts_mut_ref.is_empty();
let report_move_conflict = !conflicts_move.is_empty();

let mut occurences = match mut_outer {
Mutability::Mut => vec![Conflict::Mut { span: binding_span, name }],
Mutability::Not => vec![Conflict::Ref { span: binding_span, name }],
};
occurences.extend(conflicts_mut_mut);
occurences.extend(conflicts_mut_ref);
occurences.extend(conflicts_move);

// Report errors if any.
if !conflicts_mut_mut.is_empty() {
if report_mut_mut {
// Report mutability conflicts for e.g. `ref mut x @ Some(ref mut y)`.
let mut occurences = vec![];

for (span, name_mut) in conflicts_mut_mut {
occurences.push(MultipleMutBorrowOccurence::Mutable { span, name_mut });
}
for (span, name_immut) in conflicts_mut_ref {
occurences.push(MultipleMutBorrowOccurence::Immutable { span, name_immut });
}
for (span, name_moved) in conflicts_move {
occurences.push(MultipleMutBorrowOccurence::Moved { span, name_moved });
}
sess.emit_err(MultipleMutBorrows { span: pat.span, binding_span, occurences, name });
} else if !conflicts_mut_ref.is_empty() {
sess.emit_err(MultipleMutBorrows { span: pat.span, occurences });
} else if report_mut_ref {
// Report mutability conflicts for e.g. `ref x @ Some(ref mut y)` or the converse.
let (primary, also) = match mut_outer {
Mutability::Mut => ("mutable", "immutable"),
Mutability::Not => ("immutable", "mutable"),
match mut_outer {
Mutability::Mut => {
sess.emit_err(AlreadyMutBorrowed { span: pat.span, occurences });
}
Mutability::Not => {
sess.emit_err(AlreadyBorrowed { span: pat.span, occurences });
}
};
let msg =
format!("cannot borrow value as {} because it is also borrowed as {}", also, primary);
let mut err = sess.struct_span_err(pat.span, &msg);
err.span_label(binding_span, format!("{} borrow, by `{}`, occurs here", primary, name));
for (span, name) in conflicts_mut_ref {
err.span_label(span, format!("{} borrow, by `{}`, occurs here", also, name));
}
for (span, name) in conflicts_move {
err.span_label(span, format!("also moved into `{}` here", name));
}
err.emit();
} else if !conflicts_move.is_empty() {
} else if report_move_conflict {
// Report by-ref and by-move conflicts, e.g. `ref x @ y`.
let mut err =
sess.struct_span_err(pat.span, "cannot move out of value because it is borrowed");
err.span_label(binding_span, format!("value borrowed, by `{}`, here", name));
for (span, name) in conflicts_move {
err.span_label(span, format!("value moved into `{}` here", name));
}
err.emit();
sess.emit_err(MovedWhileBorrowed { span: pat.span, occurences });
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,17 @@ error: cannot borrow value as mutable because it is also borrowed as immutable
LL | ref foo @ [.., ref mut bar] => (),
| -------^^^^^^^^-----------^
| | |
| | mutable borrow, by `bar`, occurs here
| immutable borrow, by `foo`, occurs here
| | value is mutably borrowed by `bar` here
| value is borrowed by `foo` here

error: cannot borrow value as mutable because it is also borrowed as immutable
--> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:120:9
|
LL | ref foo @ Some(box ref mut s) => (),
| -------^^^^^^^^^^^^---------^
| | |
| | mutable borrow, by `s`, occurs here
| immutable borrow, by `foo`, occurs here
| | value is mutably borrowed by `s` here
| value is borrowed by `foo` here

error[E0382]: borrow of moved value: `x`
--> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:18:5
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ error: cannot move out of value because it is borrowed
LL | Some(ref _y @ _z) => {}
| ------^^^--
| | |
| | value moved into `_z` here
| value borrowed, by `_y`, here
| | value is moved into `_z` here
| value is borrowed by `_y` here

error: borrow of moved value
--> $DIR/bind-by-move-neither-can-live-while-the-other-survives-1.rs:19:14
Expand All @@ -28,8 +28,8 @@ error: cannot move out of value because it is borrowed
LL | Some(ref mut _y @ _z) => {}
| ----------^^^--
| | |
| | value moved into `_z` here
| value borrowed, by `_y`, here
| | value is moved into `_z` here
| value is mutably borrowed by `_y` here

error: borrow of moved value
--> $DIR/bind-by-move-neither-can-live-while-the-other-survives-1.rs:33:14
Expand Down
32 changes: 16 additions & 16 deletions tests/ui/pattern/bindings-after-at/borrowck-pat-at-and-box.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -4,71 +4,71 @@ error: cannot move out of value because it is borrowed
LL | let ref a @ box b = Box::new(NC);
| -----^^^^^^^-
| | |
| | value moved into `b` here
| value borrowed, by `a`, here
| | value is moved into `b` here
| value is borrowed by `a` here

error: cannot borrow value as mutable because it is also borrowed as immutable
--> $DIR/borrowck-pat-at-and-box.rs:34:9
|
LL | let ref a @ box ref mut b = Box::new(nc());
| -----^^^^^^^---------
| | |
| | mutable borrow, by `b`, occurs here
| immutable borrow, by `a`, occurs here
| | value is mutably borrowed by `b` here
| value is borrowed by `a` here

error: cannot borrow value as mutable because it is also borrowed as immutable
--> $DIR/borrowck-pat-at-and-box.rs:36:9
|
LL | let ref a @ box ref mut b = Box::new(NC);
| -----^^^^^^^---------
| | |
| | mutable borrow, by `b`, occurs here
| immutable borrow, by `a`, occurs here
| | value is mutably borrowed by `b` here
| value is borrowed by `a` here

error: cannot borrow value as mutable because it is also borrowed as immutable
--> $DIR/borrowck-pat-at-and-box.rs:38:9
|
LL | let ref a @ box ref mut b = Box::new(NC);
| -----^^^^^^^---------
| | |
| | mutable borrow, by `b`, occurs here
| immutable borrow, by `a`, occurs here
| | value is mutably borrowed by `b` here
| value is borrowed by `a` here

error: cannot borrow value as mutable because it is also borrowed as immutable
--> $DIR/borrowck-pat-at-and-box.rs:42:9
|
LL | let ref a @ box ref mut b = Box::new(NC);
| -----^^^^^^^---------
| | |
| | mutable borrow, by `b`, occurs here
| immutable borrow, by `a`, occurs here
| | value is mutably borrowed by `b` here
| value is borrowed by `a` here

error: cannot borrow value as immutable because it is also borrowed as mutable
--> $DIR/borrowck-pat-at-and-box.rs:48:9
|
LL | let ref mut a @ box ref b = Box::new(NC);
| ---------^^^^^^^-----
| | |
| | immutable borrow, by `b`, occurs here
| mutable borrow, by `a`, occurs here
| | value is borrowed by `b` here
| value is mutably borrowed by `a` here

error: cannot borrow value as immutable because it is also borrowed as mutable
--> $DIR/borrowck-pat-at-and-box.rs:62:9
|
LL | ref mut a @ box ref b => {
| ---------^^^^^^^-----
| | |
| | immutable borrow, by `b`, occurs here
| mutable borrow, by `a`, occurs here
| | value is borrowed by `b` here
| value is mutably borrowed by `a` here

error: cannot borrow value as immutable because it is also borrowed as mutable
--> $DIR/borrowck-pat-at-and-box.rs:54:11
|
LL | fn f5(ref mut a @ box ref b: Box<NC>) {
| ---------^^^^^^^-----
| | |
| | immutable borrow, by `b`, occurs here
| mutable borrow, by `a`, occurs here
| | value is borrowed by `b` here
| value is mutably borrowed by `a` here

error[E0382]: borrow of moved value
--> $DIR/borrowck-pat-at-and-box.rs:31:9
Expand Down
Loading