Skip to content

Commit 58befc7

Browse files
committed
Auto merge of #10855 - Centri3:explicit_deref_methods, r=llogiq
Fix suggestion on fully qualified syntax fixes #10850 changelog: [`explicit_deref_methods`]: Fix malformed suggestion on `Foo::deref(&foo)`
2 parents 167f249 + eed4662 commit 58befc7

File tree

4 files changed

+86
-19
lines changed

4 files changed

+86
-19
lines changed

clippy_lints/src/dereference.rs

+16-5
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,11 @@ declare_clippy_lint! {
5656
/// let b = &*a;
5757
/// ```
5858
///
59-
/// This lint excludes:
59+
/// This lint excludes all of:
6060
/// ```rust,ignore
6161
/// let _ = d.unwrap().deref();
62+
/// let _ = Foo::deref(&foo);
63+
/// let _ = <Foo as Deref>::deref(&foo);
6264
/// ```
6365
#[clippy::version = "1.44.0"]
6466
pub EXPLICIT_DEREF_METHODS,
@@ -1480,7 +1482,7 @@ fn report<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, state: State, data
14801482
target_mut,
14811483
} => {
14821484
let mut app = Applicability::MachineApplicable;
1483-
let (expr_str, expr_is_macro_call) = snippet_with_context(cx, expr.span, data.span.ctxt(), "..", &mut app);
1485+
let (expr_str, _expr_is_macro_call) = snippet_with_context(cx, expr.span, data.span.ctxt(), "..", &mut app);
14841486
let ty = cx.typeck_results().expr_ty(expr);
14851487
let (_, ref_count) = peel_mid_ty_refs(ty);
14861488
let deref_str = if ty_changed_count >= ref_count && ref_count != 0 {
@@ -1503,11 +1505,20 @@ fn report<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, state: State, data
15031505
"&"
15041506
};
15051507

1506-
let expr_str = if !expr_is_macro_call && is_final_ufcs && expr.precedence().order() < PREC_PREFIX {
1507-
format!("({expr_str})")
1508+
// expr_str (the suggestion) is never shown if is_final_ufcs is true, since it's
1509+
// `expr.kind == ExprKind::Call`. Therefore, this is, afaik, always unnecessary.
1510+
/*
1511+
expr_str = if !expr_is_macro_call && is_final_ufcs && expr.precedence().order() < PREC_PREFIX {
1512+
Cow::Owned(format!("({expr_str})"))
15081513
} else {
1509-
expr_str.into_owned()
1514+
expr_str
15101515
};
1516+
*/
1517+
1518+
// Fix #10850, do not lint if it's `Foo::deref` instead of `foo.deref()`.
1519+
if is_final_ufcs {
1520+
return;
1521+
}
15111522

15121523
span_lint_and_sugg(
15131524
cx,

tests/ui/explicit_deref_methods.fixed

+29-1
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
//@run-rustfix
22
#![warn(clippy::explicit_deref_methods)]
3-
#![allow(unused_variables)]
3+
#![allow(unused_variables, unused_must_use)]
44
#![allow(
55
clippy::borrow_deref_ref,
66
suspicious_double_ref_op,
77
clippy::explicit_auto_deref,
88
clippy::needless_borrow,
9+
clippy::no_effect,
910
clippy::uninlined_format_args
1011
)]
1112

@@ -28,6 +29,22 @@ impl Deref for CustomVec {
2829
}
2930
}
3031

32+
struct Aaa;
33+
34+
impl Deref for Aaa {
35+
type Target = ();
36+
37+
fn deref(&self) -> &Self::Target {
38+
todo!();
39+
}
40+
}
41+
42+
impl DerefMut for Aaa {
43+
fn deref_mut(&mut self) -> &mut Self::Target {
44+
todo!();
45+
}
46+
}
47+
3148
fn main() {
3249
let a: &mut String = &mut String::from("foo");
3350

@@ -58,6 +75,17 @@ fn main() {
5875
let opt_a = Some(a.clone());
5976
let b = &*opt_a.unwrap();
6077

78+
// make sure `Aaa::deref` instead of `aaa.deref()` is not linted, as well as fully qualified
79+
// syntax
80+
81+
Aaa::deref(&Aaa);
82+
Aaa::deref_mut(&mut Aaa);
83+
<Aaa as Deref>::deref(&Aaa);
84+
<Aaa as DerefMut>::deref_mut(&mut Aaa);
85+
let mut aaa = Aaa;
86+
Aaa::deref(&aaa);
87+
Aaa::deref_mut(&mut aaa);
88+
6189
// following should not require linting
6290

6391
let cv = CustomVec(vec![0, 42]);

tests/ui/explicit_deref_methods.rs

+29-1
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
//@run-rustfix
22
#![warn(clippy::explicit_deref_methods)]
3-
#![allow(unused_variables)]
3+
#![allow(unused_variables, unused_must_use)]
44
#![allow(
55
clippy::borrow_deref_ref,
66
suspicious_double_ref_op,
77
clippy::explicit_auto_deref,
88
clippy::needless_borrow,
9+
clippy::no_effect,
910
clippy::uninlined_format_args
1011
)]
1112

@@ -28,6 +29,22 @@ impl Deref for CustomVec {
2829
}
2930
}
3031

32+
struct Aaa;
33+
34+
impl Deref for Aaa {
35+
type Target = ();
36+
37+
fn deref(&self) -> &Self::Target {
38+
todo!();
39+
}
40+
}
41+
42+
impl DerefMut for Aaa {
43+
fn deref_mut(&mut self) -> &mut Self::Target {
44+
todo!();
45+
}
46+
}
47+
3148
fn main() {
3249
let a: &mut String = &mut String::from("foo");
3350

@@ -58,6 +75,17 @@ fn main() {
5875
let opt_a = Some(a.clone());
5976
let b = opt_a.unwrap().deref();
6077

78+
// make sure `Aaa::deref` instead of `aaa.deref()` is not linted, as well as fully qualified
79+
// syntax
80+
81+
Aaa::deref(&Aaa);
82+
Aaa::deref_mut(&mut Aaa);
83+
<Aaa as Deref>::deref(&Aaa);
84+
<Aaa as DerefMut>::deref_mut(&mut Aaa);
85+
let mut aaa = Aaa;
86+
Aaa::deref(&aaa);
87+
Aaa::deref_mut(&mut aaa);
88+
6189
// following should not require linting
6290

6391
let cv = CustomVec(vec![0, 42]);

tests/ui/explicit_deref_methods.stderr

+12-12
Original file line numberDiff line numberDiff line change
@@ -1,73 +1,73 @@
11
error: explicit `deref` method call
2-
--> $DIR/explicit_deref_methods.rs:36:19
2+
--> $DIR/explicit_deref_methods.rs:53:19
33
|
44
LL | let b: &str = a.deref();
55
| ^^^^^^^^^ help: try this: `&*a`
66
|
77
= note: `-D clippy::explicit-deref-methods` implied by `-D warnings`
88

99
error: explicit `deref_mut` method call
10-
--> $DIR/explicit_deref_methods.rs:38:23
10+
--> $DIR/explicit_deref_methods.rs:55:23
1111
|
1212
LL | let b: &mut str = a.deref_mut();
1313
| ^^^^^^^^^^^^^ help: try this: `&mut **a`
1414

1515
error: explicit `deref` method call
16-
--> $DIR/explicit_deref_methods.rs:41:39
16+
--> $DIR/explicit_deref_methods.rs:58:39
1717
|
1818
LL | let b: String = format!("{}, {}", a.deref(), a.deref());
1919
| ^^^^^^^^^ help: try this: `&*a`
2020

2121
error: explicit `deref` method call
22-
--> $DIR/explicit_deref_methods.rs:41:50
22+
--> $DIR/explicit_deref_methods.rs:58:50
2323
|
2424
LL | let b: String = format!("{}, {}", a.deref(), a.deref());
2525
| ^^^^^^^^^ help: try this: `&*a`
2626

2727
error: explicit `deref` method call
28-
--> $DIR/explicit_deref_methods.rs:43:20
28+
--> $DIR/explicit_deref_methods.rs:60:20
2929
|
3030
LL | println!("{}", a.deref());
3131
| ^^^^^^^^^ help: try this: `&*a`
3232

3333
error: explicit `deref` method call
34-
--> $DIR/explicit_deref_methods.rs:46:11
34+
--> $DIR/explicit_deref_methods.rs:63:11
3535
|
3636
LL | match a.deref() {
3737
| ^^^^^^^^^ help: try this: `&*a`
3838

3939
error: explicit `deref` method call
40-
--> $DIR/explicit_deref_methods.rs:50:28
40+
--> $DIR/explicit_deref_methods.rs:67:28
4141
|
4242
LL | let b: String = concat(a.deref());
4343
| ^^^^^^^^^ help: try this: `&*a`
4444

4545
error: explicit `deref` method call
46-
--> $DIR/explicit_deref_methods.rs:52:13
46+
--> $DIR/explicit_deref_methods.rs:69:13
4747
|
4848
LL | let b = just_return(a).deref();
4949
| ^^^^^^^^^^^^^^^^^^^^^^ help: try this: `just_return(a)`
5050

5151
error: explicit `deref` method call
52-
--> $DIR/explicit_deref_methods.rs:54:28
52+
--> $DIR/explicit_deref_methods.rs:71:28
5353
|
5454
LL | let b: String = concat(just_return(a).deref());
5555
| ^^^^^^^^^^^^^^^^^^^^^^ help: try this: `just_return(a)`
5656

5757
error: explicit `deref` method call
58-
--> $DIR/explicit_deref_methods.rs:56:19
58+
--> $DIR/explicit_deref_methods.rs:73:19
5959
|
6060
LL | let b: &str = a.deref().deref();
6161
| ^^^^^^^^^^^^^^^^^ help: try this: `&**a`
6262

6363
error: explicit `deref` method call
64-
--> $DIR/explicit_deref_methods.rs:59:13
64+
--> $DIR/explicit_deref_methods.rs:76:13
6565
|
6666
LL | let b = opt_a.unwrap().deref();
6767
| ^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&*opt_a.unwrap()`
6868

6969
error: explicit `deref` method call
70-
--> $DIR/explicit_deref_methods.rs:85:31
70+
--> $DIR/explicit_deref_methods.rs:113:31
7171
|
7272
LL | let b: &str = expr_deref!(a.deref());
7373
| ^^^^^^^^^ help: try this: `&*a`

0 commit comments

Comments
 (0)