307
307
308
308
use self :: ArmType :: * ;
309
309
use self :: Usefulness :: * ;
310
- use super :: deconstruct_pat:: { Constructor , DeconstructedPat , Fields , SplitWildcard } ;
310
+ use super :: deconstruct_pat:: { Constructor , ConstructorSet , DeconstructedPat , Fields } ;
311
311
use crate :: errors:: { NonExhaustiveOmittedPattern , Uncovered } ;
312
312
313
313
use rustc_data_structures:: captures:: Captures ;
@@ -368,8 +368,6 @@ pub(super) struct PatCtxt<'a, 'p, 'tcx> {
368
368
/// Whether the current pattern is the whole pattern as found in a match arm, or if it's a
369
369
/// subpattern.
370
370
pub ( super ) is_top_level : bool ,
371
- /// Whether the current pattern is from a `non_exhaustive` enum.
372
- pub ( super ) is_non_exhaustive : bool ,
373
371
}
374
372
375
373
impl < ' a , ' p , ' tcx > fmt:: Debug for PatCtxt < ' a , ' p , ' tcx > {
@@ -616,62 +614,41 @@ impl<'p, 'tcx> Usefulness<'p, 'tcx> {
616
614
WithWitnesses ( ref witnesses) if witnesses. is_empty ( ) => self ,
617
615
WithWitnesses ( witnesses) => {
618
616
let new_witnesses = if let Constructor :: Missing { .. } = ctor {
617
+ let mut missing = ConstructorSet :: for_ty ( pcx. cx , pcx. ty )
618
+ . compute_missing ( pcx, matrix. heads ( ) . map ( DeconstructedPat :: ctor) ) ;
619
+ if missing. iter ( ) . any ( |c| c. is_non_exhaustive ( ) ) {
620
+ // We only report `_` here; listing other constructors would be redundant.
621
+ missing = vec ! [ Constructor :: NonExhaustive ] ;
622
+ }
623
+
619
624
// We got the special `Missing` constructor, so each of the missing constructors
620
- // gives a new pattern that is not caught by the match. We list those patterns.
621
- if pcx. is_non_exhaustive {
622
- witnesses
623
- . into_iter ( )
624
- // Here we don't want the user to try to list all variants, we want them to add
625
- // a wildcard, so we only suggest that.
626
- . map ( |witness| {
627
- witness. apply_constructor ( pcx, & Constructor :: NonExhaustive )
628
- } )
629
- . collect ( )
630
- } else {
631
- let mut split_wildcard = SplitWildcard :: new ( pcx) ;
632
- split_wildcard. split ( pcx, matrix. heads ( ) . map ( DeconstructedPat :: ctor) ) ;
633
-
634
- // This lets us know if we skipped any variants because they are marked
635
- // `doc(hidden)` or they are unstable feature gate (only stdlib types).
636
- let mut hide_variant_show_wild = false ;
637
- // Construct for each missing constructor a "wild" version of this
638
- // constructor, that matches everything that can be built with
639
- // it. For example, if `ctor` is a `Constructor::Variant` for
640
- // `Option::Some`, we get the pattern `Some(_)`.
641
- let mut new_patterns: Vec < DeconstructedPat < ' _ , ' _ > > = split_wildcard
642
- . iter_missing ( pcx)
643
- . filter_map ( |missing_ctor| {
644
- // Check if this variant is marked `doc(hidden)`
645
- if missing_ctor. is_doc_hidden_variant ( pcx)
646
- || missing_ctor. is_unstable_variant ( pcx)
647
- {
648
- hide_variant_show_wild = true ;
649
- return None ;
650
- }
651
- Some ( DeconstructedPat :: wild_from_ctor ( pcx, missing_ctor. clone ( ) ) )
652
- } )
653
- . collect ( ) ;
654
-
655
- if hide_variant_show_wild {
656
- new_patterns. push ( DeconstructedPat :: wildcard ( pcx. ty , pcx. span ) ) ;
657
- }
658
-
659
- witnesses
660
- . into_iter ( )
661
- . flat_map ( |witness| {
662
- new_patterns. iter ( ) . map ( move |pat| {
663
- Witness (
664
- witness
665
- . 0
666
- . iter ( )
667
- . chain ( once ( pat) )
668
- . map ( DeconstructedPat :: clone_and_forget_reachability)
669
- . collect ( ) ,
670
- )
671
- } )
625
+ // gives a new pattern that is not caught by the match.
626
+ // We construct for each missing constructor a version of this constructor with
627
+ // wildcards for fields, i.e. that matches everything that can be built with it.
628
+ // For example, if `ctor` is a `Constructor::Variant` for `Option::Some`, we get
629
+ // the pattern `Some(_)`.
630
+ let new_patterns: Vec < DeconstructedPat < ' _ , ' _ > > = missing
631
+ . into_iter ( )
632
+ . map ( |missing_ctor| {
633
+ DeconstructedPat :: wild_from_ctor ( pcx, missing_ctor. clone ( ) )
634
+ } )
635
+ . collect ( ) ;
636
+
637
+ witnesses
638
+ . into_iter ( )
639
+ . flat_map ( |witness| {
640
+ new_patterns. iter ( ) . map ( move |pat| {
641
+ Witness (
642
+ witness
643
+ . 0
644
+ . iter ( )
645
+ . chain ( once ( pat) )
646
+ . map ( DeconstructedPat :: clone_and_forget_reachability)
647
+ . collect ( ) ,
648
+ )
672
649
} )
673
- . collect ( )
674
- }
650
+ } )
651
+ . collect ( )
675
652
} else {
676
653
witnesses
677
654
. into_iter ( )
@@ -844,9 +821,8 @@ fn is_useful<'p, 'tcx>(
844
821
ty = row. head ( ) . ty ( ) ;
845
822
}
846
823
}
847
- let is_non_exhaustive = cx. is_foreign_non_exhaustive_enum ( ty) ;
848
824
debug ! ( "v.head: {:?}, v.span: {:?}" , v. head( ) , v. head( ) . span( ) ) ;
849
- let pcx = & PatCtxt { cx, ty, span : v. head ( ) . span ( ) , is_top_level, is_non_exhaustive } ;
825
+ let pcx = & PatCtxt { cx, ty, span : v. head ( ) . span ( ) , is_top_level } ;
850
826
851
827
let v_ctor = v. head ( ) . ctor ( ) ;
852
828
debug ! ( ?v_ctor) ;
@@ -861,7 +837,8 @@ fn is_useful<'p, 'tcx>(
861
837
}
862
838
// We split the head constructor of `v`.
863
839
let split_ctors = v_ctor. split ( pcx, matrix. heads ( ) . map ( DeconstructedPat :: ctor) ) ;
864
- let is_non_exhaustive_and_wild = is_non_exhaustive && v_ctor. is_wildcard ( ) ;
840
+ let is_non_exhaustive_and_wild =
841
+ cx. is_foreign_non_exhaustive_enum ( ty) && v_ctor. is_wildcard ( ) ;
865
842
// For each constructor, we compute whether there's a value that starts with it that would
866
843
// witness the usefulness of `v`.
867
844
let start_matrix = & matrix;
@@ -895,27 +872,21 @@ fn is_useful<'p, 'tcx>(
895
872
&& usefulness. is_useful ( ) && matches ! ( witness_preference, RealArm )
896
873
&& matches ! (
897
874
& ctor,
898
- Constructor :: Missing { nonexhaustive_enum_missing_real_variants : true }
875
+ Constructor :: Missing { nonexhaustive_enum_missing_visible_variants : true }
899
876
)
900
877
{
901
- let patterns = {
902
- let mut split_wildcard = SplitWildcard :: new ( pcx) ;
903
- split_wildcard. split ( pcx, matrix. heads ( ) . map ( DeconstructedPat :: ctor) ) ;
904
- // Construct for each missing constructor a "wild" version of this
905
- // constructor, that matches everything that can be built with
906
- // it. For example, if `ctor` is a `Constructor::Variant` for
907
- // `Option::Some`, we get the pattern `Some(_)`.
908
- split_wildcard
909
- . iter_missing ( pcx)
910
- // Filter out the `NonExhaustive` because we want to list only real
911
- // variants. Also remove any unstable feature gated variants.
912
- // Because of how we computed `nonexhaustive_enum_missing_real_variants`,
913
- // this will not return an empty `Vec`.
914
- . filter ( |c| !( c. is_non_exhaustive ( ) || c. is_unstable_variant ( pcx) ) )
915
- . cloned ( )
916
- . map ( |missing_ctor| DeconstructedPat :: wild_from_ctor ( pcx, missing_ctor) )
917
- . collect :: < Vec < _ > > ( )
918
- } ;
878
+ let missing = ConstructorSet :: for_ty ( pcx. cx , pcx. ty )
879
+ . compute_missing ( pcx, matrix. heads ( ) . map ( DeconstructedPat :: ctor) ) ;
880
+ // Construct for each missing constructor a "wild" version of this constructor, that
881
+ // matches everything that can be built with it. For example, if `ctor` is a
882
+ // `Constructor::Variant` for `Option::Some`, we get the pattern `Some(_)`.
883
+ let patterns = missing
884
+ . into_iter ( )
885
+ // Because of how we computed `nonexhaustive_enum_missing_visible_variants`,
886
+ // this will not return an empty `Vec`.
887
+ . filter ( |c| !( matches ! ( c, Constructor :: NonExhaustive | Constructor :: Hidden ) ) )
888
+ . map ( |missing_ctor| DeconstructedPat :: wild_from_ctor ( pcx, missing_ctor) )
889
+ . collect :: < Vec < _ > > ( ) ;
919
890
920
891
// Report that a match of a `non_exhaustive` enum marked with `non_exhaustive_omitted_patterns`
921
892
// is not exhaustive enough.
0 commit comments