Skip to content

Commit 0b1740b

Browse files
Merge pull request rust-lang#21291 from A4-Tacks/expected-nested-match-arm-expr-ty
Fix match arm nested body invalid expected type
2 parents b9351fb + a67bc72 commit 0b1740b

3 files changed

Lines changed: 43 additions & 0 deletions

File tree

‎src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs‎

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -734,6 +734,23 @@ fn expected_type_and_name<'db>(
734734
}.map(TypeInfo::original);
735735
(ty, None)
736736
},
737+
ast::MatchArm(it) => {
738+
let on_arrow = previous_non_trivia_token(token.clone()).is_some_and(|it| T![=>] == it.kind());
739+
let in_body = it.expr().is_some_and(|it| it.syntax().text_range().contains_range(token.text_range()));
740+
let match_expr = it.parent_match();
741+
742+
let ty = if on_arrow || in_body {
743+
// match foo { ..., pat => $0 }
744+
cov_mark::hit!(expected_type_match_arm_body_without_leading_char);
745+
cov_mark::hit!(expected_type_match_arm_body_with_leading_char);
746+
sema.type_of_expr(&match_expr.into())
747+
} else {
748+
// match foo { $0 }
749+
cov_mark::hit!(expected_type_match_arm_without_leading_char);
750+
match_expr.expr().and_then(|e| sema.type_of_expr(&e))
751+
}.map(TypeInfo::original);
752+
(ty, None)
753+
},
737754
ast::IfExpr(it) => {
738755
let ty = if let Some(body) = it.then_branch()
739756
&& token.text_range().end() > body.syntax().text_range().start()

‎src/tools/rust-analyzer/crates/ide-completion/src/context/tests.rs‎

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,22 @@ fn foo() -> Foo {
256256
);
257257
}
258258

259+
#[test]
260+
fn expected_type_match_arm_block_body_without_leading_char() {
261+
cov_mark::check!(expected_type_match_arm_body_without_leading_char);
262+
cov_mark::check!(expected_type_match_arm_body_with_leading_char);
263+
check_expected_type_and_name(
264+
r#"
265+
struct Foo;
266+
enum E { X }
267+
fn foo() -> Foo {
268+
match E::X { Foo::X => { $0 } }
269+
}
270+
"#,
271+
expect![[r#"ty: Foo, name: ?"#]],
272+
);
273+
}
274+
259275
#[test]
260276
fn expected_type_match_body_arm_with_leading_char() {
261277
cov_mark::check!(expected_type_match_arm_body_with_leading_char);

‎src/tools/rust-analyzer/crates/syntax/src/ast/node_ext.rs‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1096,6 +1096,16 @@ impl ast::MatchGuard {
10961096
}
10971097
}
10981098

1099+
impl ast::MatchArm {
1100+
pub fn parent_match(&self) -> ast::MatchExpr {
1101+
self.syntax()
1102+
.parent()
1103+
.and_then(|it| it.parent())
1104+
.and_then(ast::MatchExpr::cast)
1105+
.expect("MatchArms are always nested in MatchExprs")
1106+
}
1107+
}
1108+
10991109
impl From<ast::Item> for ast::AnyHasAttrs {
11001110
fn from(node: ast::Item) -> Self {
11011111
Self::new(node)

0 commit comments

Comments
 (0)