Unnamed repository; edit this file 'description' to name the repository.
-rw-r--r--crates/hir/src/semantics.rs8
-rw-r--r--crates/hir/src/source_analyzer.rs22
-rw-r--r--crates/ide-completion/src/context/analysis.rs2
-rw-r--r--crates/ide-completion/src/context/tests.rs10
4 files changed, 41 insertions, 1 deletions
diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs
index a23d045c6f..8a761c2fc0 100644
--- a/crates/hir/src/semantics.rs
+++ b/crates/hir/src/semantics.rs
@@ -1947,6 +1947,14 @@ impl<'db> SemanticsImpl<'db> {
self.analyze(field.syntax())?.resolve_record_pat_field(self.db, field)
}
+ pub fn resolve_tuple_struct_pat_fields(
+ &self,
+ tuple_struct_pat: &ast::TupleStructPat,
+ ) -> Option<Vec<(Field, Type<'db>)>> {
+ self.analyze(tuple_struct_pat.syntax())?
+ .resolve_tuple_struct_pat_fields(self.db, tuple_struct_pat)
+ }
+
// FIXME: Replace this with `resolve_macro_call2`
pub fn resolve_macro_call(&self, macro_call: &ast::MacroCall) -> Option<Macro> {
let macro_call = self.find_file(macro_call.syntax()).with_value(macro_call);
diff --git a/crates/hir/src/source_analyzer.rs b/crates/hir/src/source_analyzer.rs
index f24ec420b5..32e6acb6c5 100644
--- a/crates/hir/src/source_analyzer.rs
+++ b/crates/hir/src/source_analyzer.rs
@@ -933,6 +933,28 @@ impl<'db> SourceAnalyzer<'db> {
))
}
+ pub(crate) fn resolve_tuple_struct_pat_fields(
+ &self,
+ db: &'db dyn HirDatabase,
+ tuple_struct_pat: &ast::TupleStructPat,
+ ) -> Option<Vec<(Field, Type<'db>)>> {
+ let interner = DbInterner::new_no_crate(db);
+ let pat_id = self.pat_id(&tuple_struct_pat.clone().into())?;
+ let variant_id = self.infer()?.variant_resolution_for_pat(pat_id.as_pat()?)?;
+ let (_adt, substs) = self.infer()?.pat_ty(pat_id.as_pat()?).as_adt()?;
+
+ Some(
+ db.field_types(variant_id)
+ .iter()
+ .map(|(local_id, ty)| {
+ let def = Field { parent: variant_id.into(), id: local_id };
+ let ty = ty.get().instantiate(interner, substs).skip_norm_wip();
+ (def, self.ty(ty))
+ })
+ .collect(),
+ )
+ }
+
pub(crate) fn resolve_bind_pat_to_const(
&self,
db: &'db dyn HirDatabase,
diff --git a/crates/ide-completion/src/context/analysis.rs b/crates/ide-completion/src/context/analysis.rs
index 7aec6f7e8f..b2ee94d49c 100644
--- a/crates/ide-completion/src/context/analysis.rs
+++ b/crates/ide-completion/src/context/analysis.rs
@@ -801,7 +801,7 @@ fn expected_type_and_name<'db>(
(ty, None)
},
ast::TupleStructPat(it) => {
- let fields = sema.type_of_pat(&it.clone().into()).map(|ty| ty.original.fields(sema.db));
+ let fields = sema.resolve_tuple_struct_pat_fields(&it);
let nr = it.fields().take_while(|it| it.syntax().text_range().end() <= token.text_range().start()).count();
let ty = fields.and_then(|fields| Some(rebase_ty(fields.get(nr)?.1.clone())));
(ty, None)
diff --git a/crates/ide-completion/src/context/tests.rs b/crates/ide-completion/src/context/tests.rs
index 706e8ea3c0..1d1a55c6fe 100644
--- a/crates/ide-completion/src/context/tests.rs
+++ b/crates/ide-completion/src/context/tests.rs
@@ -340,6 +340,16 @@ fn foo(x: Foo<Option<i32>>) -> Foo {
"#,
expect![[r#"ty: Option<i32>, name: ?"#]],
);
+ check_expected_type_and_name(
+ r#"
+//- minicore: option
+enum Foo<T> { Var(T) };
+fn foo(x: Foo<Option<i32>>) -> Foo {
+ match x { Foo::Var($0) => () }
+}
+"#,
+ expect![[r#"ty: Option<i32>, name: ?"#]],
+ );
}
#[test]