Skip to content

Commit 3a79af7

Browse files
bors[bot]k-nasa
andauthored
Merge #10491
10491: Support nested type on replace if let with match r=k-nasa a=k-nasa ## Why close: #8690 Now, Replacing if-let with match cant't output exhaustive patterns code. This was because the `else` conversion used specific types (ex. Option, Result) instead of wildcards. I thought it was more of a problem to generate non-exhaustive patterns than the benefits of using the concrete one. How about using wildcards in `else`? Is this change policy acceptable? ## What - using wildcards on `make_else_arm` - Change test cases Co-authored-by: k-nasa <[email protected]>
2 parents bfb8f73 + bd9bab8 commit 3a79af7

File tree

2 files changed

+71
-1
lines changed

2 files changed

+71
-1
lines changed

crates/ide_assists/src/handlers/replace_if_let_with_match.rs

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use syntax::{
1212
};
1313

1414
use crate::{
15-
utils::{does_pat_match_variant, unwrap_trivial_block},
15+
utils::{does_nested_pattern, does_pat_match_variant, unwrap_trivial_block},
1616
AssistContext, AssistId, AssistKind, Assists,
1717
};
1818

@@ -143,6 +143,8 @@ fn make_else_arm(
143143
Some((it, pat)) => {
144144
if does_pat_match_variant(pat, &it.sad_pattern()) {
145145
it.happy_pattern_wildcard()
146+
} else if does_nested_pattern(pat) {
147+
make::wildcard_pat().into()
146148
} else {
147149
it.sad_pattern()
148150
}
@@ -574,6 +576,33 @@ fn main() {
574576
)
575577
}
576578

579+
#[test]
580+
fn nested_type() {
581+
check_assist(
582+
replace_if_let_with_match,
583+
r#"
584+
//- minicore: result
585+
fn foo(x: Result<i32, ()>) {
586+
let bar: Result<_, ()> = Ok(Some(1));
587+
$0if let Ok(Some(_)) = bar {
588+
()
589+
} else {
590+
()
591+
}
592+
}
593+
"#,
594+
r#"
595+
fn foo(x: Result<i32, ()>) {
596+
let bar: Result<_, ()> = Ok(Some(1));
597+
match bar {
598+
Ok(Some(_)) => (),
599+
_ => (),
600+
}
601+
}
602+
"#,
603+
);
604+
}
605+
577606
#[test]
578607
fn test_replace_match_with_if_let_unwraps_simple_expressions() {
579608
check_assist(

crates/ide_assists/src/utils.rs

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,47 @@ pub(crate) fn does_pat_match_variant(pat: &ast::Pat, var: &ast::Pat) -> bool {
285285
pat_head == var_head
286286
}
287287

288+
pub(crate) fn does_nested_pattern(pat: &ast::Pat) -> bool {
289+
let depth = calc_depth(pat, 0);
290+
291+
if 1 < depth {
292+
return true;
293+
}
294+
false
295+
}
296+
297+
fn calc_depth(pat: &ast::Pat, depth: usize) -> usize {
298+
match pat {
299+
ast::Pat::IdentPat(_)
300+
| ast::Pat::BoxPat(_)
301+
| ast::Pat::RestPat(_)
302+
| ast::Pat::LiteralPat(_)
303+
| ast::Pat::MacroPat(_)
304+
| ast::Pat::OrPat(_)
305+
| ast::Pat::ParenPat(_)
306+
| ast::Pat::PathPat(_)
307+
| ast::Pat::WildcardPat(_)
308+
| ast::Pat::RangePat(_)
309+
| ast::Pat::RecordPat(_)
310+
| ast::Pat::RefPat(_)
311+
| ast::Pat::SlicePat(_)
312+
| ast::Pat::TuplePat(_)
313+
| ast::Pat::ConstBlockPat(_) => depth,
314+
315+
// FIXME: Other patterns may also be nested. Currently it simply supports only `TupleStructPat`
316+
ast::Pat::TupleStructPat(pat) => {
317+
let mut max_depth = depth;
318+
for p in pat.fields() {
319+
let d = calc_depth(&p, depth + 1);
320+
if d > max_depth {
321+
max_depth = d
322+
}
323+
}
324+
max_depth
325+
}
326+
}
327+
}
328+
288329
// Uses a syntax-driven approach to find any impl blocks for the struct that
289330
// exist within the module/file
290331
//

0 commit comments

Comments
 (0)