@@ -11,16 +11,30 @@ use rustc_pattern_analysis::usefulness::PlaceValidity;
1111mod common;
1212
1313/// Analyze a match made of these patterns.
14- fn check ( patterns : Vec < DeconstructedPat < Cx > > ) -> Vec < WitnessPat < Cx > > {
15- let ty = * patterns[ 0 ] . ty ( ) ;
14+ fn run (
15+ ty : Ty ,
16+ patterns : Vec < DeconstructedPat < Cx > > ,
17+ exhaustive_witnesses : bool ,
18+ ) -> Vec < WitnessPat < Cx > > {
1619 let arms: Vec < _ > =
1720 patterns. iter ( ) . map ( |pat| MatchArm { pat, has_guard : false , arm_data : ( ) } ) . collect ( ) ;
18- let report =
19- compute_match_usefulness ( arms. as_slice ( ) , ty, PlaceValidity :: ValidOnly , usize:: MAX )
20- . unwrap ( ) ;
21+ let report = compute_match_usefulness (
22+ arms. as_slice ( ) ,
23+ ty,
24+ PlaceValidity :: ValidOnly ,
25+ usize:: MAX ,
26+ exhaustive_witnesses,
27+ )
28+ . unwrap ( ) ;
2129 report. non_exhaustiveness_witnesses
2230}
2331
32+ /// Analyze a match made of these patterns. Panics if there are no patterns
33+ fn check ( patterns : Vec < DeconstructedPat < Cx > > ) -> Vec < WitnessPat < Cx > > {
34+ let ty = * patterns[ 0 ] . ty ( ) ;
35+ run ( ty, patterns, true )
36+ }
37+
2438#[ track_caller]
2539fn assert_exhaustive ( patterns : Vec < DeconstructedPat < Cx > > ) {
2640 let witnesses = check ( patterns) ;
@@ -35,6 +49,26 @@ fn assert_non_exhaustive(patterns: Vec<DeconstructedPat<Cx>>) {
3549 assert ! ( !witnesses. is_empty( ) )
3650}
3751
52+ use WhichWitnesses :: * ;
53+ enum WhichWitnesses {
54+ AllOfThem ,
55+ OnlySome ,
56+ }
57+
58+ #[ track_caller]
59+ /// We take the type as input to support empty matches.
60+ fn assert_witnesses (
61+ which : WhichWitnesses ,
62+ ty : Ty ,
63+ patterns : Vec < DeconstructedPat < Cx > > ,
64+ expected : Vec < & str > ,
65+ ) {
66+ let exhaustive_wit = matches ! ( which, AllOfThem ) ;
67+ let witnesses = run ( ty, patterns, exhaustive_wit) ;
68+ let witnesses: Vec < _ > = witnesses. iter ( ) . map ( |w| format ! ( "{w:?}" ) ) . collect ( ) ;
69+ assert_eq ! ( witnesses, expected)
70+ }
71+
3872#[ test]
3973fn test_int_ranges ( ) {
4074 let ty = Ty :: U8 ;
@@ -59,6 +93,8 @@ fn test_int_ranges() {
5993
6094#[ test]
6195fn test_nested ( ) {
96+ // enum E { A(bool), B(bool) }
97+ // ty = (E, E)
6298 let ty = Ty :: BigStruct { arity : 2 , ty : & Ty :: BigEnum { arity : 2 , ty : & Ty :: Bool } } ;
6399 assert_non_exhaustive ( pats ! ( ty;
64100 Struct ( Variant . 0 , _) ,
@@ -78,6 +114,52 @@ fn test_nested() {
78114 ) ) ;
79115}
80116
117+ #[ test]
118+ fn test_witnesses ( ) {
119+ // TY = Option<bool>
120+ const TY : Ty = Ty :: Enum ( & [ Ty :: Bool , Ty :: Tuple ( & [ ] ) ] ) ;
121+ // ty = (Option<bool>, Option<bool>)
122+ let ty = Ty :: Tuple ( & [ TY , TY ] ) ;
123+ assert_witnesses ( AllOfThem , ty, vec ! [ ] , vec ! [ "(_, _)" ] ) ;
124+ assert_witnesses (
125+ OnlySome ,
126+ ty,
127+ pats ! ( ty;
128+ ( Variant . 0 ( false ) , Variant . 0 ( false ) ) ,
129+ ) ,
130+ vec ! [ "(Enum::Variant1(_), _)" ] ,
131+ ) ;
132+ assert_witnesses (
133+ AllOfThem ,
134+ ty,
135+ pats ! ( ty;
136+ ( Variant . 0 ( false ) , Variant . 0 ( false ) ) ,
137+ ) ,
138+ vec ! [
139+ "(Enum::Variant0(false), Enum::Variant0(true))" ,
140+ "(Enum::Variant0(false), Enum::Variant1(_))" ,
141+ "(Enum::Variant0(true), _)" ,
142+ "(Enum::Variant1(_), _)" ,
143+ ] ,
144+ ) ;
145+ assert_witnesses (
146+ OnlySome ,
147+ ty,
148+ pats ! ( ty;
149+ ( _, Variant . 0 ( false ) ) ,
150+ ) ,
151+ vec ! [ "(_, Enum::Variant1(_))" ] ,
152+ ) ;
153+ assert_witnesses (
154+ AllOfThem ,
155+ ty,
156+ pats ! ( ty;
157+ ( _, Variant . 0 ( false ) ) ,
158+ ) ,
159+ vec ! [ "(_, Enum::Variant0(true))" , "(_, Enum::Variant1(_))" ] ,
160+ ) ;
161+ }
162+
81163#[ test]
82164fn test_empty ( ) {
83165 // `TY = Result<bool, !>`
0 commit comments