Fix match arm nested body invalid expected type

Example
---
```rust
struct Foo;
enum E { X }
fn foo() -> Foo {
    match E::X { Foo::X => { $0 } }
}
```

**Before this PR**

```text
ty: E, name: ?
```

**After this PR**

```text
ty: Foo, name: ?
```
This commit is contained in:
A4-Tacks 2025-12-17 17:34:43 +08:00
parent 2a402415ec
commit e1747f9ddf
No known key found for this signature in database
GPG Key ID: 9E63F956E66DD9C7
2 changed files with 33 additions and 0 deletions

View File

@ -734,6 +734,23 @@ fn expected_type_and_name<'db>(
}.map(TypeInfo::original);
(ty, None)
},
ast::MatchArm(it) => {
let on_arrow = previous_non_trivia_token(token.clone()).is_some_and(|it| T![=>] == it.kind());
let in_body = it.expr().is_some_and(|it| it.syntax().text_range().contains_range(token.text_range()));
let match_expr = it.syntax().ancestors().nth(2).and_then(ast::MatchExpr::cast);
let ty = if on_arrow || in_body {
// match foo { ..., pat => $0 }
cov_mark::hit!(expected_type_match_arm_body_without_leading_char);
cov_mark::hit!(expected_type_match_arm_body_with_leading_char);
match_expr.and_then(|it| sema.type_of_expr(&it.into()))
} else {
// match foo { $0 }
cov_mark::hit!(expected_type_match_arm_without_leading_char);
match_expr.and_then(|it| it.expr()).and_then(|e| sema.type_of_expr(&e))
}.map(TypeInfo::original);
(ty, None)
},
ast::IfExpr(it) => {
let ty = if let Some(body) = it.then_branch()
&& token.text_range().end() > body.syntax().text_range().start()

View File

@ -256,6 +256,22 @@ fn foo() -> Foo {
);
}
#[test]
fn expected_type_match_arm_block_body_without_leading_char() {
cov_mark::check!(expected_type_match_arm_body_without_leading_char);
cov_mark::check!(expected_type_match_arm_body_with_leading_char);
check_expected_type_and_name(
r#"
struct Foo;
enum E { X }
fn foo() -> Foo {
match E::X { Foo::X => { $0 } }
}
"#,
expect![[r#"ty: Foo, name: ?"#]],
);
}
#[test]
fn expected_type_match_body_arm_with_leading_char() {
cov_mark::check!(expected_type_match_arm_body_with_leading_char);