diff options
Diffstat (limited to 'crates/ra_hir_def/src/body/lower.rs')
-rw-r--r-- | crates/ra_hir_def/src/body/lower.rs | 27 |
1 files changed, 22 insertions, 5 deletions
diff --git a/crates/ra_hir_def/src/body/lower.rs b/crates/ra_hir_def/src/body/lower.rs index 6caa87db4..79abe55ce 100644 --- a/crates/ra_hir_def/src/body/lower.rs +++ b/crates/ra_hir_def/src/body/lower.rs | |||
@@ -33,6 +33,7 @@ use crate::{ | |||
33 | }; | 33 | }; |
34 | 34 | ||
35 | use super::{ExprSource, PatSource}; | 35 | use super::{ExprSource, PatSource}; |
36 | use ast::AstChildren; | ||
36 | 37 | ||
37 | pub(super) fn lower( | 38 | pub(super) fn lower( |
38 | db: &dyn DefDatabase, | 39 | db: &dyn DefDatabase, |
@@ -598,8 +599,8 @@ impl ExprCollector<'_> { | |||
598 | } | 599 | } |
599 | ast::Pat::TupleStructPat(p) => { | 600 | ast::Pat::TupleStructPat(p) => { |
600 | let path = p.path().and_then(|path| self.expander.parse_path(path)); | 601 | let path = p.path().and_then(|path| self.expander.parse_path(path)); |
601 | let args = p.args().map(|p| self.collect_pat(p)).collect(); | 602 | let (args, ellipsis) = self.collect_tuple_pat(p.args()); |
602 | Pat::TupleStruct { path, args } | 603 | Pat::TupleStruct { path, args, ellipsis } |
603 | } | 604 | } |
604 | ast::Pat::RefPat(p) => { | 605 | ast::Pat::RefPat(p) => { |
605 | let pat = self.collect_pat_opt(p.pat()); | 606 | let pat = self.collect_pat_opt(p.pat()); |
@@ -616,10 +617,10 @@ impl ExprCollector<'_> { | |||
616 | } | 617 | } |
617 | ast::Pat::ParenPat(p) => return self.collect_pat_opt(p.pat()), | 618 | ast::Pat::ParenPat(p) => return self.collect_pat_opt(p.pat()), |
618 | ast::Pat::TuplePat(p) => { | 619 | ast::Pat::TuplePat(p) => { |
619 | let args = p.args().map(|p| self.collect_pat(p)).collect(); | 620 | let (args, ellipsis) = self.collect_tuple_pat(p.args()); |
620 | Pat::Tuple(args) | 621 | Pat::Tuple { args, ellipsis } |
621 | } | 622 | } |
622 | ast::Pat::PlaceholderPat(_) | ast::Pat::DotDotPat(_) => Pat::Wild, | 623 | ast::Pat::PlaceholderPat(_) => Pat::Wild, |
623 | ast::Pat::RecordPat(p) => { | 624 | ast::Pat::RecordPat(p) => { |
624 | let path = p.path().and_then(|path| self.expander.parse_path(path)); | 625 | let path = p.path().and_then(|path| self.expander.parse_path(path)); |
625 | let record_field_pat_list = | 626 | let record_field_pat_list = |
@@ -665,6 +666,9 @@ impl ExprCollector<'_> { | |||
665 | Pat::Missing | 666 | Pat::Missing |
666 | } | 667 | } |
667 | } | 668 | } |
669 | ast::Pat::DotDotPat(_) => unreachable!( | ||
670 | "`DotDotPat` requires special handling and should not be mapped to a Pat." | ||
671 | ), | ||
668 | // FIXME: implement | 672 | // FIXME: implement |
669 | ast::Pat::BoxPat(_) | ast::Pat::RangePat(_) | ast::Pat::MacroPat(_) => Pat::Missing, | 673 | ast::Pat::BoxPat(_) | ast::Pat::RangePat(_) | ast::Pat::MacroPat(_) => Pat::Missing, |
670 | }; | 674 | }; |
@@ -679,6 +683,19 @@ impl ExprCollector<'_> { | |||
679 | self.missing_pat() | 683 | self.missing_pat() |
680 | } | 684 | } |
681 | } | 685 | } |
686 | |||
687 | fn collect_tuple_pat(&mut self, args: AstChildren<ast::Pat>) -> (Vec<PatId>, Option<usize>) { | ||
688 | // Find the location of the `..`, if there is one. Note that we do not | ||
689 | // consider the possiblity of there being multiple `..` here. | ||
690 | let ellipsis = args.clone().position(|p| matches!(p, ast::Pat::DotDotPat(_))); | ||
691 | // We want to skip the `..` pattern here, since we account for it above. | ||
692 | let args = args | ||
693 | .filter(|p| !matches!(p, ast::Pat::DotDotPat(_))) | ||
694 | .map(|p| self.collect_pat(p)) | ||
695 | .collect(); | ||
696 | |||
697 | (args, ellipsis) | ||
698 | } | ||
682 | } | 699 | } |
683 | 700 | ||
684 | impl From<ast::BinOp> for BinaryOp { | 701 | impl From<ast::BinOp> for BinaryOp { |