mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-27 09:14:20 +00:00
Add check for same guards in match_same_arms
This commit is contained in:
parent
74f611f7fc
commit
087c7c828d
@ -131,8 +131,7 @@ pub(super) fn check(
|
|||||||
|
|
||||||
let cast_from_ptr_size = def.repr().int.map_or(true, |ty| matches!(ty, IntegerType::Pointer(_),));
|
let cast_from_ptr_size = def.repr().int.map_or(true, |ty| matches!(ty, IntegerType::Pointer(_),));
|
||||||
let suffix = match (cast_from_ptr_size, is_isize_or_usize(cast_to)) {
|
let suffix = match (cast_from_ptr_size, is_isize_or_usize(cast_to)) {
|
||||||
(false, false) if from_nbits > to_nbits => "",
|
(_, false) if from_nbits > to_nbits => "",
|
||||||
(true, false) if from_nbits > to_nbits => "",
|
|
||||||
(false, true) if from_nbits > 64 => "",
|
(false, true) if from_nbits > 64 => "",
|
||||||
(false, true) if from_nbits > 32 => " on targets with 32-bit wide pointers",
|
(false, true) if from_nbits > 32 => " on targets with 32-bit wide pointers",
|
||||||
_ => return,
|
_ => return,
|
||||||
|
@ -64,38 +64,50 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>]) {
|
|||||||
let min_index = usize::min(lindex, rindex);
|
let min_index = usize::min(lindex, rindex);
|
||||||
let max_index = usize::max(lindex, rindex);
|
let max_index = usize::max(lindex, rindex);
|
||||||
|
|
||||||
let mut local_map: HirIdMap<HirId> = HirIdMap::default();
|
let check_eq_with_pat = |expr_a: &Expr<'_>, expr_b: &Expr<'_>| {
|
||||||
let eq_fallback = |a: &Expr<'_>, b: &Expr<'_>| {
|
let mut local_map: HirIdMap<HirId> = HirIdMap::default();
|
||||||
if let Some(a_id) = path_to_local(a)
|
let eq_fallback = |a: &Expr<'_>, b: &Expr<'_>| {
|
||||||
&& let Some(b_id) = path_to_local(b)
|
if let Some(a_id) = path_to_local(a)
|
||||||
&& let entry = match local_map.entry(a_id) {
|
&& let Some(b_id) = path_to_local(b)
|
||||||
HirIdMapEntry::Vacant(entry) => entry,
|
&& let entry = match local_map.entry(a_id) {
|
||||||
// check if using the same bindings as before
|
HirIdMapEntry::Vacant(entry) => entry,
|
||||||
HirIdMapEntry::Occupied(entry) => return *entry.get() == b_id,
|
// check if using the same bindings as before
|
||||||
}
|
HirIdMapEntry::Occupied(entry) => return *entry.get() == b_id,
|
||||||
|
}
|
||||||
// the names technically don't have to match; this makes the lint more conservative
|
// the names technically don't have to match; this makes the lint more conservative
|
||||||
&& cx.tcx.hir().name(a_id) == cx.tcx.hir().name(b_id)
|
&& cx.tcx.hir().name(a_id) == cx.tcx.hir().name(b_id)
|
||||||
&& cx.typeck_results().expr_ty(a) == cx.typeck_results().expr_ty(b)
|
&& cx.typeck_results().expr_ty(a) == cx.typeck_results().expr_ty(b)
|
||||||
&& pat_contains_local(lhs.pat, a_id)
|
&& pat_contains_local(lhs.pat, a_id)
|
||||||
&& pat_contains_local(rhs.pat, b_id)
|
&& pat_contains_local(rhs.pat, b_id)
|
||||||
{
|
{
|
||||||
entry.insert(b_id);
|
entry.insert(b_id);
|
||||||
true
|
true
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
// Arms with a guard are ignored, those can’t always be merged together
|
|
||||||
// If both arms overlap with an arm in between then these can't be merged either.
|
SpanlessEq::new(cx)
|
||||||
!(backwards_blocking_idxs[max_index] > min_index && forwards_blocking_idxs[min_index] < max_index)
|
.expr_fallback(eq_fallback)
|
||||||
&& lhs.guard.is_none()
|
.eq_expr(expr_a, expr_b)
|
||||||
&& rhs.guard.is_none()
|
|
||||||
&& SpanlessEq::new(cx)
|
|
||||||
.expr_fallback(eq_fallback)
|
|
||||||
.eq_expr(lhs.body, rhs.body)
|
|
||||||
// these checks could be removed to allow unused bindings
|
// these checks could be removed to allow unused bindings
|
||||||
&& bindings_eq(lhs.pat, local_map.keys().copied().collect())
|
&& bindings_eq(lhs.pat, local_map.keys().copied().collect())
|
||||||
&& bindings_eq(rhs.pat, local_map.values().copied().collect())
|
&& bindings_eq(rhs.pat, local_map.values().copied().collect())
|
||||||
|
};
|
||||||
|
|
||||||
|
let check_same_guard = || match (&lhs.guard, &rhs.guard) {
|
||||||
|
(None, None) => true,
|
||||||
|
(Some(lhs_guard), Some(rhs_guard)) => check_eq_with_pat(lhs_guard, rhs_guard),
|
||||||
|
_ => false,
|
||||||
|
};
|
||||||
|
|
||||||
|
let check_same_body = || check_eq_with_pat(lhs.body, rhs.body);
|
||||||
|
|
||||||
|
// Arms with different guard are ignored, those can’t always be merged together
|
||||||
|
// If both arms overlap with an arm in between then these can't be merged either.
|
||||||
|
!(backwards_blocking_idxs[max_index] > min_index && forwards_blocking_idxs[min_index] < max_index)
|
||||||
|
&& check_same_guard()
|
||||||
|
&& check_same_body()
|
||||||
};
|
};
|
||||||
|
|
||||||
let indexed_arms: Vec<(usize, &Arm<'_>)> = arms.iter().enumerate().collect();
|
let indexed_arms: Vec<(usize, &Arm<'_>)> = arms.iter().enumerate().collect();
|
||||||
|
@ -67,6 +67,20 @@ fn match_same_arms() {
|
|||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// No warning because guards are different
|
||||||
|
let _ = match Some(42) {
|
||||||
|
Some(a) if a == 42 => a,
|
||||||
|
Some(a) if a == 24 => a,
|
||||||
|
Some(_) => 24,
|
||||||
|
None => 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
let _ = match (Some(42), Some(42)) {
|
||||||
|
(Some(a), None) if a == 42 => a,
|
||||||
|
(None, Some(a)) if a == 42 => a, //~ ERROR: this match arm has an identical body to another arm
|
||||||
|
_ => 0,
|
||||||
|
};
|
||||||
|
|
||||||
match (Some(42), Some(42)) {
|
match (Some(42), Some(42)) {
|
||||||
(Some(a), ..) => bar(a), //~ ERROR: this match arm has an identical body to another arm
|
(Some(a), ..) => bar(a), //~ ERROR: this match arm has an identical body to another arm
|
||||||
(.., Some(a)) => bar(a),
|
(.., Some(a)) => bar(a),
|
||||||
|
@ -71,7 +71,22 @@ LL | (Some(a), None) => bar(a),
|
|||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: this match arm has an identical body to another arm
|
error: this match arm has an identical body to another arm
|
||||||
--> tests/ui/match_same_arms2.rs:71:9
|
--> tests/ui/match_same_arms2.rs:80:9
|
||||||
|
|
|
||||||
|
LL | (None, Some(a)) if a == 42 => a,
|
||||||
|
| ---------------^^^^^^^^^^^^^^^^
|
||||||
|
| |
|
||||||
|
| help: try merging the arm patterns: `(None, Some(a)) | (Some(a), None)`
|
||||||
|
|
|
||||||
|
= help: or try changing either arm body
|
||||||
|
note: other arm here
|
||||||
|
--> tests/ui/match_same_arms2.rs:79:9
|
||||||
|
|
|
||||||
|
LL | (Some(a), None) if a == 42 => a,
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: this match arm has an identical body to another arm
|
||||||
|
--> tests/ui/match_same_arms2.rs:85:9
|
||||||
|
|
|
|
||||||
LL | (Some(a), ..) => bar(a),
|
LL | (Some(a), ..) => bar(a),
|
||||||
| -------------^^^^^^^^^^
|
| -------------^^^^^^^^^^
|
||||||
@ -80,13 +95,13 @@ LL | (Some(a), ..) => bar(a),
|
|||||||
|
|
|
|
||||||
= help: or try changing either arm body
|
= help: or try changing either arm body
|
||||||
note: other arm here
|
note: other arm here
|
||||||
--> tests/ui/match_same_arms2.rs:72:9
|
--> tests/ui/match_same_arms2.rs:86:9
|
||||||
|
|
|
|
||||||
LL | (.., Some(a)) => bar(a),
|
LL | (.., Some(a)) => bar(a),
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: this match arm has an identical body to another arm
|
error: this match arm has an identical body to another arm
|
||||||
--> tests/ui/match_same_arms2.rs:105:9
|
--> tests/ui/match_same_arms2.rs:119:9
|
||||||
|
|
|
|
||||||
LL | (Ok(x), Some(_)) => println!("ok {}", x),
|
LL | (Ok(x), Some(_)) => println!("ok {}", x),
|
||||||
| ----------------^^^^^^^^^^^^^^^^^^^^^^^^
|
| ----------------^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
@ -95,13 +110,13 @@ LL | (Ok(x), Some(_)) => println!("ok {}", x),
|
|||||||
|
|
|
|
||||||
= help: or try changing either arm body
|
= help: or try changing either arm body
|
||||||
note: other arm here
|
note: other arm here
|
||||||
--> tests/ui/match_same_arms2.rs:106:9
|
--> tests/ui/match_same_arms2.rs:120:9
|
||||||
|
|
|
|
||||||
LL | (Ok(_), Some(x)) => println!("ok {}", x),
|
LL | (Ok(_), Some(x)) => println!("ok {}", x),
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: this match arm has an identical body to another arm
|
error: this match arm has an identical body to another arm
|
||||||
--> tests/ui/match_same_arms2.rs:121:9
|
--> tests/ui/match_same_arms2.rs:135:9
|
||||||
|
|
|
|
||||||
LL | Ok(_) => println!("ok"),
|
LL | Ok(_) => println!("ok"),
|
||||||
| -----^^^^^^^^^^^^^^^^^^
|
| -----^^^^^^^^^^^^^^^^^^
|
||||||
@ -110,13 +125,13 @@ LL | Ok(_) => println!("ok"),
|
|||||||
|
|
|
|
||||||
= help: or try changing either arm body
|
= help: or try changing either arm body
|
||||||
note: other arm here
|
note: other arm here
|
||||||
--> tests/ui/match_same_arms2.rs:120:9
|
--> tests/ui/match_same_arms2.rs:134:9
|
||||||
|
|
|
|
||||||
LL | Ok(3) => println!("ok"),
|
LL | Ok(3) => println!("ok"),
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: this match arm has an identical body to another arm
|
error: this match arm has an identical body to another arm
|
||||||
--> tests/ui/match_same_arms2.rs:148:9
|
--> tests/ui/match_same_arms2.rs:162:9
|
||||||
|
|
|
|
||||||
LL | 1 => {
|
LL | 1 => {
|
||||||
| ^ help: try merging the arm patterns: `1 | 0`
|
| ^ help: try merging the arm patterns: `1 | 0`
|
||||||
@ -128,7 +143,7 @@ LL | | },
|
|||||||
|
|
|
|
||||||
= help: or try changing either arm body
|
= help: or try changing either arm body
|
||||||
note: other arm here
|
note: other arm here
|
||||||
--> tests/ui/match_same_arms2.rs:145:9
|
--> tests/ui/match_same_arms2.rs:159:9
|
||||||
|
|
|
|
||||||
LL | / 0 => {
|
LL | / 0 => {
|
||||||
LL | | empty!(0);
|
LL | | empty!(0);
|
||||||
@ -136,7 +151,7 @@ LL | | },
|
|||||||
| |_________^
|
| |_________^
|
||||||
|
|
||||||
error: match expression looks like `matches!` macro
|
error: match expression looks like `matches!` macro
|
||||||
--> tests/ui/match_same_arms2.rs:167:16
|
--> tests/ui/match_same_arms2.rs:181:16
|
||||||
|
|
|
|
||||||
LL | let _ans = match x {
|
LL | let _ans = match x {
|
||||||
| ________________^
|
| ________________^
|
||||||
@ -150,7 +165,7 @@ LL | | };
|
|||||||
= help: to override `-D warnings` add `#[allow(clippy::match_like_matches_macro)]`
|
= help: to override `-D warnings` add `#[allow(clippy::match_like_matches_macro)]`
|
||||||
|
|
||||||
error: this match arm has an identical body to another arm
|
error: this match arm has an identical body to another arm
|
||||||
--> tests/ui/match_same_arms2.rs:199:9
|
--> tests/ui/match_same_arms2.rs:213:9
|
||||||
|
|
|
|
||||||
LL | Foo::X(0) => 1,
|
LL | Foo::X(0) => 1,
|
||||||
| ---------^^^^^
|
| ---------^^^^^
|
||||||
@ -159,13 +174,13 @@ LL | Foo::X(0) => 1,
|
|||||||
|
|
|
|
||||||
= help: or try changing either arm body
|
= help: or try changing either arm body
|
||||||
note: other arm here
|
note: other arm here
|
||||||
--> tests/ui/match_same_arms2.rs:201:9
|
--> tests/ui/match_same_arms2.rs:215:9
|
||||||
|
|
|
|
||||||
LL | Foo::Z(_) => 1,
|
LL | Foo::Z(_) => 1,
|
||||||
| ^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: this match arm has an identical body to another arm
|
error: this match arm has an identical body to another arm
|
||||||
--> tests/ui/match_same_arms2.rs:209:9
|
--> tests/ui/match_same_arms2.rs:223:9
|
||||||
|
|
|
|
||||||
LL | Foo::Z(_) => 1,
|
LL | Foo::Z(_) => 1,
|
||||||
| ---------^^^^^
|
| ---------^^^^^
|
||||||
@ -174,13 +189,13 @@ LL | Foo::Z(_) => 1,
|
|||||||
|
|
|
|
||||||
= help: or try changing either arm body
|
= help: or try changing either arm body
|
||||||
note: other arm here
|
note: other arm here
|
||||||
--> tests/ui/match_same_arms2.rs:207:9
|
--> tests/ui/match_same_arms2.rs:221:9
|
||||||
|
|
|
|
||||||
LL | Foo::X(0) => 1,
|
LL | Foo::X(0) => 1,
|
||||||
| ^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: this match arm has an identical body to another arm
|
error: this match arm has an identical body to another arm
|
||||||
--> tests/ui/match_same_arms2.rs:232:9
|
--> tests/ui/match_same_arms2.rs:246:9
|
||||||
|
|
|
|
||||||
LL | Some(Bar { y: 0, x: 5, .. }) => 1,
|
LL | Some(Bar { y: 0, x: 5, .. }) => 1,
|
||||||
| ----------------------------^^^^^
|
| ----------------------------^^^^^
|
||||||
@ -189,13 +204,13 @@ LL | Some(Bar { y: 0, x: 5, .. }) => 1,
|
|||||||
|
|
|
|
||||||
= help: or try changing either arm body
|
= help: or try changing either arm body
|
||||||
note: other arm here
|
note: other arm here
|
||||||
--> tests/ui/match_same_arms2.rs:229:9
|
--> tests/ui/match_same_arms2.rs:243:9
|
||||||
|
|
|
|
||||||
LL | Some(Bar { x: 0, y: 5, .. }) => 1,
|
LL | Some(Bar { x: 0, y: 5, .. }) => 1,
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: this match arm has an identical body to another arm
|
error: this match arm has an identical body to another arm
|
||||||
--> tests/ui/match_same_arms2.rs:246:9
|
--> tests/ui/match_same_arms2.rs:260:9
|
||||||
|
|
|
|
||||||
LL | 1 => cfg!(not_enable),
|
LL | 1 => cfg!(not_enable),
|
||||||
| -^^^^^^^^^^^^^^^^^^^^
|
| -^^^^^^^^^^^^^^^^^^^^
|
||||||
@ -204,10 +219,10 @@ LL | 1 => cfg!(not_enable),
|
|||||||
|
|
|
|
||||||
= help: or try changing either arm body
|
= help: or try changing either arm body
|
||||||
note: other arm here
|
note: other arm here
|
||||||
--> tests/ui/match_same_arms2.rs:245:9
|
--> tests/ui/match_same_arms2.rs:259:9
|
||||||
|
|
|
|
||||||
LL | 0 => cfg!(not_enable),
|
LL | 0 => cfg!(not_enable),
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: aborting due to 13 previous errors
|
error: aborting due to 14 previous errors
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user