Skip to content

Commit 63aca96

Browse files
committed
Auto merge of #6975 - Jarcho:redundant_slicing_fp, r=llogiq
Improve `redundant_slicing` fixes: #6968 changelog: Fix `redundant_slicing` suggestion when a reborrow might be required or when the value is from a macro call
2 parents f41d68f + 0ff68bb commit 63aca96

File tree

3 files changed

+78
-20
lines changed

3 files changed

+78
-20
lines changed

clippy_lints/src/redundant_slicing.rs

Lines changed: 28 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
use clippy_utils::diagnostics::span_lint_and_sugg;
2-
use clippy_utils::source::snippet_with_applicability;
2+
use clippy_utils::source::snippet_with_context;
33
use clippy_utils::ty::is_type_lang_item;
4+
use clippy_utils::{get_parent_expr, in_macro};
45
use if_chain::if_chain;
56
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};
7+
use rustc_hir::{BorrowKind, Expr, ExprKind, LangItem, Mutability};
8+
use rustc_lint::{LateContext, LateLintPass};
9+
use rustc_middle::ty::TyS;
910
use rustc_session::{declare_lint_pass, declare_tool_lint};
1011

1112
declare_clippy_lint! {
@@ -40,26 +41,44 @@ declare_lint_pass!(RedundantSlicing => [REDUNDANT_SLICING]);
4041

4142
impl LateLintPass<'_> for RedundantSlicing {
4243
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
43-
if in_external_macro(cx.sess(), expr.span) {
44+
if in_macro(expr.span) {
4445
return;
4546
}
4647

48+
let ctxt = expr.span.ctxt();
4749
if_chain! {
48-
if let ExprKind::AddrOf(_, _, addressee) = expr.kind;
50+
if let ExprKind::AddrOf(BorrowKind::Ref, mutability, addressee) = expr.kind;
51+
if addressee.span.ctxt() == ctxt;
4952
if let ExprKind::Index(indexed, range) = addressee.kind;
5053
if is_type_lang_item(cx, cx.typeck_results().expr_ty_adjusted(range), LangItem::RangeFull);
5154
if TyS::same_type(cx.typeck_results().expr_ty(expr), cx.typeck_results().expr_ty(indexed));
5255
then {
5356
let mut app = Applicability::MachineApplicable;
54-
let hint = snippet_with_applicability(cx, indexed.span, "..", &mut app).into_owned();
57+
let snip = snippet_with_context(cx, indexed.span, ctxt, "..", &mut app).0;
58+
59+
let (reborrow_str, help_str) = if mutability == Mutability::Mut {
60+
// The slice was used to reborrow the mutable reference.
61+
("&mut *", "reborrow the original value instead")
62+
} else if matches!(
63+
get_parent_expr(cx, expr),
64+
Some(Expr {
65+
kind: ExprKind::AddrOf(BorrowKind::Ref, Mutability::Mut, _),
66+
..
67+
})
68+
) {
69+
// The slice was used to make a temporary reference.
70+
("&*", "reborrow the original value instead")
71+
} else {
72+
("", "use the original value instead")
73+
};
5574

5675
span_lint_and_sugg(
5776
cx,
5877
REDUNDANT_SLICING,
5978
expr.span,
6079
"redundant slicing of the whole range",
61-
"use the original slice instead",
62-
hint,
80+
help_str,
81+
format!("{}{}", reborrow_str, snip),
6382
app,
6483
);
6584
}

tests/ui/redundant_slicing.rs

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,31 @@
22
#![warn(clippy::redundant_slicing)]
33

44
fn main() {
5-
let x: &[u32] = &[0];
6-
let err = &x[..];
5+
let slice: &[u32] = &[0];
6+
let _ = &slice[..];
77

88
let v = vec![0];
9-
let ok = &v[..];
10-
let err = &(&v[..])[..];
9+
let _ = &v[..]; // Changes the type
10+
let _ = &(&v[..])[..]; // Outer borrow is redundant
11+
12+
static S: &[u8] = &[0, 1, 2];
13+
let err = &mut &S[..]; // Should reborrow instead of slice
14+
15+
let mut vec = vec![0];
16+
let mut_slice = &mut *vec;
17+
let _ = &mut mut_slice[..]; // Should reborrow instead of slice
18+
19+
macro_rules! m {
20+
($e:expr) => {
21+
$e
22+
};
23+
}
24+
let _ = &m!(slice)[..];
25+
26+
macro_rules! m2 {
27+
($e:expr) => {
28+
&$e[..]
29+
};
30+
}
31+
let _ = m2!(slice); // Don't lint in a macro
1132
}

tests/ui/redundant_slicing.stderr

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,34 @@
11
error: redundant slicing of the whole range
2-
--> $DIR/redundant_slicing.rs:6:15
2+
--> $DIR/redundant_slicing.rs:6:13
33
|
4-
LL | let err = &x[..];
5-
| ^^^^^^ help: use the original slice instead: `x`
4+
LL | let _ = &slice[..];
5+
| ^^^^^^^^^^ help: use the original value instead: `slice`
66
|
77
= note: `-D clippy::redundant-slicing` implied by `-D warnings`
88

99
error: redundant slicing of the whole range
10-
--> $DIR/redundant_slicing.rs:10:15
10+
--> $DIR/redundant_slicing.rs:10:13
1111
|
12-
LL | let err = &(&v[..])[..];
13-
| ^^^^^^^^^^^^^ help: use the original slice instead: `(&v[..])`
12+
LL | let _ = &(&v[..])[..]; // Outer borrow is redundant
13+
| ^^^^^^^^^^^^^ help: use the original value instead: `(&v[..])`
1414

15-
error: aborting due to 2 previous errors
15+
error: redundant slicing of the whole range
16+
--> $DIR/redundant_slicing.rs:13:20
17+
|
18+
LL | let err = &mut &S[..]; // Should reborrow instead of slice
19+
| ^^^^^^ help: reborrow the original value instead: `&*S`
20+
21+
error: redundant slicing of the whole range
22+
--> $DIR/redundant_slicing.rs:17:13
23+
|
24+
LL | let _ = &mut mut_slice[..]; // Should reborrow instead of slice
25+
| ^^^^^^^^^^^^^^^^^^ help: reborrow the original value instead: `&mut *mut_slice`
26+
27+
error: redundant slicing of the whole range
28+
--> $DIR/redundant_slicing.rs:24:13
29+
|
30+
LL | let _ = &m!(slice)[..];
31+
| ^^^^^^^^^^^^^^ help: use the original value instead: `slice`
32+
33+
error: aborting due to 5 previous errors
1634

0 commit comments

Comments
 (0)