Fix wrong suggestion with MANUAL_SWAP and slices
This commit is contained in:
@@ -16,6 +16,7 @@ license = "MPL-2.0"
|
|||||||
keywords = ["clippy", "lint", "plugin"]
|
keywords = ["clippy", "lint", "plugin"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
matches = "0.1.2"
|
||||||
regex-syntax = "0.3.0"
|
regex-syntax = "0.3.0"
|
||||||
semver = "0.2.1"
|
semver = "0.2.1"
|
||||||
toml = "0.1"
|
toml = "0.1"
|
||||||
|
|||||||
@@ -42,6 +42,9 @@ extern crate rustc_plugin;
|
|||||||
extern crate rustc_const_eval;
|
extern crate rustc_const_eval;
|
||||||
extern crate rustc_const_math;
|
extern crate rustc_const_math;
|
||||||
|
|
||||||
|
#[macro_use]
|
||||||
|
extern crate matches as matches_macro;
|
||||||
|
|
||||||
macro_rules! declare_restriction_lint {
|
macro_rules! declare_restriction_lint {
|
||||||
{ pub $name:tt, $description:tt } => {
|
{ pub $name:tt, $description:tt } => {
|
||||||
declare_lint! { pub $name, Allow, $description }
|
declare_lint! { pub $name, Allow, $description }
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
use rustc::lint::*;
|
|
||||||
use rustc::hir::*;
|
use rustc::hir::*;
|
||||||
|
use rustc::lint::*;
|
||||||
|
use rustc::ty;
|
||||||
use syntax::codemap::mk_sp;
|
use syntax::codemap::mk_sp;
|
||||||
use utils::{differing_macro_contexts, snippet_opt, span_lint_and_then, SpanlessEq};
|
use utils::{differing_macro_contexts, match_type, paths, snippet, snippet_opt, span_lint_and_then, walk_ptrs_ty, SpanlessEq};
|
||||||
|
|
||||||
/// **What it does:** This lints manual swapping.
|
/// **What it does:** This lints manual swapping.
|
||||||
///
|
///
|
||||||
@@ -79,10 +80,40 @@ fn check_manual_swap(cx: &LateContext, block: &Block) {
|
|||||||
SpanlessEq::new(cx).ignore_fn().eq_expr(tmp_init, lhs1),
|
SpanlessEq::new(cx).ignore_fn().eq_expr(tmp_init, lhs1),
|
||||||
SpanlessEq::new(cx).ignore_fn().eq_expr(rhs1, lhs2)
|
SpanlessEq::new(cx).ignore_fn().eq_expr(rhs1, lhs2)
|
||||||
], {
|
], {
|
||||||
let (what, lhs, rhs) = if let (Some(first), Some(second)) = (snippet_opt(cx, lhs1.span), snippet_opt(cx, rhs1.span)) {
|
fn check_for_slice<'a>(cx: &LateContext, lhs1: &'a Expr, lhs2: &'a Expr) -> Option<(&'a Expr, &'a Expr, &'a Expr)> {
|
||||||
(format!(" `{}` and `{}`", first, second), first, second)
|
if let ExprIndex(ref lhs1, ref idx1) = lhs1.node {
|
||||||
|
if let ExprIndex(ref lhs2, ref idx2) = lhs2.node {
|
||||||
|
if SpanlessEq::new(cx).ignore_fn().eq_expr(lhs1, lhs2) {
|
||||||
|
let ty = walk_ptrs_ty(cx.tcx.expr_ty(lhs1));
|
||||||
|
|
||||||
|
if matches!(ty.sty, ty::TySlice(_)) ||
|
||||||
|
matches!(ty.sty, ty::TyArray(_, _)) ||
|
||||||
|
match_type(cx, ty, &paths::VEC) ||
|
||||||
|
match_type(cx, ty, &paths::VEC_DEQUE) {
|
||||||
|
return Some((lhs1, idx1, idx2));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
let (replace, what, sugg) = if let Some((slice, idx1, idx2)) = check_for_slice(cx, lhs1, lhs2) {
|
||||||
|
if let Some(slice) = snippet_opt(cx, slice.span) {
|
||||||
|
(false,
|
||||||
|
format!(" elements of `{}`", slice),
|
||||||
|
format!("{}.swap({}, {})",slice, snippet(cx, idx1.span, ".."), snippet(cx, idx2.span, "..")))
|
||||||
} else {
|
} else {
|
||||||
("".to_owned(), "".to_owned(), "".to_owned())
|
(false, "".to_owned(), "".to_owned())
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if let (Some(first), Some(second)) = (snippet_opt(cx, lhs1.span), snippet_opt(cx, rhs1.span)) {
|
||||||
|
(true, format!(" `{}` and `{}`", first, second),
|
||||||
|
format!("std::mem::swap(&mut {}, &mut {})", first, second))
|
||||||
|
} else {
|
||||||
|
(true, "".to_owned(), "".to_owned())
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let span = mk_sp(w[0].span.lo, second.span.hi);
|
let span = mk_sp(w[0].span.lo, second.span.hi);
|
||||||
@@ -92,11 +123,13 @@ fn check_manual_swap(cx: &LateContext, block: &Block) {
|
|||||||
span,
|
span,
|
||||||
&format!("this looks like you are swapping{} manually", what),
|
&format!("this looks like you are swapping{} manually", what),
|
||||||
|db| {
|
|db| {
|
||||||
if !what.is_empty() {
|
if !sugg.is_empty() {
|
||||||
db.span_suggestion(span, "try",
|
db.span_suggestion(span, "try", sugg);
|
||||||
format!("std::mem::swap(&mut {}, &mut {})", lhs, rhs));
|
|
||||||
|
if replace {
|
||||||
db.note("or maybe you should use `std::mem::replace`?");
|
db.note("or maybe you should use `std::mem::replace`?");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,11 +2,51 @@
|
|||||||
#![plugin(clippy)]
|
#![plugin(clippy)]
|
||||||
|
|
||||||
#![deny(clippy)]
|
#![deny(clippy)]
|
||||||
#![allow(unused_assignments)]
|
#![allow(blacklisted_name, unused_assignments)]
|
||||||
|
|
||||||
struct Foo(u32);
|
struct Foo(u32);
|
||||||
|
|
||||||
|
fn array() {
|
||||||
|
let mut foo = [1, 2];
|
||||||
|
let temp = foo[0];
|
||||||
|
foo[0] = foo[1];
|
||||||
|
foo[1] = temp;
|
||||||
|
//~^^^ ERROR this looks like you are swapping elements of `foo` manually
|
||||||
|
//~| HELP try
|
||||||
|
//~| SUGGESTION foo.swap(0, 1);
|
||||||
|
|
||||||
|
foo.swap(0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn slice() {
|
||||||
|
let foo = &mut [1, 2];
|
||||||
|
let temp = foo[0];
|
||||||
|
foo[0] = foo[1];
|
||||||
|
foo[1] = temp;
|
||||||
|
//~^^^ ERROR this looks like you are swapping elements of `foo` manually
|
||||||
|
//~| HELP try
|
||||||
|
//~| SUGGESTION foo.swap(0, 1);
|
||||||
|
|
||||||
|
foo.swap(0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn vec() {
|
||||||
|
let mut foo = vec![1, 2];
|
||||||
|
let temp = foo[0];
|
||||||
|
foo[0] = foo[1];
|
||||||
|
foo[1] = temp;
|
||||||
|
//~^^^ ERROR this looks like you are swapping elements of `foo` manually
|
||||||
|
//~| HELP try
|
||||||
|
//~| SUGGESTION foo.swap(0, 1);
|
||||||
|
|
||||||
|
foo.swap(0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
array();
|
||||||
|
slice();
|
||||||
|
vec();
|
||||||
|
|
||||||
let mut a = 42;
|
let mut a = 42;
|
||||||
let mut b = 1337;
|
let mut b = 1337;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user