Skip to content

Commit af0bc98

Browse files
authored
Check for proc macros from within explicit_deref_methods and do not lint on proc macro expansions (#15628)
Adds a `is_from_proc_macro(...,...)` check to the `explicit_deref_methods` lint. Note that this is my first contribution to clippy and i am not 100% sure that this is how such bugs are intended to be fixed, so please be kind with any feedback, I appreciate that a lot! Thanks! changelog: [`explicit_deref_methods`]: no longer triggers from within proc macro expansions fixes #15168
2 parents 14d36c7 + 3e65620 commit af0bc98

File tree

4 files changed

+52
-14
lines changed

4 files changed

+52
-14
lines changed

clippy_lints/src/dereference.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@ use clippy_utils::source::{snippet_with_applicability, snippet_with_context};
33
use clippy_utils::sugg::has_enclosing_paren;
44
use clippy_utils::ty::{adjust_derefs_manually_drop, implements_trait, is_manually_drop, peel_and_count_ty_refs};
55
use clippy_utils::{
6-
DefinedTy, ExprUseNode, expr_use_ctxt, get_parent_expr, is_block_like, is_lint_allowed, path_to_local,
6+
DefinedTy, ExprUseNode, expr_use_ctxt, get_parent_expr, is_block_like, is_from_proc_macro, is_lint_allowed,
7+
path_to_local,
78
};
89
use rustc_ast::util::parser::ExprPrecedence;
910
use rustc_data_structures::fx::FxIndexMap;
@@ -260,6 +261,13 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing<'tcx> {
260261
};
261262
self.skip_expr = skip_expr;
262263

264+
if is_from_proc_macro(cx, expr) {
265+
if let Some((state, data)) = self.state.take() {
266+
report(cx, expr, state, data, cx.typeck_results());
267+
}
268+
return;
269+
}
270+
263271
match (self.state.take(), kind) {
264272
(None, kind) => {
265273
let expr_ty = typeck.expr_ty(expr);

tests/ui/explicit_deref_methods.fixed

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
//@aux-build:proc_macros.rs
12
#![warn(clippy::explicit_deref_methods)]
23
#![allow(unused_variables, unused_must_use)]
34
#![allow(
@@ -14,6 +15,8 @@
1415

1516
use std::ops::{Deref, DerefMut};
1617

18+
extern crate proc_macros;
19+
1720
fn concat(deref_str: &str) -> String {
1821
format!("{}bar", deref_str)
1922
}
@@ -121,6 +124,18 @@ fn main() {
121124
let b: &str = expr_deref!(&*a);
122125
//~^ explicit_deref_methods
123126

127+
proc_macros::external! {
128+
let a: &mut String = &mut String::from("foo");
129+
let b: &str = a.deref();
130+
}
131+
132+
// Issue #15168
133+
proc_macros::with_span! {
134+
span
135+
let a: &mut String = &mut String::from("foo");
136+
let b: &str = a.deref();
137+
}
138+
124139
// The struct does not implement Deref trait
125140
#[derive(Copy, Clone)]
126141
struct NoLint(u32);

tests/ui/explicit_deref_methods.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
//@aux-build:proc_macros.rs
12
#![warn(clippy::explicit_deref_methods)]
23
#![allow(unused_variables, unused_must_use)]
34
#![allow(
@@ -14,6 +15,8 @@
1415

1516
use std::ops::{Deref, DerefMut};
1617

18+
extern crate proc_macros;
19+
1720
fn concat(deref_str: &str) -> String {
1821
format!("{}bar", deref_str)
1922
}
@@ -121,6 +124,18 @@ fn main() {
121124
let b: &str = expr_deref!(a.deref());
122125
//~^ explicit_deref_methods
123126

127+
proc_macros::external! {
128+
let a: &mut String = &mut String::from("foo");
129+
let b: &str = a.deref();
130+
}
131+
132+
// Issue #15168
133+
proc_macros::with_span! {
134+
span
135+
let a: &mut String = &mut String::from("foo");
136+
let b: &str = a.deref();
137+
}
138+
124139
// The struct does not implement Deref trait
125140
#[derive(Copy, Clone)]
126141
struct NoLint(u32);

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:58: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:61: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:65: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:65: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:69: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:73: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:78: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:81: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:84: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:124: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:154: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:156: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:157: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)