@@ -1058,41 +1058,30 @@ impl<'tcx> SplitWildcard<'tcx> {
1058
1058
}
1059
1059
1060
1060
/// Some fields need to be explicitly hidden away in certain cases; see the comment above the
1061
- /// `Fields` struct. This struct represents such a potentially-hidden field. When a field is hidden
1062
- /// we still keep its type around.
1061
+ /// `Fields` struct. This struct represents such a potentially-hidden field.
1063
1062
#[ derive( Debug , Copy , Clone ) ]
1064
1063
pub ( super ) enum FilteredField < ' p , ' tcx > {
1065
1064
Kept ( & ' p Pat < ' tcx > ) ,
1066
- Hidden ( Ty < ' tcx > ) ,
1065
+ Hidden ,
1067
1066
}
1068
1067
1069
1068
impl < ' p , ' tcx > FilteredField < ' p , ' tcx > {
1070
1069
fn kept ( self ) -> Option < & ' p Pat < ' tcx > > {
1071
1070
match self {
1072
1071
FilteredField :: Kept ( p) => Some ( p) ,
1073
- FilteredField :: Hidden ( _) => None ,
1074
- }
1075
- }
1076
-
1077
- fn to_pattern ( self ) -> Pat < ' tcx > {
1078
- match self {
1079
- FilteredField :: Kept ( p) => p. clone ( ) ,
1080
- FilteredField :: Hidden ( ty) => Pat :: wildcard_from_ty ( ty) ,
1072
+ FilteredField :: Hidden => None ,
1081
1073
}
1082
1074
}
1083
1075
}
1084
1076
1085
1077
/// A value can be decomposed into a constructor applied to some fields. This struct represents
1086
1078
/// those fields, generalized to allow patterns in each field. See also `Constructor`.
1079
+ /// This is constructed from a constructor using [`Fields::wildcards()`].
1087
1080
///
1088
1081
/// If a private or `non_exhaustive` field is uninhabited, the code mustn't observe that it is
1089
- /// uninhabited. For that, we filter these fields out of the matrix. This is subtle because we
1090
- /// still need to have those fields back when going to/from a `Pat`. Most of this is handled
1091
- /// automatically in `Fields`, but when constructing or deconstructing `Fields` you need to be
1092
- /// careful. As a rule, when going to/from the matrix, use the filtered field list; when going
1093
- /// to/from `Pat`, use the full field list.
1094
- /// This filtering is uncommon in practice, because uninhabited fields are rarely used, so we avoid
1095
- /// it when possible to preserve performance.
1082
+ /// uninhabited. For that, we filter these fields out of the matrix. This is handled automatically
1083
+ /// in `Fields`. This filtering is uncommon in practice, because uninhabited fields are rare used,
1084
+ /// so we avoid it when possible to preserve performance.
1096
1085
#[ derive( Debug , Clone ) ]
1097
1086
pub ( super ) enum Fields < ' p , ' tcx > {
1098
1087
/// Lists of patterns that don't contain any filtered fields.
@@ -1101,21 +1090,19 @@ pub(super) enum Fields<'p, 'tcx> {
1101
1090
/// have not measured if it really made a difference.
1102
1091
Slice ( & ' p [ Pat < ' tcx > ] ) ,
1103
1092
Vec ( SmallVec < [ & ' p Pat < ' tcx > ; 2 ] > ) ,
1104
- /// Patterns where some of the fields need to be hidden. `kept_count` caches the number of
1105
- /// non-hidden fields.
1093
+ /// Patterns where some of the fields need to be hidden. For all intents and purposes we only
1094
+ /// care about the non-hidden fields. We need to keep the real field index for those fields;
1095
+ /// we're morally storing a `Vec<(usize, &Pat)>` but what we do is more convenient.
1096
+ /// `len` counts the number of non-hidden fields
1106
1097
Filtered {
1107
1098
fields : SmallVec < [ FilteredField < ' p , ' tcx > ; 2 ] > ,
1108
- kept_count : usize ,
1099
+ len : usize ,
1109
1100
} ,
1110
1101
}
1111
1102
1112
1103
impl < ' p , ' tcx > Fields < ' p , ' tcx > {
1113
- fn empty ( ) -> Self {
1114
- Fields :: Slice ( & [ ] )
1115
- }
1116
-
1117
- /// Construct a new `Fields` from the given pattern. Must not be used if the pattern is a field
1118
- /// of a struct/tuple/variant.
1104
+ /// Internal use. Use `Fields::wildcards()` instead.
1105
+ /// Must not be used if the pattern is a field of a struct/tuple/variant.
1119
1106
fn from_single_pattern ( pat : & ' p Pat < ' tcx > ) -> Self {
1120
1107
Fields :: Slice ( std:: slice:: from_ref ( pat) )
1121
1108
}
@@ -1160,7 +1147,7 @@ impl<'p, 'tcx> Fields<'p, 'tcx> {
1160
1147
if has_no_hidden_fields {
1161
1148
Fields :: wildcards_from_tys ( cx, field_tys)
1162
1149
} else {
1163
- let mut kept_count = 0 ;
1150
+ let mut len = 0 ;
1164
1151
let fields = variant
1165
1152
. fields
1166
1153
. iter ( )
@@ -1175,14 +1162,14 @@ impl<'p, 'tcx> Fields<'p, 'tcx> {
1175
1162
// order not to reveal the uninhabitedness of the whole
1176
1163
// variant.
1177
1164
if is_uninhabited && ( !is_visible || is_non_exhaustive) {
1178
- FilteredField :: Hidden ( ty )
1165
+ FilteredField :: Hidden
1179
1166
} else {
1180
- kept_count += 1 ;
1167
+ len += 1 ;
1181
1168
FilteredField :: Kept ( wildcard_from_ty ( ty) )
1182
1169
}
1183
1170
} )
1184
1171
. collect ( ) ;
1185
- Fields :: Filtered { fields, kept_count }
1172
+ Fields :: Filtered { fields, len }
1186
1173
}
1187
1174
}
1188
1175
}
@@ -1196,7 +1183,7 @@ impl<'p, 'tcx> Fields<'p, 'tcx> {
1196
1183
_ => bug ! ( "bad slice pattern {:?} {:?}" , constructor, ty) ,
1197
1184
} ,
1198
1185
Str ( ..) | FloatRange ( ..) | IntRange ( ..) | NonExhaustive | Opaque | Missing
1199
- | Wildcard => Fields :: empty ( ) ,
1186
+ | Wildcard => Fields :: Slice ( & [ ] ) ,
1200
1187
} ;
1201
1188
debug ! ( "Fields::wildcards({:?}, {:?}) = {:#?}" , constructor, ty, ret) ;
1202
1189
ret
@@ -1218,14 +1205,16 @@ impl<'p, 'tcx> Fields<'p, 'tcx> {
1218
1205
/// `self`: `[false]`
1219
1206
/// returns `Some(false)`
1220
1207
pub ( super ) fn apply ( self , pcx : PatCtxt < ' _ , ' p , ' tcx > , ctor : & Constructor < ' tcx > ) -> Pat < ' tcx > {
1221
- let mut subpatterns = self . all_patterns ( ) ;
1208
+ let subpatterns_and_indices = self . patterns_and_indices ( ) ;
1209
+ let mut subpatterns = subpatterns_and_indices. iter ( ) . map ( |& ( _, p) | p) . cloned ( ) ;
1222
1210
1223
1211
let pat = match ctor {
1224
1212
Single | Variant ( _) => match pcx. ty . kind ( ) {
1225
1213
ty:: Adt ( ..) | ty:: Tuple ( ..) => {
1226
- let subpatterns = subpatterns
1227
- . enumerate ( )
1228
- . map ( |( i, p) | FieldPat { field : Field :: new ( i) , pattern : p } )
1214
+ // We want the real indices here.
1215
+ let subpatterns = subpatterns_and_indices
1216
+ . iter ( )
1217
+ . map ( |& ( field, p) | FieldPat { field, pattern : p. clone ( ) } )
1229
1218
. collect ( ) ;
1230
1219
1231
1220
if let ty:: Adt ( adt, substs) = pcx. ty . kind ( ) {
@@ -1290,39 +1279,42 @@ impl<'p, 'tcx> Fields<'p, 'tcx> {
1290
1279
Pat { ty : pcx. ty , span : DUMMY_SP , kind : Box :: new ( pat) }
1291
1280
}
1292
1281
1293
- /// Returns the number of patterns from the viewpoint of match-checking, i.e. excluding hidden
1294
- /// fields. This is what we want in most cases in this file, the only exception being
1295
- /// conversion to/from `Pat`.
1282
+ /// Returns the number of patterns. This is the same as the arity of the constructor used to
1283
+ /// construct `self`.
1296
1284
pub ( super ) fn len ( & self ) -> usize {
1297
1285
match self {
1298
1286
Fields :: Slice ( pats) => pats. len ( ) ,
1299
1287
Fields :: Vec ( pats) => pats. len ( ) ,
1300
- Fields :: Filtered { kept_count , .. } => * kept_count ,
1288
+ Fields :: Filtered { len , .. } => * len ,
1301
1289
}
1302
1290
}
1303
1291
1304
- /// Returns the complete list of patterns, including hidden fields.
1305
- fn all_patterns ( self ) -> impl Iterator < Item = Pat < ' tcx > > {
1306
- let pats: SmallVec < [ _ ; 2 ] > = match self {
1307
- Fields :: Slice ( pats) => pats. iter ( ) . cloned ( ) . collect ( ) ,
1308
- Fields :: Vec ( pats) => pats. into_iter ( ) . cloned ( ) . collect ( ) ,
1292
+ /// Returns the list of patterns along with the corresponding field indices.
1293
+ fn patterns_and_indices ( & self ) -> SmallVec < [ ( Field , & ' p Pat < ' tcx > ) ; 2 ] > {
1294
+ match self {
1295
+ Fields :: Slice ( pats) => {
1296
+ pats. iter ( ) . enumerate ( ) . map ( |( i, p) | ( Field :: new ( i) , p) ) . collect ( )
1297
+ }
1298
+ Fields :: Vec ( pats) => {
1299
+ pats. iter ( ) . copied ( ) . enumerate ( ) . map ( |( i, p) | ( Field :: new ( i) , p) ) . collect ( )
1300
+ }
1309
1301
Fields :: Filtered { fields, .. } => {
1310
- // We don't skip any fields here.
1311
- fields. into_iter ( ) . map ( |p| p. to_pattern ( ) ) . collect ( )
1302
+ // Indices must be relative to the full list of patterns
1303
+ fields
1304
+ . iter ( )
1305
+ . enumerate ( )
1306
+ . filter_map ( |( i, p) | Some ( ( Field :: new ( i) , p. kept ( ) ?) ) )
1307
+ . collect ( )
1312
1308
}
1313
- } ;
1314
- pats. into_iter ( )
1309
+ }
1315
1310
}
1316
1311
1317
- /// Returns the filtered list of patterns, not including hidden fields .
1318
- pub ( super ) fn filtered_patterns ( self ) -> SmallVec < [ & ' p Pat < ' tcx > ; 2 ] > {
1312
+ /// Returns the list of patterns.
1313
+ pub ( super ) fn into_patterns ( self ) -> SmallVec < [ & ' p Pat < ' tcx > ; 2 ] > {
1319
1314
match self {
1320
1315
Fields :: Slice ( pats) => pats. iter ( ) . collect ( ) ,
1321
1316
Fields :: Vec ( pats) => pats,
1322
- Fields :: Filtered { fields, .. } => {
1323
- // We skip hidden fields here
1324
- fields. into_iter ( ) . filter_map ( |p| p. kept ( ) ) . collect ( )
1325
- }
1317
+ Fields :: Filtered { fields, .. } => fields. iter ( ) . filter_map ( |p| p. kept ( ) ) . collect ( ) ,
1326
1318
}
1327
1319
}
1328
1320
@@ -1338,10 +1330,10 @@ impl<'p, 'tcx> Fields<'p, 'tcx> {
1338
1330
}
1339
1331
1340
1332
/// Overrides some of the fields with the provided patterns. This is used when a pattern
1341
- /// defines some fields but not all, for example `Foo { field1: Some(_), .. }`: here we start with a
1342
- /// `Fields` that is just one wildcard per field of the `Foo` struct, and override the entry
1343
- /// corresponding to `field1` with the pattern `Some(_)`. This is also used for slice patterns
1344
- /// for the same reason.
1333
+ /// defines some fields but not all, for example `Foo { field1: Some(_), .. }`: here we start
1334
+ /// with a `Fields` that is just one wildcard per field of the `Foo` struct, and override the
1335
+ /// entry corresponding to `field1` with the pattern `Some(_)`. This is also used for slice
1336
+ /// patterns for the same reason.
1345
1337
fn replace_fields_indexed (
1346
1338
& self ,
1347
1339
new_pats : impl IntoIterator < Item = ( usize , & ' p Pat < ' tcx > ) > ,
@@ -1369,8 +1361,8 @@ impl<'p, 'tcx> Fields<'p, 'tcx> {
1369
1361
fields
1370
1362
}
1371
1363
1372
- /// Replaces contained fields with the given filtered list of patterns, e.g. taken from the
1373
- /// matrix. There must be `len()` patterns in `pats`.
1364
+ /// Replaces contained fields with the given list of patterns. There must be `len()` patterns
1365
+ /// in `pats`.
1374
1366
pub ( super ) fn replace_fields (
1375
1367
& self ,
1376
1368
cx : & MatchCheckCtxt < ' p , ' tcx > ,
@@ -1379,7 +1371,7 @@ impl<'p, 'tcx> Fields<'p, 'tcx> {
1379
1371
let pats: & [ _ ] = cx. pattern_arena . alloc_from_iter ( pats) ;
1380
1372
1381
1373
match self {
1382
- Fields :: Filtered { fields, kept_count } => {
1374
+ Fields :: Filtered { fields, len } => {
1383
1375
let mut pats = pats. iter ( ) ;
1384
1376
let mut fields = fields. clone ( ) ;
1385
1377
for f in & mut fields {
@@ -1388,7 +1380,7 @@ impl<'p, 'tcx> Fields<'p, 'tcx> {
1388
1380
* p = pats. next ( ) . unwrap ( ) ;
1389
1381
}
1390
1382
}
1391
- Fields :: Filtered { fields, kept_count : * kept_count }
1383
+ Fields :: Filtered { fields, len : * len }
1392
1384
}
1393
1385
_ => Fields :: Slice ( pats) ,
1394
1386
}
0 commit comments