Suggest .swap() instead of mem::swap() in more cases
This commit is contained in:
parent
e927184629
commit
f9faf16181
@ -1,3 +1,5 @@
|
|||||||
|
// ignore-tidy-filelength
|
||||||
|
|
||||||
use either::Either;
|
use either::Either;
|
||||||
use rustc_data_structures::captures::Captures;
|
use rustc_data_structures::captures::Captures;
|
||||||
use rustc_data_structures::fx::FxIndexSet;
|
use rustc_data_structures::fx::FxIndexSet;
|
||||||
@ -24,6 +26,7 @@
|
|||||||
use rustc_span::symbol::{kw, sym, Ident};
|
use rustc_span::symbol::{kw, sym, Ident};
|
||||||
use rustc_span::{BytePos, Span, Symbol};
|
use rustc_span::{BytePos, Span, Symbol};
|
||||||
use rustc_trait_selection::infer::InferCtxtExt;
|
use rustc_trait_selection::infer::InferCtxtExt;
|
||||||
|
use rustc_trait_selection::traits::error_reporting::FindExprBySpan;
|
||||||
use rustc_trait_selection::traits::ObligationCtxt;
|
use rustc_trait_selection::traits::ObligationCtxt;
|
||||||
use std::iter;
|
use std::iter;
|
||||||
|
|
||||||
@ -1295,14 +1298,96 @@ fn suggest_slice_method_if_applicable(
|
|||||||
place: Place<'tcx>,
|
place: Place<'tcx>,
|
||||||
borrowed_place: Place<'tcx>,
|
borrowed_place: Place<'tcx>,
|
||||||
) {
|
) {
|
||||||
if let ([ProjectionElem::Index(_)], [ProjectionElem::Index(_)]) =
|
let tcx = self.infcx.tcx;
|
||||||
(&place.projection[..], &borrowed_place.projection[..])
|
let hir = tcx.hir();
|
||||||
|
|
||||||
|
if let ([ProjectionElem::Index(index1)], [ProjectionElem::Index(index2)])
|
||||||
|
| (
|
||||||
|
[ProjectionElem::Deref, ProjectionElem::Index(index1)],
|
||||||
|
[ProjectionElem::Deref, ProjectionElem::Index(index2)],
|
||||||
|
) = (&place.projection[..], &borrowed_place.projection[..])
|
||||||
{
|
{
|
||||||
err.help(
|
let mut note_default_suggestion = || {
|
||||||
"consider using `.split_at_mut(position)` or similar method to obtain \
|
err.help(
|
||||||
two mutable non-overlapping sub-slices",
|
"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");
|
||||||
|
};
|
||||||
|
|
||||||
|
let Some(body_id) = tcx.hir_node(self.mir_hir_id()).body_id() else {
|
||||||
|
note_default_suggestion();
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut expr_finder =
|
||||||
|
FindExprBySpan::new(self.body.local_decls[*index1].source_info.span);
|
||||||
|
expr_finder.visit_expr(hir.body(body_id).value);
|
||||||
|
let Some(index1) = expr_finder.result else {
|
||||||
|
note_default_suggestion();
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
expr_finder = FindExprBySpan::new(self.body.local_decls[*index2].source_info.span);
|
||||||
|
expr_finder.visit_expr(hir.body(body_id).value);
|
||||||
|
let Some(index2) = expr_finder.result else {
|
||||||
|
note_default_suggestion();
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
let sm = tcx.sess.source_map();
|
||||||
|
|
||||||
|
let Ok(index1_str) = sm.span_to_snippet(index1.span) else {
|
||||||
|
note_default_suggestion();
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
let Ok(index2_str) = sm.span_to_snippet(index2.span) else {
|
||||||
|
note_default_suggestion();
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
let Some(object) = hir.parent_id_iter(index1.hir_id).find_map(|id| {
|
||||||
|
if let hir::Node::Expr(expr) = tcx.hir_node(id)
|
||||||
|
&& let hir::ExprKind::Index(obj, ..) = expr.kind
|
||||||
|
{
|
||||||
|
Some(obj)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}) else {
|
||||||
|
note_default_suggestion();
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
let Ok(obj_str) = sm.span_to_snippet(object.span) else {
|
||||||
|
note_default_suggestion();
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
let Some(swap_call) = hir.parent_id_iter(object.hir_id).find_map(|id| {
|
||||||
|
if let hir::Node::Expr(call) = tcx.hir_node(id)
|
||||||
|
&& let hir::ExprKind::Call(callee, ..) = call.kind
|
||||||
|
&& let hir::ExprKind::Path(qpath) = callee.kind
|
||||||
|
&& let hir::QPath::Resolved(None, res) = qpath
|
||||||
|
&& let hir::def::Res::Def(_, did) = res.res
|
||||||
|
&& tcx.is_diagnostic_item(sym::mem_swap, did)
|
||||||
|
{
|
||||||
|
Some(call)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}) else {
|
||||||
|
note_default_suggestion();
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
err.span_suggestion(
|
||||||
|
swap_call.span,
|
||||||
|
"use `.swap()` to swap elements at the specified indices instead",
|
||||||
|
format!("{obj_str}.swap({index1_str}, {index2_str})"),
|
||||||
|
Applicability::MachineApplicable,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
9
tests/ui/suggestions/suggest-slice-swap.fixed
Normal file
9
tests/ui/suggestions/suggest-slice-swap.fixed
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
// run-rustfix
|
||||||
|
#![allow(dead_code)]
|
||||||
|
|
||||||
|
fn swap(arr: &mut [u32; 2]) {
|
||||||
|
arr.swap(1, 0);
|
||||||
|
//~^ ERROR cannot borrow `arr[_]` as mutable more than once at a time
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
9
tests/ui/suggestions/suggest-slice-swap.rs
Normal file
9
tests/ui/suggestions/suggest-slice-swap.rs
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
// run-rustfix
|
||||||
|
#![allow(dead_code)]
|
||||||
|
|
||||||
|
fn swap(arr: &mut [u32; 2]) {
|
||||||
|
std::mem::swap(&mut arr[0], &mut arr[1]);
|
||||||
|
//~^ ERROR cannot borrow `arr[_]` as mutable more than once at a time
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
17
tests/ui/suggestions/suggest-slice-swap.stderr
Normal file
17
tests/ui/suggestions/suggest-slice-swap.stderr
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
error[E0499]: cannot borrow `arr[_]` as mutable more than once at a time
|
||||||
|
--> $DIR/suggest-slice-swap.rs:5:33
|
||||||
|
|
|
||||||
|
LL | std::mem::swap(&mut arr[0], &mut arr[1]);
|
||||||
|
| -------------- ----------- ^^^^^^^^^^^ second mutable borrow occurs here
|
||||||
|
| | |
|
||||||
|
| | first mutable borrow occurs here
|
||||||
|
| first borrow later used by call
|
||||||
|
|
|
||||||
|
help: use `.swap()` to swap elements at the specified indices instead
|
||||||
|
|
|
||||||
|
LL | arr.swap(1, 0);
|
||||||
|
| ~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
error: aborting due to 1 previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0499`.
|
Loading…
Reference in New Issue
Block a user