From 55c941cd9fb90c9340f01981e113aabd058b185b Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Tue, 25 Dec 2018 13:54:38 +0100 Subject: Type field accesses --- crates/ra_hir/src/adt.rs | 9 +++++++ crates/ra_hir/src/ty.rs | 32 ++++++++++++++++++++++++- crates/ra_hir/src/ty/tests/data/0004_struct.txt | 6 +++-- 3 files changed, 44 insertions(+), 3 deletions(-) (limited to 'crates/ra_hir/src') diff --git a/crates/ra_hir/src/adt.rs b/crates/ra_hir/src/adt.rs index b44f59f0b..03770ed7d 100644 --- a/crates/ra_hir/src/adt.rs +++ b/crates/ra_hir/src/adt.rs @@ -22,6 +22,10 @@ impl Struct { self.def_id } + pub fn variant_data(&self, db: &impl HirDatabase) -> Cancelable> { + Ok(db.struct_data(self.def_id)?.variant_data.clone()) + } + pub fn struct_data(&self, db: &impl HirDatabase) -> Cancelable> { Ok(db.struct_data(self.def_id)?) } @@ -162,6 +166,11 @@ impl VariantData { StructFlavor::Unit => VariantData::Unit, }) } + + pub(crate) fn get_field_ty(&self, field_name: &str) -> Option { + self.fields().iter().find(|f| f.name == field_name).map(|f| f.ty.clone()) + } + pub fn fields(&self) -> &[StructField] { match *self { VariantData::Struct(ref fields) | VariantData::Tuple(ref fields) => fields, diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs index e2428a37f..f931f3c87 100644 --- a/crates/ra_hir/src/ty.rs +++ b/crates/ra_hir/src/ty.rs @@ -384,6 +384,14 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { }) } + fn infer_expr_opt(&mut self, expr: Option) -> Cancelable { + if let Some(e) = expr { + self.infer_expr(e) + } else { + Ok(Ty::Unknown) + } + } + fn infer_expr(&mut self, expr: ast::Expr) -> Cancelable { let ty = match expr { ast::Expr::IfExpr(e) => { @@ -559,7 +567,29 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { Ty::Unknown } ast::Expr::IndexExpr(_e) => Ty::Unknown, - ast::Expr::FieldExpr(_e) => Ty::Unknown, + ast::Expr::FieldExpr(e) => { + let receiver_ty = self.infer_expr_opt(e.expr())?; + if let Some(nr) = e.name_ref() { + let text = nr.text(); + match receiver_ty { + Ty::Tuple(fields) => { + let i = text.parse::().ok(); + i.and_then(|i| fields.get(i).cloned()).unwrap_or(Ty::Unknown) + } + Ty::Adt { def_id, .. } => { + let field_ty = match def_id.resolve(self.db)? { + Def::Struct(s) => s.variant_data(self.db)?.get_field_ty(&text), + // TODO unions + _ => None, + }; + field_ty.unwrap_or(Ty::Unknown) + } + _ => Ty::Unknown, + } + } else { + Ty::Unknown + } + }, ast::Expr::TryExpr(e) => { let _inner_ty = if let Some(e) = e.expr() { self.infer_expr(e)? diff --git a/crates/ra_hir/src/ty/tests/data/0004_struct.txt b/crates/ra_hir/src/ty/tests/data/0004_struct.txt index 41357749f..cc8f3665b 100644 --- a/crates/ra_hir/src/ty/tests/data/0004_struct.txt +++ b/crates/ra_hir/src/ty/tests/data/0004_struct.txt @@ -4,9 +4,11 @@ [129; 130) '1': [unknown] [107; 108) 'a': A [127; 128) 'C': [unknown] -[139; 142) 'a.b': [unknown] +[139; 142) 'a.b': B [114; 133) 'A { b:...C(1) }': A -[148; 151) 'a.c': [unknown] +[148; 151) 'a.c': C +[148; 149) 'a': A +[139; 140) 'a': A [72; 154) '{ ...a.c; }': () [96; 97) 'B': [unknown] [88; 89) '1': [unknown] -- cgit v1.2.3