diff options
Diffstat (limited to 'crates/hir_ty')
-rw-r--r-- | crates/hir_ty/src/diagnostics/pattern.rs | 666 |
1 files changed, 597 insertions, 69 deletions
diff --git a/crates/hir_ty/src/diagnostics/pattern.rs b/crates/hir_ty/src/diagnostics/pattern.rs index 4f88dfe60..f8d2e9baa 100644 --- a/crates/hir_ty/src/diagnostics/pattern.rs +++ b/crates/hir_ty/src/diagnostics/pattern.rs | |||
@@ -3,7 +3,7 @@ | |||
3 | //! This module provides lowering from [hir_def::expr::Pat] to [self::Pat] and match | 3 | //! This module provides lowering from [hir_def::expr::Pat] to [self::Pat] and match |
4 | //! checking algorithm. | 4 | //! checking algorithm. |
5 | //! | 5 | //! |
6 | //! It is a loose port of `rustc_mir_build::thir::pattern` module. | 6 | //! It is modeled on the rustc module `rustc_mir_build::thir::pattern`. |
7 | 7 | ||
8 | mod deconstruct_pat; | 8 | mod deconstruct_pat; |
9 | mod pat_util; | 9 | mod pat_util; |
@@ -341,136 +341,636 @@ mod tests { | |||
341 | use crate::diagnostics::tests::check_diagnostics; | 341 | use crate::diagnostics::tests::check_diagnostics; |
342 | 342 | ||
343 | #[test] | 343 | #[test] |
344 | fn unit() { | 344 | fn empty_tuple() { |
345 | check_diagnostics( | 345 | check_diagnostics( |
346 | r#" | 346 | r#" |
347 | fn main() { | 347 | fn main() { |
348 | match () { () => {} } | 348 | match () { } |
349 | match () { _ => {} } | ||
350 | match () { } | ||
351 | //^^ Missing match arm | 349 | //^^ Missing match arm |
350 | match (()) { } | ||
351 | //^^^^ Missing match arm | ||
352 | |||
353 | match () { _ => (), } | ||
354 | match () { () => (), } | ||
355 | match (()) { (()) => (), } | ||
352 | } | 356 | } |
353 | "#, | 357 | "#, |
354 | ); | 358 | ); |
355 | } | 359 | } |
356 | 360 | ||
357 | #[test] | 361 | #[test] |
358 | fn tuple_of_units() { | 362 | fn tuple_of_two_empty_tuple() { |
359 | check_diagnostics( | 363 | check_diagnostics( |
360 | r#" | 364 | r#" |
361 | fn main() { | 365 | fn main() { |
362 | match ((), ()) { ((), ()) => {} } | 366 | match ((), ()) { } |
363 | match ((), ()) { ((), _) => {} } | ||
364 | match ((), ()) { (_, _) => {} } | ||
365 | match ((), ()) { _ => {} } | ||
366 | match ((), ()) { } | ||
367 | //^^^^^^^^ Missing match arm | 367 | //^^^^^^^^ Missing match arm |
368 | |||
369 | match ((), ()) { ((), ()) => (), } | ||
368 | } | 370 | } |
369 | "#, | 371 | "#, |
370 | ); | 372 | ); |
371 | } | 373 | } |
372 | 374 | ||
373 | #[test] | 375 | #[test] |
374 | fn tuple_with_ellipsis() { | 376 | fn boolean() { |
375 | check_diagnostics( | 377 | check_diagnostics( |
376 | r#" | 378 | r#" |
377 | struct A; struct B; | 379 | fn test_main() { |
378 | fn main(v: (A, (), B)) { | 380 | match false { } |
379 | match v { (A, ..) => {} } | 381 | //^^^^^ Missing match arm |
380 | match v { (.., B) => {} } | 382 | match false { true => (), } |
381 | match v { (A, .., B) => {} } | 383 | //^^^^^ Missing match arm |
382 | match v { (..) => {} } | 384 | match (false, true) {} |
383 | match v { } | 385 | //^^^^^^^^^^^^^ Missing match arm |
384 | //^ Missing match arm | 386 | match (false, true) { (true, true) => (), } |
387 | //^^^^^^^^^^^^^ Missing match arm | ||
388 | match (false, true) { | ||
389 | //^^^^^^^^^^^^^ Missing match arm | ||
390 | (false, true) => (), | ||
391 | (false, false) => (), | ||
392 | (true, false) => (), | ||
393 | } | ||
394 | match (false, true) { (true, _x) => (), } | ||
395 | //^^^^^^^^^^^^^ Missing match arm | ||
396 | |||
397 | match false { true => (), false => (), } | ||
398 | match (false, true) { | ||
399 | (false, _) => (), | ||
400 | (true, false) => (), | ||
401 | (_, true) => (), | ||
402 | } | ||
403 | match (false, true) { | ||
404 | (true, true) => (), | ||
405 | (true, false) => (), | ||
406 | (false, true) => (), | ||
407 | (false, false) => (), | ||
408 | } | ||
409 | match (false, true) { | ||
410 | (true, _x) => (), | ||
411 | (false, true) => (), | ||
412 | (false, false) => (), | ||
413 | } | ||
414 | match (false, true, false) { | ||
415 | (false, ..) => (), | ||
416 | (true, ..) => (), | ||
417 | } | ||
418 | match (false, true, false) { | ||
419 | (.., false) => (), | ||
420 | (.., true) => (), | ||
421 | } | ||
422 | match (false, true, false) { (..) => (), } | ||
385 | } | 423 | } |
386 | "#, | 424 | "#, |
387 | ); | 425 | ); |
388 | } | 426 | } |
389 | 427 | ||
390 | #[test] | 428 | #[test] |
391 | fn strukt() { | 429 | fn tuple_of_tuple_and_bools() { |
392 | check_diagnostics( | 430 | check_diagnostics( |
393 | r#" | 431 | r#" |
394 | struct A; struct B; | 432 | fn main() { |
395 | struct S { a: A, b: B} | 433 | match (false, ((), false)) {} |
396 | fn main(v: S) { | 434 | //^^^^^^^^^^^^^^^^^^^^ Missing match arm |
397 | match v { S { a, b } => {} } | 435 | match (false, ((), false)) { (true, ((), true)) => (), } |
398 | match v { S { a: _, b: _ } => {} } | 436 | //^^^^^^^^^^^^^^^^^^^^ Missing match arm |
399 | match v { S { .. } => {} } | 437 | match (false, ((), false)) { (true, _) => (), } |
400 | match v { _ => {} } | 438 | //^^^^^^^^^^^^^^^^^^^^ Missing match arm |
401 | match v { } | 439 | |
402 | //^ Missing match arm | 440 | match (false, ((), false)) { |
441 | (true, ((), true)) => (), | ||
442 | (true, ((), false)) => (), | ||
443 | (false, ((), true)) => (), | ||
444 | (false, ((), false)) => (), | ||
445 | } | ||
446 | match (false, ((), false)) { | ||
447 | (true, ((), true)) => (), | ||
448 | (true, ((), false)) => (), | ||
449 | (false, _) => (), | ||
450 | } | ||
403 | } | 451 | } |
404 | "#, | 452 | "#, |
405 | ); | 453 | ); |
406 | } | 454 | } |
407 | 455 | ||
408 | #[test] | 456 | #[test] |
409 | fn c_enum() { | 457 | fn enums() { |
410 | check_diagnostics( | 458 | check_diagnostics( |
411 | r#" | 459 | r#" |
412 | enum E { A, B } | 460 | enum Either { A, B, } |
413 | fn main(v: E) { | 461 | |
414 | match v { E::A | E::B => {} } | 462 | fn main() { |
415 | match v { _ => {} } | 463 | match Either::A { } |
416 | match v { E::A => {} } | 464 | //^^^^^^^^^ Missing match arm |
465 | match Either::B { Either::A => (), } | ||
466 | //^^^^^^^^^ Missing match arm | ||
467 | |||
468 | match &Either::B { | ||
469 | //^^^^^^^^^^ Missing match arm | ||
470 | Either::A => (), | ||
471 | } | ||
472 | |||
473 | match Either::B { | ||
474 | Either::A => (), Either::B => (), | ||
475 | } | ||
476 | match &Either::B { | ||
477 | Either::A => (), Either::B => (), | ||
478 | } | ||
479 | } | ||
480 | "#, | ||
481 | ); | ||
482 | } | ||
483 | |||
484 | #[test] | ||
485 | fn enum_containing_bool() { | ||
486 | check_diagnostics( | ||
487 | r#" | ||
488 | enum Either { A(bool), B } | ||
489 | |||
490 | fn main() { | ||
491 | match Either::B { } | ||
492 | //^^^^^^^^^ Missing match arm | ||
493 | match Either::B { | ||
494 | //^^^^^^^^^ Missing match arm | ||
495 | Either::A(true) => (), Either::B => () | ||
496 | } | ||
497 | |||
498 | match Either::B { | ||
499 | Either::A(true) => (), | ||
500 | Either::A(false) => (), | ||
501 | Either::B => (), | ||
502 | } | ||
503 | match Either::B { | ||
504 | Either::B => (), | ||
505 | _ => (), | ||
506 | } | ||
507 | match Either::B { | ||
508 | Either::A(_) => (), | ||
509 | Either::B => (), | ||
510 | } | ||
511 | |||
512 | } | ||
513 | "#, | ||
514 | ); | ||
515 | } | ||
516 | |||
517 | #[test] | ||
518 | fn enum_different_sizes() { | ||
519 | check_diagnostics( | ||
520 | r#" | ||
521 | enum Either { A(bool), B(bool, bool) } | ||
522 | |||
523 | fn main() { | ||
524 | match Either::A(false) { | ||
525 | //^^^^^^^^^^^^^^^^ Missing match arm | ||
526 | Either::A(_) => (), | ||
527 | Either::B(false, _) => (), | ||
528 | } | ||
529 | |||
530 | match Either::A(false) { | ||
531 | Either::A(_) => (), | ||
532 | Either::B(true, _) => (), | ||
533 | Either::B(false, _) => (), | ||
534 | } | ||
535 | match Either::A(false) { | ||
536 | Either::A(true) | Either::A(false) => (), | ||
537 | Either::B(true, _) => (), | ||
538 | Either::B(false, _) => (), | ||
539 | } | ||
540 | } | ||
541 | "#, | ||
542 | ); | ||
543 | } | ||
544 | |||
545 | #[test] | ||
546 | fn tuple_of_enum_no_diagnostic() { | ||
547 | check_diagnostics( | ||
548 | r#" | ||
549 | enum Either { A(bool), B(bool, bool) } | ||
550 | enum Either2 { C, D } | ||
551 | |||
552 | fn main() { | ||
553 | match (Either::A(false), Either2::C) { | ||
554 | (Either::A(true), _) | (Either::A(false), _) => (), | ||
555 | (Either::B(true, _), Either2::C) => (), | ||
556 | (Either::B(false, _), Either2::C) => (), | ||
557 | (Either::B(_, _), Either2::D) => (), | ||
558 | } | ||
559 | } | ||
560 | "#, | ||
561 | ); | ||
562 | } | ||
563 | |||
564 | #[test] | ||
565 | fn or_pattern_no_diagnostic() { | ||
566 | check_diagnostics( | ||
567 | r#" | ||
568 | enum Either {A, B} | ||
569 | |||
570 | fn main() { | ||
571 | match (Either::A, Either::B) { | ||
572 | (Either::A | Either::B, _) => (), | ||
573 | } | ||
574 | }"#, | ||
575 | ) | ||
576 | } | ||
577 | |||
578 | #[test] | ||
579 | fn mismatched_types() { | ||
580 | // Match statements with arms that don't match the | ||
581 | // expression pattern do not fire this diagnostic. | ||
582 | check_diagnostics( | ||
583 | r#" | ||
584 | enum Either { A, B } | ||
585 | enum Either2 { C, D } | ||
586 | |||
587 | fn main() { | ||
588 | match Either::A { | ||
589 | Either2::C => (), | ||
590 | Either2::D => (), | ||
591 | } | ||
592 | match (true, false) { | ||
593 | (true, false, true) => (), | ||
594 | (true) => (), | ||
595 | } | ||
596 | match (0) { () => () } | ||
597 | match Unresolved::Bar { Unresolved::Baz => () } | ||
598 | } | ||
599 | "#, | ||
600 | ); | ||
601 | } | ||
602 | |||
603 | #[test] | ||
604 | fn malformed_match_arm_tuple_enum_missing_pattern() { | ||
605 | // We are testing to be sure we don't panic here when the match | ||
606 | // arm `Either::B` is missing its pattern. | ||
607 | check_diagnostics( | ||
608 | r#" | ||
609 | enum Either { A, B(u32) } | ||
610 | |||
611 | fn main() { | ||
612 | match Either::A { | ||
613 | Either::A => (), | ||
614 | Either::B() => (), | ||
615 | } | ||
616 | } | ||
617 | "#, | ||
618 | ); | ||
619 | } | ||
620 | |||
621 | #[test] | ||
622 | fn expr_diverges() { | ||
623 | check_diagnostics( | ||
624 | r#" | ||
625 | enum Either { A, B } | ||
626 | |||
627 | fn main() { | ||
628 | match loop {} { | ||
629 | Either::A => (), | ||
630 | Either::B => (), | ||
631 | } | ||
632 | match loop {} { | ||
633 | Either::A => (), | ||
634 | } | ||
635 | match loop { break Foo::A } { | ||
636 | //^^^^^^^^^^^^^^^^^^^^^ Missing match arm | ||
637 | Either::A => (), | ||
638 | } | ||
639 | match loop { break Foo::A } { | ||
640 | Either::A => (), | ||
641 | Either::B => (), | ||
642 | } | ||
643 | } | ||
644 | "#, | ||
645 | ); | ||
646 | } | ||
647 | |||
648 | #[test] | ||
649 | fn expr_partially_diverges() { | ||
650 | check_diagnostics( | ||
651 | r#" | ||
652 | enum Either<T> { A(T), B } | ||
653 | |||
654 | fn foo() -> Either<!> { Either::B } | ||
655 | fn main() -> u32 { | ||
656 | match foo() { | ||
657 | Either::A(val) => val, | ||
658 | Either::B => 0, | ||
659 | } | ||
660 | } | ||
661 | "#, | ||
662 | ); | ||
663 | } | ||
664 | |||
665 | #[test] | ||
666 | fn enum_record() { | ||
667 | check_diagnostics( | ||
668 | r#" | ||
669 | enum Either { A { foo: bool }, B } | ||
670 | |||
671 | fn main() { | ||
672 | let a = Either::A { foo: true }; | ||
673 | match a { } | ||
417 | //^ Missing match arm | 674 | //^ Missing match arm |
418 | match v { } | 675 | match a { Either::A { foo: true } => () } |
419 | //^ Missing match arm | 676 | //^ Missing match arm |
677 | match a { | ||
678 | Either::A { } => (), | ||
679 | //^^^^^^^^^ Missing structure fields: | ||
680 | // | - foo | ||
681 | Either::B => (), | ||
682 | } | ||
683 | match a { | ||
684 | //^ Missing match arm | ||
685 | Either::A { } => (), | ||
686 | } //^^^^^^^^^ Missing structure fields: | ||
687 | // | - foo | ||
688 | |||
689 | match a { | ||
690 | Either::A { foo: true } => (), | ||
691 | Either::A { foo: false } => (), | ||
692 | Either::B => (), | ||
693 | } | ||
694 | match a { | ||
695 | Either::A { foo: _ } => (), | ||
696 | Either::B => (), | ||
697 | } | ||
420 | } | 698 | } |
421 | "#, | 699 | "#, |
422 | ); | 700 | ); |
423 | } | 701 | } |
424 | 702 | ||
425 | #[test] | 703 | #[test] |
426 | fn enum_() { | 704 | fn enum_record_fields_out_of_order() { |
427 | check_diagnostics( | 705 | check_diagnostics( |
428 | r#" | 706 | r#" |
429 | struct A; struct B; | 707 | enum Either { |
430 | enum E { Tuple(A, B), Struct{ a: A, b: B } } | 708 | A { foo: bool, bar: () }, |
431 | fn main(v: E) { | 709 | B, |
432 | match v { | 710 | } |
433 | E::Tuple(a, b) => {} | 711 | |
434 | E::Struct{ a, b } => {} | 712 | fn main() { |
435 | } | 713 | let a = Either::A { foo: true, bar: () }; |
436 | match v { | 714 | match a { |
437 | E::Tuple(_, _) => {} | ||
438 | E::Struct{..} => {} | ||
439 | } | ||
440 | match v { | ||
441 | E::Tuple(..) => {} | ||
442 | _ => {} | ||
443 | } | ||
444 | match v { E::Tuple(..) => {} } | ||
445 | //^ Missing match arm | 715 | //^ Missing match arm |
446 | match v { } | 716 | Either::A { bar: (), foo: false } => (), |
717 | Either::A { foo: true, bar: () } => (), | ||
718 | } | ||
719 | |||
720 | match a { | ||
721 | Either::A { bar: (), foo: false } => (), | ||
722 | Either::A { foo: true, bar: () } => (), | ||
723 | Either::B => (), | ||
724 | } | ||
725 | } | ||
726 | "#, | ||
727 | ); | ||
728 | } | ||
729 | |||
730 | #[test] | ||
731 | fn enum_record_ellipsis() { | ||
732 | check_diagnostics( | ||
733 | r#" | ||
734 | enum Either { | ||
735 | A { foo: bool, bar: bool }, | ||
736 | B, | ||
737 | } | ||
738 | |||
739 | fn main() { | ||
740 | let a = Either::B; | ||
741 | match a { | ||
742 | //^ Missing match arm | ||
743 | Either::A { foo: true, .. } => (), | ||
744 | Either::B => (), | ||
745 | } | ||
746 | match a { | ||
447 | //^ Missing match arm | 747 | //^ Missing match arm |
748 | Either::A { .. } => (), | ||
749 | } | ||
750 | |||
751 | match a { | ||
752 | Either::A { foo: true, .. } => (), | ||
753 | Either::A { foo: false, .. } => (), | ||
754 | Either::B => (), | ||
755 | } | ||
756 | |||
757 | match a { | ||
758 | Either::A { .. } => (), | ||
759 | Either::B => (), | ||
760 | } | ||
448 | } | 761 | } |
449 | "#, | 762 | "#, |
450 | ); | 763 | ); |
451 | } | 764 | } |
452 | 765 | ||
453 | #[test] | 766 | #[test] |
454 | fn boolean() { | 767 | fn enum_tuple_partial_ellipsis() { |
455 | check_diagnostics( | 768 | check_diagnostics( |
456 | r#" | 769 | r#" |
770 | enum Either { | ||
771 | A(bool, bool, bool, bool), | ||
772 | B, | ||
773 | } | ||
774 | |||
457 | fn main() { | 775 | fn main() { |
458 | match true { | 776 | match Either::B { |
459 | true => {} | 777 | //^^^^^^^^^ Missing match arm |
460 | false => {} | 778 | Either::A(true, .., true) => (), |
779 | Either::A(true, .., false) => (), | ||
780 | Either::A(false, .., false) => (), | ||
781 | Either::B => (), | ||
461 | } | 782 | } |
462 | match true { | 783 | match Either::B { |
463 | true | false => {} | 784 | //^^^^^^^^^ Missing match arm |
785 | Either::A(true, .., true) => (), | ||
786 | Either::A(true, .., false) => (), | ||
787 | Either::A(.., true) => (), | ||
788 | Either::B => (), | ||
464 | } | 789 | } |
465 | match true { | 790 | |
466 | true => {} | 791 | match Either::B { |
467 | _ => {} | 792 | Either::A(true, .., true) => (), |
793 | Either::A(true, .., false) => (), | ||
794 | Either::A(false, .., true) => (), | ||
795 | Either::A(false, .., false) => (), | ||
796 | Either::B => (), | ||
797 | } | ||
798 | match Either::B { | ||
799 | Either::A(true, .., true) => (), | ||
800 | Either::A(true, .., false) => (), | ||
801 | Either::A(.., true) => (), | ||
802 | Either::A(.., false) => (), | ||
803 | Either::B => (), | ||
804 | } | ||
805 | } | ||
806 | "#, | ||
807 | ); | ||
808 | } | ||
809 | |||
810 | #[test] | ||
811 | fn never() { | ||
812 | check_diagnostics( | ||
813 | r#" | ||
814 | enum Never {} | ||
815 | |||
816 | fn enum_(never: Never) { | ||
817 | match never {} | ||
818 | } | ||
819 | fn enum_ref(never: &Never) { | ||
820 | match never {} | ||
821 | //^^^^^ Missing match arm | ||
822 | } | ||
823 | fn bang(never: !) { | ||
824 | match never {} | ||
825 | } | ||
826 | "#, | ||
827 | ); | ||
828 | } | ||
829 | |||
830 | #[test] | ||
831 | fn unknown_type() { | ||
832 | check_diagnostics( | ||
833 | r#" | ||
834 | enum Option<T> { Some(T), None } | ||
835 | |||
836 | fn main() { | ||
837 | // `Never` is deliberately not defined so that it's an uninferred type. | ||
838 | match Option::<Never>::None { | ||
839 | None => (), | ||
840 | Some(never) => match never {}, | ||
841 | } | ||
842 | } | ||
843 | "#, | ||
844 | ); | ||
845 | } | ||
846 | |||
847 | #[test] | ||
848 | fn tuple_of_bools_with_ellipsis_at_end_missing_arm() { | ||
849 | check_diagnostics( | ||
850 | r#" | ||
851 | fn main() { | ||
852 | match (false, true, false) { | ||
853 | //^^^^^^^^^^^^^^^^^^^^ Missing match arm | ||
854 | (false, ..) => (), | ||
855 | } | ||
856 | }"#, | ||
857 | ); | ||
858 | } | ||
859 | |||
860 | #[test] | ||
861 | fn tuple_of_bools_with_ellipsis_at_beginning_missing_arm() { | ||
862 | check_diagnostics( | ||
863 | r#" | ||
864 | fn main() { | ||
865 | match (false, true, false) { | ||
866 | //^^^^^^^^^^^^^^^^^^^^ Missing match arm | ||
867 | (.., false) => (), | ||
868 | } | ||
869 | }"#, | ||
870 | ); | ||
871 | } | ||
872 | |||
873 | #[test] | ||
874 | fn tuple_of_bools_with_ellipsis_in_middle_missing_arm() { | ||
875 | check_diagnostics( | ||
876 | r#" | ||
877 | fn main() { | ||
878 | match (false, true, false) { | ||
879 | //^^^^^^^^^^^^^^^^^^^^ Missing match arm | ||
880 | (true, .., false) => (), | ||
881 | } | ||
882 | }"#, | ||
883 | ); | ||
884 | } | ||
885 | |||
886 | #[test] | ||
887 | fn record_struct() { | ||
888 | check_diagnostics( | ||
889 | r#"struct Foo { a: bool } | ||
890 | fn main(f: Foo) { | ||
891 | match f {} | ||
892 | //^ Missing match arm | ||
893 | match f { Foo { a: true } => () } | ||
894 | //^ Missing match arm | ||
895 | match &f { Foo { a: true } => () } | ||
896 | //^^ Missing match arm | ||
897 | match f { Foo { a: _ } => () } | ||
898 | match f { | ||
899 | Foo { a: true } => (), | ||
900 | Foo { a: false } => (), | ||
901 | } | ||
902 | match &f { | ||
903 | Foo { a: true } => (), | ||
904 | Foo { a: false } => (), | ||
905 | } | ||
906 | } | ||
907 | "#, | ||
908 | ); | ||
468 | } | 909 | } |
469 | match true {} | ||
470 | //^^^^ Missing match arm | ||
471 | match true { true => {} } | ||
472 | //^^^^ Missing match arm | ||
473 | 910 | ||
911 | #[test] | ||
912 | fn tuple_struct() { | ||
913 | check_diagnostics( | ||
914 | r#"struct Foo(bool); | ||
915 | fn main(f: Foo) { | ||
916 | match f {} | ||
917 | //^ Missing match arm | ||
918 | match f { Foo(true) => () } | ||
919 | //^ Missing match arm | ||
920 | match f { | ||
921 | Foo(true) => (), | ||
922 | Foo(false) => (), | ||
923 | } | ||
924 | } | ||
925 | "#, | ||
926 | ); | ||
927 | } | ||
928 | |||
929 | #[test] | ||
930 | fn unit_struct() { | ||
931 | check_diagnostics( | ||
932 | r#"struct Foo; | ||
933 | fn main(f: Foo) { | ||
934 | match f {} | ||
935 | //^ Missing match arm | ||
936 | match f { Foo => () } | ||
937 | } | ||
938 | "#, | ||
939 | ); | ||
940 | } | ||
941 | |||
942 | #[test] | ||
943 | fn record_struct_ellipsis() { | ||
944 | check_diagnostics( | ||
945 | r#"struct Foo { foo: bool, bar: bool } | ||
946 | fn main(f: Foo) { | ||
947 | match f { Foo { foo: true, .. } => () } | ||
948 | //^ Missing match arm | ||
949 | match f { | ||
950 | //^ Missing match arm | ||
951 | Foo { foo: true, .. } => (), | ||
952 | Foo { bar: false, .. } => () | ||
953 | } | ||
954 | match f { Foo { .. } => () } | ||
955 | match f { | ||
956 | Foo { foo: true, .. } => (), | ||
957 | Foo { foo: false, .. } => () | ||
958 | } | ||
959 | } | ||
960 | "#, | ||
961 | ); | ||
962 | } | ||
963 | |||
964 | #[test] | ||
965 | fn internal_or() { | ||
966 | check_diagnostics( | ||
967 | r#" | ||
968 | fn main() { | ||
969 | enum Either { A(bool), B } | ||
970 | match Either::B { | ||
971 | //^^^^^^^^^ Missing match arm | ||
972 | Either::A(true | false) => (), | ||
973 | } | ||
474 | } | 974 | } |
475 | "#, | 975 | "#, |
476 | ); | 976 | ); |
@@ -483,7 +983,7 @@ fn main() { | |||
483 | struct S { a: char} | 983 | struct S { a: char} |
484 | fn main(v: S) { | 984 | fn main(v: S) { |
485 | match v { S{ a } => {} } | 985 | match v { S{ a } => {} } |
486 | match v { S{ a: _x } => {} } | 986 | match v { S{ a: _x } => {} } |
487 | match v { S{ a: 'a' } => {} } | 987 | match v { S{ a: 'a' } => {} } |
488 | match v { S{..} => {} } | 988 | match v { S{..} => {} } |
489 | match v { _ => {} } | 989 | match v { _ => {} } |
@@ -509,4 +1009,32 @@ fn main() { | |||
509 | "#, | 1009 | "#, |
510 | ); | 1010 | ); |
511 | } | 1011 | } |
1012 | |||
1013 | mod false_negatives { | ||
1014 | //! The implementation of match checking here is a work in progress. As we roll this out, we | ||
1015 | //! prefer false negatives to false positives (ideally there would be no false positives). This | ||
1016 | //! test module should document known false negatives. Eventually we will have a complete | ||
1017 | //! implementation of match checking and this module will be empty. | ||
1018 | //! | ||
1019 | //! The reasons for documenting known false negatives: | ||
1020 | //! | ||
1021 | //! 1. It acts as a backlog of work that can be done to improve the behavior of the system. | ||
1022 | //! 2. It ensures the code doesn't panic when handling these cases. | ||
1023 | use super::*; | ||
1024 | |||
1025 | #[test] | ||
1026 | fn integers() { | ||
1027 | // We don't currently check integer exhaustiveness. | ||
1028 | check_diagnostics( | ||
1029 | r#" | ||
1030 | fn main() { | ||
1031 | match 5 { | ||
1032 | 10 => (), | ||
1033 | 11..20 => (), | ||
1034 | } | ||
1035 | } | ||
1036 | "#, | ||
1037 | ); | ||
1038 | } | ||
1039 | } | ||
512 | } | 1040 | } |