|
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::TyS; |
| 9 | +use rustc_middle::ty::{subst::GenericArg, TyS}; |
10 | 10 | use rustc_session::{declare_lint_pass, declare_tool_lint};
|
11 | 11 |
|
12 | 12 | declare_clippy_lint! {
|
@@ -54,34 +54,64 @@ impl LateLintPass<'_> for RedundantSlicing {
|
54 | 54 | if addressee.span.ctxt() == ctxt;
|
55 | 55 | if let ExprKind::Index(indexed, range) = addressee.kind;
|
56 | 56 | if is_type_lang_item(cx, cx.typeck_results().expr_ty_adjusted(range), LangItem::RangeFull);
|
57 |
| - if TyS::same_type(cx.typeck_results().expr_ty(expr), cx.typeck_results().expr_ty(indexed)); |
58 | 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)); |
59 | 60 | let mut app = Applicability::MachineApplicable;
|
60 |
| - let snip = snippet_with_context(cx, indexed.span, ctxt, "..", &mut app).0; |
61 | 61 |
|
62 |
| - let (reborrow_str, help_str) = if mutability == Mutability::Mut { |
63 |
| - // The slice was used to reborrow the mutable reference. |
64 |
| - ("&mut *", "reborrow the original value instead") |
65 |
| - } else if matches!( |
66 |
| - get_parent_expr(cx, expr), |
67 |
| - Some(Expr { |
68 |
| - kind: ExprKind::AddrOf(BorrowKind::Ref, Mutability::Mut, _), |
69 |
| - .. |
70 |
| - }) |
71 |
| - ) { |
72 |
| - // The slice was used to make a temporary reference. |
73 |
| - ("&*", "reborrow the original value instead") |
| 62 | + let (help, sugg) = if TyS::same_type(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 TyS::same_type(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 | + } |
74 | 104 | } else {
|
75 |
| - ("", "use the original value instead") |
| 105 | + return; |
76 | 106 | };
|
77 | 107 |
|
78 | 108 | span_lint_and_sugg(
|
79 | 109 | cx,
|
80 | 110 | REDUNDANT_SLICING,
|
81 | 111 | expr.span,
|
82 | 112 | "redundant slicing of the whole range",
|
83 |
| - help_str, |
84 |
| - format!("{}{}", reborrow_str, snip), |
| 113 | + help, |
| 114 | + sugg, |
85 | 115 | app,
|
86 | 116 | );
|
87 | 117 | }
|
|
0 commit comments