aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_ty/src/infer
diff options
context:
space:
mode:
authorLukas Wirth <[email protected]>2020-11-24 12:41:21 +0000
committerLukas Wirth <[email protected]>2020-11-24 12:56:20 +0000
commit35dd62e915905b6a93e2069a6d155cdf00cd254a (patch)
treeebaf611da8e52f8df0c2d308b18bb9b6368fe3ef /crates/hir_ty/src/infer
parent6294286fee6e53c29e8ad563f476721ad85ef266 (diff)
Properly infer tuple patterns when encountering ellipsis
Diffstat (limited to 'crates/hir_ty/src/infer')
-rw-r--r--crates/hir_ty/src/infer/pat.rs25
1 files changed, 17 insertions, 8 deletions
diff --git a/crates/hir_ty/src/infer/pat.rs b/crates/hir_ty/src/infer/pat.rs
index cde2ab82b..b3fd74eab 100644
--- a/crates/hir_ty/src/infer/pat.rs
+++ b/crates/hir_ty/src/infer/pat.rs
@@ -111,20 +111,29 @@ impl<'a> InferenceContext<'a> {
111 let expected = expected; 111 let expected = expected;
112 112
113 let ty = match &body[pat] { 113 let ty = match &body[pat] {
114 Pat::Tuple { ref args, .. } => { 114 Pat::Tuple { ref args, ellipsis } => {
115 let expectations = match expected.as_tuple() { 115 let expectations = match expected.as_tuple() {
116 Some(parameters) => &*parameters.0, 116 Some(parameters) => &*parameters.0,
117 _ => &[], 117 _ => &[],
118 }; 118 };
119 let expectations_iter = expectations.iter().chain(repeat(&Ty::Unknown));
120 119
121 let inner_tys = args 120 let (pre, post) = match ellipsis {
122 .iter() 121 &Some(idx) => args.split_at(idx),
123 .zip(expectations_iter) 122 None => (&args[..], &[][..]),
124 .map(|(&pat, ty)| self.infer_pat(pat, ty, default_bm)) 123 };
125 .collect(); 124 let uncovered_range = pre.len()..expectations.len().saturating_sub(post.len());
125 let mut expectations_iter = expectations.iter().chain(repeat(&Ty::Unknown));
126 let mut infer_pat = |(&pat, ty)| self.infer_pat(pat, ty, default_bm);
127
128 let mut inner_tys = Vec::with_capacity(expectations.len());
129 inner_tys.extend(pre.iter().zip(expectations_iter.by_ref()).map(&mut infer_pat));
130 inner_tys.extend(expectations_iter.by_ref().take(uncovered_range.len()).cloned());
131 inner_tys.extend(post.iter().zip(expectations_iter).map(infer_pat));
126 132
127 Ty::apply(TypeCtor::Tuple { cardinality: args.len() as u16 }, Substs(inner_tys)) 133 Ty::apply(
134 TypeCtor::Tuple { cardinality: inner_tys.len() as u16 },
135 Substs(inner_tys.into()),
136 )
128 } 137 }
129 Pat::Or(ref pats) => { 138 Pat::Or(ref pats) => {
130 if let Some((first_pat, rest)) = pats.split_first() { 139 if let Some((first_pat, rest)) = pats.split_first() {