]> git.lizzy.rs Git - rust.git/blob - clippy_lints/src/redundant_slicing.rs
Merge commit '0e87918536b9833bbc6c683d1f9d51ee2bf03ef1' into clippyup
[rust.git] / clippy_lints / src / redundant_slicing.rs
1 use clippy_utils::diagnostics::span_lint_and_sugg;
2 use clippy_utils::source::snippet_with_applicability;
3 use clippy_utils::ty::is_type_lang_item;
4 use if_chain::if_chain;
5 use rustc_errors::Applicability;
6 use rustc_hir::{Expr, ExprKind, LangItem};
7 use rustc_lint::{LateContext, LateLintPass, LintContext};
8 use rustc_middle::{lint::in_external_macro, ty::TyS};
9 use rustc_session::{declare_lint_pass, declare_tool_lint};
10
11 declare_clippy_lint! {
12     /// **What it does:** Checks for redundant slicing expressions which use the full range, and
13     /// do not change the type.
14     ///
15     /// **Why is this bad?** It unnecessarily adds complexity to the expression.
16     ///
17     /// **Known problems:** If the type being sliced has an implementation of `Index<RangeFull>`
18     /// that actually changes anything then it can't be removed. However, this would be surprising
19     /// to people reading the code and should have a note with it.
20     ///
21     /// **Example:**
22     ///
23     /// ```ignore
24     /// fn get_slice(x: &[u32]) -> &[u32] {
25     ///     &x[..]
26     /// }
27     /// ```
28     /// Use instead:
29     /// ```ignore
30     /// fn get_slice(x: &[u32]) -> &[u32] {
31     ///     x
32     /// }
33     /// ```
34     pub REDUNDANT_SLICING,
35     complexity,
36     "redundant slicing of the whole range of a type"
37 }
38
39 declare_lint_pass!(RedundantSlicing => [REDUNDANT_SLICING]);
40
41 impl LateLintPass<'_> for RedundantSlicing {
42     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
43         if in_external_macro(cx.sess(), expr.span) {
44             return;
45         }
46
47         if_chain! {
48             if let ExprKind::AddrOf(_, _, addressee) = expr.kind;
49             if let ExprKind::Index(indexed, range) = addressee.kind;
50             if is_type_lang_item(cx, cx.typeck_results().expr_ty_adjusted(range), LangItem::RangeFull);
51             if TyS::same_type(cx.typeck_results().expr_ty(expr), cx.typeck_results().expr_ty(indexed));
52             then {
53                 let mut app = Applicability::MachineApplicable;
54                 let hint = snippet_with_applicability(cx, indexed.span, "..", &mut app).into_owned();
55
56                 span_lint_and_sugg(
57                     cx,
58                     REDUNDANT_SLICING,
59                     expr.span,
60                     "redundant slicing of the whole range",
61                     "use the original slice instead",
62                     hint,
63                     app,
64                 );
65             }
66         }
67     }
68 }