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 +++-- crates/ra_syntax/src/ast/generated.rs | 10 +++++++- crates/ra_syntax/src/grammar.ron | 2 +- 5 files changed, 54 insertions(+), 5 deletions(-) (limited to 'crates') 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] diff --git a/crates/ra_syntax/src/ast/generated.rs b/crates/ra_syntax/src/ast/generated.rs index 35a9770a6..4e0550487 100644 --- a/crates/ra_syntax/src/ast/generated.rs +++ b/crates/ra_syntax/src/ast/generated.rs @@ -1123,7 +1123,15 @@ impl> FieldExprNode { } -impl<'a> FieldExpr<'a> {} +impl<'a> FieldExpr<'a> { + pub fn expr(self) -> Option> { + super::child_opt(self) + } + + pub fn name_ref(self) -> Option> { + super::child_opt(self) + } +} // FieldPatList #[derive(Debug, Clone, Copy,)] diff --git a/crates/ra_syntax/src/grammar.ron b/crates/ra_syntax/src/grammar.ron index e4e41d077..923da0324 100644 --- a/crates/ra_syntax/src/grammar.ron +++ b/crates/ra_syntax/src/grammar.ron @@ -406,7 +406,7 @@ Grammar( options: [ "Expr" ], ), "IndexExpr": (), - "FieldExpr": (), + "FieldExpr": (options: ["Expr", "NameRef"]), "TryExpr": (options: ["Expr"]), "CastExpr": (options: ["Expr", "TypeRef"]), "RefExpr": (options: ["Expr"]), -- cgit v1.2.3