Unnamed repository; edit this file 'description' to name the repository.
Merge pull request #22449 from A4-Tacks/expect-enum-struct-pat-ty
fix: analysis expected ty in enum variant
| -rw-r--r-- | crates/hir/src/semantics.rs | 9 | ||||
| -rw-r--r-- | crates/hir/src/source_analyzer.rs | 22 | ||||
| -rw-r--r-- | crates/ide-completion/src/context/analysis.rs | 2 | ||||
| -rw-r--r-- | crates/ide-completion/src/context/tests.rs | 10 |
4 files changed, 42 insertions, 1 deletions
diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs index a23d045c6f..0d6f9accf8 100644 --- a/crates/hir/src/semantics.rs +++ b/crates/hir/src/semantics.rs @@ -1947,6 +1947,15 @@ impl<'db> SemanticsImpl<'db> { self.analyze(field.syntax())?.resolve_record_pat_field(self.db, field) } + // FIXME: Remove this from https://github.com/rust-lang/rust-analyzer/pull/22449#discussion_r3299763452 + 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] |