Skip to content

Commit 94eb537

Browse files
committed
allow explicit deref method call in deref or deref_mut impl of Deref trait
1 parent 2a6197e commit 94eb537

File tree

4 files changed

+86
-13
lines changed

4 files changed

+86
-13
lines changed

clippy_lints/src/dereference.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -937,6 +937,19 @@ fn report<'tcx>(
937937
is_ufcs,
938938
mutbl,
939939
} => {
940+
// Skip when inside a `deref` or `deref_mut` implementation of the `Deref` trait.
941+
let fn_def_id = cx.tcx.hir_enclosing_body_owner(expr.hir_id).to_def_id();
942+
if !cx.tcx.is_closure_like(fn_def_id)
943+
&& matches!(cx.tcx.item_name(fn_def_id), sym::deref | sym::deref_mut)
944+
&& let Some(impl_defid) = cx.tcx.impl_of_assoc(fn_def_id)
945+
&& let Some(impl_trait_ref) = cx.tcx.impl_trait_ref(impl_defid)
946+
&& cx
947+
.tcx
948+
.is_diagnostic_item(sym::Deref, impl_trait_ref.skip_binder().def_id)
949+
{
950+
return;
951+
}
952+
940953
let mut app = Applicability::MachineApplicable;
941954
let (expr_str, expr_is_macro_call) =
942955
snippet_with_context(cx, expr.span, data.first_expr.span.ctxt(), "..", &mut app);

tests/ui/explicit_deref_methods.fixed

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,36 @@ impl DerefMut for Aaa {
4747
}
4848
}
4949

50+
mod issue_15392 {
51+
use std::ops::{Deref, DerefMut};
52+
53+
struct Inner;
54+
55+
struct WrapperA(Inner);
56+
57+
impl Deref for WrapperA {
58+
type Target = Inner;
59+
fn deref(&self) -> &Inner {
60+
&self.0
61+
}
62+
}
63+
64+
enum MyEnum {
65+
A(WrapperA),
66+
}
67+
68+
impl Deref for MyEnum {
69+
type Target = Inner;
70+
71+
fn deref(&self) -> &Inner {
72+
// forwarding is ok
73+
match self {
74+
MyEnum::A(wrap_a) => Deref::deref(wrap_a),
75+
}
76+
}
77+
}
78+
}
79+
5080
fn main() {
5181
let a: &mut String = &mut String::from("foo");
5282

tests/ui/explicit_deref_methods.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,36 @@ impl DerefMut for Aaa {
4747
}
4848
}
4949

50+
mod issue_15392 {
51+
use std::ops::{Deref, DerefMut};
52+
53+
struct Inner;
54+
55+
struct WrapperA(Inner);
56+
57+
impl Deref for WrapperA {
58+
type Target = Inner;
59+
fn deref(&self) -> &Inner {
60+
&self.0
61+
}
62+
}
63+
64+
enum MyEnum {
65+
A(WrapperA),
66+
}
67+
68+
impl Deref for MyEnum {
69+
type Target = Inner;
70+
71+
fn deref(&self) -> &Inner {
72+
// forwarding is ok
73+
match self {
74+
MyEnum::A(wrap_a) => Deref::deref(wrap_a),
75+
}
76+
}
77+
}
78+
}
79+
5080
fn main() {
5181
let a: &mut String = &mut String::from("foo");
5282

tests/ui/explicit_deref_methods.stderr

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error: explicit `deref` method call
2-
--> tests/ui/explicit_deref_methods.rs:55:19
2+
--> tests/ui/explicit_deref_methods.rs:85:19
33
|
44
LL | let b: &str = a.deref();
55
| ^^^^^^^^^ help: try: `&*a`
@@ -8,73 +8,73 @@ LL | let b: &str = a.deref();
88
= help: to override `-D warnings` add `#[allow(clippy::explicit_deref_methods)]`
99

1010
error: explicit `deref_mut` method call
11-
--> tests/ui/explicit_deref_methods.rs:58:23
11+
--> tests/ui/explicit_deref_methods.rs:88:23
1212
|
1313
LL | let b: &mut str = a.deref_mut();
1414
| ^^^^^^^^^^^^^ help: try: `&mut **a`
1515

1616
error: explicit `deref` method call
17-
--> tests/ui/explicit_deref_methods.rs:62:39
17+
--> tests/ui/explicit_deref_methods.rs:92:39
1818
|
1919
LL | let b: String = format!("{}, {}", a.deref(), a.deref());
2020
| ^^^^^^^^^ help: try: `&*a`
2121

2222
error: explicit `deref` method call
23-
--> tests/ui/explicit_deref_methods.rs:62:50
23+
--> tests/ui/explicit_deref_methods.rs:92:50
2424
|
2525
LL | let b: String = format!("{}, {}", a.deref(), a.deref());
2626
| ^^^^^^^^^ help: try: `&*a`
2727

2828
error: explicit `deref` method call
29-
--> tests/ui/explicit_deref_methods.rs:66:20
29+
--> tests/ui/explicit_deref_methods.rs:96:20
3030
|
3131
LL | println!("{}", a.deref());
3232
| ^^^^^^^^^ help: try: `&*a`
3333

3434
error: explicit `deref` method call
35-
--> tests/ui/explicit_deref_methods.rs:70:11
35+
--> tests/ui/explicit_deref_methods.rs:100:11
3636
|
3737
LL | match a.deref() {
3838
| ^^^^^^^^^ help: try: `&*a`
3939

4040
error: explicit `deref` method call
41-
--> tests/ui/explicit_deref_methods.rs:75:28
41+
--> tests/ui/explicit_deref_methods.rs:105:28
4242
|
4343
LL | let b: String = concat(a.deref());
4444
| ^^^^^^^^^ help: try: `&*a`
4545

4646
error: explicit `deref` method call
47-
--> tests/ui/explicit_deref_methods.rs:78:13
47+
--> tests/ui/explicit_deref_methods.rs:108:13
4848
|
4949
LL | let b = just_return(a).deref();
5050
| ^^^^^^^^^^^^^^^^^^^^^^ help: try: `just_return(a)`
5151

5252
error: explicit `deref` method call
53-
--> tests/ui/explicit_deref_methods.rs:81:28
53+
--> tests/ui/explicit_deref_methods.rs:111:28
5454
|
5555
LL | let b: String = concat(just_return(a).deref());
5656
| ^^^^^^^^^^^^^^^^^^^^^^ help: try: `just_return(a)`
5757

5858
error: explicit `deref` method call
59-
--> tests/ui/explicit_deref_methods.rs:121:31
59+
--> tests/ui/explicit_deref_methods.rs:151:31
6060
|
6161
LL | let b: &str = expr_deref!(a.deref());
6262
| ^^^^^^^^^ help: try: `&*a`
6363

6464
error: explicit `deref` method call
65-
--> tests/ui/explicit_deref_methods.rs:139:14
65+
--> tests/ui/explicit_deref_methods.rs:169:14
6666
|
6767
LL | let _ = &Deref::deref(&"foo");
6868
| ^^^^^^^^^^^^^^^^^^^^ help: try: `*&"foo"`
6969

7070
error: explicit `deref_mut` method call
71-
--> tests/ui/explicit_deref_methods.rs:141:14
71+
--> tests/ui/explicit_deref_methods.rs:171:14
7272
|
7373
LL | let _ = &DerefMut::deref_mut(&mut x);
7474
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&mut **&mut x`
7575

7676
error: explicit `deref_mut` method call
77-
--> tests/ui/explicit_deref_methods.rs:142:14
77+
--> tests/ui/explicit_deref_methods.rs:172:14
7878
|
7979
LL | let _ = &DerefMut::deref_mut((&mut &mut x).deref_mut());
8080
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&mut ***(&mut &mut x)`

0 commit comments

Comments
 (0)