aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Diebold <[email protected]>2018-12-25 12:54:38 +0000
committerFlorian Diebold <[email protected]>2018-12-25 14:16:42 +0000
commit55c941cd9fb90c9340f01981e113aabd058b185b (patch)
treef07828a8eaabab7c20b2b4d3b98519956b981f17
parent07a72859650254d8ba326e2c9683ae52164cb3b5 (diff)
Type field accesses
-rw-r--r--crates/ra_hir/src/adt.rs9
-rw-r--r--crates/ra_hir/src/ty.rs32
-rw-r--r--crates/ra_hir/src/ty/tests/data/0004_struct.txt6
-rw-r--r--crates/ra_syntax/src/ast/generated.rs10
-rw-r--r--crates/ra_syntax/src/grammar.ron2
5 files changed, 54 insertions, 5 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]
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<R: TreeRoot<RaTypes>> FieldExprNode<R> {
1123} 1123}
1124 1124
1125 1125
1126impl<'a> FieldExpr<'a> {} 1126impl<'a> FieldExpr<'a> {
1127 pub fn expr(self) -> Option<Expr<'a>> {
1128 super::child_opt(self)
1129 }
1130
1131 pub fn name_ref(self) -> Option<NameRef<'a>> {
1132 super::child_opt(self)
1133 }
1134}
1127 1135
1128// FieldPatList 1136// FieldPatList
1129#[derive(Debug, Clone, Copy,)] 1137#[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(
406 options: [ "Expr" ], 406 options: [ "Expr" ],
407 ), 407 ),
408 "IndexExpr": (), 408 "IndexExpr": (),
409 "FieldExpr": (), 409 "FieldExpr": (options: ["Expr", "NameRef"]),
410 "TryExpr": (options: ["Expr"]), 410 "TryExpr": (options: ["Expr"]),
411 "CastExpr": (options: ["Expr", "TypeRef"]), 411 "CastExpr": (options: ["Expr", "TypeRef"]),
412 "RefExpr": (options: ["Expr"]), 412 "RefExpr": (options: ["Expr"]),