Skip to content

Commit c36b5b5

Browse files
committed
allow explicit deref method call in deref or deref_mut impl of Deref trait
1 parent 30c73fe commit c36b5b5

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
@@ -945,6 +945,19 @@ fn report<'tcx>(
945945
is_ufcs,
946946
mutbl,
947947
} => {
948+
// Skip when inside a `deref` or `deref_mut` implementation of the `Deref` trait.
949+
let fn_def_id = cx.tcx.hir_enclosing_body_owner(expr.hir_id).to_def_id();
950+
if !cx.tcx.is_closure_like(fn_def_id)
951+
&& matches!(cx.tcx.item_name(fn_def_id), sym::deref | sym::deref_mut)
952+
&& let Some(impl_defid) = cx.tcx.impl_of_assoc(fn_def_id)
953+
&& let Some(impl_trait_ref) = cx.tcx.impl_trait_ref(impl_defid)
954+
&& cx
955+
.tcx
956+
.is_diagnostic_item(sym::Deref, impl_trait_ref.skip_binder().def_id)
957+
{
958+
return;
959+
}
960+
948961
let mut app = Applicability::MachineApplicable;
949962
let (expr_str, expr_is_macro_call) =
950963
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
@@ -50,6 +50,36 @@ impl DerefMut for Aaa {
5050
}
5151
}
5252

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

tests/ui/explicit_deref_methods.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,36 @@ impl DerefMut for Aaa {
5050
}
5151
}
5252

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

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:58:19
2+
--> tests/ui/explicit_deref_methods.rs:88: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:61:23
11+
--> tests/ui/explicit_deref_methods.rs:91: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:65:39
17+
--> tests/ui/explicit_deref_methods.rs:95: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:65:50
23+
--> tests/ui/explicit_deref_methods.rs:95: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:69:20
29+
--> tests/ui/explicit_deref_methods.rs:99: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:73:11
35+
--> tests/ui/explicit_deref_methods.rs:103: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:78:28
41+
--> tests/ui/explicit_deref_methods.rs:108: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:81:13
47+
--> tests/ui/explicit_deref_methods.rs:111: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:84:28
53+
--> tests/ui/explicit_deref_methods.rs:114: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:124:31
59+
--> tests/ui/explicit_deref_methods.rs:154: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:154:14
65+
--> tests/ui/explicit_deref_methods.rs:184: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:156:14
71+
--> tests/ui/explicit_deref_methods.rs:186: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:157:14
77+
--> tests/ui/explicit_deref_methods.rs:187: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)