aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarcus Klaas de Vries <[email protected]>2019-01-16 23:08:10 +0000
committerAleksey Kladov <[email protected]>2019-01-19 12:37:25 +0000
commitac216880f5d1a3e5727b96d7b22433beec10382b (patch)
treef9d87289f7d870e5346ecb5c007a9ea43e63651b
parent3340807bd24f398dca158e85eebae74012d8ef4b (diff)
Implement unlabeled struct field pattern inference
-rw-r--r--crates/ra_hir/src/expr.rs11
-rw-r--r--crates/ra_hir/src/ty.rs15
-rw-r--r--crates/ra_hir/src/ty/tests.rs5
-rw-r--r--crates/ra_syntax/src/ast.rs42
4 files changed, 26 insertions, 47 deletions
diff --git a/crates/ra_hir/src/expr.rs b/crates/ra_hir/src/expr.rs
index 893bad9cd..e7235c1a1 100644
--- a/crates/ra_hir/src/expr.rs
+++ b/crates/ra_hir/src/expr.rs
@@ -332,7 +332,7 @@ impl_arena_id!(PatId);
332#[derive(Debug, Clone, Eq, PartialEq)] 332#[derive(Debug, Clone, Eq, PartialEq)]
333pub struct FieldPat { 333pub struct FieldPat {
334 pub(crate) name: Name, 334 pub(crate) name: Name,
335 pub(crate) pat: Option<PatId>, 335 pub(crate) pat: PatId,
336} 336}
337 337
338/// Close relative to rustc's hir::PatKind 338/// Close relative to rustc's hir::PatKind
@@ -393,7 +393,7 @@ impl Pat {
393 total_iter.map(|pat| *pat).for_each(f); 393 total_iter.map(|pat| *pat).for_each(f);
394 } 394 }
395 Pat::Struct { args, .. } => { 395 Pat::Struct { args, .. } => {
396 args.iter().filter_map(|a| a.pat).for_each(f); 396 args.iter().map(|f| f.pat).for_each(f);
397 } 397 }
398 } 398 }
399 } 399 }
@@ -821,9 +821,10 @@ impl ExprCollector {
821 .expect("every struct should have a field list") 821 .expect("every struct should have a field list")
822 .field_pats() 822 .field_pats()
823 .into_iter() 823 .into_iter()
824 .map(|f| FieldPat { 824 .map(|f| {
825 name: Name::new(f.ident), 825 let name = Name::new(f.ident);
826 pat: f.pat.as_ref().map(|p| self.collect_pat(p)), 826 let pat = self.collect_pat(&*f.pat);
827 FieldPat { name, pat }
827 }) 828 })
828 .collect(); 829 .collect();
829 830
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs
index 6bad61a2a..66940ec30 100644
--- a/crates/ra_hir/src/ty.rs
+++ b/crates/ra_hir/src/ty.rs
@@ -937,19 +937,12 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
937 }; 937 };
938 938
939 for sub_pat in sub_pats { 939 for sub_pat in sub_pats {
940 let tyref = fields 940 let matching_field = fields.iter().find(|field| field.name == sub_pat.name);
941 .iter()
942 .find(|field| field.name == sub_pat.name)
943 .map(|field| &field.type_ref);
944 941
945 if let Some(typeref) = tyref { 942 if let Some(field) = matching_field {
943 let typeref = &field.type_ref;
946 let sub_ty = Ty::from_hir(self.db, &self.module, self.impl_block.as_ref(), typeref); 944 let sub_ty = Ty::from_hir(self.db, &self.module, self.impl_block.as_ref(), typeref);
947 945 self.infer_pat(sub_pat.pat, &Expectation::has_type(sub_ty));
948 if let Some(pat) = sub_pat.pat {
949 self.infer_pat(pat, &Expectation::has_type(sub_ty));
950 } else {
951 // TODO: deal with this case: S { x, y }
952 }
953 } 946 }
954 } 947 }
955 948
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs
index 75fe2cc6e..10842f967 100644
--- a/crates/ra_hir/src/ty/tests.rs
+++ b/crates/ra_hir/src/ty/tests.rs
@@ -389,6 +389,11 @@ fn test() {
389 389
390 let S(y, z) = foo; 390 let S(y, z) = foo;
391 let E::A { x: new_var } = e; 391 let E::A { x: new_var } = e;
392
393 match e {
394 E::A { x } => x,
395 E::B => 1,
396 };
392} 397}
393"#, 398"#,
394 "adt_pattern.txt", 399 "adt_pattern.txt",
diff --git a/crates/ra_syntax/src/ast.rs b/crates/ra_syntax/src/ast.rs
index 3df23b16f..4b7edbbe7 100644
--- a/crates/ra_syntax/src/ast.rs
+++ b/crates/ra_syntax/src/ast.rs
@@ -664,36 +664,11 @@ impl LiteralExpr {
664 } 664 }
665} 665}
666 666
667// STRUCT_PAT@[20; 42)
668// PATH@[20; 26)
669// PATH_SEGMENT@[20; 26)
670// NAME_REF@[20; 26)
671// IDENT@[20; 26) "Strukt"
672// WHITESPACE@[26; 27)
673// FIELD_PAT_LIST@[27; 42)
674// L_CURLY@[27; 28)
675// WHITESPACE@[28; 29)
676// IDENT@[29; 30) "x"
677// COLON@[30; 31)
678// WHITESPACE@[31; 32)
679// BIND_PAT@[32; 33)
680// NAME@[32; 33)
681// IDENT@[32; 33) "x"
682// COMMA@[33; 34)
683// WHITESPACE@[34; 35)
684// BIND_PAT@[35; 36)
685// NAME@[35; 36)
686// IDENT@[35; 36) "y"
687// COMMA@[36; 37)
688// WHITESPACE@[37; 38)
689// DOTDOT@[38; 40)
690// WHITESPACE@[40; 41)
691// R_CURLY@[41; 42)
692
693#[derive(Clone, Debug, PartialEq, Eq, Hash)] 667#[derive(Clone, Debug, PartialEq, Eq, Hash)]
694pub struct FieldPat { 668pub struct FieldPat {
695 pub ident: SmolStr, 669 pub ident: SmolStr,
696 pub pat: Option<TreeArc<Pat>>, 670 // FIXME: could we use a regular reference?
671 pub pat: TreeArc<Pat>,
697} 672}
698 673
699impl FieldPatList { 674impl FieldPatList {
@@ -704,12 +679,17 @@ impl FieldPatList {
704 let mut pats = Vec::new(); 679 let mut pats = Vec::new();
705 680
706 while let Some(node) = child_iter.next() { 681 while let Some(node) = child_iter.next() {
707 if node.kind() != IDENT { 682 let kind = node.kind();
683 if kind != IDENT && kind != BIND_PAT {
708 continue; 684 continue;
709 } 685 }
710 686
711 let ident = node.leaf_text().unwrap().clone(); 687 let ident = if let Some(text) = node.leaf_text() {
712 let mut pat = None; 688 text.clone()
689 } else {
690 SmolStr::new(node.text().to_string())
691 };
692 let mut pat = Pat::cast(node).map(AstNode::to_owned);
713 693
714 // get pat 694 // get pat
715 while let Some(node) = child_iter.next() { 695 while let Some(node) = child_iter.next() {
@@ -724,7 +704,7 @@ impl FieldPatList {
724 704
725 let field_pat = FieldPat { 705 let field_pat = FieldPat {
726 ident: ident, 706 ident: ident,
727 pat: pat, 707 pat: pat.unwrap(),
728 }; 708 };
729 pats.push(field_pat); 709 pats.push(field_pat);
730 } 710 }