diff options
Diffstat (limited to 'crates/ra_hir')
-rw-r--r-- | crates/ra_hir/src/adt.rs | 9 | ||||
-rw-r--r-- | crates/ra_hir/src/ty.rs | 32 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/tests/data/0004_struct.txt | 6 |
3 files changed, 44 insertions, 3 deletions
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 { | |||
22 | self.def_id | 22 | self.def_id |
23 | } | 23 | } |
24 | 24 | ||
25 | pub fn variant_data(&self, db: &impl HirDatabase) -> Cancelable<Arc<VariantData>> { | ||
26 | Ok(db.struct_data(self.def_id)?.variant_data.clone()) | ||
27 | } | ||
28 | |||
25 | pub fn struct_data(&self, db: &impl HirDatabase) -> Cancelable<Arc<StructData>> { | 29 | pub fn struct_data(&self, db: &impl HirDatabase) -> Cancelable<Arc<StructData>> { |
26 | Ok(db.struct_data(self.def_id)?) | 30 | Ok(db.struct_data(self.def_id)?) |
27 | } | 31 | } |
@@ -162,6 +166,11 @@ impl VariantData { | |||
162 | StructFlavor::Unit => VariantData::Unit, | 166 | StructFlavor::Unit => VariantData::Unit, |
163 | }) | 167 | }) |
164 | } | 168 | } |
169 | |||
170 | pub(crate) fn get_field_ty(&self, field_name: &str) -> Option<Ty> { | ||
171 | self.fields().iter().find(|f| f.name == field_name).map(|f| f.ty.clone()) | ||
172 | } | ||
173 | |||
165 | pub fn fields(&self) -> &[StructField] { | 174 | pub fn fields(&self) -> &[StructField] { |
166 | match *self { | 175 | match *self { |
167 | VariantData::Struct(ref fields) | VariantData::Tuple(ref fields) => fields, | 176 | 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> { | |||
384 | }) | 384 | }) |
385 | } | 385 | } |
386 | 386 | ||
387 | fn infer_expr_opt(&mut self, expr: Option<ast::Expr>) -> Cancelable<Ty> { | ||
388 | if let Some(e) = expr { | ||
389 | self.infer_expr(e) | ||
390 | } else { | ||
391 | Ok(Ty::Unknown) | ||
392 | } | ||
393 | } | ||
394 | |||
387 | fn infer_expr(&mut self, expr: ast::Expr) -> Cancelable<Ty> { | 395 | fn infer_expr(&mut self, expr: ast::Expr) -> Cancelable<Ty> { |
388 | let ty = match expr { | 396 | let ty = match expr { |
389 | ast::Expr::IfExpr(e) => { | 397 | ast::Expr::IfExpr(e) => { |
@@ -559,7 +567,29 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
559 | Ty::Unknown | 567 | Ty::Unknown |
560 | } | 568 | } |
561 | ast::Expr::IndexExpr(_e) => Ty::Unknown, | 569 | ast::Expr::IndexExpr(_e) => Ty::Unknown, |
562 | ast::Expr::FieldExpr(_e) => Ty::Unknown, | 570 | ast::Expr::FieldExpr(e) => { |
571 | let receiver_ty = self.infer_expr_opt(e.expr())?; | ||
572 | if let Some(nr) = e.name_ref() { | ||
573 | let text = nr.text(); | ||
574 | match receiver_ty { | ||
575 | Ty::Tuple(fields) => { | ||
576 | let i = text.parse::<usize>().ok(); | ||
577 | i.and_then(|i| fields.get(i).cloned()).unwrap_or(Ty::Unknown) | ||
578 | } | ||
579 | Ty::Adt { def_id, .. } => { | ||
580 | let field_ty = match def_id.resolve(self.db)? { | ||
581 | Def::Struct(s) => s.variant_data(self.db)?.get_field_ty(&text), | ||
582 | // TODO unions | ||
583 | _ => None, | ||
584 | }; | ||
585 | field_ty.unwrap_or(Ty::Unknown) | ||
586 | } | ||
587 | _ => Ty::Unknown, | ||
588 | } | ||
589 | } else { | ||
590 | Ty::Unknown | ||
591 | } | ||
592 | }, | ||
563 | ast::Expr::TryExpr(e) => { | 593 | ast::Expr::TryExpr(e) => { |
564 | let _inner_ty = if let Some(e) = e.expr() { | 594 | let _inner_ty = if let Some(e) = e.expr() { |
565 | self.infer_expr(e)? | 595 | 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 @@ | |||
4 | [129; 130) '1': [unknown] | 4 | [129; 130) '1': [unknown] |
5 | [107; 108) 'a': A | 5 | [107; 108) 'a': A |
6 | [127; 128) 'C': [unknown] | 6 | [127; 128) 'C': [unknown] |
7 | [139; 142) 'a.b': [unknown] | 7 | [139; 142) 'a.b': B |
8 | [114; 133) 'A { b:...C(1) }': A | 8 | [114; 133) 'A { b:...C(1) }': A |
9 | [148; 151) 'a.c': [unknown] | 9 | [148; 151) 'a.c': C |
10 | [148; 149) 'a': A | ||
11 | [139; 140) 'a': A | ||
10 | [72; 154) '{ ...a.c; }': () | 12 | [72; 154) '{ ...a.c; }': () |
11 | [96; 97) 'B': [unknown] | 13 | [96; 97) 'B': [unknown] |
12 | [88; 89) '1': [unknown] | 14 | [88; 89) '1': [unknown] |