diff options
author | Marcus Klaas de Vries <[email protected]> | 2019-01-16 23:08:10 +0000 |
---|---|---|
committer | Aleksey Kladov <[email protected]> | 2019-01-19 12:37:25 +0000 |
commit | ac216880f5d1a3e5727b96d7b22433beec10382b (patch) | |
tree | f9d87289f7d870e5346ecb5c007a9ea43e63651b | |
parent | 3340807bd24f398dca158e85eebae74012d8ef4b (diff) |
Implement unlabeled struct field pattern inference
-rw-r--r-- | crates/ra_hir/src/expr.rs | 11 | ||||
-rw-r--r-- | crates/ra_hir/src/ty.rs | 15 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/tests.rs | 5 | ||||
-rw-r--r-- | crates/ra_syntax/src/ast.rs | 42 |
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)] |
333 | pub struct FieldPat { | 333 | pub 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)] |
694 | pub struct FieldPat { | 668 | pub 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 | ||
699 | impl FieldPatList { | 674 | impl 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 | } |