@@ -8,7 +8,7 @@ use rustc_hash::FxHashMap;
8
8
use rustc_pattern_analysis:: {
9
9
constructor:: { Constructor , ConstructorSet , VariantVisibility } ,
10
10
index:: IdxContainer ,
11
- Captures , PrivateUninhabitedField , TypeCx ,
11
+ Captures , PatCx , PrivateUninhabitedField ,
12
12
} ;
13
13
use smallvec:: { smallvec, SmallVec } ;
14
14
use stdx:: never;
@@ -107,15 +107,17 @@ impl<'p> MatchCheckCtx<'p> {
107
107
}
108
108
109
109
pub ( crate ) fn lower_pat ( & self , pat : & Pat ) -> DeconstructedPat < ' p > {
110
- let singleton = |pat| vec ! [ pat] ;
110
+ let singleton = |pat : DeconstructedPat < ' p > | vec ! [ pat. at_index ( 0 ) ] ;
111
111
let ctor;
112
- let fields: Vec < _ > ;
112
+ let mut fields: Vec < _ > ;
113
+ let arity;
113
114
114
115
match pat. kind . as_ref ( ) {
115
116
PatKind :: Binding { subpattern : Some ( subpat) , .. } => return self . lower_pat ( subpat) ,
116
117
PatKind :: Binding { subpattern : None , .. } | PatKind :: Wild => {
117
118
ctor = Wildcard ;
118
119
fields = Vec :: new ( ) ;
120
+ arity = 0 ;
119
121
}
120
122
PatKind :: Deref { subpattern } => {
121
123
ctor = match pat. ty . kind ( Interner ) {
@@ -128,23 +130,22 @@ impl<'p> MatchCheckCtx<'p> {
128
130
}
129
131
} ;
130
132
fields = singleton ( self . lower_pat ( subpattern) ) ;
133
+ arity = 1 ;
131
134
}
132
135
PatKind :: Leaf { subpatterns } | PatKind :: Variant { subpatterns, .. } => {
136
+ fields = subpatterns
137
+ . iter ( )
138
+ . map ( |pat| {
139
+ let idx: u32 = pat. field . into_raw ( ) . into ( ) ;
140
+ self . lower_pat ( & pat. pattern ) . at_index ( idx as usize )
141
+ } )
142
+ . collect ( ) ;
133
143
match pat. ty . kind ( Interner ) {
134
144
TyKind :: Tuple ( _, substs) => {
135
145
ctor = Struct ;
136
- let mut wilds: Vec < _ > = substs
137
- . iter ( Interner )
138
- . map ( |arg| arg. assert_ty_ref ( Interner ) . clone ( ) )
139
- . map ( DeconstructedPat :: wildcard)
140
- . collect ( ) ;
141
- for pat in subpatterns {
142
- let idx: u32 = pat. field . into_raw ( ) . into ( ) ;
143
- wilds[ idx as usize ] = self . lower_pat ( & pat. pattern ) ;
144
- }
145
- fields = wilds
146
+ arity = substs. len ( Interner ) ;
146
147
}
147
- TyKind :: Adt ( adt, substs ) if is_box ( self . db , adt. 0 ) => {
148
+ TyKind :: Adt ( adt, _ ) if is_box ( self . db , adt. 0 ) => {
148
149
// The only legal patterns of type `Box` (outside `std`) are `_` and box
149
150
// patterns. If we're here we can assume this is a box pattern.
150
151
// FIXME(Nadrieril): A `Box` can in theory be matched either with `Box(_,
@@ -157,16 +158,9 @@ impl<'p> MatchCheckCtx<'p> {
157
158
// normally or through box-patterns. We'll have to figure out a proper
158
159
// solution when we introduce generalized deref patterns. Also need to
159
160
// prevent mixing of those two options.
160
- let pat =
161
- subpatterns. iter ( ) . find ( |pat| pat. field . into_raw ( ) == 0u32 . into ( ) ) ;
162
- let field = if let Some ( pat) = pat {
163
- self . lower_pat ( & pat. pattern )
164
- } else {
165
- let ty = substs. at ( Interner , 0 ) . assert_ty_ref ( Interner ) . clone ( ) ;
166
- DeconstructedPat :: wildcard ( ty)
167
- } ;
161
+ fields. retain ( |ipat| ipat. idx == 0 ) ;
168
162
ctor = Struct ;
169
- fields = singleton ( field ) ;
163
+ arity = 1 ;
170
164
}
171
165
& TyKind :: Adt ( adt, _) => {
172
166
ctor = match pat. kind . as_ref ( ) {
@@ -181,37 +175,33 @@ impl<'p> MatchCheckCtx<'p> {
181
175
}
182
176
} ;
183
177
let variant = Self :: variant_id_for_adt ( & ctor, adt. 0 ) . unwrap ( ) ;
184
- // Fill a vec with wildcards, then place the fields we have at the right
185
- // index.
186
- let mut wilds: Vec < _ > = self
187
- . list_variant_fields ( & pat. ty , variant)
188
- . map ( |( _, ty) | ty)
189
- . map ( DeconstructedPat :: wildcard)
190
- . collect ( ) ;
191
- for pat in subpatterns {
192
- let field_id: u32 = pat. field . into_raw ( ) . into ( ) ;
193
- wilds[ field_id as usize ] = self . lower_pat ( & pat. pattern ) ;
194
- }
195
- fields = wilds;
178
+ arity = variant. variant_data ( self . db . upcast ( ) ) . fields ( ) . len ( ) ;
196
179
}
197
180
_ => {
198
181
never ! ( "pattern has unexpected type: pat: {:?}, ty: {:?}" , pat, & pat. ty) ;
199
182
ctor = Wildcard ;
200
- fields = Vec :: new ( ) ;
183
+ fields. clear ( ) ;
184
+ arity = 0 ;
201
185
}
202
186
}
203
187
}
204
188
& PatKind :: LiteralBool { value } => {
205
189
ctor = Bool ( value) ;
206
190
fields = Vec :: new ( ) ;
191
+ arity = 0 ;
207
192
}
208
193
PatKind :: Or { pats } => {
209
194
ctor = Or ;
210
- fields = pats. iter ( ) . map ( |pat| self . lower_pat ( pat) ) . collect ( ) ;
195
+ fields = pats
196
+ . iter ( )
197
+ . enumerate ( )
198
+ . map ( |( i, pat) | self . lower_pat ( pat) . at_index ( i) )
199
+ . collect ( ) ;
200
+ arity = pats. len ( ) ;
211
201
}
212
202
}
213
203
let data = PatData { db : self . db } ;
214
- DeconstructedPat :: new ( ctor, fields, pat. ty . clone ( ) , data)
204
+ DeconstructedPat :: new ( ctor, fields, arity , pat. ty . clone ( ) , data)
215
205
}
216
206
217
207
pub ( crate ) fn hoist_witness_pat ( & self , pat : & WitnessPat < ' p > ) -> Pat {
@@ -271,7 +261,7 @@ impl<'p> MatchCheckCtx<'p> {
271
261
}
272
262
}
273
263
274
- impl < ' p > TypeCx for MatchCheckCtx < ' p > {
264
+ impl < ' p > PatCx for MatchCheckCtx < ' p > {
275
265
type Error = ( ) ;
276
266
type Ty = Ty ;
277
267
type VariantIdx = EnumVariantId ;
@@ -453,7 +443,7 @@ impl<'p> TypeCx for MatchCheckCtx<'p> {
453
443
let variant =
454
444
pat. ty ( ) . as_adt ( ) . and_then ( |( adt, _) | Self :: variant_id_for_adt ( pat. ctor ( ) , adt) ) ;
455
445
456
- let db = pat. data ( ) . unwrap ( ) . db ;
446
+ let db = pat. data ( ) . db ;
457
447
if let Some ( variant) = variant {
458
448
match variant {
459
449
VariantId :: EnumVariantId ( v) => {
0 commit comments