@@ -10,6 +10,7 @@ use crate::usefulness::PlaceCtxt;
10
10
use crate :: { Captures , TypeCx } ;
11
11
12
12
use self :: Constructor :: * ;
13
+ use self :: PatOrWild :: * ;
13
14
14
15
/// Values and patterns can be represented as a constructor applied to some fields. This represents
15
16
/// a pattern in this form.
@@ -50,14 +51,6 @@ impl<'p, Cx: TypeCx> DeconstructedPat<'p, Cx> {
50
51
pub ( crate ) fn is_or_pat ( & self ) -> bool {
51
52
matches ! ( self . ctor, Or )
52
53
}
53
- /// Expand this (possibly-nested) or-pattern into its alternatives.
54
- pub ( crate ) fn flatten_or_pat ( & self ) -> SmallVec < [ & Self ; 1 ] > {
55
- if self . is_or_pat ( ) {
56
- self . iter_fields ( ) . flat_map ( |p| p. flatten_or_pat ( ) ) . collect ( )
57
- } else {
58
- smallvec ! [ self ]
59
- }
60
- }
61
54
62
55
pub fn ctor ( & self ) -> & Constructor < Cx > {
63
56
& self . ctor
@@ -79,17 +72,11 @@ impl<'p, Cx: TypeCx> DeconstructedPat<'p, Cx> {
79
72
/// `other_ctor` can be different from `self.ctor`, but must be covered by it.
80
73
pub ( crate ) fn specialize (
81
74
& self ,
82
- pcx : & PlaceCtxt < ' _ , ' p , Cx > ,
75
+ _pcx : & PlaceCtxt < ' _ , ' p , Cx > ,
83
76
other_ctor : & Constructor < Cx > ,
84
77
ctor_sub_tys : & [ Cx :: Ty ] ,
85
- ) -> SmallVec < [ & ' p DeconstructedPat < ' p , Cx > ; 2 ] > {
86
- let wildcard_sub_tys = || {
87
- ctor_sub_tys
88
- . iter ( )
89
- . map ( |ty| DeconstructedPat :: wildcard ( * ty) )
90
- . map ( |pat| pcx. mcx . wildcard_arena . alloc ( pat) as & _ )
91
- . collect ( )
92
- } ;
78
+ ) -> SmallVec < [ PatOrWild < ' p , Cx > ; 2 ] > {
79
+ let wildcard_sub_tys = || ctor_sub_tys. iter ( ) . map ( |_| Wild ) . collect ( ) ;
93
80
match ( & self . ctor , other_ctor) {
94
81
// Return a wildcard for each field of `other_ctor`.
95
82
( Wildcard , _) => wildcard_sub_tys ( ) ,
@@ -105,14 +92,14 @@ impl<'p, Cx: TypeCx> DeconstructedPat<'p, Cx> {
105
92
// Fill in the fields from both ends.
106
93
let new_arity = fields. len ( ) ;
107
94
for i in 0 ..prefix {
108
- fields[ i] = & self . fields [ i] ;
95
+ fields[ i] = Pat ( & self . fields [ i] ) ;
109
96
}
110
97
for i in 0 ..suffix {
111
- fields[ new_arity - 1 - i] = & self . fields [ self . fields . len ( ) - 1 - i] ;
98
+ fields[ new_arity - 1 - i] = Pat ( & self . fields [ self . fields . len ( ) - 1 - i] ) ;
112
99
}
113
100
fields
114
101
}
115
- _ => self . fields . iter ( ) . collect ( ) ,
102
+ _ => self . fields . iter ( ) . map ( Pat ) . collect ( ) ,
116
103
}
117
104
}
118
105
@@ -153,14 +140,87 @@ impl<'p, Cx: TypeCx> DeconstructedPat<'p, Cx> {
153
140
}
154
141
}
155
142
156
- /// This is mostly copied from the `Pat` impl. This is best effort and not good enough for a
157
- /// `Display` impl.
143
+ /// This is best effort and not good enough for a `Display` impl.
158
144
impl < ' p , Cx : TypeCx > fmt:: Debug for DeconstructedPat < ' p , Cx > {
159
145
fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
160
146
Cx :: debug_pat ( f, self )
161
147
}
162
148
}
163
149
150
+ /// Represents either a pattern obtained from user input or a wildcard constructed during the
151
+ /// algorithm. Do not use `Wild` to represent a wildcard pattern comping from user input.
152
+ ///
153
+ /// This is morally `Option<&'p DeconstructedPat>` where `None` is interpreted as a wildcard.
154
+ #[ derive( derivative:: Derivative ) ]
155
+ #[ derivative( Clone ( bound = "" ) , Copy ( bound = "" ) ) ]
156
+ pub ( crate ) enum PatOrWild < ' p , Cx : TypeCx > {
157
+ /// A non-user-provided wildcard, created during specialization.
158
+ Wild ,
159
+ /// A user-provided pattern.
160
+ Pat ( & ' p DeconstructedPat < ' p , Cx > ) ,
161
+ }
162
+
163
+ impl < ' p , Cx : TypeCx > PatOrWild < ' p , Cx > {
164
+ pub ( crate ) fn as_pat ( & self ) -> Option < & ' p DeconstructedPat < ' p , Cx > > {
165
+ match self {
166
+ Wild => None ,
167
+ Pat ( pat) => Some ( pat) ,
168
+ }
169
+ }
170
+ pub ( crate ) fn ctor ( self ) -> & ' p Constructor < Cx > {
171
+ match self {
172
+ Wild => & Wildcard ,
173
+ Pat ( pat) => pat. ctor ( ) ,
174
+ }
175
+ }
176
+
177
+ pub ( crate ) fn is_or_pat ( & self ) -> bool {
178
+ match self {
179
+ Wild => false ,
180
+ Pat ( pat) => pat. is_or_pat ( ) ,
181
+ }
182
+ }
183
+
184
+ /// Expand this (possibly-nested) or-pattern into its alternatives.
185
+ pub ( crate ) fn flatten_or_pat ( self ) -> SmallVec < [ Self ; 1 ] > {
186
+ match self {
187
+ Pat ( pat) if pat. is_or_pat ( ) => {
188
+ pat. iter_fields ( ) . flat_map ( |p| Pat ( p) . flatten_or_pat ( ) ) . collect ( )
189
+ }
190
+ _ => smallvec ! [ self ] ,
191
+ }
192
+ }
193
+
194
+ /// Specialize this pattern with a constructor.
195
+ /// `other_ctor` can be different from `self.ctor`, but must be covered by it.
196
+ pub ( crate ) fn specialize (
197
+ & self ,
198
+ pcx : & PlaceCtxt < ' _ , ' p , Cx > ,
199
+ other_ctor : & Constructor < Cx > ,
200
+ ctor_sub_tys : & [ Cx :: Ty ] ,
201
+ ) -> SmallVec < [ PatOrWild < ' p , Cx > ; 2 ] > {
202
+ match self {
203
+ Wild => ctor_sub_tys. iter ( ) . map ( |_| Wild ) . collect ( ) ,
204
+ Pat ( pat) => pat. specialize ( pcx, other_ctor, ctor_sub_tys) ,
205
+ }
206
+ }
207
+
208
+ pub ( crate ) fn set_useful ( & self ) {
209
+ if let Pat ( pat) = self {
210
+ pat. set_useful ( )
211
+ }
212
+ }
213
+ }
214
+
215
+ impl < ' p , Cx : TypeCx > fmt:: Debug for PatOrWild < ' p , Cx > {
216
+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
217
+ match self {
218
+ Wild => write ! ( f, "_" ) ,
219
+ Pat ( pat) => pat. fmt ( f) ,
220
+ }
221
+ }
222
+ }
223
+
164
224
/// Same idea as `DeconstructedPat`, except this is a fictitious pattern built up for diagnostics
165
225
/// purposes. As such they don't use interning and can be cloned.
166
226
#[ derive( derivative:: Derivative ) ]
0 commit comments