From ee822d19b7662a9055bc6693c4c40d8dcf752ea1 Mon Sep 17 00:00:00 2001 From: Josh Mcguigan Date: Sun, 12 Apr 2020 08:40:09 -0700 Subject: handle tuple patterns with ellipsis --- crates/ra_hir_def/src/body/lower.rs | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) (limited to 'crates/ra_hir_def/src/body') 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::{ }; use super::{ExprSource, PatSource}; +use ast::AstChildren; pub(super) fn lower( db: &dyn DefDatabase, @@ -598,8 +599,8 @@ impl ExprCollector<'_> { } ast::Pat::TupleStructPat(p) => { let path = p.path().and_then(|path| self.expander.parse_path(path)); - let args = p.args().map(|p| self.collect_pat(p)).collect(); - Pat::TupleStruct { path, args } + let (args, ellipsis) = self.collect_tuple_pat(p.args()); + Pat::TupleStruct { path, args, ellipsis } } ast::Pat::RefPat(p) => { let pat = self.collect_pat_opt(p.pat()); @@ -616,10 +617,10 @@ impl ExprCollector<'_> { } ast::Pat::ParenPat(p) => return self.collect_pat_opt(p.pat()), ast::Pat::TuplePat(p) => { - let args = p.args().map(|p| self.collect_pat(p)).collect(); - Pat::Tuple(args) + let (args, ellipsis) = self.collect_tuple_pat(p.args()); + Pat::Tuple { args, ellipsis } } - ast::Pat::PlaceholderPat(_) | ast::Pat::DotDotPat(_) => Pat::Wild, + ast::Pat::PlaceholderPat(_) => Pat::Wild, ast::Pat::RecordPat(p) => { let path = p.path().and_then(|path| self.expander.parse_path(path)); let record_field_pat_list = @@ -665,6 +666,9 @@ impl ExprCollector<'_> { Pat::Missing } } + ast::Pat::DotDotPat(_) => unreachable!( + "`DotDotPat` requires special handling and should not be mapped to a Pat." + ), // FIXME: implement ast::Pat::BoxPat(_) | ast::Pat::RangePat(_) | ast::Pat::MacroPat(_) => Pat::Missing, }; @@ -679,6 +683,19 @@ impl ExprCollector<'_> { self.missing_pat() } } + + fn collect_tuple_pat(&mut self, args: AstChildren) -> (Vec, Option) { + // Find the location of the `..`, if there is one. Note that we do not + // consider the possiblity of there being multiple `..` here. + let ellipsis = args.clone().position(|p| matches!(p, ast::Pat::DotDotPat(_))); + // We want to skip the `..` pattern here, since we account for it above. + let args = args + .filter(|p| !matches!(p, ast::Pat::DotDotPat(_))) + .map(|p| self.collect_pat(p)) + .collect(); + + (args, ellipsis) + } } impl From for BinaryOp { -- cgit v1.2.3