Merge #10491
10491: Support nested type on replace if let with match r=k-nasa a=k-nasa ## Why close: https://github.com/rust-analyzer/rust-analyzer/issues/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 <htilcs1115@gmail.com>
This commit is contained in:
commit
3a79af7e27
@ -12,7 +12,7 @@
|
||||
};
|
||||
|
||||
use crate::{
|
||||
utils::{does_pat_match_variant, unwrap_trivial_block},
|
||||
utils::{does_nested_pattern, does_pat_match_variant, unwrap_trivial_block},
|
||||
AssistContext, AssistId, AssistKind, Assists,
|
||||
};
|
||||
|
||||
@ -143,6 +143,8 @@ fn make_else_arm(
|
||||
Some((it, pat)) => {
|
||||
if does_pat_match_variant(pat, &it.sad_pattern()) {
|
||||
it.happy_pattern_wildcard()
|
||||
} else if does_nested_pattern(pat) {
|
||||
make::wildcard_pat().into()
|
||||
} else {
|
||||
it.sad_pattern()
|
||||
}
|
||||
@ -574,6 +576,33 @@ fn main() {
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn nested_type() {
|
||||
check_assist(
|
||||
replace_if_let_with_match,
|
||||
r#"
|
||||
//- minicore: result
|
||||
fn foo(x: Result<i32, ()>) {
|
||||
let bar: Result<_, ()> = Ok(Some(1));
|
||||
$0if let Ok(Some(_)) = bar {
|
||||
()
|
||||
} else {
|
||||
()
|
||||
}
|
||||
}
|
||||
"#,
|
||||
r#"
|
||||
fn foo(x: Result<i32, ()>) {
|
||||
let bar: Result<_, ()> = Ok(Some(1));
|
||||
match bar {
|
||||
Ok(Some(_)) => (),
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_replace_match_with_if_let_unwraps_simple_expressions() {
|
||||
check_assist(
|
||||
|
@ -285,6 +285,47 @@ pub(crate) fn does_pat_match_variant(pat: &ast::Pat, var: &ast::Pat) -> bool {
|
||||
pat_head == var_head
|
||||
}
|
||||
|
||||
pub(crate) fn does_nested_pattern(pat: &ast::Pat) -> bool {
|
||||
let depth = calc_depth(pat, 0);
|
||||
|
||||
if 1 < depth {
|
||||
return true;
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
fn calc_depth(pat: &ast::Pat, depth: usize) -> usize {
|
||||
match pat {
|
||||
ast::Pat::IdentPat(_)
|
||||
| ast::Pat::BoxPat(_)
|
||||
| ast::Pat::RestPat(_)
|
||||
| ast::Pat::LiteralPat(_)
|
||||
| ast::Pat::MacroPat(_)
|
||||
| ast::Pat::OrPat(_)
|
||||
| ast::Pat::ParenPat(_)
|
||||
| ast::Pat::PathPat(_)
|
||||
| ast::Pat::WildcardPat(_)
|
||||
| ast::Pat::RangePat(_)
|
||||
| ast::Pat::RecordPat(_)
|
||||
| ast::Pat::RefPat(_)
|
||||
| ast::Pat::SlicePat(_)
|
||||
| ast::Pat::TuplePat(_)
|
||||
| ast::Pat::ConstBlockPat(_) => depth,
|
||||
|
||||
// FIXME: Other patterns may also be nested. Currently it simply supports only `TupleStructPat`
|
||||
ast::Pat::TupleStructPat(pat) => {
|
||||
let mut max_depth = depth;
|
||||
for p in pat.fields() {
|
||||
let d = calc_depth(&p, depth + 1);
|
||||
if d > max_depth {
|
||||
max_depth = d
|
||||
}
|
||||
}
|
||||
max_depth
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Uses a syntax-driven approach to find any impl blocks for the struct that
|
||||
// exist within the module/file
|
||||
//
|
||||
|
Loading…
Reference in New Issue
Block a user