Skip to content

Commit 8bcc093

Browse files
committed
fix(equatable_if_let): don't lint if pattern or initializer come from expansion
1 parent 2b5f831 commit 8bcc093

File tree

4 files changed

+155
-39
lines changed

4 files changed

+155
-39
lines changed

clippy_lints/src/equatable_if_let.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,8 @@ impl<'tcx> LateLintPass<'tcx> for PatternEquality {
105105
if let ExprKind::Let(let_expr) = expr.kind
106106
&& is_unary_pattern(let_expr.pat)
107107
&& !expr.span.in_external_macro(cx.sess().source_map())
108+
&& !let_expr.pat.span.from_expansion()
109+
&& !let_expr.init.span.from_expansion()
108110
{
109111
let exp_ty = cx.typeck_results().expr_ty(let_expr.init);
110112
let pat_ty = cx.typeck_results().pat_ty(let_expr.pat);

tests/ui/equatable_if_let.fixed

Lines changed: 68 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@ impl PartialEq for NotStructuralEq {
4040
}
4141
}
4242

43-
#[inline_macros]
4443
fn main() {
4544
let a = 2;
4645
let b = 3;
@@ -87,13 +86,6 @@ fn main() {
8786
//~^ equatable_if_let
8887
if matches!(h, NoPartialEqStruct { a: 2, b: false }) {}
8988
//~^ equatable_if_let
90-
91-
if "abc" == inline!("abc") {
92-
//~^ equatable_if_let
93-
println!("OK");
94-
}
95-
96-
external!({ if let 2 = $a {} });
9789
}
9890

9991
mod issue8710 {
@@ -131,3 +123,71 @@ mod issue8710 {
131123
}
132124
}
133125
}
126+
127+
#[inline_macros]
128+
fn issue14548() {
129+
if let inline!("abc") = "abc" {
130+
println!("OK");
131+
}
132+
133+
let a = 2;
134+
external!({ if let 2 = $a {} });
135+
136+
// Don't lint: `==`/`matches!` might be correct for a particular `$($font)|*`, but not in general
137+
macro_rules! m1 {
138+
($($font:pat_param)|*) => {
139+
if let $($font)|* = "from_expansion" {}
140+
}
141+
}
142+
m1!("foo");
143+
m1!("Sans" | "Serif" | "Sans Mono");
144+
m1!(inline!("foo"));
145+
146+
// Don't lint: the suggestion might be correct for a particular `$from_root_ctxt`, but not in
147+
// general
148+
macro_rules! m2 {
149+
($from_root_ctxt:pat) => {
150+
if let $from_root_ctxt = "from_expansion" {}
151+
};
152+
}
153+
m2!("foo");
154+
m2!("Sans" | "Serif" | "Sans Mono");
155+
m2!(inline!("foo"));
156+
157+
// Don't lint: the suggestion might be correct for a particular `$from_root_ctxt`, but not in
158+
// general
159+
macro_rules! m3 {
160+
($from_root_ctxt:expr) => {
161+
if let "from_expansion" = $from_root_ctxt {}
162+
};
163+
}
164+
m3!("foo");
165+
m3!("foo");
166+
m3!(inline!("foo"));
167+
168+
// Don't lint: the suggestion might be correct for a particular `$from_root_ctxt`, but not in
169+
// general. Don't get confused by the scrutinee coming from macro invocation
170+
macro_rules! m4 {
171+
($from_root_ctxt:pat) => {
172+
if let $from_root_ctxt = inline!("from_expansion") {}
173+
};
174+
}
175+
m4!("foo");
176+
m4!("Sans" | "Serif" | "Sans Mono");
177+
m4!(inline!("foo"));
178+
179+
// Don't lint: the suggestion might be correct for a particular `$from_root_ctxt`, but not in
180+
// general. Don't get confused by the scrutinee coming from macro invocation
181+
macro_rules! m5 {
182+
($from_root_ctxt:expr) => {
183+
if let inline!("from_expansion") = $from_root_ctxt {}
184+
};
185+
}
186+
m5!("foo");
187+
m5!("foo");
188+
m5!(inline!("foo"));
189+
190+
// (Would be nice to) lint: both sides are macro _invocations_, so the suggestion is correct in
191+
// general
192+
if let inline!("foo") = inline!("bar") {}
193+
}

tests/ui/equatable_if_let.rs

Lines changed: 68 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@ impl PartialEq for NotStructuralEq {
4040
}
4141
}
4242

43-
#[inline_macros]
4443
fn main() {
4544
let a = 2;
4645
let b = 3;
@@ -87,13 +86,6 @@ fn main() {
8786
//~^ equatable_if_let
8887
if let NoPartialEqStruct { a: 2, b: false } = h {}
8988
//~^ equatable_if_let
90-
91-
if let inline!("abc") = "abc" {
92-
//~^ equatable_if_let
93-
println!("OK");
94-
}
95-
96-
external!({ if let 2 = $a {} });
9789
}
9890

9991
mod issue8710 {
@@ -131,3 +123,71 @@ mod issue8710 {
131123
}
132124
}
133125
}
126+
127+
#[inline_macros]
128+
fn issue14548() {
129+
if let inline!("abc") = "abc" {
130+
println!("OK");
131+
}
132+
133+
let a = 2;
134+
external!({ if let 2 = $a {} });
135+
136+
// Don't lint: `==`/`matches!` might be correct for a particular `$($font)|*`, but not in general
137+
macro_rules! m1 {
138+
($($font:pat_param)|*) => {
139+
if let $($font)|* = "from_expansion" {}
140+
}
141+
}
142+
m1!("foo");
143+
m1!("Sans" | "Serif" | "Sans Mono");
144+
m1!(inline!("foo"));
145+
146+
// Don't lint: the suggestion might be correct for a particular `$from_root_ctxt`, but not in
147+
// general
148+
macro_rules! m2 {
149+
($from_root_ctxt:pat) => {
150+
if let $from_root_ctxt = "from_expansion" {}
151+
};
152+
}
153+
m2!("foo");
154+
m2!("Sans" | "Serif" | "Sans Mono");
155+
m2!(inline!("foo"));
156+
157+
// Don't lint: the suggestion might be correct for a particular `$from_root_ctxt`, but not in
158+
// general
159+
macro_rules! m3 {
160+
($from_root_ctxt:expr) => {
161+
if let "from_expansion" = $from_root_ctxt {}
162+
};
163+
}
164+
m3!("foo");
165+
m3!("foo");
166+
m3!(inline!("foo"));
167+
168+
// Don't lint: the suggestion might be correct for a particular `$from_root_ctxt`, but not in
169+
// general. Don't get confused by the scrutinee coming from macro invocation
170+
macro_rules! m4 {
171+
($from_root_ctxt:pat) => {
172+
if let $from_root_ctxt = inline!("from_expansion") {}
173+
};
174+
}
175+
m4!("foo");
176+
m4!("Sans" | "Serif" | "Sans Mono");
177+
m4!(inline!("foo"));
178+
179+
// Don't lint: the suggestion might be correct for a particular `$from_root_ctxt`, but not in
180+
// general. Don't get confused by the scrutinee coming from macro invocation
181+
macro_rules! m5 {
182+
($from_root_ctxt:expr) => {
183+
if let inline!("from_expansion") = $from_root_ctxt {}
184+
};
185+
}
186+
m5!("foo");
187+
m5!("foo");
188+
m5!(inline!("foo"));
189+
190+
// (Would be nice to) lint: both sides are macro _invocations_, so the suggestion is correct in
191+
// general
192+
if let inline!("foo") = inline!("bar") {}
193+
}

tests/ui/equatable_if_let.stderr

Lines changed: 17 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error: this pattern matching can be expressed using equality
2-
--> tests/ui/equatable_if_let.rs:56:8
2+
--> tests/ui/equatable_if_let.rs:55:8
33
|
44
LL | if let 2 = a {}
55
| ^^^^^^^^^ help: try: `a == 2`
@@ -8,100 +8,94 @@ LL | if let 2 = a {}
88
= help: to override `-D warnings` add `#[allow(clippy::equatable_if_let)]`
99

1010
error: this pattern matching can be expressed using equality
11-
--> tests/ui/equatable_if_let.rs:58:8
11+
--> tests/ui/equatable_if_let.rs:57:8
1212
|
1313
LL | if let Ordering::Greater = a.cmp(&b) {}
1414
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `a.cmp(&b) == Ordering::Greater`
1515

1616
error: this pattern matching can be expressed using equality
17-
--> tests/ui/equatable_if_let.rs:60:8
17+
--> tests/ui/equatable_if_let.rs:59:8
1818
|
1919
LL | if let Some(2) = c {}
2020
| ^^^^^^^^^^^^^^^ help: try: `c == Some(2)`
2121

2222
error: this pattern matching can be expressed using equality
23-
--> tests/ui/equatable_if_let.rs:62:8
23+
--> tests/ui/equatable_if_let.rs:61:8
2424
|
2525
LL | if let Struct { a: 2, b: false } = d {}
2626
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `d == (Struct { a: 2, b: false })`
2727

2828
error: this pattern matching can be expressed using equality
29-
--> tests/ui/equatable_if_let.rs:64:8
29+
--> tests/ui/equatable_if_let.rs:63:8
3030
|
3131
LL | if let Enum::TupleVariant(32, 64) = e {}
3232
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `e == Enum::TupleVariant(32, 64)`
3333

3434
error: this pattern matching can be expressed using equality
35-
--> tests/ui/equatable_if_let.rs:66:8
35+
--> tests/ui/equatable_if_let.rs:65:8
3636
|
3737
LL | if let Enum::RecordVariant { a: 64, b: 32 } = e {}
3838
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `e == (Enum::RecordVariant { a: 64, b: 32 })`
3939

4040
error: this pattern matching can be expressed using equality
41-
--> tests/ui/equatable_if_let.rs:68:8
41+
--> tests/ui/equatable_if_let.rs:67:8
4242
|
4343
LL | if let Enum::UnitVariant = e {}
4444
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `e == Enum::UnitVariant`
4545

4646
error: this pattern matching can be expressed using equality
47-
--> tests/ui/equatable_if_let.rs:70:8
47+
--> tests/ui/equatable_if_let.rs:69:8
4848
|
4949
LL | if let (Enum::UnitVariant, &Struct { a: 2, b: false }) = (e, &d) {}
5050
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `(e, &d) == (Enum::UnitVariant, &Struct { a: 2, b: false })`
5151

5252
error: this pattern matching can be expressed using `matches!`
53-
--> tests/ui/equatable_if_let.rs:80:8
53+
--> tests/ui/equatable_if_let.rs:79:8
5454
|
5555
LL | if let NotPartialEq::A = f {}
5656
| ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `matches!(f, NotPartialEq::A)`
5757

5858
error: this pattern matching can be expressed using equality
59-
--> tests/ui/equatable_if_let.rs:82:8
59+
--> tests/ui/equatable_if_let.rs:81:8
6060
|
6161
LL | if let NotStructuralEq::A = g {}
6262
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `g == NotStructuralEq::A`
6363

6464
error: this pattern matching can be expressed using `matches!`
65-
--> tests/ui/equatable_if_let.rs:84:8
65+
--> tests/ui/equatable_if_let.rs:83:8
6666
|
6767
LL | if let Some(NotPartialEq::A) = Some(f) {}
6868
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `matches!(Some(f), Some(NotPartialEq::A))`
6969

7070
error: this pattern matching can be expressed using equality
71-
--> tests/ui/equatable_if_let.rs:86:8
71+
--> tests/ui/equatable_if_let.rs:85:8
7272
|
7373
LL | if let Some(NotStructuralEq::A) = Some(g) {}
7474
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Some(g) == Some(NotStructuralEq::A)`
7575

7676
error: this pattern matching can be expressed using `matches!`
77-
--> tests/ui/equatable_if_let.rs:88:8
77+
--> tests/ui/equatable_if_let.rs:87:8
7878
|
7979
LL | if let NoPartialEqStruct { a: 2, b: false } = h {}
8080
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `matches!(h, NoPartialEqStruct { a: 2, b: false })`
8181

82-
error: this pattern matching can be expressed using equality
83-
--> tests/ui/equatable_if_let.rs:91:8
84-
|
85-
LL | if let inline!("abc") = "abc" {
86-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `"abc" == inline!("abc")`
87-
8882
error: this pattern matching can be expressed using `matches!`
89-
--> tests/ui/equatable_if_let.rs:101:12
83+
--> tests/ui/equatable_if_let.rs:93:12
9084
|
9185
LL | if let Some('i') = cs.iter().next() {
9286
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `matches!(cs.iter().next(), Some('i'))`
9387

9488
error: this pattern matching can be expressed using `matches!`
95-
--> tests/ui/equatable_if_let.rs:109:12
89+
--> tests/ui/equatable_if_let.rs:101:12
9690
|
9791
LL | if let Some(1) = cs.iter().next() {
9892
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `matches!(cs.iter().next(), Some(1))`
9993

10094
error: this pattern matching can be expressed using `matches!`
101-
--> tests/ui/equatable_if_let.rs:127:12
95+
--> tests/ui/equatable_if_let.rs:119:12
10296
|
10397
LL | if let Some(MyEnum::B) = get_enum() {
10498
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `matches!(get_enum(), Some(MyEnum::B))`
10599

106-
error: aborting due to 17 previous errors
100+
error: aborting due to 16 previous errors
107101

0 commit comments

Comments
 (0)