|
216 | 216 | //! U(P, p) := U(P, (r_1, p_2, .., p_n)) |
217 | 217 | //! || U(P, (r_2, p_2, .., p_n)) |
218 | 218 | //! ``` |
219 | | -use std::sync::Arc; |
| 219 | +use std::{iter, sync::Arc}; |
220 | 220 |
|
221 | 221 | use arena::Idx; |
222 | 222 | use hir_def::{ |
@@ -366,16 +366,17 @@ impl PatStack { |
366 | 366 |
|
367 | 367 | let head_pat = head.as_pat(cx); |
368 | 368 | let result = match (head_pat, constructor) { |
369 | | - (Pat::Tuple { args: ref pat_ids, ellipsis }, Constructor::Tuple { arity: _ }) => { |
370 | | - if ellipsis.is_some() { |
371 | | - // If there are ellipsis here, we should add the correct number of |
372 | | - // Pat::Wild patterns to `pat_ids`. We should be able to use the |
373 | | - // constructors arity for this, but at the time of writing we aren't |
374 | | - // correctly calculating this arity when ellipsis are present. |
375 | | - return Err(MatchCheckErr::NotImplemented); |
| 369 | + (Pat::Tuple { args: pat_ids, ellipsis }, &Constructor::Tuple { arity }) => { |
| 370 | + if let Some(ellipsis) = ellipsis { |
| 371 | + let (pre, post) = pat_ids.split_at(ellipsis); |
| 372 | + let n_wild_pats = arity.saturating_sub(pat_ids.len()); |
| 373 | + let pre_iter = pre.iter().map(Into::into); |
| 374 | + let wildcards = iter::repeat(PatIdOrWild::Wild).take(n_wild_pats); |
| 375 | + let post_iter = post.iter().map(Into::into); |
| 376 | + Some(self.replace_head_with(pre_iter.chain(wildcards).chain(post_iter))) |
| 377 | + } else { |
| 378 | + Some(self.replace_head_with(pat_ids.iter())) |
376 | 379 | } |
377 | | - |
378 | | - Some(self.replace_head_with(pat_ids.iter())) |
379 | 380 | } |
380 | 381 | (Pat::Lit(lit_expr), Constructor::Bool(constructor_val)) => { |
381 | 382 | match cx.body.exprs[lit_expr] { |
@@ -767,10 +768,11 @@ impl Constructor { |
767 | 768 | fn pat_constructor(cx: &MatchCheckCtx, pat: PatIdOrWild) -> MatchCheckResult<Option<Constructor>> { |
768 | 769 | let res = match pat.as_pat(cx) { |
769 | 770 | Pat::Wild => None, |
770 | | - // FIXME somehow create the Tuple constructor with the proper arity. If there are |
771 | | - // ellipsis, the arity is not equal to the number of patterns. |
772 | | - Pat::Tuple { args: pats, ellipsis } if ellipsis.is_none() => { |
773 | | - Some(Constructor::Tuple { arity: pats.len() }) |
| 771 | + Pat::Tuple { .. } => { |
| 772 | + let pat_id = pat.as_id().expect("we already know this pattern is not a wild"); |
| 773 | + Some(Constructor::Tuple { |
| 774 | + arity: cx.infer.type_of_pat[pat_id].as_tuple().ok_or(MatchCheckErr::Unknown)?.len(), |
| 775 | + }) |
774 | 776 | } |
775 | 777 | Pat::Lit(lit_expr) => match cx.body.exprs[lit_expr] { |
776 | 778 | Expr::Literal(Literal::Bool(val)) => Some(Constructor::Bool(val)), |
@@ -1352,6 +1354,31 @@ fn main() { |
1352 | 1354 | ); |
1353 | 1355 | } |
1354 | 1356 |
|
| 1357 | + #[test] |
| 1358 | + fn tuple_of_bools_with_ellipsis_at_end_missing_arm() { |
| 1359 | + check_diagnostics( |
| 1360 | + r#" |
| 1361 | +fn main() { |
| 1362 | + match (false, true, false) { |
| 1363 | + //^^^^^^^^^^^^^^^^^^^^ Missing match arm |
| 1364 | + (false, ..) => (), |
| 1365 | + } |
| 1366 | +}"#, |
| 1367 | + ); |
| 1368 | + } |
| 1369 | + |
| 1370 | + #[test] |
| 1371 | + fn tuple_of_bools_with_ellipsis_at_beginning_missing_arm() { |
| 1372 | + check_diagnostics( |
| 1373 | + r#" |
| 1374 | +fn main() { |
| 1375 | + match (false, true, false) { |
| 1376 | + //^^^^^^^^^^^^^^^^^^^^ Missing match arm |
| 1377 | + (.., false) => (), |
| 1378 | + } |
| 1379 | +}"#, |
| 1380 | + ); |
| 1381 | + } |
1355 | 1382 | mod false_negatives { |
1356 | 1383 | //! The implementation of match checking here is a work in progress. As we roll this out, we |
1357 | 1384 | //! prefer false negatives to false positives (ideally there would be no false positives). This |
@@ -1394,34 +1421,6 @@ fn main() { |
1394 | 1421 | ); |
1395 | 1422 | } |
1396 | 1423 |
|
1397 | | - #[test] |
1398 | | - fn tuple_of_bools_with_ellipsis_at_end_missing_arm() { |
1399 | | - // We don't currently handle tuple patterns with ellipsis. |
1400 | | - check_diagnostics( |
1401 | | - r#" |
1402 | | -fn main() { |
1403 | | - match (false, true, false) { |
1404 | | - (false, ..) => (), |
1405 | | - } |
1406 | | -} |
1407 | | -"#, |
1408 | | - ); |
1409 | | - } |
1410 | | - |
1411 | | - #[test] |
1412 | | - fn tuple_of_bools_with_ellipsis_at_beginning_missing_arm() { |
1413 | | - // We don't currently handle tuple patterns with ellipsis. |
1414 | | - check_diagnostics( |
1415 | | - r#" |
1416 | | -fn main() { |
1417 | | - match (false, true, false) { |
1418 | | - (.., false) => (), |
1419 | | - } |
1420 | | -} |
1421 | | -"#, |
1422 | | - ); |
1423 | | - } |
1424 | | - |
1425 | 1424 | #[test] |
1426 | 1425 | fn struct_missing_arm() { |
1427 | 1426 | // We don't currently handle structs. |
|
0 commit comments