about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--clippy_lints/src/get_first.rs68
-rw-r--r--clippy_lints/src/lib.register_all.rs2
-rw-r--r--clippy_lints/src/lib.register_lints.rs2
-rw-r--r--clippy_lints/src/lib.register_style.rs2
-rw-r--r--clippy_lints/src/lib.rs2
-rw-r--r--clippy_lints/src/methods/get_first.rs39
-rw-r--r--clippy_lints/src/methods/mod.rs36
7 files changed, 76 insertions, 75 deletions
diff --git a/clippy_lints/src/get_first.rs b/clippy_lints/src/get_first.rs
deleted file mode 100644
index 529f7babaa5..00000000000
--- a/clippy_lints/src/get_first.rs
+++ /dev/null
@@ -1,68 +0,0 @@
-use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::source::snippet_with_applicability;
-use clippy_utils::{is_slice_of_primitives, match_def_path, paths};
-use if_chain::if_chain;
-use rustc_ast::LitKind;
-use rustc_errors::Applicability;
-use rustc_hir as hir;
-use rustc_lint::{LateContext, LateLintPass};
-use rustc_session::{declare_lint_pass, declare_tool_lint};
-use rustc_span::source_map::Spanned;
-
-declare_clippy_lint! {
-    /// ### What it does
-    /// Checks for using `x.get(0)` instead of
-    /// `x.first()`.
-    ///
-    /// ### Why is this bad?
-    /// Using `x.first()` is easier to read and has the same
-    /// result.
-    ///
-    /// ### Example
-    /// ```rust
-    /// let x = vec![2, 3, 5];
-    /// let first_element = x.get(0);
-    /// ```
-    ///
-    /// Use instead:
-    /// ```rust
-    /// let x = vec![2, 3, 5];
-    /// let first_element = x.first();
-    /// ```
-    #[clippy::version = "1.63.0"]
-    pub GET_FIRST,
-    style,
-    "Using `x.get(0)` when `x.first()` is simpler"
-}
-declare_lint_pass!(GetFirst => [GET_FIRST]);
-
-impl<'tcx> LateLintPass<'tcx> for GetFirst {
-    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) {
-        if_chain! {
-            if let hir::ExprKind::MethodCall(_, [struct_calling_on, method_arg], _) = &expr.kind;
-            if let Some(expr_def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id);
-            if match_def_path(cx, expr_def_id, &paths::SLICE_GET);
-
-            if let Some(_) = is_slice_of_primitives(cx, struct_calling_on);
-            if let hir::ExprKind::Lit(Spanned { node: LitKind::Int(0, _), .. }) = method_arg.kind;
-
-            then {
-                let mut applicability = Applicability::MachineApplicable;
-                let slice_name = snippet_with_applicability(
-                    cx,
-                    struct_calling_on.span, "..",
-                    &mut applicability,
-                );
-                span_lint_and_sugg(
-                    cx,
-                    GET_FIRST,
-                    expr.span,
-                    &format!("accessing first element with `{0}.get(0)`", slice_name),
-                    "try",
-                    format!("{}.first()", slice_name),
-                    applicability,
-                );
-            }
-        }
-    }
-}
diff --git a/clippy_lints/src/lib.register_all.rs b/clippy_lints/src/lib.register_all.rs
index f48e542ee41..8ce0a26915f 100644
--- a/clippy_lints/src/lib.register_all.rs
+++ b/clippy_lints/src/lib.register_all.rs
@@ -81,7 +81,6 @@ store.register_group(true, "clippy::all", Some("clippy_all"), vec![
     LintId::of(functions::NOT_UNSAFE_PTR_ARG_DEREF),
     LintId::of(functions::RESULT_UNIT_ERR),
     LintId::of(functions::TOO_MANY_ARGUMENTS),
-    LintId::of(get_first::GET_FIRST),
     LintId::of(if_let_mutex::IF_LET_MUTEX),
     LintId::of(indexing_slicing::OUT_OF_BOUNDS_INDEXING),
     LintId::of(infinite_iter::INFINITE_ITER),
@@ -162,6 +161,7 @@ store.register_group(true, "clippy::all", Some("clippy_all"), vec![
     LintId::of(methods::FILTER_MAP_IDENTITY),
     LintId::of(methods::FILTER_NEXT),
     LintId::of(methods::FLAT_MAP_IDENTITY),
+    LintId::of(methods::GET_FIRST),
     LintId::of(methods::GET_LAST_WITH_LEN),
     LintId::of(methods::INSPECT_FOR_EACH),
     LintId::of(methods::INTO_ITER_ON_REF),
diff --git a/clippy_lints/src/lib.register_lints.rs b/clippy_lints/src/lib.register_lints.rs
index 10ff1fa1f58..a6224035ec8 100644
--- a/clippy_lints/src/lib.register_lints.rs
+++ b/clippy_lints/src/lib.register_lints.rs
@@ -174,7 +174,6 @@ store.register_lints(&[
     functions::TOO_MANY_ARGUMENTS,
     functions::TOO_MANY_LINES,
     future_not_send::FUTURE_NOT_SEND,
-    get_first::GET_FIRST,
     if_let_mutex::IF_LET_MUTEX,
     if_not_else::IF_NOT_ELSE,
     if_then_some_else_none::IF_THEN_SOME_ELSE_NONE,
@@ -302,6 +301,7 @@ store.register_lints(&[
     methods::FLAT_MAP_IDENTITY,
     methods::FLAT_MAP_OPTION,
     methods::FROM_ITER_INSTEAD_OF_COLLECT,
+    methods::GET_FIRST,
     methods::GET_LAST_WITH_LEN,
     methods::GET_UNWRAP,
     methods::IMPLICIT_CLONE,
diff --git a/clippy_lints/src/lib.register_style.rs b/clippy_lints/src/lib.register_style.rs
index 6972c75597a..5ddaba2396e 100644
--- a/clippy_lints/src/lib.register_style.rs
+++ b/clippy_lints/src/lib.register_style.rs
@@ -29,7 +29,6 @@ store.register_group(true, "clippy::style", Some("clippy_style"), vec![
     LintId::of(functions::DOUBLE_MUST_USE),
     LintId::of(functions::MUST_USE_UNIT),
     LintId::of(functions::RESULT_UNIT_ERR),
-    LintId::of(get_first::GET_FIRST),
     LintId::of(inherent_to_string::INHERENT_TO_STRING),
     LintId::of(init_numbered_fields::INIT_NUMBERED_FIELDS),
     LintId::of(len_zero::COMPARISON_TO_EMPTY),
@@ -62,6 +61,7 @@ store.register_group(true, "clippy::style", Some("clippy_style"), vec![
     LintId::of(methods::CHARS_LAST_CMP),
     LintId::of(methods::CHARS_NEXT_CMP),
     LintId::of(methods::ERR_EXPECT),
+    LintId::of(methods::GET_FIRST),
     LintId::of(methods::INTO_ITER_ON_REF),
     LintId::of(methods::IS_DIGIT_ASCII_RADIX),
     LintId::of(methods::ITER_CLONED_COLLECT),
diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs
index 68f69dc64b8..3fcdc84113d 100644
--- a/clippy_lints/src/lib.rs
+++ b/clippy_lints/src/lib.rs
@@ -233,7 +233,6 @@ mod from_over_into;
 mod from_str_radix_10;
 mod functions;
 mod future_not_send;
-mod get_first;
 mod if_let_mutex;
 mod if_not_else;
 mod if_then_some_else_none;
@@ -907,7 +906,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     store.register_late_pass(|| Box::new(strings::TrimSplitWhitespace));
     store.register_late_pass(|| Box::new(rc_clone_in_vec_init::RcCloneInVecInit));
     store.register_early_pass(|| Box::new(duplicate_mod::DuplicateMod::default()));
-    store.register_late_pass(|| Box::new(get_first::GetFirst));
     store.register_early_pass(|| Box::new(unused_rounding::UnusedRounding));
     store.register_early_pass(move || Box::new(almost_complete_letter_range::AlmostCompleteLetterRange::new(msrv)));
     store.register_late_pass(|| Box::new(swap_ptr_to_ref::SwapPtrToRef));
diff --git a/clippy_lints/src/methods/get_first.rs b/clippy_lints/src/methods/get_first.rs
new file mode 100644
index 00000000000..4de77de7404
--- /dev/null
+++ b/clippy_lints/src/methods/get_first.rs
@@ -0,0 +1,39 @@
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::is_slice_of_primitives;
+use clippy_utils::source::snippet_with_applicability;
+use if_chain::if_chain;
+use rustc_ast::LitKind;
+use rustc_errors::Applicability;
+use rustc_hir as hir;
+use rustc_lint::LateContext;
+use rustc_span::source_map::Spanned;
+
+use super::GET_FIRST;
+
+pub(super) fn check<'tcx>(
+    cx: &LateContext<'tcx>,
+    expr: &'tcx hir::Expr<'_>,
+    recv: &'tcx hir::Expr<'_>,
+    arg: &'tcx hir::Expr<'_>,
+) {
+    if_chain! {
+        if let Some(method_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id);
+        if let Some(impl_id) = cx.tcx.impl_of_method(method_id);
+        if cx.tcx.type_of(impl_id).is_slice();
+        if let Some(_) = is_slice_of_primitives(cx, recv);
+        if let hir::ExprKind::Lit(Spanned { node: LitKind::Int(0, _), .. }) = arg.kind;
+        then {
+            let mut app = Applicability::MachineApplicable;
+            let slice_name = snippet_with_applicability(cx, recv.span, "..", &mut app);
+            span_lint_and_sugg(
+                cx,
+                GET_FIRST,
+                expr.span,
+                &format!("accessing first element with `{0}.get(0)`", slice_name),
+                "try",
+                format!("{}.first()", slice_name),
+                app,
+            );
+        }
+    }
+}
diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs
index 0bb247c7e81..c3438426985 100644
--- a/clippy_lints/src/methods/mod.rs
+++ b/clippy_lints/src/methods/mod.rs
@@ -24,6 +24,7 @@ mod filter_next;
 mod flat_map_identity;
 mod flat_map_option;
 mod from_iter_instead_of_collect;
+mod get_first;
 mod get_last_with_len;
 mod get_unwrap;
 mod implicit_clone;
@@ -2457,6 +2458,32 @@ declare_clippy_lint! {
     "Checks for calls to ends_with with case-sensitive file extensions"
 }
 
+declare_clippy_lint! {
+    /// ### What it does
+    /// Checks for using `x.get(0)` instead of
+    /// `x.first()`.
+    ///
+    /// ### Why is this bad?
+    /// Using `x.first()` is easier to read and has the same
+    /// result.
+    ///
+    /// ### Example
+    /// ```rust
+    /// let x = vec![2, 3, 5];
+    /// let first_element = x.get(0);
+    /// ```
+    ///
+    /// Use instead:
+    /// ```rust
+    /// let x = vec![2, 3, 5];
+    /// let first_element = x.first();
+    /// ```
+    #[clippy::version = "1.63.0"]
+    pub GET_FIRST,
+    style,
+    "Using `x.get(0)` when `x.first()` is simpler"
+}
+
 pub struct Methods {
     avoid_breaking_exported_api: bool,
     msrv: Option<RustcVersion>,
@@ -2564,6 +2591,7 @@ impl_lint_pass!(Methods => [
     NAIVE_BYTECOUNT,
     BYTES_COUNT_TO_LEN,
     CASE_SENSITIVE_FILE_EXTENSION_COMPARISONS,
+    GET_FIRST,
 ]);
 
 /// Extracts a method call name, args, and `Span` of the method name.
@@ -2833,7 +2861,8 @@ impl Methods {
                 },
                 ("ends_with", [arg]) => {
                     if let ExprKind::MethodCall(_, _, span) = expr.kind {
-                    case_sensitive_file_extension_comparisons::check(cx, expr, span, recv, arg);
+                        case_sensitive_file_extension_comparisons::check(cx, expr, span, recv, arg);
+                    }
                 },
                 ("expect", [_]) => match method_call(recv) {
                     Some(("ok", [recv], _)) => ok_expect::check(cx, expr, recv),
@@ -2867,7 +2896,10 @@ impl Methods {
                         inspect_for_each::check(cx, expr, span2);
                     }
                 },
-                ("get", [arg]) => get_last_with_len::check(cx, expr, recv, arg),
+                ("get", [arg]) => {
+                    get_first::check(cx, expr, recv, arg);
+                    get_last_with_len::check(cx, expr, recv, arg);
+                },
                 ("get_or_insert_with", [arg]) => unnecessary_lazy_eval::check(cx, expr, recv, arg, "get_or_insert"),
                 ("is_file", []) => filetype_is_file::check(cx, expr, recv),
                 ("is_digit", [radix]) => is_digit_ascii_radix::check(cx, expr, recv, radix, self.msrv),