@@ -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
@@ -82,14 +75,8 @@ impl<'p, Cx: TypeCx> DeconstructedPat<'p, Cx> {
82
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,82 @@ 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
+ #[ derive( derivative:: Derivative ) ]
153
+ #[ derivative( Clone ( bound = "" ) , Copy ( bound = "" ) ) ]
154
+ pub ( crate ) enum PatOrWild < ' p , Cx : TypeCx > {
155
+ /// A non-user-provided wildcard, created during specialization.
156
+ Wild ,
157
+ /// A user-provided pattern.
158
+ Pat ( & ' p DeconstructedPat < ' p , Cx > ) ,
159
+ }
160
+
161
+ impl < ' p , Cx : TypeCx > PatOrWild < ' p , Cx > {
162
+ pub ( crate ) fn as_pat ( & self ) -> Option < & ' p DeconstructedPat < ' p , Cx > > {
163
+ match self {
164
+ Wild => None ,
165
+ Pat ( pat) => Some ( pat) ,
166
+ }
167
+ }
168
+ pub ( crate ) fn ctor ( self ) -> & ' p Constructor < Cx > {
169
+ match self {
170
+ Wild => & Wildcard ,
171
+ Pat ( pat) => pat. ctor ( ) ,
172
+ }
173
+ }
174
+
175
+ pub ( crate ) fn is_or_pat ( & self ) -> bool {
176
+ matches ! ( self . ctor( ) , Or )
177
+ }
178
+
179
+ /// Expand this (possibly-nested) or-pattern into its alternatives.
180
+ pub ( crate ) fn flatten_or_pat ( self ) -> SmallVec < [ Self ; 1 ] > {
181
+ match self {
182
+ Pat ( pat) if pat. is_or_pat ( ) => {
183
+ pat. iter_fields ( ) . flat_map ( |p| Pat ( p) . flatten_or_pat ( ) ) . collect ( )
184
+ }
185
+ _ => smallvec ! [ self ] ,
186
+ }
187
+ }
188
+
189
+ /// Specialize this pattern with a constructor.
190
+ /// `other_ctor` can be different from `self.ctor`, but must be covered by it.
191
+ pub ( crate ) fn specialize (
192
+ & self ,
193
+ pcx : & PlaceCtxt < ' _ , ' p , Cx > ,
194
+ other_ctor : & Constructor < Cx > ,
195
+ ctor_sub_tys : & [ Cx :: Ty ] ,
196
+ ) -> SmallVec < [ PatOrWild < ' p , Cx > ; 2 ] > {
197
+ match self {
198
+ Wild => ctor_sub_tys. iter ( ) . map ( |_| Wild ) . collect ( ) ,
199
+ Pat ( pat) => pat. specialize ( pcx, other_ctor, ctor_sub_tys) ,
200
+ }
201
+ }
202
+
203
+ pub ( crate ) fn set_useful ( & self ) {
204
+ if let Pat ( pat) = self {
205
+ pat. set_useful ( )
206
+ }
207
+ }
208
+ }
209
+
210
+ impl < ' p , Cx : TypeCx > fmt:: Debug for PatOrWild < ' p , Cx > {
211
+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
212
+ match self {
213
+ Wild => write ! ( f, "_" ) ,
214
+ Pat ( pat) => pat. fmt ( f) ,
215
+ }
216
+ }
217
+ }
218
+
164
219
/// Same idea as `DeconstructedPat`, except this is a fictitious pattern built up for diagnostics
165
220
/// purposes. As such they don't use interning and can be cloned.
166
221
#[ derive( derivative:: Derivative ) ]
0 commit comments