diff --git a/clippy_lints/src/matches.rs b/clippy_lints/src/matches.rs index 206a842d21c..bfd97689d2d 100644 --- a/clippy_lints/src/matches.rs +++ b/clippy_lints/src/matches.rs @@ -389,6 +389,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Matches { fn check_local(&mut self, cx: &LateContext<'a, 'tcx>, local: &'tcx Local<'_>) { if_chain! { + if !in_external_macro(cx.sess(), local.span); + if !in_macro(local.span); if let Some(ref expr) = local.init; if let ExprKind::Match(ref target, ref arms, MatchSource::Normal) = expr.kind; if arms.len() == 1 && arms[0].guard.is_none(); @@ -423,6 +425,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Matches { fn check_pat(&mut self, cx: &LateContext<'a, 'tcx>, pat: &'tcx Pat<'_>) { if_chain! { + if !in_external_macro(cx.sess(), pat.span); + if !in_macro(pat.span); if let PatKind::Struct(ref qpath, fields, true) = pat.kind; if let QPath::Resolved(_, ref path) = qpath; if let Some(def_id) = path.res.opt_def_id(); diff --git a/tests/ui/infallible_destructuring_match.fixed b/tests/ui/infallible_destructuring_match.fixed index f16f0fd0019..b8e40d99553 100644 --- a/tests/ui/infallible_destructuring_match.fixed +++ b/tests/ui/infallible_destructuring_match.fixed @@ -11,12 +11,23 @@ struct TupleStruct(i32); enum EmptyEnum {} +macro_rules! match_enum { + ($param:expr) => { + let data = match $param { + SingleVariantEnum::Variant(i) => i, + }; + }; +} + fn infallible_destructuring_match_enum() { let wrapper = SingleVariantEnum::Variant(0); // This should lint! let SingleVariantEnum::Variant(data) = wrapper; + // This shouldn't (inside macro) + match_enum!(wrapper); + // This shouldn't! let data = match wrapper { SingleVariantEnum::Variant(_) => -1, @@ -30,12 +41,23 @@ fn infallible_destructuring_match_enum() { let SingleVariantEnum::Variant(data) = wrapper; } +macro_rules! match_struct { + ($param:expr) => { + let data = match $param { + TupleStruct(i) => i, + }; + }; +} + fn infallible_destructuring_match_struct() { let wrapper = TupleStruct(0); // This should lint! let TupleStruct(data) = wrapper; + // This shouldn't (inside macro) + match_struct!(wrapper); + // This shouldn't! let data = match wrapper { TupleStruct(_) => -1, @@ -49,12 +71,23 @@ fn infallible_destructuring_match_struct() { let TupleStruct(data) = wrapper; } +macro_rules! match_never_enum { + ($param:expr) => { + let data = match $param { + Ok(i) => i, + }; + }; +} + fn never_enum() { let wrapper: Result = Ok(23); // This should lint! let Ok(data) = wrapper; + // This shouldn't (inside macro) + match_never_enum!(wrapper); + // This shouldn't! let data = match wrapper { Ok(_) => -1, diff --git a/tests/ui/infallible_destructuring_match.rs b/tests/ui/infallible_destructuring_match.rs index a4823ad60ad..106cd438b90 100644 --- a/tests/ui/infallible_destructuring_match.rs +++ b/tests/ui/infallible_destructuring_match.rs @@ -11,6 +11,14 @@ struct TupleStruct(i32); enum EmptyEnum {} +macro_rules! match_enum { + ($param:expr) => { + let data = match $param { + SingleVariantEnum::Variant(i) => i, + }; + }; +} + fn infallible_destructuring_match_enum() { let wrapper = SingleVariantEnum::Variant(0); @@ -19,6 +27,9 @@ fn infallible_destructuring_match_enum() { SingleVariantEnum::Variant(i) => i, }; + // This shouldn't (inside macro) + match_enum!(wrapper); + // This shouldn't! let data = match wrapper { SingleVariantEnum::Variant(_) => -1, @@ -32,6 +43,14 @@ fn infallible_destructuring_match_enum() { let SingleVariantEnum::Variant(data) = wrapper; } +macro_rules! match_struct { + ($param:expr) => { + let data = match $param { + TupleStruct(i) => i, + }; + }; +} + fn infallible_destructuring_match_struct() { let wrapper = TupleStruct(0); @@ -40,6 +59,9 @@ fn infallible_destructuring_match_struct() { TupleStruct(i) => i, }; + // This shouldn't (inside macro) + match_struct!(wrapper); + // This shouldn't! let data = match wrapper { TupleStruct(_) => -1, @@ -53,6 +75,14 @@ fn infallible_destructuring_match_struct() { let TupleStruct(data) = wrapper; } +macro_rules! match_never_enum { + ($param:expr) => { + let data = match $param { + Ok(i) => i, + }; + }; +} + fn never_enum() { let wrapper: Result = Ok(23); @@ -61,6 +91,9 @@ fn never_enum() { Ok(i) => i, }; + // This shouldn't (inside macro) + match_never_enum!(wrapper); + // This shouldn't! let data = match wrapper { Ok(_) => -1, diff --git a/tests/ui/infallible_destructuring_match.stderr b/tests/ui/infallible_destructuring_match.stderr index 2f6b81cf3b5..1b78db42014 100644 --- a/tests/ui/infallible_destructuring_match.stderr +++ b/tests/ui/infallible_destructuring_match.stderr @@ -1,5 +1,5 @@ error: you seem to be trying to use `match` to destructure a single infallible pattern. Consider using `let` - --> $DIR/infallible_destructuring_match.rs:18:5 + --> $DIR/infallible_destructuring_match.rs:26:5 | LL | / let data = match wrapper { LL | | SingleVariantEnum::Variant(i) => i, @@ -9,7 +9,7 @@ LL | | }; = note: `-D clippy::infallible-destructuring-match` implied by `-D warnings` error: you seem to be trying to use `match` to destructure a single infallible pattern. Consider using `let` - --> $DIR/infallible_destructuring_match.rs:39:5 + --> $DIR/infallible_destructuring_match.rs:58:5 | LL | / let data = match wrapper { LL | | TupleStruct(i) => i, @@ -17,7 +17,7 @@ LL | | }; | |______^ help: try this: `let TupleStruct(data) = wrapper;` error: you seem to be trying to use `match` to destructure a single infallible pattern. Consider using `let` - --> $DIR/infallible_destructuring_match.rs:60:5 + --> $DIR/infallible_destructuring_match.rs:90:5 | LL | / let data = match wrapper { LL | | Ok(i) => i, diff --git a/tests/ui/match_single_binding.fixed b/tests/ui/match_single_binding.fixed index 90f00aa7871..f3627902eec 100644 --- a/tests/ui/match_single_binding.fixed +++ b/tests/ui/match_single_binding.fixed @@ -12,6 +12,14 @@ fn coords() -> Point { Point { x: 1, y: 2 } } +macro_rules! foo { + ($param:expr) => { + match $param { + _ => println!("whatever"), + } + }; +} + fn main() { let a = 1; let b = 2; @@ -25,6 +33,8 @@ fn main() { let (x, y, z) = (a, b, c); println!("{} {} {}", x, y, z); // Ok + foo!(a); + // Ok match a { 2 => println!("2"), _ => println!("Not 2"), diff --git a/tests/ui/match_single_binding.rs b/tests/ui/match_single_binding.rs index 4a4b290036c..8c182148ae1 100644 --- a/tests/ui/match_single_binding.rs +++ b/tests/ui/match_single_binding.rs @@ -12,6 +12,14 @@ fn coords() -> Point { Point { x: 1, y: 2 } } +macro_rules! foo { + ($param:expr) => { + match $param { + _ => println!("whatever"), + } + }; +} + fn main() { let a = 1; let b = 2; @@ -27,6 +35,8 @@ fn main() { (x, y, z) => println!("{} {} {}", x, y, z), } // Ok + foo!(a); + // Ok match a { 2 => println!("2"), _ => println!("Not 2"), diff --git a/tests/ui/match_single_binding.stderr b/tests/ui/match_single_binding.stderr index cf741a989c2..795c8c3e24d 100644 --- a/tests/ui/match_single_binding.stderr +++ b/tests/ui/match_single_binding.stderr @@ -1,5 +1,5 @@ error: this match could be written as a `let` statement - --> $DIR/match_single_binding.rs:20:5 + --> $DIR/match_single_binding.rs:28:5 | LL | / match (a, b, c) { LL | | (x, y, z) => { @@ -18,7 +18,7 @@ LL | } | error: this match could be written as a `let` statement - --> $DIR/match_single_binding.rs:26:5 + --> $DIR/match_single_binding.rs:34:5 | LL | / match (a, b, c) { LL | | (x, y, z) => println!("{} {} {}", x, y, z), @@ -32,7 +32,7 @@ LL | println!("{} {} {}", x, y, z); | error: this match could be replaced by its body itself - --> $DIR/match_single_binding.rs:41:5 + --> $DIR/match_single_binding.rs:51:5 | LL | / match a { LL | | _ => println!("whatever"), @@ -40,7 +40,7 @@ LL | | } | |_____^ help: consider using the match body instead: `println!("whatever");` error: this match could be replaced by its body itself - --> $DIR/match_single_binding.rs:45:5 + --> $DIR/match_single_binding.rs:55:5 | LL | / match a { LL | | _ => { @@ -59,7 +59,7 @@ LL | } | error: this match could be replaced by its body itself - --> $DIR/match_single_binding.rs:52:5 + --> $DIR/match_single_binding.rs:62:5 | LL | / match a { LL | | _ => { @@ -81,7 +81,7 @@ LL | } | error: this match could be written as a `let` statement - --> $DIR/match_single_binding.rs:62:5 + --> $DIR/match_single_binding.rs:72:5 | LL | / match p { LL | | Point { x, y } => println!("Coords: ({}, {})", x, y), @@ -95,7 +95,7 @@ LL | println!("Coords: ({}, {})", x, y); | error: this match could be written as a `let` statement - --> $DIR/match_single_binding.rs:66:5 + --> $DIR/match_single_binding.rs:76:5 | LL | / match p { LL | | Point { x: x1, y: y1 } => println!("Coords: ({}, {})", x1, y1), @@ -109,7 +109,7 @@ LL | println!("Coords: ({}, {})", x1, y1); | error: this match could be written as a `let` statement - --> $DIR/match_single_binding.rs:71:5 + --> $DIR/match_single_binding.rs:81:5 | LL | / match x { LL | | ref r => println!("Got a reference to {}", r), @@ -123,7 +123,7 @@ LL | println!("Got a reference to {}", r); | error: this match could be written as a `let` statement - --> $DIR/match_single_binding.rs:76:5 + --> $DIR/match_single_binding.rs:86:5 | LL | / match x { LL | | ref mut mr => println!("Got a mutable reference to {}", mr), @@ -137,7 +137,7 @@ LL | println!("Got a mutable reference to {}", mr); | error: this match could be written as a `let` statement - --> $DIR/match_single_binding.rs:80:5 + --> $DIR/match_single_binding.rs:90:5 | LL | / let product = match coords() { LL | | Point { x, y } => x * y, @@ -151,7 +151,7 @@ LL | let product = x * y; | error: this match could be written as a `let` statement - --> $DIR/match_single_binding.rs:88:18 + --> $DIR/match_single_binding.rs:98:18 | LL | .map(|i| match i.unwrap() { | __________________^ diff --git a/tests/ui/rest_pat_in_fully_bound_structs.rs b/tests/ui/rest_pat_in_fully_bound_structs.rs index 22e4d4edd78..38fc9969804 100644 --- a/tests/ui/rest_pat_in_fully_bound_structs.rs +++ b/tests/ui/rest_pat_in_fully_bound_structs.rs @@ -6,6 +6,15 @@ struct A { c: &'static str, } +macro_rules! foo { + ($param:expr) => { + match $param { + A { a: 0, b: 0, c: "", .. } => {}, + _ => {}, + } + }; +} + fn main() { let a_struct = A { a: 5, b: 42, c: "A" }; @@ -27,4 +36,7 @@ fn main() { A { a: 0, b: 0, .. } => {}, _ => {}, } + + // No lint + foo!(a_struct); } diff --git a/tests/ui/rest_pat_in_fully_bound_structs.stderr b/tests/ui/rest_pat_in_fully_bound_structs.stderr index effa46b4b0f..57ebd47f8c7 100644 --- a/tests/ui/rest_pat_in_fully_bound_structs.stderr +++ b/tests/ui/rest_pat_in_fully_bound_structs.stderr @@ -1,5 +1,5 @@ error: unnecessary use of `..` pattern in struct binding. All fields were already bound - --> $DIR/rest_pat_in_fully_bound_structs.rs:13:9 + --> $DIR/rest_pat_in_fully_bound_structs.rs:22:9 | LL | A { a: 5, b: 42, c: "", .. } => {}, // Lint | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -8,7 +8,7 @@ LL | A { a: 5, b: 42, c: "", .. } => {}, // Lint = help: consider removing `..` from this binding error: unnecessary use of `..` pattern in struct binding. All fields were already bound - --> $DIR/rest_pat_in_fully_bound_structs.rs:14:9 + --> $DIR/rest_pat_in_fully_bound_structs.rs:23:9 | LL | A { a: 0, b: 0, c: "", .. } => {}, // Lint | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -16,7 +16,7 @@ LL | A { a: 0, b: 0, c: "", .. } => {}, // Lint = help: consider removing `..` from this binding error: unnecessary use of `..` pattern in struct binding. All fields were already bound - --> $DIR/rest_pat_in_fully_bound_structs.rs:20:9 + --> $DIR/rest_pat_in_fully_bound_structs.rs:29:9 | LL | A { a: 0, b: 0, c: "", .. } => {}, // Lint | ^^^^^^^^^^^^^^^^^^^^^^^^^^^