Unnamed repository; edit this file 'description' to name the repository.
Merge pull request #21333 from A4-Tacks/expected-tuple-struct-pat
Fix tuple struct pat expected type
Lukas Wirth 8 weeks ago
parent 4142824 · parent c0aa088 · commit 721a1c5
-rw-r--r--crates/ide-completion/src/context/analysis.rs10
-rw-r--r--crates/ide-completion/src/context/tests.rs44
2 files changed, 54 insertions, 0 deletions
diff --git a/crates/ide-completion/src/context/analysis.rs b/crates/ide-completion/src/context/analysis.rs
index 4ab2850ece..bf899539a2 100644
--- a/crates/ide-completion/src/context/analysis.rs
+++ b/crates/ide-completion/src/context/analysis.rs
@@ -778,6 +778,16 @@ fn expected_type_and_name<'db>(
let ty = sema.type_of_pat(&ast::Pat::from(it)).map(TypeInfo::original);
(ty, None)
},
+ ast::TupleStructPat(it) => {
+ let fields = it.path().and_then(|path| match sema.resolve_path(&path)? {
+ hir::PathResolution::Def(hir::ModuleDef::Adt(adt)) => Some(adt.as_struct()?.fields(sema.db)),
+ hir::PathResolution::Def(hir::ModuleDef::Variant(variant)) => Some(variant.fields(sema.db)),
+ _ => None,
+ });
+ let nr = it.fields().take_while(|it| it.syntax().text_range().end() <= token.text_range().start()).count();
+ let ty = fields.and_then(|fields| Some(fields.get(nr)?.ty(sema.db).to_type(sema.db)));
+ (ty, None)
+ },
ast::Fn(it) => {
cov_mark::hit!(expected_type_fn_ret_with_leading_char);
cov_mark::hit!(expected_type_fn_ret_without_leading_char);
diff --git a/crates/ide-completion/src/context/tests.rs b/crates/ide-completion/src/context/tests.rs
index e97d9720e3..94d904932a 100644
--- a/crates/ide-completion/src/context/tests.rs
+++ b/crates/ide-completion/src/context/tests.rs
@@ -288,6 +288,50 @@ fn foo() -> Foo {
}
#[test]
+fn expected_type_tuple_struct_pat() {
+ check_expected_type_and_name(
+ r#"
+//- minicore: option
+struct Foo(Option<i32>);
+fn foo(x: Foo) -> Foo {
+ match x { Foo($0) => () }
+}
+"#,
+ expect![[r#"ty: Option<i32>, name: ?"#]],
+ );
+
+ check_expected_type_and_name(
+ r#"
+struct Foo(i32, u32, f32);
+fn foo(x: Foo) -> Foo {
+ match x { Foo($0) => () }
+}
+"#,
+ expect![[r#"ty: i32, name: ?"#]],
+ );
+
+ check_expected_type_and_name(
+ r#"
+struct Foo(i32, u32, f32);
+fn foo(x: Foo) -> Foo {
+ match x { Foo(num,$0) => () }
+}
+"#,
+ expect![[r#"ty: u32, name: ?"#]],
+ );
+
+ check_expected_type_and_name(
+ r#"
+struct Foo(i32, u32, f32);
+fn foo(x: Foo) -> Foo {
+ match x { Foo(num,$0,float) => () }
+}
+"#,
+ expect![[r#"ty: u32, name: ?"#]],
+ );
+}
+
+#[test]
fn expected_type_if_let_without_leading_char() {
cov_mark::check!(expected_type_if_let_without_leading_char);
check_expected_type_and_name(