diff --git a/clippy_lints/src/equatable_if_let.rs b/clippy_lints/src/equatable_if_let.rs index 036a843c8507..a92bfd45df0c 100644 --- a/clippy_lints/src/equatable_if_let.rs +++ b/clippy_lints/src/equatable_if_let.rs @@ -106,6 +106,8 @@ impl<'tcx> LateLintPass<'tcx> for PatternEquality { if let ExprKind::Let(let_expr) = expr.kind && is_unary_pattern(let_expr.pat) && !expr.span.in_external_macro(cx.sess().source_map()) + && !let_expr.pat.span.from_expansion() + && !let_expr.init.span.from_expansion() { let exp_ty = cx.typeck_results().expr_ty(let_expr.init); let pat_ty = cx.typeck_results().pat_ty(let_expr.pat); diff --git a/tests/ui/equatable_if_let.fixed b/tests/ui/equatable_if_let.fixed index f1f4fed13dd8..2cf69cf7b2fd 100644 --- a/tests/ui/equatable_if_let.fixed +++ b/tests/ui/equatable_if_let.fixed @@ -40,7 +40,6 @@ impl PartialEq for NotStructuralEq { } } -#[inline_macros] fn main() { let a = 2; let b = 3; @@ -87,13 +86,6 @@ fn main() { //~^ equatable_if_let if matches!(h, NoPartialEqStruct { a: 2, b: false }) {} //~^ equatable_if_let - - if "abc" == inline!("abc") { - //~^ equatable_if_let - println!("OK"); - } - - external!({ if let 2 = $a {} }); } mod issue8710 { @@ -132,6 +124,74 @@ mod issue8710 { } } +#[inline_macros] +fn issue14548() { + if let inline!("abc") = "abc" { + println!("OK"); + } + + let a = 2; + external!({ if let 2 = $a {} }); + + // Don't lint: `==`/`matches!` might be correct for a particular `$($font)|*`, but not in general + macro_rules! m1 { + ($($font:pat_param)|*) => { + if let $($font)|* = "from_expansion" {} + } + } + m1!("foo"); + m1!("Sans" | "Serif" | "Sans Mono"); + m1!(inline!("foo")); + + // Don't lint: the suggestion might be correct for a particular `$from_root_ctxt`, but not in + // general + macro_rules! m2 { + ($from_root_ctxt:pat) => { + if let $from_root_ctxt = "from_expansion" {} + }; + } + m2!("foo"); + m2!("Sans" | "Serif" | "Sans Mono"); + m2!(inline!("foo")); + + // Don't lint: the suggestion might be correct for a particular `$from_root_ctxt`, but not in + // general + macro_rules! m3 { + ($from_root_ctxt:expr) => { + if let "from_expansion" = $from_root_ctxt {} + }; + } + m3!("foo"); + m3!("foo"); + m3!(inline!("foo")); + + // Don't lint: the suggestion might be correct for a particular `$from_root_ctxt`, but not in + // general. Don't get confused by the scrutinee coming from macro invocation + macro_rules! m4 { + ($from_root_ctxt:pat) => { + if let $from_root_ctxt = inline!("from_expansion") {} + }; + } + m4!("foo"); + m4!("Sans" | "Serif" | "Sans Mono"); + m4!(inline!("foo")); + + // Don't lint: the suggestion might be correct for a particular `$from_root_ctxt`, but not in + // general. Don't get confused by the scrutinee coming from macro invocation + macro_rules! m5 { + ($from_root_ctxt:expr) => { + if let inline!("from_expansion") = $from_root_ctxt {} + }; + } + m5!("foo"); + m5!("foo"); + m5!(inline!("foo")); + + // Would be nice to lint: both sides are macro _invocations_, so the suggestion is correct in + // general + if let inline!("foo") = inline!("bar") {} +} + // PartialEq is not stable in consts yet fn issue15376() { enum NonConstEq { diff --git a/tests/ui/equatable_if_let.rs b/tests/ui/equatable_if_let.rs index 97557c750bb2..94302b3dfa65 100644 --- a/tests/ui/equatable_if_let.rs +++ b/tests/ui/equatable_if_let.rs @@ -40,7 +40,6 @@ impl PartialEq for NotStructuralEq { } } -#[inline_macros] fn main() { let a = 2; let b = 3; @@ -87,13 +86,6 @@ fn main() { //~^ equatable_if_let if let NoPartialEqStruct { a: 2, b: false } = h {} //~^ equatable_if_let - - if let inline!("abc") = "abc" { - //~^ equatable_if_let - println!("OK"); - } - - external!({ if let 2 = $a {} }); } mod issue8710 { @@ -132,6 +124,74 @@ mod issue8710 { } } +#[inline_macros] +fn issue14548() { + if let inline!("abc") = "abc" { + println!("OK"); + } + + let a = 2; + external!({ if let 2 = $a {} }); + + // Don't lint: `==`/`matches!` might be correct for a particular `$($font)|*`, but not in general + macro_rules! m1 { + ($($font:pat_param)|*) => { + if let $($font)|* = "from_expansion" {} + } + } + m1!("foo"); + m1!("Sans" | "Serif" | "Sans Mono"); + m1!(inline!("foo")); + + // Don't lint: the suggestion might be correct for a particular `$from_root_ctxt`, but not in + // general + macro_rules! m2 { + ($from_root_ctxt:pat) => { + if let $from_root_ctxt = "from_expansion" {} + }; + } + m2!("foo"); + m2!("Sans" | "Serif" | "Sans Mono"); + m2!(inline!("foo")); + + // Don't lint: the suggestion might be correct for a particular `$from_root_ctxt`, but not in + // general + macro_rules! m3 { + ($from_root_ctxt:expr) => { + if let "from_expansion" = $from_root_ctxt {} + }; + } + m3!("foo"); + m3!("foo"); + m3!(inline!("foo")); + + // Don't lint: the suggestion might be correct for a particular `$from_root_ctxt`, but not in + // general. Don't get confused by the scrutinee coming from macro invocation + macro_rules! m4 { + ($from_root_ctxt:pat) => { + if let $from_root_ctxt = inline!("from_expansion") {} + }; + } + m4!("foo"); + m4!("Sans" | "Serif" | "Sans Mono"); + m4!(inline!("foo")); + + // Don't lint: the suggestion might be correct for a particular `$from_root_ctxt`, but not in + // general. Don't get confused by the scrutinee coming from macro invocation + macro_rules! m5 { + ($from_root_ctxt:expr) => { + if let inline!("from_expansion") = $from_root_ctxt {} + }; + } + m5!("foo"); + m5!("foo"); + m5!(inline!("foo")); + + // Would be nice to lint: both sides are macro _invocations_, so the suggestion is correct in + // general + if let inline!("foo") = inline!("bar") {} +} + // PartialEq is not stable in consts yet fn issue15376() { enum NonConstEq { diff --git a/tests/ui/equatable_if_let.stderr b/tests/ui/equatable_if_let.stderr index ecedd479a462..8cc78daa2535 100644 --- a/tests/ui/equatable_if_let.stderr +++ b/tests/ui/equatable_if_let.stderr @@ -1,5 +1,5 @@ error: this pattern matching can be expressed using equality - --> tests/ui/equatable_if_let.rs:56:8 + --> tests/ui/equatable_if_let.rs:55:8 | LL | if let 2 = a {} | ^^^^^^^^^ help: try: `a == 2` @@ -8,112 +8,106 @@ LL | if let 2 = a {} = help: to override `-D warnings` add `#[allow(clippy::equatable_if_let)]` error: this pattern matching can be expressed using equality - --> tests/ui/equatable_if_let.rs:58:8 + --> tests/ui/equatable_if_let.rs:57:8 | LL | if let Ordering::Greater = a.cmp(&b) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `a.cmp(&b) == Ordering::Greater` error: this pattern matching can be expressed using equality - --> tests/ui/equatable_if_let.rs:60:8 + --> tests/ui/equatable_if_let.rs:59:8 | LL | if let Some(2) = c {} | ^^^^^^^^^^^^^^^ help: try: `c == Some(2)` error: this pattern matching can be expressed using equality - --> tests/ui/equatable_if_let.rs:62:8 + --> tests/ui/equatable_if_let.rs:61:8 | LL | if let Struct { a: 2, b: false } = d {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `d == (Struct { a: 2, b: false })` error: this pattern matching can be expressed using equality - --> tests/ui/equatable_if_let.rs:64:8 + --> tests/ui/equatable_if_let.rs:63:8 | LL | if let Enum::TupleVariant(32, 64) = e {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `e == Enum::TupleVariant(32, 64)` error: this pattern matching can be expressed using equality - --> tests/ui/equatable_if_let.rs:66:8 + --> tests/ui/equatable_if_let.rs:65:8 | LL | if let Enum::RecordVariant { a: 64, b: 32 } = e {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `e == (Enum::RecordVariant { a: 64, b: 32 })` error: this pattern matching can be expressed using equality - --> tests/ui/equatable_if_let.rs:68:8 + --> tests/ui/equatable_if_let.rs:67:8 | LL | if let Enum::UnitVariant = e {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `e == Enum::UnitVariant` error: this pattern matching can be expressed using equality - --> tests/ui/equatable_if_let.rs:70:8 + --> tests/ui/equatable_if_let.rs:69:8 | LL | if let (Enum::UnitVariant, &Struct { a: 2, b: false }) = (e, &d) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `(e, &d) == (Enum::UnitVariant, &Struct { a: 2, b: false })` error: this pattern matching can be expressed using `matches!` - --> tests/ui/equatable_if_let.rs:80:8 + --> tests/ui/equatable_if_let.rs:79:8 | LL | if let NotPartialEq::A = f {} | ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `matches!(f, NotPartialEq::A)` error: this pattern matching can be expressed using equality - --> tests/ui/equatable_if_let.rs:82:8 + --> tests/ui/equatable_if_let.rs:81:8 | LL | if let NotStructuralEq::A = g {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `g == NotStructuralEq::A` error: this pattern matching can be expressed using `matches!` - --> tests/ui/equatable_if_let.rs:84:8 + --> tests/ui/equatable_if_let.rs:83:8 | LL | if let Some(NotPartialEq::A) = Some(f) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `matches!(Some(f), Some(NotPartialEq::A))` error: this pattern matching can be expressed using equality - --> tests/ui/equatable_if_let.rs:86:8 + --> tests/ui/equatable_if_let.rs:85:8 | LL | if let Some(NotStructuralEq::A) = Some(g) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Some(g) == Some(NotStructuralEq::A)` error: this pattern matching can be expressed using `matches!` - --> tests/ui/equatable_if_let.rs:88:8 + --> tests/ui/equatable_if_let.rs:87:8 | LL | if let NoPartialEqStruct { a: 2, b: false } = h {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `matches!(h, NoPartialEqStruct { a: 2, b: false })` -error: this pattern matching can be expressed using equality - --> tests/ui/equatable_if_let.rs:91:8 - | -LL | if let inline!("abc") = "abc" { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `"abc" == inline!("abc")` - error: this pattern matching can be expressed using `matches!` - --> tests/ui/equatable_if_let.rs:101:12 + --> tests/ui/equatable_if_let.rs:93:12 | LL | if let Some('i') = cs.iter().next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `matches!(cs.iter().next(), Some('i'))` error: this pattern matching can be expressed using `matches!` - --> tests/ui/equatable_if_let.rs:109:12 + --> tests/ui/equatable_if_let.rs:101:12 | LL | if let Some(1) = cs.iter().next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `matches!(cs.iter().next(), Some(1))` error: this pattern matching can be expressed using `matches!` - --> tests/ui/equatable_if_let.rs:127:12 + --> tests/ui/equatable_if_let.rs:119:12 | LL | if let Some(MyEnum::B) = get_enum() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `matches!(get_enum(), Some(MyEnum::B))` error: this pattern matching can be expressed using `matches!` - --> tests/ui/equatable_if_let.rs:158:23 + --> tests/ui/equatable_if_let.rs:210:23 | LL | const _: u32 = if let NonConstEq::A = N { 0 } else { 1 }; | ^^^^^^^^^^^^^^^^^^^^^ help: try: `matches!(N, NonConstEq::A)` error: this pattern matching can be expressed using `matches!` - --> tests/ui/equatable_if_let.rs:160:23 + --> tests/ui/equatable_if_let.rs:212:23 | LL | const _: u32 = if let Some(NonConstEq::A) = Some(N) { 0 } else { 1 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `matches!(Some(N), Some(NonConstEq::A))` -error: aborting due to 19 previous errors +error: aborting due to 18 previous errors