@@ -11,16 +11,30 @@ use rustc_pattern_analysis::usefulness::PlaceValidity;
11
11
mod common;
12
12
13
13
/// 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 > > {
16
19
let arms: Vec < _ > =
17
20
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 ( ) ;
21
29
report. non_exhaustiveness_witnesses
22
30
}
23
31
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
+
24
38
#[ track_caller]
25
39
fn assert_exhaustive ( patterns : Vec < DeconstructedPat < Cx > > ) {
26
40
let witnesses = check ( patterns) ;
@@ -35,6 +49,26 @@ fn assert_non_exhaustive(patterns: Vec<DeconstructedPat<Cx>>) {
35
49
assert ! ( !witnesses. is_empty( ) )
36
50
}
37
51
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
+
38
72
#[ test]
39
73
fn test_int_ranges ( ) {
40
74
let ty = Ty :: U8 ;
@@ -59,6 +93,8 @@ fn test_int_ranges() {
59
93
60
94
#[ test]
61
95
fn test_nested ( ) {
96
+ // enum E { A(bool), B(bool) }
97
+ // ty = (E, E)
62
98
let ty = Ty :: BigStruct { arity : 2 , ty : & Ty :: BigEnum { arity : 2 , ty : & Ty :: Bool } } ;
63
99
assert_non_exhaustive ( pats ! ( ty;
64
100
Struct ( Variant . 0 , _) ,
@@ -78,6 +114,52 @@ fn test_nested() {
78
114
) ) ;
79
115
}
80
116
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
+
81
163
#[ test]
82
164
fn test_empty ( ) {
83
165
// `TY = Result<bool, !>`
0 commit comments