Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit 65bc6cb

Browse files
committed
Lint explicit_auto_deref without a leading borrow
1 parent 442a68c commit 65bc6cb

10 files changed

+72
-11
lines changed

clippy_lints/src/dereference.rs

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,8 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing {
246246
(None, kind) => {
247247
let expr_ty = typeck.expr_ty(expr);
248248
let (position, parent_ctxt) = get_expr_position(cx, expr);
249+
let (stability, adjustments) = walk_parents(cx, expr);
250+
249251
match kind {
250252
RefOp::Deref => {
251253
if let Position::FieldAccess(name) = position
@@ -255,6 +257,11 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing {
255257
State::ExplicitDerefField { name },
256258
StateData { span: expr.span, hir_id: expr.hir_id },
257259
));
260+
} else if stability.is_deref_stable() {
261+
self.state = Some((
262+
State::ExplicitDeref { deref_span: expr.span, deref_hir_id: expr.hir_id },
263+
StateData { span: expr.span, hir_id: expr.hir_id },
264+
));
258265
}
259266
}
260267
RefOp::Method(target_mut)
@@ -278,7 +285,6 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing {
278285
));
279286
},
280287
RefOp::AddrOf => {
281-
let (stability, adjustments) = walk_parents(cx, expr);
282288
// Find the number of times the borrow is auto-derefed.
283289
let mut iter = adjustments.iter();
284290
let mut deref_count = 0usize;
@@ -632,6 +638,7 @@ impl AutoDerefStability {
632638
/// Walks up the parent expressions attempting to determine both how stable the auto-deref result
633639
/// is, and which adjustments will be applied to it. Note this will not consider auto-borrow
634640
/// locations as those follow different rules.
641+
#[allow(clippy::too_many_lines)]
635642
fn walk_parents<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> (AutoDerefStability, &'tcx [Adjustment<'tcx>]) {
636643
let mut adjustments = [].as_slice();
637644
let stability = walk_to_expr_usage(cx, e, &mut |node, child_id| {
@@ -643,16 +650,26 @@ fn walk_parents<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> (AutoDerefSt
643650
Node::Local(Local { ty: Some(ty), .. }) => Some(binding_ty_auto_deref_stability(ty)),
644651
Node::Item(&Item {
645652
kind: ItemKind::Static(..) | ItemKind::Const(..),
653+
def_id,
646654
..
647655
})
648656
| Node::TraitItem(&TraitItem {
649657
kind: TraitItemKind::Const(..),
658+
def_id,
650659
..
651660
})
652661
| Node::ImplItem(&ImplItem {
653662
kind: ImplItemKind::Const(..),
663+
def_id,
654664
..
655-
}) => Some(AutoDerefStability::Deref),
665+
}) => {
666+
let ty = cx.tcx.type_of(def_id);
667+
Some(if ty.is_ref() {
668+
AutoDerefStability::None
669+
} else {
670+
AutoDerefStability::Deref
671+
})
672+
},
656673

657674
Node::Item(&Item {
658675
kind: ItemKind::Fn(..),
@@ -670,7 +687,9 @@ fn walk_parents<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> (AutoDerefSt
670687
..
671688
}) => {
672689
let output = cx.tcx.fn_sig(def_id.to_def_id()).skip_binder().output();
673-
Some(if output.has_placeholders() || output.has_opaque_types() {
690+
Some(if !output.is_ref() {
691+
AutoDerefStability::None
692+
} else if output.has_placeholders() || output.has_opaque_types() {
674693
AutoDerefStability::Reborrow
675694
} else {
676695
AutoDerefStability::Deref
@@ -684,7 +703,9 @@ fn walk_parents<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> (AutoDerefSt
684703
.fn_sig(cx.tcx.hir().body_owner_def_id(cx.enclosing_body.unwrap()))
685704
.skip_binder()
686705
.output();
687-
Some(if output.has_placeholders() || output.has_opaque_types() {
706+
Some(if !output.is_ref() {
707+
AutoDerefStability::None
708+
} else if output.has_placeholders() || output.has_opaque_types() {
688709
AutoDerefStability::Reborrow
689710
} else {
690711
AutoDerefStability::Deref

tests/ui/explicit_auto_deref.fixed

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
unused_braces,
77
clippy::borrowed_box,
88
clippy::needless_borrow,
9+
clippy::needless_return,
910
clippy::ptr_arg,
1011
clippy::redundant_field_names,
1112
clippy::too_many_arguments,
@@ -184,4 +185,17 @@ fn main() {
184185
}
185186
let s6 = S6 { foo: S5 { foo: 5 } };
186187
let _ = (*s6).foo; // Don't lint. `S6` also has a field named `foo`
188+
189+
let ref_str = &"foo";
190+
let _ = f_str(ref_str);
191+
let ref_ref_str = &ref_str;
192+
let _ = f_str(ref_ref_str);
193+
194+
fn _f5(x: &u32) -> u32 {
195+
if true {
196+
*x
197+
} else {
198+
return *x;
199+
}
200+
}
187201
}

tests/ui/explicit_auto_deref.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
unused_braces,
77
clippy::borrowed_box,
88
clippy::needless_borrow,
9+
clippy::needless_return,
910
clippy::ptr_arg,
1011
clippy::redundant_field_names,
1112
clippy::too_many_arguments,
@@ -184,4 +185,17 @@ fn main() {
184185
}
185186
let s6 = S6 { foo: S5 { foo: 5 } };
186187
let _ = (*s6).foo; // Don't lint. `S6` also has a field named `foo`
188+
189+
let ref_str = &"foo";
190+
let _ = f_str(*ref_str);
191+
let ref_ref_str = &ref_str;
192+
let _ = f_str(**ref_ref_str);
193+
194+
fn _f5(x: &u32) -> u32 {
195+
if true {
196+
*x
197+
} else {
198+
return *x;
199+
}
200+
}
187201
}

tests/ui/explicit_auto_deref.stderr

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,5 +168,17 @@ error: deref which would be done by auto-deref
168168
LL | let _ = (**b).foo;
169169
| ^^^^^ help: try this: `b`
170170

171-
error: aborting due to 28 previous errors
171+
error: deref which would be done by auto-deref
172+
--> $DIR/explicit_auto_deref.rs:189:19
173+
|
174+
LL | let _ = f_str(*ref_str);
175+
| ^^^^^^^^ help: try this: `ref_str`
176+
177+
error: deref which would be done by auto-deref
178+
--> $DIR/explicit_auto_deref.rs:191:19
179+
|
180+
LL | let _ = f_str(**ref_ref_str);
181+
| ^^^^^^^^^^^^^ help: try this: `ref_ref_str`
182+
183+
error: aborting due to 30 previous errors
172184

tests/ui/needless_borrow_pat.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// FIXME: run-rustfix waiting on multi-span suggestions
22

33
#![warn(clippy::needless_borrow)]
4-
#![allow(clippy::needless_borrowed_reference)]
4+
#![allow(clippy::needless_borrowed_reference, clippy::explicit_auto_deref)]
55

66
fn f1(_: &str) {}
77
macro_rules! m1 {

tests/ui/ref_binding_to_reference.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
#![feature(lint_reasons)]
44
#![warn(clippy::ref_binding_to_reference)]
5-
#![allow(clippy::needless_borrowed_reference)]
5+
#![allow(clippy::needless_borrowed_reference, clippy::explicit_auto_deref)]
66

77
fn f1(_: &str) {}
88
macro_rules! m2 {

tests/ui/search_is_some_fixable_none.fixed

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// run-rustfix
2-
#![allow(dead_code)]
2+
#![allow(dead_code, clippy::explicit_auto_deref)]
33
#![warn(clippy::search_is_some)]
44

55
fn main() {

tests/ui/search_is_some_fixable_none.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// run-rustfix
2-
#![allow(dead_code)]
2+
#![allow(dead_code, clippy::explicit_auto_deref)]
33
#![warn(clippy::search_is_some)]
44

55
fn main() {

tests/ui/search_is_some_fixable_some.fixed

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// run-rustfix
2-
#![allow(dead_code)]
2+
#![allow(dead_code, clippy::explicit_auto_deref)]
33
#![warn(clippy::search_is_some)]
44

55
fn main() {

tests/ui/search_is_some_fixable_some.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// run-rustfix
2-
#![allow(dead_code)]
2+
#![allow(dead_code, clippy::explicit_auto_deref)]
33
#![warn(clippy::search_is_some)]
44

55
fn main() {

0 commit comments

Comments
 (0)