Skip to content

Commit ba4253b

Browse files
committed
Fix capacity overflow in single_match with deref patterns
1 parent 76118ec commit ba4253b

File tree

4 files changed

+47
-8
lines changed

4 files changed

+47
-8
lines changed

clippy_lints/src/matches/single_match.rs

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -152,21 +152,26 @@ fn report_single_pattern(
152152
}) if lit.node.is_str() || lit.node.is_bytestr() => pat_ref_count + 1,
153153
_ => pat_ref_count,
154154
};
155-
// References are only implicitly added to the pattern, so no overflow here.
156-
// e.g. will work: match &Some(_) { Some(_) => () }
157-
// will not: match Some(_) { &Some(_) => () }
158-
let ref_count_diff = ty_ref_count - pat_ref_count;
159155

160-
// Try to remove address of expressions first.
161-
let (ex, removed) = peel_n_hir_expr_refs(ex, ref_count_diff);
162-
let ref_count_diff = ref_count_diff - removed;
156+
// References are implicitly removed when `deref_patterns` are used.
157+
// They are implicitly added when match ergonomics are used.
158+
let (ex, ref_or_deref_adjust) = if ty_ref_count > pat_ref_count {
159+
let ref_count_diff = ty_ref_count - pat_ref_count;
160+
161+
// Try to remove address of expressions first.
162+
let (ex, removed) = peel_n_hir_expr_refs(ex, ref_count_diff);
163+
164+
(ex, "&".repeat(ref_count_diff - removed))
165+
} else {
166+
(ex, "*".repeat(pat_ref_count - ty_ref_count))
167+
};
163168

164169
let msg = "you seem to be trying to use `match` for an equality check. Consider using `if`";
165170
let sugg = format!(
166171
"if {} == {}{} {}{els_str}",
167172
snippet_with_context(cx, ex.span, ctxt, "..", &mut app).0,
168173
// PartialEq for different reference counts may not exist.
169-
"&".repeat(ref_count_diff),
174+
ref_or_deref_adjust,
170175
snippet_with_applicability(cx, arm.pat.span, "..", &mut app),
171176
expr_block(cx, arm.body, ctxt, "..", Some(expr.span), &mut app),
172177
);
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#![feature(deref_patterns)]
2+
#![allow(incomplete_features, clippy::eq_op)]
3+
#![warn(clippy::single_match_else)]
4+
5+
fn string() {
6+
if *"" == *"" {}
7+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#![feature(deref_patterns)]
2+
#![allow(incomplete_features, clippy::eq_op)]
3+
#![warn(clippy::single_match_else)]
4+
5+
fn string() {
6+
match *"" {
7+
//~^ single_match
8+
"" => {},
9+
_ => {},
10+
}
11+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
error: you seem to be trying to use `match` for an equality check. Consider using `if`
2+
--> tests/ui/single_match_else_deref_patterns.rs:6:5
3+
|
4+
LL | / match *"" {
5+
LL | |
6+
LL | | "" => {},
7+
LL | | _ => {},
8+
LL | | }
9+
| |_____^ help: try: `if *"" == *"" {}`
10+
|
11+
= note: you might want to preserve the comments from inside the `match`
12+
= note: `-D clippy::single-match` implied by `-D warnings`
13+
= help: to override `-D warnings` add `#[allow(clippy::single_match)]`
14+
15+
error: aborting due to 1 previous error
16+

0 commit comments

Comments
 (0)