Skip to content

Commit a31eaad

Browse files
committed
Lint explicit_auto_deref without a leading borrow
1 parent 818f534 commit a31eaad

11 files changed

+101
-40
lines changed

clippy_lints/src/dereference.rs

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,8 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing {
237237
(None, kind) => {
238238
let expr_ty = typeck.expr_ty(expr);
239239
let (position, parent_ctxt) = get_expr_position(cx, expr);
240+
let (stability, adjustments) = walk_parents(cx, expr);
241+
240242
match kind {
241243
RefOp::Deref => {
242244
if let Position::FieldAccess(name) = position
@@ -246,6 +248,11 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing {
246248
State::ExplicitDerefField { name },
247249
StateData { span: expr.span },
248250
));
251+
} else if stability.is_deref_stable() {
252+
self.state = Some((
253+
State::ExplicitDeref { deref_span: expr.span },
254+
StateData { span: expr.span },
255+
));
249256
}
250257
}
251258
RefOp::Method(target_mut)
@@ -266,7 +273,6 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing {
266273
));
267274
},
268275
RefOp::AddrOf => {
269-
let (stability, adjustments) = walk_parents(cx, expr);
270276
// Find the number of times the borrow is auto-derefed.
271277
let mut iter = adjustments.iter();
272278
let mut deref_count = 0usize;
@@ -581,6 +587,7 @@ impl AutoDerefStability {
581587
/// Walks up the parent expressions attempting to determine both how stable the auto-deref result
582588
/// is, and which adjustments will be applied to it. Note this will not consider auto-borrow
583589
/// locations as those follow different rules.
590+
#[allow(clippy::too_many_lines)]
584591
fn walk_parents<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> (AutoDerefStability, &'tcx [Adjustment<'tcx>]) {
585592
let mut adjustments = [].as_slice();
586593
let stability = walk_to_expr_usage(cx, e, &mut |node, child_id| {
@@ -592,16 +599,26 @@ fn walk_parents<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> (AutoDerefSt
592599
Node::Local(Local { ty: Some(ty), .. }) => Some(binding_ty_auto_deref_stability(ty)),
593600
Node::Item(&Item {
594601
kind: ItemKind::Static(..) | ItemKind::Const(..),
602+
def_id,
595603
..
596604
})
597605
| Node::TraitItem(&TraitItem {
598606
kind: TraitItemKind::Const(..),
607+
def_id,
599608
..
600609
})
601610
| Node::ImplItem(&ImplItem {
602611
kind: ImplItemKind::Const(..),
612+
def_id,
603613
..
604-
}) => Some(AutoDerefStability::Deref),
614+
}) => {
615+
let ty = cx.tcx.type_of(def_id);
616+
Some(if ty.is_ref() {
617+
AutoDerefStability::None
618+
} else {
619+
AutoDerefStability::Deref
620+
})
621+
},
605622

606623
Node::Item(&Item {
607624
kind: ItemKind::Fn(..),
@@ -619,7 +636,9 @@ fn walk_parents<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> (AutoDerefSt
619636
..
620637
}) => {
621638
let output = cx.tcx.fn_sig(def_id.to_def_id()).skip_binder().output();
622-
Some(if output.has_placeholders() || output.has_opaque_types() {
639+
Some(if !output.is_ref() {
640+
AutoDerefStability::None
641+
} else if output.has_placeholders() || output.has_opaque_types() {
623642
AutoDerefStability::Reborrow
624643
} else {
625644
AutoDerefStability::Deref
@@ -633,7 +652,9 @@ fn walk_parents<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> (AutoDerefSt
633652
.fn_sig(cx.tcx.hir().body_owner_def_id(cx.enclosing_body.unwrap()))
634653
.skip_binder()
635654
.output();
636-
Some(if output.has_placeholders() || output.has_opaque_types() {
655+
Some(if !output.is_ref() {
656+
AutoDerefStability::None
657+
} else if output.has_placeholders() || output.has_opaque_types() {
637658
AutoDerefStability::Reborrow
638659
} else {
639660
AutoDerefStability::Deref

clippy_utils/src/ty.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ pub fn is_must_use_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
168168
ty::Slice(ty) | ty::Array(ty, _) | ty::RawPtr(ty::TypeAndMut { ty, .. }) | ty::Ref(_, ty, _) => {
169169
// for the Array case we don't need to care for the len == 0 case
170170
// because we don't want to lint functions returning empty arrays
171-
is_must_use_ty(cx, *ty)
171+
is_must_use_ty(cx, ty)
172172
},
173173
ty::Tuple(substs) => substs.types().any(|ty| is_must_use_ty(cx, ty)),
174174
ty::Opaque(ref def_id, _) => {

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
@@ -183,4 +184,17 @@ fn main() {
183184
}
184185
let s6 = S6 { foo: S5 { foo: 5 } };
185186
let _ = (*s6).foo; // Don't lint. `S6` also has a field named `foo`
187+
188+
let ref_str = &"foo";
189+
let _ = f_str(ref_str);
190+
let ref_ref_str = &ref_str;
191+
let _ = f_str(ref_ref_str);
192+
193+
fn _f5(x: &u32) -> u32 {
194+
if true {
195+
*x
196+
} else {
197+
return *x;
198+
}
199+
}
186200
}

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
@@ -183,4 +184,17 @@ fn main() {
183184
}
184185
let s6 = S6 { foo: S5 { foo: 5 } };
185186
let _ = (*s6).foo; // Don't lint. `S6` also has a field named `foo`
187+
188+
let ref_str = &"foo";
189+
let _ = f_str(*ref_str);
190+
let ref_ref_str = &ref_str;
191+
let _ = f_str(**ref_ref_str);
192+
193+
fn _f5(x: &u32) -> u32 {
194+
if true {
195+
*x
196+
} else {
197+
return *x;
198+
}
199+
}
186200
}

tests/ui/explicit_auto_deref.stderr

Lines changed: 41 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,172 +1,184 @@
11
error: deref which would be done by auto-deref
2-
--> $DIR/explicit_auto_deref.rs:62:20
2+
--> $DIR/explicit_auto_deref.rs:63:20
33
|
44
LL | let _: &str = &*s;
55
| ^^ help: try this: `s`
66
|
77
= note: `-D clippy::explicit-auto-deref` implied by `-D warnings`
88

99
error: deref which would be done by auto-deref
10-
--> $DIR/explicit_auto_deref.rs:66:12
10+
--> $DIR/explicit_auto_deref.rs:67:12
1111
|
1212
LL | f_str(&*s);
1313
| ^^ help: try this: `s`
1414

1515
error: deref which would be done by auto-deref
16-
--> $DIR/explicit_auto_deref.rs:70:14
16+
--> $DIR/explicit_auto_deref.rs:71:14
1717
|
1818
LL | f_str_t(&*s, &*s); // Don't lint second param.
1919
| ^^ help: try this: `s`
2020

2121
error: deref which would be done by auto-deref
22-
--> $DIR/explicit_auto_deref.rs:73:25
22+
--> $DIR/explicit_auto_deref.rs:74:25
2323
|
2424
LL | let _: &Box<i32> = &**b;
2525
| ^^^ help: try this: `b`
2626

2727
error: deref which would be done by auto-deref
28-
--> $DIR/explicit_auto_deref.rs:79:8
28+
--> $DIR/explicit_auto_deref.rs:80:8
2929
|
3030
LL | c(&*s);
3131
| ^^ help: try this: `s`
3232

3333
error: deref which would be done by auto-deref
34-
--> $DIR/explicit_auto_deref.rs:85:9
34+
--> $DIR/explicit_auto_deref.rs:86:9
3535
|
3636
LL | &**x
3737
| ^^^^ help: try this: `x`
3838

3939
error: deref which would be done by auto-deref
40-
--> $DIR/explicit_auto_deref.rs:89:11
40+
--> $DIR/explicit_auto_deref.rs:90:11
4141
|
4242
LL | { &**x }
4343
| ^^^^ help: try this: `x`
4444

4545
error: deref which would be done by auto-deref
46-
--> $DIR/explicit_auto_deref.rs:93:9
46+
--> $DIR/explicit_auto_deref.rs:94:9
4747
|
4848
LL | &**{ x }
4949
| ^^^^^^^^ help: try this: `{ x }`
5050

5151
error: deref which would be done by auto-deref
52-
--> $DIR/explicit_auto_deref.rs:97:9
52+
--> $DIR/explicit_auto_deref.rs:98:9
5353
|
5454
LL | &***x
5555
| ^^^^^ help: try this: `x`
5656

5757
error: deref which would be done by auto-deref
58-
--> $DIR/explicit_auto_deref.rs:114:13
58+
--> $DIR/explicit_auto_deref.rs:115:13
5959
|
6060
LL | f1(&*x);
6161
| ^^ help: try this: `x`
6262

6363
error: deref which would be done by auto-deref
64-
--> $DIR/explicit_auto_deref.rs:115:13
64+
--> $DIR/explicit_auto_deref.rs:116:13
6565
|
6666
LL | f2(&*x);
6767
| ^^ help: try this: `x`
6868

6969
error: deref which would be done by auto-deref
70-
--> $DIR/explicit_auto_deref.rs:116:13
70+
--> $DIR/explicit_auto_deref.rs:117:13
7171
|
7272
LL | f3(&*x);
7373
| ^^ help: try this: `x`
7474

7575
error: deref which would be done by auto-deref
76-
--> $DIR/explicit_auto_deref.rs:117:28
76+
--> $DIR/explicit_auto_deref.rs:118:28
7777
|
7878
LL | f4.callable_str()(&*x);
7979
| ^^ help: try this: `x`
8080

8181
error: deref which would be done by auto-deref
82-
--> $DIR/explicit_auto_deref.rs:118:13
82+
--> $DIR/explicit_auto_deref.rs:119:13
8383
|
8484
LL | f5(&*x);
8585
| ^^ help: try this: `x`
8686

8787
error: deref which would be done by auto-deref
88-
--> $DIR/explicit_auto_deref.rs:119:13
88+
--> $DIR/explicit_auto_deref.rs:120:13
8989
|
9090
LL | f6(&*x);
9191
| ^^ help: try this: `x`
9292

9393
error: deref which would be done by auto-deref
94-
--> $DIR/explicit_auto_deref.rs:120:28
94+
--> $DIR/explicit_auto_deref.rs:121:28
9595
|
9696
LL | f7.callable_str()(&*x);
9797
| ^^ help: try this: `x`
9898

9999
error: deref which would be done by auto-deref
100-
--> $DIR/explicit_auto_deref.rs:121:26
100+
--> $DIR/explicit_auto_deref.rs:122:26
101101
|
102102
LL | f8.callable_t()(&*x);
103103
| ^^ help: try this: `x`
104104

105105
error: deref which would be done by auto-deref
106-
--> $DIR/explicit_auto_deref.rs:122:13
106+
--> $DIR/explicit_auto_deref.rs:123:13
107107
|
108108
LL | f9(&*x);
109109
| ^^ help: try this: `x`
110110

111111
error: deref which would be done by auto-deref
112-
--> $DIR/explicit_auto_deref.rs:123:14
112+
--> $DIR/explicit_auto_deref.rs:124:14
113113
|
114114
LL | f10(&*x);
115115
| ^^ help: try this: `x`
116116

117117
error: deref which would be done by auto-deref
118-
--> $DIR/explicit_auto_deref.rs:124:27
118+
--> $DIR/explicit_auto_deref.rs:125:27
119119
|
120120
LL | f11.callable_t()(&*x);
121121
| ^^ help: try this: `x`
122122

123123
error: deref which would be done by auto-deref
124-
--> $DIR/explicit_auto_deref.rs:128:17
124+
--> $DIR/explicit_auto_deref.rs:129:17
125125
|
126126
LL | let _ = S1(&*s);
127127
| ^^ help: try this: `s`
128128

129129
error: deref which would be done by auto-deref
130-
--> $DIR/explicit_auto_deref.rs:133:22
130+
--> $DIR/explicit_auto_deref.rs:134:22
131131
|
132132
LL | let _ = S2 { s: &*s };
133133
| ^^ help: try this: `s`
134134

135135
error: deref which would be done by auto-deref
136-
--> $DIR/explicit_auto_deref.rs:149:30
136+
--> $DIR/explicit_auto_deref.rs:150:30
137137
|
138138
LL | let _ = Self::S1(&**s);
139139
| ^^^^ help: try this: `s`
140140

141141
error: deref which would be done by auto-deref
142-
--> $DIR/explicit_auto_deref.rs:150:35
142+
--> $DIR/explicit_auto_deref.rs:151:35
143143
|
144144
LL | let _ = Self::S2 { s: &**s };
145145
| ^^^^ help: try this: `s`
146146

147147
error: deref which would be done by auto-deref
148-
--> $DIR/explicit_auto_deref.rs:153:21
148+
--> $DIR/explicit_auto_deref.rs:154:21
149149
|
150150
LL | let _ = E1::S1(&*s);
151151
| ^^ help: try this: `s`
152152

153153
error: deref which would be done by auto-deref
154-
--> $DIR/explicit_auto_deref.rs:154:26
154+
--> $DIR/explicit_auto_deref.rs:155:26
155155
|
156156
LL | let _ = E1::S2 { s: &*s };
157157
| ^^ help: try this: `s`
158158

159159
error: deref which would be done by auto-deref
160-
--> $DIR/explicit_auto_deref.rs:172:13
160+
--> $DIR/explicit_auto_deref.rs:173:13
161161
|
162162
LL | let _ = (*b).foo;
163163
| ^^^^ help: try this: `b`
164164

165165
error: deref which would be done by auto-deref
166-
--> $DIR/explicit_auto_deref.rs:173:13
166+
--> $DIR/explicit_auto_deref.rs:174:13
167167
|
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
@@ -1,7 +1,7 @@
11
// FIXME: run-rustfix waiting on multi-span suggestions
22

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

66
fn f1(_: &str) {}
77
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() {

0 commit comments

Comments
 (0)