|
1 | 1 | use clippy_utils::diagnostics::span_lint_and_sugg; |
2 | 2 | use clippy_utils::get_parent_expr; |
3 | 3 | use clippy_utils::source::snippet_with_context; |
4 | | -use clippy_utils::ty::is_type_lang_item; |
| 4 | +use clippy_utils::ty::{is_type_lang_item, peel_mid_ty_refs}; |
5 | 5 | use if_chain::if_chain; |
6 | 6 | use rustc_errors::Applicability; |
7 | 7 | use rustc_hir::{BorrowKind, Expr, ExprKind, LangItem, Mutability}; |
8 | 8 | use rustc_lint::{LateContext, LateLintPass}; |
| 9 | +use rustc_middle::ty::subst::GenericArg; |
9 | 10 | use rustc_session::{declare_lint_pass, declare_tool_lint}; |
10 | 11 |
|
11 | 12 | declare_clippy_lint! { |
@@ -53,34 +54,64 @@ impl<'tcx> LateLintPass<'tcx> for RedundantSlicing { |
53 | 54 | if addressee.span.ctxt() == ctxt; |
54 | 55 | if let ExprKind::Index(indexed, range) = addressee.kind; |
55 | 56 | if is_type_lang_item(cx, cx.typeck_results().expr_ty_adjusted(range), LangItem::RangeFull); |
56 | | - if cx.typeck_results().expr_ty(expr) == cx.typeck_results().expr_ty(indexed); |
57 | 57 | then { |
| 58 | + let (expr_ty, expr_ref_count) = peel_mid_ty_refs(cx.typeck_results().expr_ty(expr)); |
| 59 | + let (indexed_ty, indexed_ref_count) = peel_mid_ty_refs(cx.typeck_results().expr_ty(indexed)); |
58 | 60 | let mut app = Applicability::MachineApplicable; |
59 | | - let snip = snippet_with_context(cx, indexed.span, ctxt, "..", &mut app).0; |
60 | 61 |
|
61 | | - let (reborrow_str, help_str) = if mutability == Mutability::Mut { |
62 | | - // The slice was used to reborrow the mutable reference. |
63 | | - ("&mut *", "reborrow the original value instead") |
64 | | - } else if matches!( |
65 | | - get_parent_expr(cx, expr), |
66 | | - Some(Expr { |
67 | | - kind: ExprKind::AddrOf(BorrowKind::Ref, Mutability::Mut, _), |
68 | | - .. |
69 | | - }) |
70 | | - ) { |
71 | | - // The slice was used to make a temporary reference. |
72 | | - ("&*", "reborrow the original value instead") |
| 62 | + let (help, sugg) = if expr_ty == indexed_ty { |
| 63 | + if expr_ref_count > indexed_ref_count { |
| 64 | + return; |
| 65 | + } |
| 66 | + |
| 67 | + let (reborrow_str, help_str) = if mutability == Mutability::Mut { |
| 68 | + // The slice was used to reborrow the mutable reference. |
| 69 | + ("&mut *", "reborrow the original value instead") |
| 70 | + } else if matches!( |
| 71 | + get_parent_expr(cx, expr), |
| 72 | + Some(Expr { |
| 73 | + kind: ExprKind::AddrOf(BorrowKind::Ref, Mutability::Mut, _), |
| 74 | + .. |
| 75 | + }) |
| 76 | + ) { |
| 77 | + // The slice was used to make a temporary reference. |
| 78 | + ("&*", "reborrow the original value instead") |
| 79 | + } else if expr_ref_count != indexed_ref_count { |
| 80 | + ("", "dereference the original value instead") |
| 81 | + } else { |
| 82 | + ("", "use the original value instead") |
| 83 | + }; |
| 84 | + |
| 85 | + let snip = snippet_with_context(cx, indexed.span, ctxt, "..", &mut app).0; |
| 86 | + (help_str, format!("{}{}{}", reborrow_str, "*".repeat(indexed_ref_count - expr_ref_count), snip)) |
| 87 | + } else if let Some(target_id) = cx.tcx.lang_items().deref_target() { |
| 88 | + if let Ok(deref_ty) = cx.tcx.try_normalize_erasing_regions( |
| 89 | + cx.param_env, |
| 90 | + cx.tcx.mk_projection(target_id, cx.tcx.mk_substs([GenericArg::from(indexed_ty)].into_iter())), |
| 91 | + ) { |
| 92 | + if deref_ty == expr_ty { |
| 93 | + let snip = snippet_with_context(cx, indexed.span, ctxt, "..", &mut app).0; |
| 94 | + ( |
| 95 | + "dereference the original value instead", |
| 96 | + format!("&{}{}*{}", mutability.prefix_str(), "*".repeat(indexed_ref_count), snip), |
| 97 | + ) |
| 98 | + } else { |
| 99 | + return; |
| 100 | + } |
| 101 | + } else { |
| 102 | + return; |
| 103 | + } |
73 | 104 | } else { |
74 | | - ("", "use the original value instead") |
| 105 | + return; |
75 | 106 | }; |
76 | 107 |
|
77 | 108 | span_lint_and_sugg( |
78 | 109 | cx, |
79 | 110 | REDUNDANT_SLICING, |
80 | 111 | expr.span, |
81 | 112 | "redundant slicing of the whole range", |
82 | | - help_str, |
83 | | - format!("{}{}", reborrow_str, snip), |
| 113 | + help, |
| 114 | + sugg, |
84 | 115 | app, |
85 | 116 | ); |
86 | 117 | } |
|
0 commit comments