From 7a0c93c58ac17b089edd8c9763fef303b7a81414 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Sun, 23 May 2021 18:10:40 +0200 Subject: Infer correct expected type for generic struct fields --- crates/hir/src/lib.rs | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) (limited to 'crates/hir') diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index a7c42ca1e..edee99356 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -513,9 +513,9 @@ impl Field { } /// Returns the type as in the signature of the struct (i.e., with - /// placeholder types for type parameters). This is good for showing - /// signature help, but not so good to actually get the type of the field - /// when you actually have a variable of the struct. + /// placeholder types for type parameters). Only use this in the context of + /// the field *definition*; if you've already got a variable of the struct + /// type, use `Type::field_type` to get to the field type. pub fn ty(&self, db: &dyn HirDatabase) -> Type { let var_id = self.parent.into(); let generic_def_id: GenericDefId = match self.parent { @@ -1944,6 +1944,18 @@ impl Type { } } + pub fn field_type(&self, db: &dyn HirDatabase, field: Field) -> Option { + let (adt_id, substs) = self.ty.as_adt()?; + let variant_id: hir_def::VariantId = field.parent.into(); + if variant_id.adt_id() != adt_id { + return None; + } + + let ty = db.field_types(variant_id).get(field.id)?.clone(); + let ty = ty.substitute(&Interner, substs); + Some(self.derived(ty)) + } + pub fn fields(&self, db: &dyn HirDatabase) -> Vec<(Field, Type)> { let (variant_id, substs) = match self.ty.kind(&Interner) { &TyKind::Adt(hir_ty::AdtId(AdtId::StructId(s)), ref substs) => (s.into(), substs), -- cgit v1.2.3