From 94fb2b58a30f46cd462bea088ea523ed8f4d9580 Mon Sep 17 00:00:00 2001 From: Takayuki Maeda Date: Sat, 13 Mar 2021 17:17:10 +0900 Subject: [PATCH 01/19] move chars_cmp and chars_next_cmp to its own modules --- clippy_lints/src/methods/chars_cmp.rs | 54 ++++++++++++++++++++ clippy_lints/src/methods/chars_next_cmp.rs | 8 +++ clippy_lints/src/methods/mod.rs | 59 +++------------------- 3 files changed, 68 insertions(+), 53 deletions(-) create mode 100644 clippy_lints/src/methods/chars_cmp.rs create mode 100644 clippy_lints/src/methods/chars_next_cmp.rs diff --git a/clippy_lints/src/methods/chars_cmp.rs b/clippy_lints/src/methods/chars_cmp.rs new file mode 100644 index 000000000000..f9af06d200c8 --- /dev/null +++ b/clippy_lints/src/methods/chars_cmp.rs @@ -0,0 +1,54 @@ +use crate::utils::{method_chain_args, single_segment_path}; +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::source::snippet_with_applicability; +use if_chain::if_chain; +use rustc_errors::Applicability; +use rustc_hir as hir; +use rustc_lint::LateContext; +use rustc_lint::Lint; +use rustc_middle::ty; +use rustc_span::sym; + +/// Wrapper fn for `CHARS_NEXT_CMP` and `CHARS_LAST_CMP` lints. +pub(super) fn check( + cx: &LateContext<'_>, + info: &crate::methods::BinaryExprInfo<'_>, + chain_methods: &[&str], + lint: &'static Lint, + suggest: &str, +) -> bool { + if_chain! { + if let Some(args) = method_chain_args(info.chain, chain_methods); + if let hir::ExprKind::Call(ref fun, ref arg_char) = info.other.kind; + if arg_char.len() == 1; + if let hir::ExprKind::Path(ref qpath) = fun.kind; + if let Some(segment) = single_segment_path(qpath); + if segment.ident.name == sym::Some; + then { + let mut applicability = Applicability::MachineApplicable; + let self_ty = cx.typeck_results().expr_ty_adjusted(&args[0][0]).peel_refs(); + + if *self_ty.kind() != ty::Str { + return false; + } + + span_lint_and_sugg( + cx, + lint, + info.expr.span, + &format!("you should use the `{}` method", suggest), + "like this", + format!("{}{}.{}({})", + if info.eq { "" } else { "!" }, + snippet_with_applicability(cx, args[0][0].span, "..", &mut applicability), + suggest, + snippet_with_applicability(cx, arg_char[0].span, "..", &mut applicability)), + applicability, + ); + + return true; + } + } + + false +} diff --git a/clippy_lints/src/methods/chars_next_cmp.rs b/clippy_lints/src/methods/chars_next_cmp.rs new file mode 100644 index 000000000000..a6701d8830e7 --- /dev/null +++ b/clippy_lints/src/methods/chars_next_cmp.rs @@ -0,0 +1,8 @@ +use rustc_lint::LateContext; + +use super::CHARS_NEXT_CMP; + +/// Checks for the `CHARS_NEXT_CMP` lint. +pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, info: &crate::methods::BinaryExprInfo<'_>) -> bool { + crate::methods::chars_cmp::check(cx, info, &["chars", "next"], CHARS_NEXT_CMP, "starts_with") +} diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index cbfb350ebb13..d288c51907e2 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -1,5 +1,7 @@ mod bind_instead_of_map; mod bytes_nth; +mod chars_cmp; +mod chars_next_cmp; mod clone_on_copy; mod clone_on_ref_ptr; mod expect_fun_call; @@ -2024,7 +2026,7 @@ struct BinaryExprInfo<'a> { /// Checks for the `CHARS_NEXT_CMP` and `CHARS_LAST_CMP` lints. fn lint_binary_expr_with_method_call(cx: &LateContext<'_>, info: &mut BinaryExprInfo<'_>) { macro_rules! lint_with_both_lhs_and_rhs { - ($func:ident, $cx:expr, $info:ident) => { + ($func:expr, $cx:expr, $info:ident) => { if !$func($cx, $info) { ::std::mem::swap(&mut $info.chain, &mut $info.other); if $func($cx, $info) { @@ -2034,67 +2036,18 @@ fn lint_binary_expr_with_method_call(cx: &LateContext<'_>, info: &mut BinaryExpr }; } - lint_with_both_lhs_and_rhs!(lint_chars_next_cmp, cx, info); + lint_with_both_lhs_and_rhs!(chars_next_cmp::check, cx, info); lint_with_both_lhs_and_rhs!(lint_chars_last_cmp, cx, info); lint_with_both_lhs_and_rhs!(lint_chars_next_cmp_with_unwrap, cx, info); lint_with_both_lhs_and_rhs!(lint_chars_last_cmp_with_unwrap, cx, info); } -/// Wrapper fn for `CHARS_NEXT_CMP` and `CHARS_LAST_CMP` lints. -fn lint_chars_cmp( - cx: &LateContext<'_>, - info: &BinaryExprInfo<'_>, - chain_methods: &[&str], - lint: &'static Lint, - suggest: &str, -) -> bool { - if_chain! { - if let Some(args) = method_chain_args(info.chain, chain_methods); - if let hir::ExprKind::Call(ref fun, ref arg_char) = info.other.kind; - if arg_char.len() == 1; - if let hir::ExprKind::Path(ref qpath) = fun.kind; - if let Some(segment) = single_segment_path(qpath); - if segment.ident.name == sym::Some; - then { - let mut applicability = Applicability::MachineApplicable; - let self_ty = cx.typeck_results().expr_ty_adjusted(&args[0][0]).peel_refs(); - - if *self_ty.kind() != ty::Str { - return false; - } - - span_lint_and_sugg( - cx, - lint, - info.expr.span, - &format!("you should use the `{}` method", suggest), - "like this", - format!("{}{}.{}({})", - if info.eq { "" } else { "!" }, - snippet_with_applicability(cx, args[0][0].span, "..", &mut applicability), - suggest, - snippet_with_applicability(cx, arg_char[0].span, "..", &mut applicability)), - applicability, - ); - - return true; - } - } - - false -} - -/// Checks for the `CHARS_NEXT_CMP` lint. -fn lint_chars_next_cmp<'tcx>(cx: &LateContext<'tcx>, info: &BinaryExprInfo<'_>) -> bool { - lint_chars_cmp(cx, info, &["chars", "next"], CHARS_NEXT_CMP, "starts_with") -} - /// Checks for the `CHARS_LAST_CMP` lint. fn lint_chars_last_cmp<'tcx>(cx: &LateContext<'tcx>, info: &BinaryExprInfo<'_>) -> bool { - if lint_chars_cmp(cx, info, &["chars", "last"], CHARS_LAST_CMP, "ends_with") { + if chars_cmp::check(cx, info, &["chars", "last"], CHARS_LAST_CMP, "ends_with") { true } else { - lint_chars_cmp(cx, info, &["chars", "next_back"], CHARS_LAST_CMP, "ends_with") + chars_cmp::check(cx, info, &["chars", "next_back"], CHARS_LAST_CMP, "ends_with") } } From 058d8c878ab51ccd65e636456207b3d63ee532b5 Mon Sep 17 00:00:00 2001 From: Takayuki Maeda Date: Sat, 13 Mar 2021 17:28:22 +0900 Subject: [PATCH 02/19] move chars_cmp_with_unwrap, chars_last_cmp and chars_next_cmp_with_unwrap to their own modules --- .../src/methods/chars_cmp_with_unwrap.rs | 44 +++++++++++++ clippy_lints/src/methods/chars_last_cmp.rs | 13 ++++ .../src/methods/chars_next_cmp_with_unwrap.rs | 8 +++ clippy_lints/src/methods/mod.rs | 64 +++---------------- 4 files changed, 74 insertions(+), 55 deletions(-) create mode 100644 clippy_lints/src/methods/chars_cmp_with_unwrap.rs create mode 100644 clippy_lints/src/methods/chars_last_cmp.rs create mode 100644 clippy_lints/src/methods/chars_next_cmp_with_unwrap.rs diff --git a/clippy_lints/src/methods/chars_cmp_with_unwrap.rs b/clippy_lints/src/methods/chars_cmp_with_unwrap.rs new file mode 100644 index 000000000000..3ba59171f771 --- /dev/null +++ b/clippy_lints/src/methods/chars_cmp_with_unwrap.rs @@ -0,0 +1,44 @@ +use crate::utils::method_chain_args; +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::source::snippet_with_applicability; +use if_chain::if_chain; +use rustc_ast::ast; +use rustc_errors::Applicability; +use rustc_hir as hir; +use rustc_lint::LateContext; +use rustc_lint::Lint; + +/// Wrapper fn for `CHARS_NEXT_CMP` and `CHARS_LAST_CMP` lints with `unwrap()`. +pub(super) fn check<'tcx>( + cx: &LateContext<'tcx>, + info: &crate::methods::BinaryExprInfo<'_>, + chain_methods: &[&str], + lint: &'static Lint, + suggest: &str, +) -> bool { + if_chain! { + if let Some(args) = method_chain_args(info.chain, chain_methods); + if let hir::ExprKind::Lit(ref lit) = info.other.kind; + if let ast::LitKind::Char(c) = lit.node; + then { + let mut applicability = Applicability::MachineApplicable; + span_lint_and_sugg( + cx, + lint, + info.expr.span, + &format!("you should use the `{}` method", suggest), + "like this", + format!("{}{}.{}('{}')", + if info.eq { "" } else { "!" }, + snippet_with_applicability(cx, args[0][0].span, "..", &mut applicability), + suggest, + c), + applicability, + ); + + true + } else { + false + } + } +} diff --git a/clippy_lints/src/methods/chars_last_cmp.rs b/clippy_lints/src/methods/chars_last_cmp.rs new file mode 100644 index 000000000000..07bbc5ca1bf4 --- /dev/null +++ b/clippy_lints/src/methods/chars_last_cmp.rs @@ -0,0 +1,13 @@ +use crate::methods::chars_cmp; +use rustc_lint::LateContext; + +use super::CHARS_LAST_CMP; + +/// Checks for the `CHARS_LAST_CMP` lint. +pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, info: &crate::methods::BinaryExprInfo<'_>) -> bool { + if chars_cmp::check(cx, info, &["chars", "last"], CHARS_LAST_CMP, "ends_with") { + true + } else { + chars_cmp::check(cx, info, &["chars", "next_back"], CHARS_LAST_CMP, "ends_with") + } +} diff --git a/clippy_lints/src/methods/chars_next_cmp_with_unwrap.rs b/clippy_lints/src/methods/chars_next_cmp_with_unwrap.rs new file mode 100644 index 000000000000..28ede28e9358 --- /dev/null +++ b/clippy_lints/src/methods/chars_next_cmp_with_unwrap.rs @@ -0,0 +1,8 @@ +use rustc_lint::LateContext; + +use super::CHARS_NEXT_CMP; + +/// Checks for the `CHARS_NEXT_CMP` lint with `unwrap()`. +pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, info: &crate::methods::BinaryExprInfo<'_>) -> bool { + crate::methods::chars_cmp_with_unwrap::check(cx, info, &["chars", "next", "unwrap"], CHARS_NEXT_CMP, "starts_with") +} diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index d288c51907e2..b4c32e45da97 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -1,7 +1,10 @@ mod bind_instead_of_map; mod bytes_nth; mod chars_cmp; +mod chars_cmp_with_unwrap; +mod chars_last_cmp; mod chars_next_cmp; +mod chars_next_cmp_with_unwrap; mod clone_on_copy; mod clone_on_ref_ptr; mod expect_fun_call; @@ -54,7 +57,7 @@ mod wrong_self_convention; mod zst_offset; use bind_instead_of_map::BindInsteadOfMap; -use clippy_utils::diagnostics::{span_lint, span_lint_and_help, span_lint_and_sugg}; +use clippy_utils::diagnostics::{span_lint, span_lint_and_help}; use clippy_utils::source::snippet_with_applicability; use clippy_utils::ty::{contains_ty, implements_trait, is_copy, is_type_diagnostic_item}; use clippy_utils::{ @@ -66,7 +69,7 @@ use rustc_ast::ast; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_hir::{TraitItem, TraitItemKind}; -use rustc_lint::{LateContext, LateLintPass, Lint, LintContext}; +use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::lint::in_external_macro; use rustc_middle::ty::{self, TraitRef, Ty, TyS}; use rustc_semver::RustcVersion; @@ -2037,66 +2040,17 @@ fn lint_binary_expr_with_method_call(cx: &LateContext<'_>, info: &mut BinaryExpr } lint_with_both_lhs_and_rhs!(chars_next_cmp::check, cx, info); - lint_with_both_lhs_and_rhs!(lint_chars_last_cmp, cx, info); - lint_with_both_lhs_and_rhs!(lint_chars_next_cmp_with_unwrap, cx, info); + lint_with_both_lhs_and_rhs!(chars_last_cmp::check, cx, info); + lint_with_both_lhs_and_rhs!(chars_next_cmp_with_unwrap::check, cx, info); lint_with_both_lhs_and_rhs!(lint_chars_last_cmp_with_unwrap, cx, info); } -/// Checks for the `CHARS_LAST_CMP` lint. -fn lint_chars_last_cmp<'tcx>(cx: &LateContext<'tcx>, info: &BinaryExprInfo<'_>) -> bool { - if chars_cmp::check(cx, info, &["chars", "last"], CHARS_LAST_CMP, "ends_with") { - true - } else { - chars_cmp::check(cx, info, &["chars", "next_back"], CHARS_LAST_CMP, "ends_with") - } -} - -/// Wrapper fn for `CHARS_NEXT_CMP` and `CHARS_LAST_CMP` lints with `unwrap()`. -fn lint_chars_cmp_with_unwrap<'tcx>( - cx: &LateContext<'tcx>, - info: &BinaryExprInfo<'_>, - chain_methods: &[&str], - lint: &'static Lint, - suggest: &str, -) -> bool { - if_chain! { - if let Some(args) = method_chain_args(info.chain, chain_methods); - if let hir::ExprKind::Lit(ref lit) = info.other.kind; - if let ast::LitKind::Char(c) = lit.node; - then { - let mut applicability = Applicability::MachineApplicable; - span_lint_and_sugg( - cx, - lint, - info.expr.span, - &format!("you should use the `{}` method", suggest), - "like this", - format!("{}{}.{}('{}')", - if info.eq { "" } else { "!" }, - snippet_with_applicability(cx, args[0][0].span, "..", &mut applicability), - suggest, - c), - applicability, - ); - - true - } else { - false - } - } -} - -/// Checks for the `CHARS_NEXT_CMP` lint with `unwrap()`. -fn lint_chars_next_cmp_with_unwrap<'tcx>(cx: &LateContext<'tcx>, info: &BinaryExprInfo<'_>) -> bool { - lint_chars_cmp_with_unwrap(cx, info, &["chars", "next", "unwrap"], CHARS_NEXT_CMP, "starts_with") -} - /// Checks for the `CHARS_LAST_CMP` lint with `unwrap()`. fn lint_chars_last_cmp_with_unwrap<'tcx>(cx: &LateContext<'tcx>, info: &BinaryExprInfo<'_>) -> bool { - if lint_chars_cmp_with_unwrap(cx, info, &["chars", "last", "unwrap"], CHARS_LAST_CMP, "ends_with") { + if chars_cmp_with_unwrap::check(cx, info, &["chars", "last", "unwrap"], CHARS_LAST_CMP, "ends_with") { true } else { - lint_chars_cmp_with_unwrap(cx, info, &["chars", "next_back", "unwrap"], CHARS_LAST_CMP, "ends_with") + chars_cmp_with_unwrap::check(cx, info, &["chars", "next_back", "unwrap"], CHARS_LAST_CMP, "ends_with") } } From c07c046b317bf9a75b04e97c37396436351d80ab Mon Sep 17 00:00:00 2001 From: Takayuki Maeda Date: Sat, 13 Mar 2021 17:36:04 +0900 Subject: [PATCH 03/19] refactor string_extend_chars: return when obj type is not string --- .../src/methods/string_extend_chars.rs | 57 ++++++++++--------- 1 file changed, 29 insertions(+), 28 deletions(-) diff --git a/clippy_lints/src/methods/string_extend_chars.rs b/clippy_lints/src/methods/string_extend_chars.rs index 52b26a36fe3b..5c688ac56211 100644 --- a/clippy_lints/src/methods/string_extend_chars.rs +++ b/clippy_lints/src/methods/string_extend_chars.rs @@ -12,34 +12,35 @@ use super::STRING_EXTEND_CHARS; pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, args: &[hir::Expr<'_>]) { let obj_ty = cx.typeck_results().expr_ty(&args[0]).peel_refs(); - if is_type_diagnostic_item(cx, obj_ty, sym::string_type) { - let arg = &args[1]; - if let Some(arglists) = method_chain_args(arg, &["chars"]) { - let target = &arglists[0][0]; - let self_ty = cx.typeck_results().expr_ty(target).peel_refs(); - let ref_str = if *self_ty.kind() == ty::Str { - "" - } else if is_type_diagnostic_item(cx, self_ty, sym::string_type) { - "&" - } else { - return; - }; + if !is_type_diagnostic_item(cx, obj_ty, sym::string_type) { + return; + } + let arg = &args[1]; + if let Some(arglists) = method_chain_args(arg, &["chars"]) { + let target = &arglists[0][0]; + let self_ty = cx.typeck_results().expr_ty(target).peel_refs(); + let ref_str = if *self_ty.kind() == ty::Str { + "" + } else if is_type_diagnostic_item(cx, self_ty, sym::string_type) { + "&" + } else { + return; + }; - let mut applicability = Applicability::MachineApplicable; - span_lint_and_sugg( - cx, - STRING_EXTEND_CHARS, - expr.span, - "calling `.extend(_.chars())`", - "try this", - format!( - "{}.push_str({}{})", - snippet_with_applicability(cx, args[0].span, "..", &mut applicability), - ref_str, - snippet_with_applicability(cx, target.span, "..", &mut applicability) - ), - applicability, - ); - } + let mut applicability = Applicability::MachineApplicable; + span_lint_and_sugg( + cx, + STRING_EXTEND_CHARS, + expr.span, + "calling `.extend(_.chars())`", + "try this", + format!( + "{}.push_str({}{})", + snippet_with_applicability(cx, args[0].span, "..", &mut applicability), + ref_str, + snippet_with_applicability(cx, target.span, "..", &mut applicability) + ), + applicability, + ); } } From e578a536c703cd799b74f261e345121bd889be45 Mon Sep 17 00:00:00 2001 From: Takayuki Maeda Date: Sat, 13 Mar 2021 18:13:31 +0900 Subject: [PATCH 04/19] move derefs_to_slice to methods/utils.rs --- clippy_lints/src/methods/utils.rs | 46 +++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 clippy_lints/src/methods/utils.rs diff --git a/clippy_lints/src/methods/utils.rs b/clippy_lints/src/methods/utils.rs new file mode 100644 index 000000000000..3596aaa089b3 --- /dev/null +++ b/clippy_lints/src/methods/utils.rs @@ -0,0 +1,46 @@ +use crate::utils::is_type_diagnostic_item; +use rustc_hir as hir; +use rustc_lint::LateContext; +use rustc_middle::ty; +use rustc_middle::ty::Ty; +use rustc_span::symbol::sym; + +pub fn derefs_to_slice<'tcx>( + cx: &LateContext<'tcx>, + expr: &'tcx hir::Expr<'tcx>, + ty: Ty<'tcx>, +) -> Option<&'tcx hir::Expr<'tcx>> { + fn may_slice<'a>(cx: &LateContext<'a>, ty: Ty<'a>) -> bool { + match ty.kind() { + ty::Slice(_) => true, + ty::Adt(def, _) if def.is_box() => may_slice(cx, ty.boxed_ty()), + ty::Adt(..) => is_type_diagnostic_item(cx, ty, sym::vec_type), + ty::Array(_, size) => size + .try_eval_usize(cx.tcx, cx.param_env) + .map_or(false, |size| size < 32), + ty::Ref(_, inner, _) => may_slice(cx, inner), + _ => false, + } + } + + if let hir::ExprKind::MethodCall(ref path, _, ref args, _) = expr.kind { + if path.ident.name == sym::iter && may_slice(cx, cx.typeck_results().expr_ty(&args[0])) { + Some(&args[0]) + } else { + None + } + } else { + match ty.kind() { + ty::Slice(_) => Some(expr), + ty::Adt(def, _) if def.is_box() && may_slice(cx, ty.boxed_ty()) => Some(expr), + ty::Ref(_, inner, _) => { + if may_slice(cx, inner) { + Some(expr) + } else { + None + } + }, + _ => None, + } + } +} From 1bec8b606540813cc068c5b564aa2dbd3d212823 Mon Sep 17 00:00:00 2001 From: Takayuki Maeda Date: Sat, 13 Mar 2021 18:16:38 +0900 Subject: [PATCH 05/19] use derefs_to_slice in methods/utils.rs --- clippy_lints/src/methods/get_unwrap.rs | 2 +- .../src/methods/iter_cloned_collect.rs | 2 +- clippy_lints/src/methods/iter_count.rs | 2 +- clippy_lints/src/methods/iter_next_slice.rs | 2 +- clippy_lints/src/methods/iter_nth.rs | 2 +- clippy_lints/src/methods/mod.rs | 42 +------------------ 6 files changed, 6 insertions(+), 46 deletions(-) diff --git a/clippy_lints/src/methods/get_unwrap.rs b/clippy_lints/src/methods/get_unwrap.rs index b122a0a0b896..b3a9743c6147 100644 --- a/clippy_lints/src/methods/get_unwrap.rs +++ b/clippy_lints/src/methods/get_unwrap.rs @@ -1,4 +1,4 @@ -use crate::methods::derefs_to_slice; +use super::utils::derefs_to_slice; use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::snippet_with_applicability; use clippy_utils::ty::{is_type_diagnostic_item, match_type}; diff --git a/clippy_lints/src/methods/iter_cloned_collect.rs b/clippy_lints/src/methods/iter_cloned_collect.rs index cd575c9cb021..848f47e39f6b 100644 --- a/clippy_lints/src/methods/iter_cloned_collect.rs +++ b/clippy_lints/src/methods/iter_cloned_collect.rs @@ -1,4 +1,4 @@ -use crate::methods::derefs_to_slice; +use crate::methods::utils::derefs_to_slice; use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::ty::is_type_diagnostic_item; use if_chain::if_chain; diff --git a/clippy_lints/src/methods/iter_count.rs b/clippy_lints/src/methods/iter_count.rs index fd3d53816a12..e394a8fe8195 100644 --- a/clippy_lints/src/methods/iter_count.rs +++ b/clippy_lints/src/methods/iter_count.rs @@ -1,4 +1,4 @@ -use crate::methods::derefs_to_slice; +use super::utils::derefs_to_slice; use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::paths; use clippy_utils::source::snippet_with_applicability; diff --git a/clippy_lints/src/methods/iter_next_slice.rs b/clippy_lints/src/methods/iter_next_slice.rs index feebf8b82096..869b2cdd1a66 100644 --- a/clippy_lints/src/methods/iter_next_slice.rs +++ b/clippy_lints/src/methods/iter_next_slice.rs @@ -1,4 +1,4 @@ -use crate::methods::derefs_to_slice; +use crate::methods::utils::derefs_to_slice; use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::snippet_with_applicability; use clippy_utils::ty::is_type_diagnostic_item; diff --git a/clippy_lints/src/methods/iter_nth.rs b/clippy_lints/src/methods/iter_nth.rs index 2619793e1e2d..2e7220025f81 100644 --- a/clippy_lints/src/methods/iter_nth.rs +++ b/clippy_lints/src/methods/iter_nth.rs @@ -1,7 +1,7 @@ -use crate::methods::derefs_to_slice; use crate::methods::iter_nth_zero; use clippy_utils::diagnostics::span_lint_and_help; use clippy_utils::ty::is_type_diagnostic_item; +use crate::methods::utils::derefs_to_slice; use rustc_hir as hir; use rustc_lint::LateContext; use rustc_span::symbol::sym; diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index b4c32e45da97..e16ab4bc20bb 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -53,6 +53,7 @@ mod unnecessary_fold; mod unnecessary_lazy_eval; mod unwrap_used; mod useless_asref; +mod utils; mod wrong_self_convention; mod zst_offset; @@ -1976,47 +1977,6 @@ impl<'tcx> LateLintPass<'tcx> for Methods { extract_msrv_attr!(LateContext); } - -fn derefs_to_slice<'tcx>( - cx: &LateContext<'tcx>, - expr: &'tcx hir::Expr<'tcx>, - ty: Ty<'tcx>, -) -> Option<&'tcx hir::Expr<'tcx>> { - fn may_slice<'a>(cx: &LateContext<'a>, ty: Ty<'a>) -> bool { - match ty.kind() { - ty::Slice(_) => true, - ty::Adt(def, _) if def.is_box() => may_slice(cx, ty.boxed_ty()), - ty::Adt(..) => is_type_diagnostic_item(cx, ty, sym::vec_type), - ty::Array(_, size) => size - .try_eval_usize(cx.tcx, cx.param_env) - .map_or(false, |size| size < 32), - ty::Ref(_, inner, _) => may_slice(cx, inner), - _ => false, - } - } - - if let hir::ExprKind::MethodCall(ref path, _, ref args, _) = expr.kind { - if path.ident.name == sym::iter && may_slice(cx, cx.typeck_results().expr_ty(&args[0])) { - Some(&args[0]) - } else { - None - } - } else { - match ty.kind() { - ty::Slice(_) => Some(expr), - ty::Adt(def, _) if def.is_box() && may_slice(cx, ty.boxed_ty()) => Some(expr), - ty::Ref(_, inner, _) => { - if may_slice(cx, inner) { - Some(expr) - } else { - None - } - }, - _ => None, - } - } -} - /// Used for `lint_binary_expr_with_method_call`. #[derive(Copy, Clone)] struct BinaryExprInfo<'a> { From f0a101d81dc25fae998d0670348d928f1789439b Mon Sep 17 00:00:00 2001 From: Takayuki Maeda Date: Sun, 14 Mar 2021 01:05:37 +0900 Subject: [PATCH 06/19] remove a needless variable --- clippy_lints/src/methods/iter_skip_next.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/clippy_lints/src/methods/iter_skip_next.rs b/clippy_lints/src/methods/iter_skip_next.rs index ea01860b456c..b1d398876d3a 100644 --- a/clippy_lints/src/methods/iter_skip_next.rs +++ b/clippy_lints/src/methods/iter_skip_next.rs @@ -12,14 +12,13 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, skip_args: &[hir // lint if caller of skip is an Iterator if is_trait_method(cx, expr, sym::Iterator) { if let [caller, n] = skip_args { - let hint = format!(".nth({})", snippet(cx, n.span, "..")); span_lint_and_sugg( cx, ITER_SKIP_NEXT, expr.span.trim_start(caller.span).unwrap(), "called `skip(..).next()` on an iterator", "use `nth` instead", - hint, + format!(".nth({})", snippet(cx, n.span, "..")), Applicability::MachineApplicable, ); } From 0c81311bf0093e991c0b5ca8b69096a5c5cd161c Mon Sep 17 00:00:00 2001 From: Takayuki Maeda Date: Sun, 14 Mar 2021 01:18:04 +0900 Subject: [PATCH 07/19] extract a condition into a function. --- clippy_lints/src/methods/iter_next_slice.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/clippy_lints/src/methods/iter_next_slice.rs b/clippy_lints/src/methods/iter_next_slice.rs index 869b2cdd1a66..2155159bf7cb 100644 --- a/clippy_lints/src/methods/iter_next_slice.rs +++ b/clippy_lints/src/methods/iter_next_slice.rs @@ -47,12 +47,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>, ite ); } } - } else if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(caller_expr), sym::vec_type) - || matches!( - &cx.typeck_results().expr_ty(caller_expr).peel_refs().kind(), - ty::Array(_, _) - ) - { + } else if is_vec_or_array(cx, caller_expr) { // caller is a Vec or an Array let mut applicability = Applicability::MachineApplicable; span_lint_and_sugg( @@ -69,3 +64,8 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>, ite ); } } + +fn is_vec_or_array<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) -> bool { + is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(expr), sym::vec_type) + || matches!(&cx.typeck_results().expr_ty(expr).peel_refs().kind(), ty::Array(_, _)) +} From b6597eec0b3fcd9598fd4f90daa2d4d781e0aabc Mon Sep 17 00:00:00 2001 From: Takayuki Maeda Date: Sun, 14 Mar 2021 01:37:33 +0900 Subject: [PATCH 08/19] remove unused arguments --- clippy_lints/src/methods/filter_flat_map.rs | 7 +------ clippy_lints/src/methods/filter_map_flat_map.rs | 7 +------ clippy_lints/src/methods/filter_map_map.rs | 7 +------ clippy_lints/src/methods/mod.rs | 6 +++--- 4 files changed, 6 insertions(+), 21 deletions(-) diff --git a/clippy_lints/src/methods/filter_flat_map.rs b/clippy_lints/src/methods/filter_flat_map.rs index 2f3a3c55ab59..1588eec88824 100644 --- a/clippy_lints/src/methods/filter_flat_map.rs +++ b/clippy_lints/src/methods/filter_flat_map.rs @@ -7,12 +7,7 @@ use rustc_span::sym; use super::FILTER_MAP; /// lint use of `filter().flat_map()` for `Iterators` -pub(super) fn check<'tcx>( - cx: &LateContext<'tcx>, - expr: &'tcx hir::Expr<'_>, - _filter_args: &'tcx [hir::Expr<'_>], - _map_args: &'tcx [hir::Expr<'_>], -) { +pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) { // lint if caller of `.filter().flat_map()` is an Iterator if is_trait_method(cx, expr, sym::Iterator) { let msg = "called `filter(..).flat_map(..)` on an `Iterator`"; diff --git a/clippy_lints/src/methods/filter_map_flat_map.rs b/clippy_lints/src/methods/filter_map_flat_map.rs index b1a4dc98eb8d..741b1e7e3612 100644 --- a/clippy_lints/src/methods/filter_map_flat_map.rs +++ b/clippy_lints/src/methods/filter_map_flat_map.rs @@ -7,12 +7,7 @@ use rustc_span::sym; use super::FILTER_MAP; /// lint use of `filter_map().flat_map()` for `Iterators` -pub(super) fn check<'tcx>( - cx: &LateContext<'tcx>, - expr: &'tcx hir::Expr<'_>, - _filter_args: &'tcx [hir::Expr<'_>], - _map_args: &'tcx [hir::Expr<'_>], -) { +pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) { // lint if caller of `.filter_map().flat_map()` is an Iterator if is_trait_method(cx, expr, sym::Iterator) { let msg = "called `filter_map(..).flat_map(..)` on an `Iterator`"; diff --git a/clippy_lints/src/methods/filter_map_map.rs b/clippy_lints/src/methods/filter_map_map.rs index 0b0a8b1dd3b9..713bbf258370 100644 --- a/clippy_lints/src/methods/filter_map_map.rs +++ b/clippy_lints/src/methods/filter_map_map.rs @@ -7,12 +7,7 @@ use rustc_span::sym; use super::FILTER_MAP; /// lint use of `filter_map().map()` for `Iterators` -pub(super) fn check<'tcx>( - cx: &LateContext<'tcx>, - expr: &'tcx hir::Expr<'_>, - _filter_args: &'tcx [hir::Expr<'_>], - _map_args: &'tcx [hir::Expr<'_>], -) { +pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) { // lint if caller of `.filter_map().map()` is an Iterator if is_trait_method(cx, expr, sym::Iterator) { let msg = "called `filter_map(..).map(..)` on an `Iterator`"; diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index e16ab4bc20bb..044348a2c345 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -1715,11 +1715,11 @@ impl<'tcx> LateLintPass<'tcx> for Methods { ["next", "skip_while"] => skip_while_next::check(cx, expr, arg_lists[1]), ["next", "iter"] => iter_next_slice::check(cx, expr, arg_lists[1]), ["map", "filter"] => filter_map::check(cx, expr, false), - ["map", "filter_map"] => filter_map_map::check(cx, expr, arg_lists[1], arg_lists[0]), + ["map", "filter_map"] => filter_map_map::check(cx, expr), ["next", "filter_map"] => filter_map_next::check(cx, expr, arg_lists[1], self.msrv.as_ref()), ["map", "find"] => filter_map::check(cx, expr, true), - ["flat_map", "filter"] => filter_flat_map::check(cx, expr, arg_lists[1], arg_lists[0]), - ["flat_map", "filter_map"] => filter_map_flat_map::check(cx, expr, arg_lists[1], arg_lists[0]), + ["flat_map", "filter"] => filter_flat_map::check(cx, expr), + ["flat_map", "filter_map"] => filter_map_flat_map::check(cx, expr), ["flat_map", ..] => flat_map_identity::check(cx, expr, arg_lists[0], method_spans[0]), ["flatten", "map"] => map_flatten::check(cx, expr, arg_lists[1]), ["is_some", "find"] => search_is_some::check(cx, expr, "find", arg_lists[1], arg_lists[0], method_spans[1]), From f0f787192006a7b0a508b90a03dcfdd37b3c31d2 Mon Sep 17 00:00:00 2001 From: Takayuki Maeda Date: Wed, 17 Mar 2021 11:15:25 +0900 Subject: [PATCH 09/19] fmt --- clippy_lints/src/methods/iter_nth.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/methods/iter_nth.rs b/clippy_lints/src/methods/iter_nth.rs index 2e7220025f81..bf1575660d11 100644 --- a/clippy_lints/src/methods/iter_nth.rs +++ b/clippy_lints/src/methods/iter_nth.rs @@ -1,7 +1,7 @@ use crate::methods::iter_nth_zero; +use crate::methods::utils::derefs_to_slice; use clippy_utils::diagnostics::span_lint_and_help; use clippy_utils::ty::is_type_diagnostic_item; -use crate::methods::utils::derefs_to_slice; use rustc_hir as hir; use rustc_lint::LateContext; use rustc_span::symbol::sym; From 48430849465ae94255e78f895197b09c2ce3b03e Mon Sep 17 00:00:00 2001 From: Takayuki Maeda Date: Wed, 17 Mar 2021 11:18:02 +0900 Subject: [PATCH 10/19] use clippy_utils::ty::is_type_diagnostic_item --- clippy_lints/src/methods/utils.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/methods/utils.rs b/clippy_lints/src/methods/utils.rs index 3596aaa089b3..4d801148cbc7 100644 --- a/clippy_lints/src/methods/utils.rs +++ b/clippy_lints/src/methods/utils.rs @@ -1,4 +1,4 @@ -use crate::utils::is_type_diagnostic_item; +use clippy_utils::ty::is_type_diagnostic_item; use rustc_hir as hir; use rustc_lint::LateContext; use rustc_middle::ty; From 3d9b45df0fa6bc04d864aa4a67fdb631b9bf0a99 Mon Sep 17 00:00:00 2001 From: Takayuki Maeda Date: Wed, 17 Mar 2021 12:33:09 +0900 Subject: [PATCH 11/19] move single_char_add_str to its own module --- clippy_lints/src/methods/single_char_add_str.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 clippy_lints/src/methods/single_char_add_str.rs diff --git a/clippy_lints/src/methods/single_char_add_str.rs b/clippy_lints/src/methods/single_char_add_str.rs new file mode 100644 index 000000000000..3df88e5b69c9 --- /dev/null +++ b/clippy_lints/src/methods/single_char_add_str.rs @@ -0,0 +1,15 @@ +use crate::methods::{single_char_insert_string, single_char_push_string}; +use crate::utils::match_def_path; +use crate::utils::paths; +use rustc_hir as hir; +use rustc_lint::LateContext; + +pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, args: &[hir::Expr<'_>]) { + if let Some(fn_def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id) { + if match_def_path(cx, fn_def_id, &paths::PUSH_STR) { + single_char_push_string::check(cx, expr, args); + } else if match_def_path(cx, fn_def_id, &paths::INSERT_STR) { + single_char_insert_string::check(cx, expr, args); + } + } +} From 62490c41af1a5dab806e45dd2bc0b8d56a3c3c23 Mon Sep 17 00:00:00 2001 From: Takayuki Maeda Date: Wed, 17 Mar 2021 12:34:37 +0900 Subject: [PATCH 12/19] extract conditions into modules --- clippy_lints/src/methods/clone_on_copy.rs | 10 ++++++++-- clippy_lints/src/methods/clone_on_ref_ptr.rs | 8 ++++++-- .../src/methods/inefficient_to_string.rs | 11 ++++++---- clippy_lints/src/methods/mod.rs | 20 +++++-------------- 4 files changed, 26 insertions(+), 23 deletions(-) diff --git a/clippy_lints/src/methods/clone_on_copy.rs b/clippy_lints/src/methods/clone_on_copy.rs index 949152cf789a..edb6649b87b4 100644 --- a/clippy_lints/src/methods/clone_on_copy.rs +++ b/clippy_lints/src/methods/clone_on_copy.rs @@ -4,14 +4,20 @@ use clippy_utils::ty::is_copy; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_lint::LateContext; -use rustc_middle::ty::{self, Ty}; +use rustc_middle::ty; +use rustc_span::symbol::{sym, Symbol}; use std::iter; use super::CLONE_DOUBLE_REF; use super::CLONE_ON_COPY; /// Checks for the `CLONE_ON_COPY` lint. -pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, arg: &hir::Expr<'_>, arg_ty: Ty<'_>) { +pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, method_name: Symbol, args: &[hir::Expr<'_>]) { + if !(args.len() == 1 && method_name == sym::clone) { + return; + } + let arg = &args[0]; + let arg_ty = cx.typeck_results().expr_ty_adjusted(&args[0]); let ty = cx.typeck_results().expr_ty(expr); if let ty::Ref(_, inner, _) = arg_ty.kind() { if let ty::Ref(_, innermost, _) = inner.kind() { diff --git a/clippy_lints/src/methods/clone_on_ref_ptr.rs b/clippy_lints/src/methods/clone_on_ref_ptr.rs index 03c949d5c31a..6417bc813047 100644 --- a/clippy_lints/src/methods/clone_on_ref_ptr.rs +++ b/clippy_lints/src/methods/clone_on_ref_ptr.rs @@ -6,11 +6,15 @@ use rustc_errors::Applicability; use rustc_hir as hir; use rustc_lint::LateContext; use rustc_middle::ty; -use rustc_span::symbol::sym; +use rustc_span::symbol::{sym, Symbol}; use super::CLONE_ON_REF_PTR; -pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, arg: &hir::Expr<'_>) { +pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, method_name: Symbol, args: &[hir::Expr<'_>]) { + if !(args.len() == 1 && method_name == sym::clone) { + return; + } + let arg = &args[0]; let obj_ty = cx.typeck_results().expr_ty(arg).peel_refs(); if let ty::Adt(_, subst) = obj_ty.kind() { diff --git a/clippy_lints/src/methods/inefficient_to_string.rs b/clippy_lints/src/methods/inefficient_to_string.rs index d10a540c24ea..950ec62c9fe4 100644 --- a/clippy_lints/src/methods/inefficient_to_string.rs +++ b/clippy_lints/src/methods/inefficient_to_string.rs @@ -1,4 +1,3 @@ -use super::INEFFICIENT_TO_STRING; use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::source::snippet_with_applicability; use clippy_utils::ty::{is_type_diagnostic_item, walk_ptrs_ty_depth}; @@ -8,14 +7,18 @@ use rustc_errors::Applicability; use rustc_hir as hir; use rustc_lint::LateContext; use rustc_middle::ty::{self, Ty}; -use rustc_span::sym; +use rustc_span::symbol::{sym, Symbol}; + +use super::INEFFICIENT_TO_STRING; /// Checks for the `INEFFICIENT_TO_STRING` lint -pub fn check<'tcx>(cx: &LateContext<'tcx>, expr: &hir::Expr<'_>, arg: &hir::Expr<'_>, arg_ty: Ty<'tcx>) { +pub fn check<'tcx>(cx: &LateContext<'tcx>, expr: &hir::Expr<'_>, method_name: Symbol, args: &[hir::Expr<'_>]) { if_chain! { + if args.len() == 1 && method_name == sym!(to_string); if let Some(to_string_meth_did) = cx.typeck_results().type_dependent_def_id(expr.hir_id); if match_def_path(cx, to_string_meth_did, &paths::TO_STRING_METHOD); if let Some(substs) = cx.typeck_results().node_substs_opt(expr.hir_id); + let arg_ty = cx.typeck_results().expr_ty_adjusted(&args[0]); let self_ty = substs.type_at(0); let (deref_self_ty, deref_count) = walk_ptrs_ty_depth(self_ty); if deref_count >= 1; @@ -32,7 +35,7 @@ pub fn check<'tcx>(cx: &LateContext<'tcx>, expr: &hir::Expr<'_>, arg: &hir::Expr self_ty, deref_self_ty )); let mut applicability = Applicability::MachineApplicable; - let arg_snippet = snippet_with_applicability(cx, arg.span, "..", &mut applicability); + let arg_snippet = snippet_with_applicability(cx, args[0].span, "..", &mut applicability); diag.span_suggestion( expr.span, "try dereferencing the receiver", diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 044348a2c345..bbf7f1d312b9 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -41,6 +41,7 @@ mod option_map_or_none; mod option_map_unwrap_or; mod or_fun_call; mod search_is_some; +mod single_char_add_str; mod single_char_insert_string; mod single_char_pattern; mod single_char_push_string; @@ -1785,23 +1786,12 @@ impl<'tcx> LateLintPass<'tcx> for Methods { hir::ExprKind::MethodCall(ref method_call, ref method_span, ref args, _) => { or_fun_call::check(cx, expr, *method_span, &method_call.ident.as_str(), args); expect_fun_call::check(cx, expr, *method_span, &method_call.ident.as_str(), args); + clone_on_copy::check(cx, expr, method_call.ident.name, args); + clone_on_ref_ptr::check(cx, expr, method_call.ident.name, args); let self_ty = cx.typeck_results().expr_ty_adjusted(&args[0]); - if args.len() == 1 && method_call.ident.name == sym::clone { - clone_on_copy::check(cx, expr, &args[0], self_ty); - clone_on_ref_ptr::check(cx, expr, &args[0]); - } - if args.len() == 1 && method_call.ident.name == sym!(to_string) { - inefficient_to_string::check(cx, expr, &args[0], self_ty); - } - - if let Some(fn_def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id) { - if match_def_path(cx, fn_def_id, &paths::PUSH_STR) { - single_char_push_string::check(cx, expr, args); - } else if match_def_path(cx, fn_def_id, &paths::INSERT_STR) { - single_char_insert_string::check(cx, expr, args); - } - } + inefficient_to_string::check(cx, expr, method_call.ident.name, args); + single_char_add_str::check(cx, expr, args); match self_ty.kind() { ty::Ref(_, ty, _) if *ty.kind() == ty::Str => { From d38076995258ed7f1ebd270f2f32b1744c688e71 Mon Sep 17 00:00:00 2001 From: Takayuki Maeda Date: Wed, 17 Mar 2021 13:22:25 +0900 Subject: [PATCH 13/19] extract conditions for `from_iter_instead_of_collect` into its own module --- clippy_lints/src/methods/chars_cmp.rs | 2 +- clippy_lints/src/methods/chars_cmp_with_unwrap.rs | 2 +- .../src/methods/from_iter_instead_of_collect.rs | 12 +++++++----- clippy_lints/src/methods/mod.rs | 13 ++++--------- clippy_lints/src/methods/single_char_add_str.rs | 3 +-- 5 files changed, 14 insertions(+), 18 deletions(-) diff --git a/clippy_lints/src/methods/chars_cmp.rs b/clippy_lints/src/methods/chars_cmp.rs index f9af06d200c8..c668fe52781d 100644 --- a/clippy_lints/src/methods/chars_cmp.rs +++ b/clippy_lints/src/methods/chars_cmp.rs @@ -1,6 +1,6 @@ -use crate::utils::{method_chain_args, single_segment_path}; use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::snippet_with_applicability; +use clippy_utils::{method_chain_args, single_segment_path}; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir as hir; diff --git a/clippy_lints/src/methods/chars_cmp_with_unwrap.rs b/clippy_lints/src/methods/chars_cmp_with_unwrap.rs index 3ba59171f771..4275857757fe 100644 --- a/clippy_lints/src/methods/chars_cmp_with_unwrap.rs +++ b/clippy_lints/src/methods/chars_cmp_with_unwrap.rs @@ -1,5 +1,5 @@ -use crate::utils::method_chain_args; use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::method_chain_args; use clippy_utils::source::snippet_with_applicability; use if_chain::if_chain; use rustc_ast::ast; diff --git a/clippy_lints/src/methods/from_iter_instead_of_collect.rs b/clippy_lints/src/methods/from_iter_instead_of_collect.rs index 2095a60e44b2..15cf56743138 100644 --- a/clippy_lints/src/methods/from_iter_instead_of_collect.rs +++ b/clippy_lints/src/methods/from_iter_instead_of_collect.rs @@ -1,20 +1,22 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::ty::implements_trait; -use clippy_utils::{get_trait_def_id, paths, sugg}; +use clippy_utils::{get_trait_def_id, match_qpath, paths, sugg}; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir as hir; +use rustc_hir::ExprKind; use rustc_lint::{LateContext, LintContext}; use rustc_middle::ty::Ty; use rustc_span::sym; use super::FROM_ITER_INSTEAD_OF_COLLECT; -pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, args: &[hir::Expr<'_>]) { - let ty = cx.typeck_results().expr_ty(expr); - let arg_ty = cx.typeck_results().expr_ty(&args[0]); - +pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, args: &[hir::Expr<'_>], func_kind: &ExprKind<'_>) { if_chain! { + if let hir::ExprKind::Path(path) = func_kind; + if match_qpath(path, &["from_iter"]); + let ty = cx.typeck_results().expr_ty(expr); + let arg_ty = cx.typeck_results().expr_ty(&args[0]); if let Some(from_iter_id) = get_trait_def_id(cx, &paths::FROM_ITERATOR); if let Some(iter_id) = cx.tcx.get_diagnostic_item(sym::Iterator); diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index bbf7f1d312b9..808b64d9493f 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -63,8 +63,8 @@ use clippy_utils::diagnostics::{span_lint, span_lint_and_help}; use clippy_utils::source::snippet_with_applicability; use clippy_utils::ty::{contains_ty, implements_trait, is_copy, is_type_diagnostic_item}; use clippy_utils::{ - contains_return, get_trait_def_id, in_macro, iter_input_pats, match_def_path, match_qpath, method_calls, - method_chain_args, paths, return_ty, single_segment_path, SpanlessEq, + contains_return, get_trait_def_id, in_macro, iter_input_pats, match_qpath, method_calls, paths, return_ty, + SpanlessEq, }; use if_chain::if_chain; use rustc_ast::ast; @@ -1777,22 +1777,17 @@ impl<'tcx> LateLintPass<'tcx> for Methods { match expr.kind { hir::ExprKind::Call(ref func, ref args) => { - if let hir::ExprKind::Path(path) = &func.kind { - if match_qpath(path, &["from_iter"]) { - from_iter_instead_of_collect::check(cx, expr, args); - } - } + from_iter_instead_of_collect::check(cx, expr, args, &func.kind); }, hir::ExprKind::MethodCall(ref method_call, ref method_span, ref args, _) => { or_fun_call::check(cx, expr, *method_span, &method_call.ident.as_str(), args); expect_fun_call::check(cx, expr, *method_span, &method_call.ident.as_str(), args); clone_on_copy::check(cx, expr, method_call.ident.name, args); clone_on_ref_ptr::check(cx, expr, method_call.ident.name, args); - - let self_ty = cx.typeck_results().expr_ty_adjusted(&args[0]); inefficient_to_string::check(cx, expr, method_call.ident.name, args); single_char_add_str::check(cx, expr, args); + let self_ty = cx.typeck_results().expr_ty_adjusted(&args[0]); match self_ty.kind() { ty::Ref(_, ty, _) if *ty.kind() == ty::Str => { for &(method, pos) in &PATTERN_METHODS { diff --git a/clippy_lints/src/methods/single_char_add_str.rs b/clippy_lints/src/methods/single_char_add_str.rs index 3df88e5b69c9..9a5fabcf7cd5 100644 --- a/clippy_lints/src/methods/single_char_add_str.rs +++ b/clippy_lints/src/methods/single_char_add_str.rs @@ -1,6 +1,5 @@ use crate::methods::{single_char_insert_string, single_char_push_string}; -use crate::utils::match_def_path; -use crate::utils::paths; +use clippy_utils::{match_def_path, paths}; use rustc_hir as hir; use rustc_lint::LateContext; From 7a7fcc0eda1d62f44ec374bad3d14226888238ad Mon Sep 17 00:00:00 2001 From: Takayuki Maeda Date: Wed, 17 Mar 2021 14:14:06 +0900 Subject: [PATCH 14/19] extract condition for into_iter_on_ref to its own module --- clippy_lints/src/methods/into_iter_on_ref.rs | 47 ++++++++++++-------- clippy_lints/src/methods/mod.rs | 7 +-- 2 files changed, 31 insertions(+), 23 deletions(-) diff --git a/clippy_lints/src/methods/into_iter_on_ref.rs b/clippy_lints/src/methods/into_iter_on_ref.rs index cfe749cf3611..5d59fa86c9e8 100644 --- a/clippy_lints/src/methods/into_iter_on_ref.rs +++ b/clippy_lints/src/methods/into_iter_on_ref.rs @@ -1,32 +1,43 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::ty::has_iter_method; use clippy_utils::{match_trait_method, paths}; +use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_lint::LateContext; use rustc_middle::ty::{self, Ty}; use rustc_span::source_map::Span; -use rustc_span::symbol::Symbol; +use rustc_span::symbol::{sym, Symbol}; use super::INTO_ITER_ON_REF; -pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, self_ref_ty: Ty<'_>, method_span: Span) { - if !match_trait_method(cx, expr, &paths::INTO_ITERATOR) { - return; - } - if let Some((kind, method_name)) = ty_has_iter_method(cx, self_ref_ty) { - span_lint_and_sugg( - cx, - INTO_ITER_ON_REF, - method_span, - &format!( - "this `.into_iter()` call is equivalent to `.{}()` and will not consume the `{}`", - method_name, kind, - ), - "call directly", - method_name.to_string(), - Applicability::MachineApplicable, - ); +pub(super) fn check( + cx: &LateContext<'_>, + expr: &hir::Expr<'_>, + method_span: Span, + method_name: Symbol, + args: &[hir::Expr<'_>], +) { + let self_ty = cx.typeck_results().expr_ty_adjusted(&args[0]); + if_chain! { + if let ty::Ref(..) = self_ty.kind(); + if method_name == sym::into_iter; + if match_trait_method(cx, expr, &paths::INTO_ITERATOR); + if let Some((kind, method_name)) = ty_has_iter_method(cx, self_ty); + then { + span_lint_and_sugg( + cx, + INTO_ITER_ON_REF, + method_span, + &format!( + "this `.into_iter()` call is equivalent to `.{}()` and will not consume the `{}`", + method_name, kind, + ), + "call directly", + method_name.to_string(), + Applicability::MachineApplicable, + ); + } } } diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 808b64d9493f..e8cefbd74221 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -1786,9 +1786,9 @@ impl<'tcx> LateLintPass<'tcx> for Methods { clone_on_ref_ptr::check(cx, expr, method_call.ident.name, args); inefficient_to_string::check(cx, expr, method_call.ident.name, args); single_char_add_str::check(cx, expr, args); + into_iter_on_ref::check(cx, expr, *method_span, method_call.ident.name, args); - let self_ty = cx.typeck_results().expr_ty_adjusted(&args[0]); - match self_ty.kind() { + match cx.typeck_results().expr_ty_adjusted(&args[0]).kind() { ty::Ref(_, ty, _) if *ty.kind() == ty::Str => { for &(method, pos) in &PATTERN_METHODS { if method_call.ident.name.as_str() == method && args.len() > pos { @@ -1796,9 +1796,6 @@ impl<'tcx> LateLintPass<'tcx> for Methods { } } }, - ty::Ref(..) if method_call.ident.name == sym::into_iter => { - into_iter_on_ref::check(cx, expr, self_ty, *method_span); - }, _ => (), } }, From 4d1f2bc56519a9b37daaec84273f97e3aba4318b Mon Sep 17 00:00:00 2001 From: Takayuki Maeda Date: Wed, 17 Mar 2021 14:26:27 +0900 Subject: [PATCH 15/19] extract conditions for single_char_pattern into its own module --- clippy_lints/src/methods/mod.rs | 12 +------ .../src/methods/single_char_pattern.rs | 36 ++++++++++++------- 2 files changed, 25 insertions(+), 23 deletions(-) diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index e8cefbd74221..b97dee27c520 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -1787,17 +1787,7 @@ impl<'tcx> LateLintPass<'tcx> for Methods { inefficient_to_string::check(cx, expr, method_call.ident.name, args); single_char_add_str::check(cx, expr, args); into_iter_on_ref::check(cx, expr, *method_span, method_call.ident.name, args); - - match cx.typeck_results().expr_ty_adjusted(&args[0]).kind() { - ty::Ref(_, ty, _) if *ty.kind() == ty::Str => { - for &(method, pos) in &PATTERN_METHODS { - if method_call.ident.name.as_str() == method && args.len() > pos { - single_char_pattern::check(cx, expr, &args[pos]); - } - } - }, - _ => (), - } + single_char_pattern::check(cx, expr, method_call.ident.name, args); }, hir::ExprKind::Binary(op, ref lhs, ref rhs) if op.node == hir::BinOpKind::Eq || op.node == hir::BinOpKind::Ne => diff --git a/clippy_lints/src/methods/single_char_pattern.rs b/clippy_lints/src/methods/single_char_pattern.rs index 12d6418d7001..ae998468c2d9 100644 --- a/clippy_lints/src/methods/single_char_pattern.rs +++ b/clippy_lints/src/methods/single_char_pattern.rs @@ -1,23 +1,35 @@ use crate::methods::get_hint_if_single_char_arg; use clippy_utils::diagnostics::span_lint_and_sugg; +use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_lint::LateContext; +use rustc_middle::ty; +use rustc_span::symbol::Symbol; use super::SINGLE_CHAR_PATTERN; /// lint for length-1 `str`s for methods in `PATTERN_METHODS` -pub(super) fn check(cx: &LateContext<'_>, _expr: &hir::Expr<'_>, arg: &hir::Expr<'_>) { - let mut applicability = Applicability::MachineApplicable; - if let Some(hint) = get_hint_if_single_char_arg(cx, arg, &mut applicability) { - span_lint_and_sugg( - cx, - SINGLE_CHAR_PATTERN, - arg.span, - "single-character string constant used as pattern", - "try using a `char` instead", - hint, - applicability, - ); +pub(super) fn check(cx: &LateContext<'_>, _expr: &hir::Expr<'_>, method_name: Symbol, args: &[hir::Expr<'_>]) { + for &(method, pos) in &crate::methods::PATTERN_METHODS { + if_chain! { + if let ty::Ref(_, ty, _) = cx.typeck_results().expr_ty_adjusted(&args[0]).kind(); + if *ty.kind() == ty::Str; + if method_name.as_str() == method && args.len() > pos; + let arg = &args[pos]; + let mut applicability = Applicability::MachineApplicable; + if let Some(hint) = get_hint_if_single_char_arg(cx, arg, &mut applicability); + then { + span_lint_and_sugg( + cx, + SINGLE_CHAR_PATTERN, + arg.span, + "single-character string constant used as pattern", + "try using a `char` instead", + hint, + applicability, + ); + } + } } } From 27963c8dce5b2db8c6c308681682bbb33938e125 Mon Sep 17 00:00:00 2001 From: Takayuki Maeda Date: Wed, 17 Mar 2021 14:34:20 +0900 Subject: [PATCH 16/19] move chars_last_cmp_with_unwrap to its own module --- .../src/methods/chars_last_cmp_with_unwrap.rs | 13 +++++++++++++ clippy_lints/src/methods/mod.rs | 12 ++---------- 2 files changed, 15 insertions(+), 10 deletions(-) create mode 100644 clippy_lints/src/methods/chars_last_cmp_with_unwrap.rs diff --git a/clippy_lints/src/methods/chars_last_cmp_with_unwrap.rs b/clippy_lints/src/methods/chars_last_cmp_with_unwrap.rs new file mode 100644 index 000000000000..c29ee0ec8c8c --- /dev/null +++ b/clippy_lints/src/methods/chars_last_cmp_with_unwrap.rs @@ -0,0 +1,13 @@ +use crate::methods::chars_cmp_with_unwrap; +use rustc_lint::LateContext; + +use super::CHARS_LAST_CMP; + +/// Checks for the `CHARS_LAST_CMP` lint with `unwrap()`. +pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, info: &crate::methods::BinaryExprInfo<'_>) -> bool { + if chars_cmp_with_unwrap::check(cx, info, &["chars", "last", "unwrap"], CHARS_LAST_CMP, "ends_with") { + true + } else { + chars_cmp_with_unwrap::check(cx, info, &["chars", "next_back", "unwrap"], CHARS_LAST_CMP, "ends_with") + } +} diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index b97dee27c520..f124d0b12f5f 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -3,6 +3,7 @@ mod bytes_nth; mod chars_cmp; mod chars_cmp_with_unwrap; mod chars_last_cmp; +mod chars_last_cmp_with_unwrap; mod chars_next_cmp; mod chars_next_cmp_with_unwrap; mod clone_on_copy; @@ -1974,16 +1975,7 @@ fn lint_binary_expr_with_method_call(cx: &LateContext<'_>, info: &mut BinaryExpr lint_with_both_lhs_and_rhs!(chars_next_cmp::check, cx, info); lint_with_both_lhs_and_rhs!(chars_last_cmp::check, cx, info); lint_with_both_lhs_and_rhs!(chars_next_cmp_with_unwrap::check, cx, info); - lint_with_both_lhs_and_rhs!(lint_chars_last_cmp_with_unwrap, cx, info); -} - -/// Checks for the `CHARS_LAST_CMP` lint with `unwrap()`. -fn lint_chars_last_cmp_with_unwrap<'tcx>(cx: &LateContext<'tcx>, info: &BinaryExprInfo<'_>) -> bool { - if chars_cmp_with_unwrap::check(cx, info, &["chars", "last", "unwrap"], CHARS_LAST_CMP, "ends_with") { - true - } else { - chars_cmp_with_unwrap::check(cx, info, &["chars", "next_back", "unwrap"], CHARS_LAST_CMP, "ends_with") - } + lint_with_both_lhs_and_rhs!(chars_last_cmp_with_unwrap::check, cx, info); } fn get_hint_if_single_char_arg( From 602bcf3e4f5f540e2f81d9e807e28b35c7bee0ed Mon Sep 17 00:00:00 2001 From: Takayuki Maeda Date: Wed, 17 Mar 2021 14:45:20 +0900 Subject: [PATCH 17/19] move get_hint_if_single_char_arg to methods/utils.rs --- clippy_lints/src/methods/mod.rs | 31 ----------------- .../src/methods/single_char_insert_string.rs | 2 +- .../src/methods/single_char_pattern.rs | 2 +- .../src/methods/single_char_push_string.rs | 2 +- clippy_lints/src/methods/utils.rs | 34 ++++++++++++++++++- 5 files changed, 36 insertions(+), 35 deletions(-) diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index f124d0b12f5f..a80162015dc9 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -61,15 +61,12 @@ mod zst_offset; use bind_instead_of_map::BindInsteadOfMap; use clippy_utils::diagnostics::{span_lint, span_lint_and_help}; -use clippy_utils::source::snippet_with_applicability; use clippy_utils::ty::{contains_ty, implements_trait, is_copy, is_type_diagnostic_item}; use clippy_utils::{ contains_return, get_trait_def_id, in_macro, iter_input_pats, match_qpath, method_calls, paths, return_ty, SpanlessEq, }; use if_chain::if_chain; -use rustc_ast::ast; -use rustc_errors::Applicability; use rustc_hir as hir; use rustc_hir::{TraitItem, TraitItemKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; @@ -1978,34 +1975,6 @@ fn lint_binary_expr_with_method_call(cx: &LateContext<'_>, info: &mut BinaryExpr lint_with_both_lhs_and_rhs!(chars_last_cmp_with_unwrap::check, cx, info); } -fn get_hint_if_single_char_arg( - cx: &LateContext<'_>, - arg: &hir::Expr<'_>, - applicability: &mut Applicability, -) -> Option { - if_chain! { - if let hir::ExprKind::Lit(lit) = &arg.kind; - if let ast::LitKind::Str(r, style) = lit.node; - let string = r.as_str(); - if string.chars().count() == 1; - then { - let snip = snippet_with_applicability(cx, arg.span, &string, applicability); - let ch = if let ast::StrStyle::Raw(nhash) = style { - let nhash = nhash as usize; - // for raw string: r##"a"## - &snip[(nhash + 2)..(snip.len() - 1 - nhash)] - } else { - // for regular string: "a" - &snip[1..(snip.len() - 1)] - }; - let hint = format!("'{}'", if ch == "'" { "\\'" } else { ch }); - Some(hint) - } else { - None - } - } -} - const FN_HEADER: hir::FnHeader = hir::FnHeader { unsafety: hir::Unsafety::Normal, constness: hir::Constness::NotConst, diff --git a/clippy_lints/src/methods/single_char_insert_string.rs b/clippy_lints/src/methods/single_char_insert_string.rs index cd87d2c56b72..3f3e3bd7dfde 100644 --- a/clippy_lints/src/methods/single_char_insert_string.rs +++ b/clippy_lints/src/methods/single_char_insert_string.rs @@ -1,4 +1,4 @@ -use crate::methods::get_hint_if_single_char_arg; +use crate::methods::utils::get_hint_if_single_char_arg; use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::snippet_with_applicability; use rustc_errors::Applicability; diff --git a/clippy_lints/src/methods/single_char_pattern.rs b/clippy_lints/src/methods/single_char_pattern.rs index ae998468c2d9..abead199098c 100644 --- a/clippy_lints/src/methods/single_char_pattern.rs +++ b/clippy_lints/src/methods/single_char_pattern.rs @@ -1,4 +1,4 @@ -use crate::methods::get_hint_if_single_char_arg; +use crate::methods::utils::get_hint_if_single_char_arg; use clippy_utils::diagnostics::span_lint_and_sugg; use if_chain::if_chain; use rustc_errors::Applicability; diff --git a/clippy_lints/src/methods/single_char_push_string.rs b/clippy_lints/src/methods/single_char_push_string.rs index 882703a987d3..189157f819ec 100644 --- a/clippy_lints/src/methods/single_char_push_string.rs +++ b/clippy_lints/src/methods/single_char_push_string.rs @@ -1,4 +1,4 @@ -use crate::methods::get_hint_if_single_char_arg; +use crate::methods::utils::get_hint_if_single_char_arg; use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::snippet_with_applicability; use rustc_errors::Applicability; diff --git a/clippy_lints/src/methods/utils.rs b/clippy_lints/src/methods/utils.rs index 4d801148cbc7..8de23e1bc6e9 100644 --- a/clippy_lints/src/methods/utils.rs +++ b/clippy_lints/src/methods/utils.rs @@ -1,11 +1,15 @@ +use clippy_utils::source::snippet_with_applicability; use clippy_utils::ty::is_type_diagnostic_item; +use if_chain::if_chain; +use rustc_ast::ast; +use rustc_errors::Applicability; use rustc_hir as hir; use rustc_lint::LateContext; use rustc_middle::ty; use rustc_middle::ty::Ty; use rustc_span::symbol::sym; -pub fn derefs_to_slice<'tcx>( +pub(super) fn derefs_to_slice<'tcx>( cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>, ty: Ty<'tcx>, @@ -44,3 +48,31 @@ pub fn derefs_to_slice<'tcx>( } } } + +pub(super) fn get_hint_if_single_char_arg( + cx: &LateContext<'_>, + arg: &hir::Expr<'_>, + applicability: &mut Applicability, +) -> Option { + if_chain! { + if let hir::ExprKind::Lit(lit) = &arg.kind; + if let ast::LitKind::Str(r, style) = lit.node; + let string = r.as_str(); + if string.chars().count() == 1; + then { + let snip = snippet_with_applicability(cx, arg.span, &string, applicability); + let ch = if let ast::StrStyle::Raw(nhash) = style { + let nhash = nhash as usize; + // for raw string: r##"a"## + &snip[(nhash + 2)..(snip.len() - 1 - nhash)] + } else { + // for regular string: "a" + &snip[1..(snip.len() - 1)] + }; + let hint = format!("'{}'", if ch == "'" { "\\'" } else { ch }); + Some(hint) + } else { + None + } + } +} From 0edd5f881d287dcff1b7401c44c8482cbd627c6b Mon Sep 17 00:00:00 2001 From: Takayuki Maeda Date: Thu, 18 Mar 2021 01:06:24 +0900 Subject: [PATCH 18/19] remove the use of paths --- clippy_lints/src/methods/into_iter_on_ref.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/methods/into_iter_on_ref.rs b/clippy_lints/src/methods/into_iter_on_ref.rs index 5d59fa86c9e8..da13b4ba37a5 100644 --- a/clippy_lints/src/methods/into_iter_on_ref.rs +++ b/clippy_lints/src/methods/into_iter_on_ref.rs @@ -1,6 +1,6 @@ use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::is_trait_method; use clippy_utils::ty::has_iter_method; -use clippy_utils::{match_trait_method, paths}; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir as hir; @@ -22,7 +22,7 @@ pub(super) fn check( if_chain! { if let ty::Ref(..) = self_ty.kind(); if method_name == sym::into_iter; - if match_trait_method(cx, expr, &paths::INTO_ITERATOR); + if is_trait_method(cx, expr, sym::IntoIterator); if let Some((kind, method_name)) = ty_has_iter_method(cx, self_ty); then { span_lint_and_sugg( From b6a2757561167f831939f874735e259e655031a1 Mon Sep 17 00:00:00 2001 From: Takayuki Maeda Date: Thu, 18 Mar 2021 01:23:37 +0900 Subject: [PATCH 19/19] replace crate::methods::utils with super::utils --- clippy_lints/src/methods/iter_next_slice.rs | 2 +- clippy_lints/src/methods/iter_nth.rs | 2 +- clippy_lints/src/methods/single_char_insert_string.rs | 2 +- clippy_lints/src/methods/single_char_pattern.rs | 2 +- clippy_lints/src/methods/single_char_push_string.rs | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/clippy_lints/src/methods/iter_next_slice.rs b/clippy_lints/src/methods/iter_next_slice.rs index 2155159bf7cb..e9b37b6f2bd9 100644 --- a/clippy_lints/src/methods/iter_next_slice.rs +++ b/clippy_lints/src/methods/iter_next_slice.rs @@ -1,4 +1,4 @@ -use crate::methods::utils::derefs_to_slice; +use super::utils::derefs_to_slice; use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::snippet_with_applicability; use clippy_utils::ty::is_type_diagnostic_item; diff --git a/clippy_lints/src/methods/iter_nth.rs b/clippy_lints/src/methods/iter_nth.rs index bf1575660d11..c46af427b3c6 100644 --- a/clippy_lints/src/methods/iter_nth.rs +++ b/clippy_lints/src/methods/iter_nth.rs @@ -1,5 +1,5 @@ +use super::utils::derefs_to_slice; use crate::methods::iter_nth_zero; -use crate::methods::utils::derefs_to_slice; use clippy_utils::diagnostics::span_lint_and_help; use clippy_utils::ty::is_type_diagnostic_item; use rustc_hir as hir; diff --git a/clippy_lints/src/methods/single_char_insert_string.rs b/clippy_lints/src/methods/single_char_insert_string.rs index 3f3e3bd7dfde..6cdc954c03be 100644 --- a/clippy_lints/src/methods/single_char_insert_string.rs +++ b/clippy_lints/src/methods/single_char_insert_string.rs @@ -1,4 +1,4 @@ -use crate::methods::utils::get_hint_if_single_char_arg; +use super::utils::get_hint_if_single_char_arg; use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::snippet_with_applicability; use rustc_errors::Applicability; diff --git a/clippy_lints/src/methods/single_char_pattern.rs b/clippy_lints/src/methods/single_char_pattern.rs index abead199098c..f4090c7c617d 100644 --- a/clippy_lints/src/methods/single_char_pattern.rs +++ b/clippy_lints/src/methods/single_char_pattern.rs @@ -1,4 +1,4 @@ -use crate::methods::utils::get_hint_if_single_char_arg; +use super::utils::get_hint_if_single_char_arg; use clippy_utils::diagnostics::span_lint_and_sugg; use if_chain::if_chain; use rustc_errors::Applicability; diff --git a/clippy_lints/src/methods/single_char_push_string.rs b/clippy_lints/src/methods/single_char_push_string.rs index 189157f819ec..0237d39cbdb4 100644 --- a/clippy_lints/src/methods/single_char_push_string.rs +++ b/clippy_lints/src/methods/single_char_push_string.rs @@ -1,4 +1,4 @@ -use crate::methods::utils::get_hint_if_single_char_arg; +use super::utils::get_hint_if_single_char_arg; use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::snippet_with_applicability; use rustc_errors::Applicability;