Don't suggest split_at_mut
when the multiple borrows have the same index
This commit is contained in:
parent
9f9f0aa534
commit
ad6ae61246
5 changed files with 60 additions and 5 deletions
|
@ -2136,10 +2136,14 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||||
}
|
}
|
||||||
let Some(index1) = self.find_expr(span) else { return };
|
let Some(index1) = self.find_expr(span) else { return };
|
||||||
let hir::Node::Expr(parent) = tcx.parent_hir_node(index1.hir_id) else { return };
|
let hir::Node::Expr(parent) = tcx.parent_hir_node(index1.hir_id) else { return };
|
||||||
let hir::ExprKind::Index(..) = parent.kind else { return };
|
let hir::ExprKind::Index(_, idx1, _) = parent.kind else { return };
|
||||||
let Some(index2) = self.find_expr(issued_span) else { return };
|
let Some(index2) = self.find_expr(issued_span) else { return };
|
||||||
let hir::Node::Expr(parent) = tcx.parent_hir_node(index2.hir_id) else { return };
|
let hir::Node::Expr(parent) = tcx.parent_hir_node(index2.hir_id) else { return };
|
||||||
let hir::ExprKind::Index(..) = parent.kind else { return };
|
let hir::ExprKind::Index(_, idx2, _) = parent.kind else { return };
|
||||||
|
if idx1.equals(idx2) {
|
||||||
|
// `let a = &mut foo[0]` and `let b = &mut foo[0]`? Don't mention `split_at_mut`
|
||||||
|
return;
|
||||||
|
}
|
||||||
err.help("use `.split_at_mut(position)` to obtain two mutable non-overlapping sub-slices");
|
err.help("use `.split_at_mut(position)` to obtain two mutable non-overlapping sub-slices");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1811,6 +1811,41 @@ impl Expr<'_> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Whether this and the `other` expression are the same for purposes of an indexing operation.
|
||||||
|
///
|
||||||
|
/// This is only used for diagnostics to see if we have things like `foo[i]` where `foo` is
|
||||||
|
/// borrowed multiple times with `i`.
|
||||||
|
pub fn equals(&self, other: &Expr<'_>) -> bool {
|
||||||
|
match (self.kind, other.kind) {
|
||||||
|
(ExprKind::Lit(lit1), ExprKind::Lit(lit2)) => lit1.node == lit2.node,
|
||||||
|
(
|
||||||
|
ExprKind::Path(QPath::LangItem(item1, _)),
|
||||||
|
ExprKind::Path(QPath::LangItem(item2, _)),
|
||||||
|
) => item1 == item2,
|
||||||
|
(
|
||||||
|
ExprKind::Path(QPath::Resolved(None, path1)),
|
||||||
|
ExprKind::Path(QPath::Resolved(None, path2)),
|
||||||
|
) => path1.res == path2.res,
|
||||||
|
(
|
||||||
|
ExprKind::Struct(QPath::LangItem(LangItem::RangeTo, _), [val1], None),
|
||||||
|
ExprKind::Struct(QPath::LangItem(LangItem::RangeTo, _), [val2], None),
|
||||||
|
)
|
||||||
|
| (
|
||||||
|
ExprKind::Struct(QPath::LangItem(LangItem::RangeToInclusive, _), [val1], None),
|
||||||
|
ExprKind::Struct(QPath::LangItem(LangItem::RangeToInclusive, _), [val2], None),
|
||||||
|
)
|
||||||
|
| (
|
||||||
|
ExprKind::Struct(QPath::LangItem(LangItem::RangeFrom, _), [val1], None),
|
||||||
|
ExprKind::Struct(QPath::LangItem(LangItem::RangeFrom, _), [val2], None),
|
||||||
|
) => val1.expr.equals(val2.expr),
|
||||||
|
(
|
||||||
|
ExprKind::Struct(QPath::LangItem(LangItem::Range, _), [val1, val3], None),
|
||||||
|
ExprKind::Struct(QPath::LangItem(LangItem::Range, _), [val2, val4], None),
|
||||||
|
) => val1.expr.equals(val2.expr) && val3.expr.equals(val4.expr),
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn method_ident(&self) -> Option<Ident> {
|
pub fn method_ident(&self) -> Option<Ident> {
|
||||||
match self.kind {
|
match self.kind {
|
||||||
ExprKind::MethodCall(receiver_method, ..) => Some(receiver_method.ident),
|
ExprKind::MethodCall(receiver_method, ..) => Some(receiver_method.ident),
|
||||||
|
|
|
@ -9,8 +9,6 @@ LL | p[0] = 5;
|
||||||
LL |
|
LL |
|
||||||
LL | println!("{}", *q);
|
LL | println!("{}", *q);
|
||||||
| -- immutable borrow later used here
|
| -- immutable borrow later used here
|
||||||
|
|
|
||||||
= help: use `.split_at_mut(position)` to obtain two mutable non-overlapping sub-slices
|
|
||||||
|
|
||||||
error[E0502]: cannot borrow `p` as mutable because it is also borrowed as immutable
|
error[E0502]: cannot borrow `p` as mutable because it is also borrowed as immutable
|
||||||
--> $DIR/borrowck-assign-comp-idx.rs:27:9
|
--> $DIR/borrowck-assign-comp-idx.rs:27:9
|
||||||
|
|
|
@ -48,6 +48,14 @@ fn bat() {
|
||||||
println!("{:?} {:?}", a, b);
|
println!("{:?} {:?}", a, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn ang() {
|
||||||
|
let mut foo = [1,2,3,4];
|
||||||
|
let a = &mut foo[0..];
|
||||||
|
let b = &foo[0..]; //~ ERROR cannot borrow `foo` as immutable because it is also borrowed as mutable
|
||||||
|
a[0] = 5;
|
||||||
|
println!("{:?} {:?}", a, b);
|
||||||
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
foo();
|
foo();
|
||||||
bar();
|
bar();
|
||||||
|
|
|
@ -75,7 +75,17 @@ LL | *a = 5;
|
||||||
= help: consider using `.split_at_mut(position)` or similar method to obtain two mutable non-overlapping sub-slices
|
= help: consider using `.split_at_mut(position)` or similar method to obtain two mutable non-overlapping sub-slices
|
||||||
= help: consider using `.swap(index_1, index_2)` to swap elements at the specified indices
|
= help: consider using `.swap(index_1, index_2)` to swap elements at the specified indices
|
||||||
|
|
||||||
error: aborting due to 6 previous errors
|
error[E0502]: cannot borrow `foo` as immutable because it is also borrowed as mutable
|
||||||
|
--> $DIR/suggest-split-at-mut.rs:54:14
|
||||||
|
|
|
||||||
|
LL | let a = &mut foo[0..];
|
||||||
|
| --- mutable borrow occurs here
|
||||||
|
LL | let b = &foo[0..];
|
||||||
|
| ^^^ immutable borrow occurs here
|
||||||
|
LL | a[0] = 5;
|
||||||
|
| ---- mutable borrow later used here
|
||||||
|
|
||||||
|
error: aborting due to 7 previous errors
|
||||||
|
|
||||||
Some errors have detailed explanations: E0499, E0502.
|
Some errors have detailed explanations: E0499, E0502.
|
||||||
For more information about an error, try `rustc --explain E0499`.
|
For more information about an error, try `rustc --explain E0499`.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue