Skip to content

Commit dda27e0

Browse files
committed
needless_deref
1 parent 1dd5547 commit dda27e0

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+325
-94
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -3296,6 +3296,7 @@ Released 2018-09-13
32963296
[`bool_assert_comparison`]: https://rust-lang.github.io/rust-clippy/master/index.html#bool_assert_comparison
32973297
[`bool_comparison`]: https://rust-lang.github.io/rust-clippy/master/index.html#bool_comparison
32983298
[`borrow_as_ptr`]: https://rust-lang.github.io/rust-clippy/master/index.html#borrow_as_ptr
3299+
[`borrow_deref_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#borrow_deref_ref
32993300
[`borrow_interior_mutable_const`]: https://rust-lang.github.io/rust-clippy/master/index.html#borrow_interior_mutable_const
33003301
[`borrowed_box`]: https://rust-lang.github.io/rust-clippy/master/index.html#borrowed_box
33013302
[`box_collection`]: https://rust-lang.github.io/rust-clippy/master/index.html#box_collection

clippy_lints/src/borrow_deref_ref.rs

+118
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
use crate::reference::DEREF_ADDROF;
2+
use clippy_utils::diagnostics::span_lint_and_then;
3+
use clippy_utils::source::snippet_opt;
4+
use clippy_utils::ty::implements_trait;
5+
use clippy_utils::{get_parent_expr, is_lint_allowed};
6+
use rustc_errors::Applicability;
7+
use rustc_hir::{ExprKind, UnOp};
8+
use rustc_lint::{LateContext, LateLintPass};
9+
use rustc_middle::mir::Mutability;
10+
use rustc_middle::ty;
11+
use rustc_session::{declare_lint_pass, declare_tool_lint};
12+
13+
declare_clippy_lint! {
14+
/// ### What it does
15+
/// Checks for `&*(&T)`.
16+
///
17+
/// ### Why is this bad?
18+
/// Dereferencing and then borrowing a reference value has no effect in most cases.
19+
///
20+
/// ### Known problems
21+
/// false negative on such code:
22+
/// ```
23+
/// let x = &12;
24+
/// let addr_x = &x as *const _ as usize;
25+
/// let addr_y = &&*x as *const _ as usize; // assert ok now, and lint triggerd.
26+
/// // But if we fix it, assert will fail.
27+
/// assert_ne!(addr_x, addr_y);
28+
/// ```
29+
///
30+
/// ### Example
31+
/// ```rust
32+
/// let s = &String::new();
33+
///
34+
/// // Bad
35+
/// let a: &String = &* s;
36+
/// foo(&*s);
37+
///
38+
/// // Good
39+
/// let a: &String = s;
40+
/// foo(&**s);
41+
///
42+
/// fn foo(_: &str){ }
43+
/// ```
44+
#[clippy::version = "1.59.0"]
45+
pub BORROW_DEREF_REF,
46+
complexity,
47+
"deref on an immutable reference returns the same type as itself"
48+
}
49+
50+
declare_lint_pass!(BorrowDerefRef => [BORROW_DEREF_REF]);
51+
52+
impl LateLintPass<'_> for BorrowDerefRef {
53+
fn check_expr(&mut self, cx: &LateContext<'_>, e: &rustc_hir::Expr<'_>) {
54+
if_chain! {
55+
if !e.span.from_expansion();
56+
if let ExprKind::AddrOf(_, Mutability::Not, addrof_target) = e.kind;
57+
if !addrof_target.span.from_expansion();
58+
if let ExprKind::Unary(UnOp::Deref, deref_target) = addrof_target.kind;
59+
if !deref_target.span.from_expansion();
60+
if !matches!(deref_target.kind, ExprKind::Unary(UnOp::Deref, ..) );
61+
let ref_ty = cx.typeck_results().expr_ty(deref_target);
62+
if let ty::Ref(_, inner_ty, Mutability::Not) = ref_ty.kind();
63+
then{
64+
65+
if let Some(parent_expr) = get_parent_expr(cx, e){
66+
if matches!(parent_expr.kind, ExprKind::Unary(UnOp::Deref, ..)) &&
67+
!is_lint_allowed(cx, DEREF_ADDROF, parent_expr.hir_id) {
68+
return;
69+
}
70+
71+
// modification to `&mut &*x` is different from `&mut x`
72+
if matches!(deref_target.kind, ExprKind::Path(..)
73+
| ExprKind::Field(..)
74+
| ExprKind::Index(..)
75+
| ExprKind::Unary(UnOp::Deref, ..))
76+
&& matches!(parent_expr.kind, ExprKind::AddrOf(_, Mutability::Mut, _)) {
77+
return;
78+
}
79+
}
80+
81+
span_lint_and_then(
82+
cx,
83+
BORROW_DEREF_REF,
84+
e.span,
85+
"deref on an immutable reference",
86+
|diag| {
87+
diag.span_suggestion(
88+
e.span,
89+
"if you would like to reborrow, try removing `&*`",
90+
snippet_opt(cx, deref_target.span).unwrap(),
91+
Applicability::MachineApplicable
92+
);
93+
94+
// has deref trait -> give 2 help
95+
// doesn't have deref trait -> give 1 help
96+
if let Some(deref_trait_id) = cx.tcx.lang_items().deref_trait(){
97+
if !implements_trait(cx, *inner_ty, deref_trait_id, &[]) {
98+
return;
99+
}
100+
}
101+
102+
diag.span_suggestion(
103+
e.span,
104+
"if you would like to deref, try using `&**`",
105+
format!(
106+
"&**{}",
107+
&snippet_opt(cx, deref_target.span).unwrap(),
108+
),
109+
Applicability::MaybeIncorrect
110+
);
111+
112+
}
113+
);
114+
115+
}
116+
}
117+
}
118+
}

clippy_lints/src/checked_conversions.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -318,7 +318,7 @@ fn get_implementing_type<'a>(path: &QPath<'_>, candidates: &'a [&str], function:
318318
if let QPath::TypeRelative(ty, path) = &path;
319319
if path.ident.name.as_str() == function;
320320
if let TyKind::Path(QPath::Resolved(None, tp)) = &ty.kind;
321-
if let [int] = &*tp.segments;
321+
if let [int] = tp.segments;
322322
then {
323323
let name = int.ident.name.as_str();
324324
candidates.iter().find(|c| &name == *c).copied()
@@ -332,7 +332,7 @@ fn get_implementing_type<'a>(path: &QPath<'_>, candidates: &'a [&str], function:
332332
fn int_ty_to_sym<'tcx>(path: &QPath<'_>) -> Option<&'tcx str> {
333333
if_chain! {
334334
if let QPath::Resolved(_, path) = *path;
335-
if let [ty] = &*path.segments;
335+
if let [ty] = path.segments;
336336
then {
337337
let name = ty.ident.name.as_str();
338338
INTS.iter().find(|c| &name == *c).copied()

clippy_lints/src/let_if_seq.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ impl<'tcx> LateLintPass<'tcx> for LetIfSeq {
6868
if let hir::ExprKind::If(hir::Expr { kind: hir::ExprKind::DropTemps(cond), ..}, then, else_) = if_.kind;
6969
if !is_local_used(cx, *cond, canonical_id);
7070
if let hir::ExprKind::Block(then, _) = then.kind;
71-
if let Some(value) = check_assign(cx, canonical_id, &*then);
71+
if let Some(value) = check_assign(cx, canonical_id, then);
7272
if !is_local_used(cx, value, canonical_id);
7373
then {
7474
let span = stmt.span.to(if_.span);

clippy_lints/src/lib.register_all.rs

+1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ store.register_group(true, "clippy::all", Some("clippy_all"), vec![
2424
LintId::of(bool_assert_comparison::BOOL_ASSERT_COMPARISON),
2525
LintId::of(booleans::LOGIC_BUG),
2626
LintId::of(booleans::NONMINIMAL_BOOL),
27+
LintId::of(borrow_deref_ref::BORROW_DEREF_REF),
2728
LintId::of(bytes_count_to_len::BYTES_COUNT_TO_LEN),
2829
LintId::of(casts::CAST_ABS_TO_UNSIGNED),
2930
LintId::of(casts::CAST_ENUM_CONSTRUCTOR),

clippy_lints/src/lib.register_complexity.rs

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
store.register_group(true, "clippy::complexity", Some("clippy_complexity"), vec![
66
LintId::of(attrs::DEPRECATED_CFG_ATTR),
77
LintId::of(booleans::NONMINIMAL_BOOL),
8+
LintId::of(borrow_deref_ref::BORROW_DEREF_REF),
89
LintId::of(bytes_count_to_len::BYTES_COUNT_TO_LEN),
910
LintId::of(casts::CHAR_LIT_AS_U8),
1011
LintId::of(casts::UNNECESSARY_CAST),

clippy_lints/src/lib.register_lints.rs

+1
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ store.register_lints(&[
6464
booleans::LOGIC_BUG,
6565
booleans::NONMINIMAL_BOOL,
6666
borrow_as_ptr::BORROW_AS_PTR,
67+
borrow_deref_ref::BORROW_DEREF_REF,
6768
bytecount::NAIVE_BYTECOUNT,
6869
bytes_count_to_len::BYTES_COUNT_TO_LEN,
6970
cargo::CARGO_COMMON_METADATA,

clippy_lints/src/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,7 @@ mod blocks_in_if_conditions;
183183
mod bool_assert_comparison;
184184
mod booleans;
185185
mod borrow_as_ptr;
186+
mod borrow_deref_ref;
186187
mod bytecount;
187188
mod bytes_count_to_len;
188189
mod cargo;
@@ -637,6 +638,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
637638
store.register_late_pass(|| Box::new(mutex_atomic::Mutex));
638639
store.register_late_pass(|| Box::new(needless_update::NeedlessUpdate));
639640
store.register_late_pass(|| Box::new(needless_borrowed_ref::NeedlessBorrowedRef));
641+
store.register_late_pass(|| Box::new(borrow_deref_ref::BorrowDerefRef));
640642
store.register_late_pass(|| Box::new(no_effect::NoEffect));
641643
store.register_late_pass(|| Box::new(temporary_assignment::TemporaryAssignment));
642644
store.register_late_pass(|| Box::new(transmute::Transmute));

clippy_lints/src/loops/never_loop.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ fn never_loop_expr(expr: &Expr<'_>, main_loop_id: HirId) -> NeverLoopResult {
146146
if arms.is_empty() {
147147
e
148148
} else {
149-
let arms = never_loop_expr_branch(&mut arms.iter().map(|a| &*a.body), main_loop_id);
149+
let arms = never_loop_expr_branch(&mut arms.iter().map(|a| a.body), main_loop_id);
150150
combine_seq(e, arms)
151151
}
152152
},

clippy_lints/src/matches/match_bool.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@ pub(crate) fn check(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>], expr:
2424
let exprs = if let PatKind::Lit(arm_bool) = arms[0].pat.kind {
2525
if let ExprKind::Lit(ref lit) = arm_bool.kind {
2626
match lit.node {
27-
LitKind::Bool(true) => Some((&*arms[0].body, &*arms[1].body)),
28-
LitKind::Bool(false) => Some((&*arms[1].body, &*arms[0].body)),
27+
LitKind::Bool(true) => Some((arms[0].body, arms[1].body)),
28+
LitKind::Bool(false) => Some((arms[1].body, arms[0].body)),
2929
_ => None,
3030
}
3131
} else {

clippy_lints/src/methods/unnecessary_to_owned.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -415,7 +415,7 @@ fn is_cloned_or_copied(cx: &LateContext<'_>, method_name: Symbol, method_def_id:
415415
/// Returns true if the named method can be used to convert the receiver to its "owned"
416416
/// representation.
417417
fn is_to_owned_like(cx: &LateContext<'_>, method_name: Symbol, method_def_id: DefId) -> bool {
418-
is_clone_like(cx, &*method_name.as_str(), method_def_id)
418+
is_clone_like(cx, method_name.as_str(), method_def_id)
419419
|| is_cow_into_owned(cx, method_name, method_def_id)
420420
|| is_to_string(cx, method_name, method_def_id)
421421
}

clippy_lints/src/mixed_read_write_in_expression.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ impl<'a, 'tcx> DivergenceVisitor<'a, 'tcx> {
120120
self.visit_expr(if_expr);
121121
}
122122
// make sure top level arm expressions aren't linted
123-
self.maybe_walk_expr(&*arm.body);
123+
self.maybe_walk_expr(arm.body);
124124
}
125125
},
126126
_ => walk_expr(self, e),

clippy_lints/src/mut_key.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ impl<'tcx> LateLintPass<'tcx> for MutableKeyType {
105105
if let hir::PatKind::Wild = local.pat.kind {
106106
return;
107107
}
108-
check_ty(cx, local.span, cx.typeck_results().pat_ty(&*local.pat));
108+
check_ty(cx, local.span, cx.typeck_results().pat_ty(local.pat));
109109
}
110110
}
111111

clippy_lints/src/panic_in_result_fn.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ fn lint_impl_body<'tcx>(cx: &LateContext<'tcx>, impl_span: Span, body: &'tcx hir
6161
expr_visitor_no_bodies(|expr| {
6262
let Some(macro_call) = root_macro_call_first_node(cx, expr) else { return true };
6363
if matches!(
64-
&*cx.tcx.item_name(macro_call.def_id).as_str(),
64+
cx.tcx.item_name(macro_call.def_id).as_str(),
6565
"unimplemented" | "unreachable" | "panic" | "todo" | "assert" | "assert_eq" | "assert_ne"
6666
) {
6767
panics.push(macro_call.span);

clippy_lints/src/pass_by_ref_or_value.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,7 @@ impl<'tcx> LateLintPass<'tcx> for PassByRefOrValue {
233233
}
234234

235235
if let hir::TraitItemKind::Fn(method_sig, _) = &item.kind {
236-
self.check_poly_fn(cx, item.def_id, &*method_sig.decl, None);
236+
self.check_poly_fn(cx, item.def_id, method_sig.decl, None);
237237
}
238238
}
239239

clippy_lints/src/redundant_clone.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -288,8 +288,8 @@ fn is_call_with_ref_arg<'tcx>(
288288
if let mir::TerminatorKind::Call { func, args, destination, .. } = kind;
289289
if args.len() == 1;
290290
if let mir::Operand::Move(mir::Place { local, .. }) = &args[0];
291-
if let ty::FnDef(def_id, _) = *func.ty(&*mir, cx.tcx).kind();
292-
if let (inner_ty, 1) = walk_ptrs_ty_depth(args[0].ty(&*mir, cx.tcx));
291+
if let ty::FnDef(def_id, _) = *func.ty(mir, cx.tcx).kind();
292+
if let (inner_ty, 1) = walk_ptrs_ty_depth(args[0].ty(mir, cx.tcx));
293293
if !is_copy(cx, inner_ty);
294294
then {
295295
Some((def_id, *local, inner_ty, destination.as_ref().map(|(dest, _)| dest)?.as_local()?))
@@ -318,7 +318,7 @@ fn find_stmt_assigns_to<'tcx>(
318318
None
319319
})?;
320320

321-
match (by_ref, &*rvalue) {
321+
match (by_ref, rvalue) {
322322
(true, mir::Rvalue::Ref(_, _, place)) | (false, mir::Rvalue::Use(mir::Operand::Copy(place))) => {
323323
Some(base_local_and_movability(cx, mir, *place))
324324
},

clippy_lints/src/redundant_static_lifetimes.rs

+3-6
Original file line numberDiff line numberDiff line change
@@ -51,12 +51,12 @@ impl RedundantStaticLifetimes {
5151
fn visit_type(&mut self, ty: &Ty, cx: &EarlyContext<'_>, reason: &str) {
5252
match ty.kind {
5353
// Be careful of nested structures (arrays and tuples)
54-
TyKind::Array(ref ty, _) => {
55-
self.visit_type(&*ty, cx, reason);
54+
TyKind::Array(ref ty, _) | TyKind::Slice(ref ty) => {
55+
self.visit_type(ty, cx, reason);
5656
},
5757
TyKind::Tup(ref tup) => {
5858
for tup_ty in tup {
59-
self.visit_type(&*tup_ty, cx, reason);
59+
self.visit_type(tup_ty, cx, reason);
6060
}
6161
},
6262
// This is what we are looking for !
@@ -89,9 +89,6 @@ impl RedundantStaticLifetimes {
8989
}
9090
self.visit_type(&*borrow_type.ty, cx, reason);
9191
},
92-
TyKind::Slice(ref ty) => {
93-
self.visit_type(ty, cx, reason);
94-
},
9592
_ => {},
9693
}
9794
}

clippy_lints/src/size_of_in_element_count.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ fn get_pointee_ty_and_count_expr<'tcx>(
110110
// Find calls to copy_{from,to}{,_nonoverlapping} and write_bytes methods
111111
if let ExprKind::MethodCall(method_path, [ptr_self, .., count], _) = expr.kind;
112112
let method_ident = method_path.ident.as_str();
113-
if METHODS.iter().any(|m| *m == &*method_ident);
113+
if METHODS.iter().any(|m| *m == method_ident);
114114

115115
// Get the pointee type
116116
if let ty::RawPtr(TypeAndMut { ty: pointee_ty, .. }) =

clippy_lints/src/utils/internal_lints.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -422,7 +422,7 @@ impl<'tcx> LateLintPass<'tcx> for LintWithoutLintPass {
422422
}
423423
} else if let Some(macro_call) = root_macro_call_first_node(cx, item) {
424424
if !matches!(
425-
&*cx.tcx.item_name(macro_call.def_id).as_str(),
425+
cx.tcx.item_name(macro_call.def_id).as_str(),
426426
"impl_lint_pass" | "declare_lint_pass"
427427
) {
428428
return;
@@ -504,7 +504,7 @@ fn check_invalid_clippy_version_attribute(cx: &LateContext<'_>, item: &'_ Item<'
504504
return;
505505
}
506506

507-
if RustcVersion::parse(&*value.as_str()).is_err() {
507+
if RustcVersion::parse(value.as_str()).is_err() {
508508
span_lint_and_help(
509509
cx,
510510
INVALID_CLIPPY_VERSION_ATTRIBUTE,
@@ -595,7 +595,7 @@ impl<'tcx> LateLintPass<'tcx> for CompilerLintFunctions {
595595
if_chain! {
596596
if let ExprKind::MethodCall(path, [self_arg, ..], _) = &expr.kind;
597597
let fn_name = path.ident;
598-
if let Some(sugg) = self.map.get(&*fn_name.as_str());
598+
if let Some(sugg) = self.map.get(fn_name.as_str());
599599
let ty = cx.typeck_results().expr_ty(self_arg).peel_refs();
600600
if match_type(cx, ty, &paths::EARLY_CONTEXT)
601601
|| match_type(cx, ty, &paths::LATE_CONTEXT);
@@ -679,7 +679,7 @@ impl<'tcx> LateLintPass<'tcx> for CollapsibleCalls {
679679
then {
680680
let and_then_snippets = get_and_then_snippets(cx, and_then_args);
681681
let mut sle = SpanlessEq::new(cx).deny_side_effects();
682-
match &*ps.ident.as_str() {
682+
match ps.ident.as_str() {
683683
"span_suggestion" if sle.eq_expr(&and_then_args[2], &span_call_args[1]) => {
684684
suggest_suggestion(cx, expr, &and_then_snippets, &span_suggestion_snippets(cx, span_call_args));
685685
},

clippy_lints/src/utils/internal_lints/metadata_collector.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -527,12 +527,11 @@ fn extract_attr_docs_or_lint(cx: &LateContext<'_>, item: &Item<'_>) -> Option<St
527527
fn extract_attr_docs(cx: &LateContext<'_>, item: &Item<'_>) -> Option<String> {
528528
let attrs = cx.tcx.hir().attrs(item.hir_id());
529529
let mut lines = attrs.iter().filter_map(ast::Attribute::doc_str);
530-
let mut docs = String::from(&*lines.next()?.as_str());
530+
let mut docs = String::from(lines.next()?.as_str());
531531
let mut in_code_block = false;
532532
let mut is_code_block_rust = false;
533533
for line in lines {
534534
let line = line.as_str();
535-
let line = &*line;
536535

537536
// Rustdoc hides code lines starting with `# ` and this removes them from Clippy's lint list :)
538537
if is_code_block_rust && line.trim_start().starts_with("# ") {

clippy_utils/src/consts.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -478,7 +478,7 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> {
478478
fn ifthenelse(&mut self, cond: &Expr<'_>, then: &Expr<'_>, otherwise: Option<&Expr<'_>>) -> Option<Constant> {
479479
if let Some(Constant::Bool(b)) = self.expr(cond) {
480480
if b {
481-
self.expr(&*then)
481+
self.expr(then)
482482
} else {
483483
otherwise.as_ref().and_then(|expr| self.expr(expr))
484484
}

clippy_utils/src/higher.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ impl<'tcx> ForLoop<'tcx> {
3535
if let hir::ExprKind::Match(iterexpr, [arm], hir::MatchSource::ForLoopDesugar) = e.kind;
3636
if let hir::ExprKind::Call(_, [arg]) = iterexpr.kind;
3737
if let hir::ExprKind::Loop(block, ..) = arm.body.kind;
38-
if let [stmt] = &*block.stmts;
38+
if let [stmt] = block.stmts;
3939
if let hir::StmtKind::Expr(e) = stmt.kind;
4040
if let hir::ExprKind::Match(_, [_, some_arm], _) = e.kind;
4141
if let hir::PatKind::Struct(_, [field], _) = some_arm.pat.kind;

0 commit comments

Comments
 (0)