Skip to content

Commit 9205e3d

Browse files
committed
Auto merge of #7800 - 1nF0rmed:no-lint-in-match-single-amp, r=llogiq
Refactor `clippy::match_ref_pats` to check for multiple reference patterns fixes #7740 When there is only one pattern, to begin with, i.e. a single deref(`&`), then in such cases we suppress `clippy::match_ref_pats`. This is done by checking the count of the reference pattern and emitting `clippy::match_ref_pats` when more than one pattern is present. Removed certain errors in the `stderr` tests as they would not be triggered. changelog: Refactor `clippy::match_ref_pats` to check for multiple reference patterns
2 parents 8f1555f + 1080f6c commit 9205e3d

File tree

4 files changed

+58
-86
lines changed

4 files changed

+58
-86
lines changed

clippy_lints/src/matches.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -1187,7 +1187,7 @@ where
11871187
'b: 'a,
11881188
I: Clone + Iterator<Item = &'a Pat<'b>>,
11891189
{
1190-
if !has_only_ref_pats(pats.clone()) {
1190+
if !has_multiple_ref_pats(pats.clone()) {
11911191
return;
11921192
}
11931193

@@ -1693,26 +1693,26 @@ fn is_ref_some_arm(cx: &LateContext<'_>, arm: &Arm<'_>) -> Option<BindingAnnotat
16931693
None
16941694
}
16951695

1696-
fn has_only_ref_pats<'a, 'b, I>(pats: I) -> bool
1696+
fn has_multiple_ref_pats<'a, 'b, I>(pats: I) -> bool
16971697
where
16981698
'b: 'a,
16991699
I: Iterator<Item = &'a Pat<'b>>,
17001700
{
1701-
let mut at_least_one_is_true = false;
1701+
let mut ref_count = 0;
17021702
for opt in pats.map(|pat| match pat.kind {
17031703
PatKind::Ref(..) => Some(true), // &-patterns
17041704
PatKind::Wild => Some(false), // an "anything" wildcard is also fine
17051705
_ => None, // any other pattern is not fine
17061706
}) {
17071707
if let Some(inner) = opt {
17081708
if inner {
1709-
at_least_one_is_true = true;
1709+
ref_count += 1;
17101710
}
17111711
} else {
17121712
return false;
17131713
}
17141714
}
1715-
at_least_one_is_true
1715+
ref_count > 1
17161716
}
17171717

17181718
pub fn overlapping<T>(ranges: &[SpannedRange<T>]) -> Option<(&SpannedRange<T>, &SpannedRange<T>)>

tests/ui/match_expr_like_matches_macro.stderr

+1-34
Original file line numberDiff line numberDiff line change
@@ -110,23 +110,6 @@ LL | | _ => false,
110110
LL | | };
111111
| |_________^ help: try this: `matches!(&val, &Some(ref _a))`
112112

113-
error: you don't need to add `&` to both the expression and the patterns
114-
--> $DIR/match_expr_like_matches_macro.rs:166:20
115-
|
116-
LL | let _res = match &val {
117-
| ____________________^
118-
LL | | &Some(ref _a) => true,
119-
LL | | _ => false,
120-
LL | | };
121-
| |_________^
122-
|
123-
= note: `-D clippy::match-ref-pats` implied by `-D warnings`
124-
help: try
125-
|
126-
LL ~ let _res = match val {
127-
LL ~ Some(ref _a) => true,
128-
|
129-
130113
error: match expression looks like `matches!` macro
131114
--> $DIR/match_expr_like_matches_macro.rs:178:20
132115
|
@@ -137,21 +120,5 @@ LL | | _ => false,
137120
LL | | };
138121
| |_________^ help: try this: `matches!(&val, &Some(ref _a))`
139122

140-
error: you don't need to add `&` to both the expression and the patterns
141-
--> $DIR/match_expr_like_matches_macro.rs:178:20
142-
|
143-
LL | let _res = match &val {
144-
| ____________________^
145-
LL | | &Some(ref _a) => true,
146-
LL | | _ => false,
147-
LL | | };
148-
| |_________^
149-
|
150-
help: try
151-
|
152-
LL ~ let _res = match val {
153-
LL ~ Some(ref _a) => true,
154-
|
155-
156-
error: aborting due to 14 previous errors
123+
error: aborting due to 12 previous errors
157124

tests/ui/match_ref_pats.rs

+42
Original file line numberDiff line numberDiff line change
@@ -72,4 +72,46 @@ mod ice_3719 {
7272
}
7373
}
7474

75+
mod issue_7740 {
76+
macro_rules! foobar_variant(
77+
($idx:expr) => (FooBar::get($idx).unwrap())
78+
);
79+
80+
enum FooBar {
81+
Foo,
82+
Bar,
83+
FooBar,
84+
BarFoo,
85+
}
86+
87+
impl FooBar {
88+
fn get(idx: u8) -> Option<&'static Self> {
89+
match idx {
90+
0 => Some(&FooBar::Foo),
91+
1 => Some(&FooBar::Bar),
92+
2 => Some(&FooBar::FooBar),
93+
3 => Some(&FooBar::BarFoo),
94+
_ => None,
95+
}
96+
}
97+
}
98+
99+
fn issue_7740() {
100+
// Issue #7740
101+
match foobar_variant!(0) {
102+
&FooBar::Foo => println!("Foo"),
103+
&FooBar::Bar => println!("Bar"),
104+
&FooBar::FooBar => println!("FooBar"),
105+
_ => println!("Wild"),
106+
}
107+
108+
// This shouldn't trigger
109+
if let &FooBar::BarFoo = foobar_variant!(3) {
110+
println!("BarFoo");
111+
} else {
112+
println!("Wild");
113+
}
114+
}
115+
}
116+
75117
fn main() {}

tests/ui/match_ref_pats.stderr

+10-47
Original file line numberDiff line numberDiff line change
@@ -15,21 +15,6 @@ LL ~ Some(v) => println!("{:?}", v),
1515
LL ~ None => println!("none"),
1616
|
1717

18-
error: you don't need to add `&` to all patterns
19-
--> $DIR/match_ref_pats.rs:18:5
20-
|
21-
LL | / match tup {
22-
LL | | &(v, 1) => println!("{}", v),
23-
LL | | _ => println!("none"),
24-
LL | | }
25-
| |_____^
26-
|
27-
help: instead of prefixing all patterns with `&`, you can dereference the expression
28-
|
29-
LL ~ match *tup {
30-
LL ~ (v, 1) => println!("{}", v),
31-
|
32-
3318
error: you don't need to add `&` to both the expression and the patterns
3419
--> $DIR/match_ref_pats.rs:24:5
3520
|
@@ -54,52 +39,30 @@ LL | if let &None = a {
5439
|
5540
= note: `-D clippy::redundant-pattern-matching` implied by `-D warnings`
5641

57-
error: you don't need to add `&` to all patterns
58-
--> $DIR/match_ref_pats.rs:36:5
59-
|
60-
LL | / if let &None = a {
61-
LL | | println!("none");
62-
LL | | }
63-
| |_____^
64-
|
65-
help: instead of prefixing all patterns with `&`, you can dereference the expression
66-
|
67-
LL | if let None = *a {
68-
| ~~~~ ~~
69-
7042
error: redundant pattern matching, consider using `is_none()`
7143
--> $DIR/match_ref_pats.rs:41:12
7244
|
7345
LL | if let &None = &b {
7446
| -------^^^^^----- help: try this: `if b.is_none()`
7547

76-
error: you don't need to add `&` to both the expression and the patterns
77-
--> $DIR/match_ref_pats.rs:41:5
78-
|
79-
LL | / if let &None = &b {
80-
LL | | println!("none");
81-
LL | | }
82-
| |_____^
83-
|
84-
help: try
85-
|
86-
LL | if let None = b {
87-
| ~~~~ ~
88-
8948
error: you don't need to add `&` to all patterns
90-
--> $DIR/match_ref_pats.rs:68:9
49+
--> $DIR/match_ref_pats.rs:101:9
9150
|
92-
LL | / match foo_variant!(0) {
93-
LL | | &Foo::A => println!("A"),
51+
LL | / match foobar_variant!(0) {
52+
LL | | &FooBar::Foo => println!("Foo"),
53+
LL | | &FooBar::Bar => println!("Bar"),
54+
LL | | &FooBar::FooBar => println!("FooBar"),
9455
LL | | _ => println!("Wild"),
9556
LL | | }
9657
| |_________^
9758
|
9859
help: instead of prefixing all patterns with `&`, you can dereference the expression
9960
|
100-
LL ~ match *foo_variant!(0) {
101-
LL ~ Foo::A => println!("A"),
61+
LL ~ match *foobar_variant!(0) {
62+
LL ~ FooBar::Foo => println!("Foo"),
63+
LL ~ FooBar::Bar => println!("Bar"),
64+
LL ~ FooBar::FooBar => println!("FooBar"),
10265
|
10366

104-
error: aborting due to 8 previous errors
67+
error: aborting due to 5 previous errors
10568

0 commit comments

Comments
 (0)