@@ -1058,41 +1058,30 @@ impl<'tcx> SplitWildcard<'tcx> {
10581058}
10591059
10601060/// 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.
10631062#[ derive( Debug , Copy , Clone ) ]
10641063pub ( super ) enum FilteredField < ' p , ' tcx > {
10651064 Kept ( & ' p Pat < ' tcx > ) ,
1066- Hidden ( Ty < ' tcx > ) ,
1065+ Hidden ,
10671066}
10681067
10691068impl < ' p , ' tcx > FilteredField < ' p , ' tcx > {
10701069 fn kept ( self ) -> Option < & ' p Pat < ' tcx > > {
10711070 match self {
10721071 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 ,
10811073 }
10821074 }
10831075}
10841076
10851077/// A value can be decomposed into a constructor applied to some fields. This struct represents
10861078/// those fields, generalized to allow patterns in each field. See also `Constructor`.
1079+ /// This is constructed from a constructor using [`Fields::wildcards()`].
10871080///
10881081/// 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.
10961085#[ derive( Debug , Clone ) ]
10971086pub ( super ) enum Fields < ' p , ' tcx > {
10981087 /// Lists of patterns that don't contain any filtered fields.
@@ -1101,21 +1090,19 @@ pub(super) enum Fields<'p, 'tcx> {
11011090 /// have not measured if it really made a difference.
11021091 Slice ( & ' p [ Pat < ' tcx > ] ) ,
11031092 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
11061097 Filtered {
11071098 fields : SmallVec < [ FilteredField < ' p , ' tcx > ; 2 ] > ,
1108- kept_count : usize ,
1099+ len : usize ,
11091100 } ,
11101101}
11111102
11121103impl < ' 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.
11191106 fn from_single_pattern ( pat : & ' p Pat < ' tcx > ) -> Self {
11201107 Fields :: Slice ( std:: slice:: from_ref ( pat) )
11211108 }
@@ -1160,7 +1147,7 @@ impl<'p, 'tcx> Fields<'p, 'tcx> {
11601147 if has_no_hidden_fields {
11611148 Fields :: wildcards_from_tys ( cx, field_tys)
11621149 } else {
1163- let mut kept_count = 0 ;
1150+ let mut len = 0 ;
11641151 let fields = variant
11651152 . fields
11661153 . iter ( )
@@ -1175,14 +1162,14 @@ impl<'p, 'tcx> Fields<'p, 'tcx> {
11751162 // order not to reveal the uninhabitedness of the whole
11761163 // variant.
11771164 if is_uninhabited && ( !is_visible || is_non_exhaustive) {
1178- FilteredField :: Hidden ( ty )
1165+ FilteredField :: Hidden
11791166 } else {
1180- kept_count += 1 ;
1167+ len += 1 ;
11811168 FilteredField :: Kept ( wildcard_from_ty ( ty) )
11821169 }
11831170 } )
11841171 . collect ( ) ;
1185- Fields :: Filtered { fields, kept_count }
1172+ Fields :: Filtered { fields, len }
11861173 }
11871174 }
11881175 }
@@ -1196,7 +1183,7 @@ impl<'p, 'tcx> Fields<'p, 'tcx> {
11961183 _ => bug ! ( "bad slice pattern {:?} {:?}" , constructor, ty) ,
11971184 } ,
11981185 Str ( ..) | FloatRange ( ..) | IntRange ( ..) | NonExhaustive | Opaque | Missing
1199- | Wildcard => Fields :: empty ( ) ,
1186+ | Wildcard => Fields :: Slice ( & [ ] ) ,
12001187 } ;
12011188 debug ! ( "Fields::wildcards({:?}, {:?}) = {:#?}" , constructor, ty, ret) ;
12021189 ret
@@ -1218,14 +1205,16 @@ impl<'p, 'tcx> Fields<'p, 'tcx> {
12181205 /// `self`: `[false]`
12191206 /// returns `Some(false)`
12201207 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 ( ) ;
12221210
12231211 let pat = match ctor {
12241212 Single | Variant ( _) => match pcx. ty . kind ( ) {
12251213 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 ( ) } )
12291218 . collect ( ) ;
12301219
12311220 if let ty:: Adt ( adt, substs) = pcx. ty . kind ( ) {
@@ -1290,39 +1279,42 @@ impl<'p, 'tcx> Fields<'p, 'tcx> {
12901279 Pat { ty : pcx. ty , span : DUMMY_SP , kind : Box :: new ( pat) }
12911280 }
12921281
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`.
12961284 pub ( super ) fn len ( & self ) -> usize {
12971285 match self {
12981286 Fields :: Slice ( pats) => pats. len ( ) ,
12991287 Fields :: Vec ( pats) => pats. len ( ) ,
1300- Fields :: Filtered { kept_count , .. } => * kept_count ,
1288+ Fields :: Filtered { len , .. } => * len ,
13011289 }
13021290 }
13031291
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+ }
13091301 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 ( )
13121308 }
1313- } ;
1314- pats. into_iter ( )
1309+ }
13151310 }
13161311
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 ] > {
13191314 match self {
13201315 Fields :: Slice ( pats) => pats. iter ( ) . collect ( ) ,
13211316 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 ( ) ,
13261318 }
13271319 }
13281320
@@ -1338,10 +1330,10 @@ impl<'p, 'tcx> Fields<'p, 'tcx> {
13381330 }
13391331
13401332 /// 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.
13451337 fn replace_fields_indexed (
13461338 & self ,
13471339 new_pats : impl IntoIterator < Item = ( usize , & ' p Pat < ' tcx > ) > ,
@@ -1369,8 +1361,8 @@ impl<'p, 'tcx> Fields<'p, 'tcx> {
13691361 fields
13701362 }
13711363
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`.
13741366 pub ( super ) fn replace_fields (
13751367 & self ,
13761368 cx : & MatchCheckCtxt < ' p , ' tcx > ,
@@ -1379,7 +1371,7 @@ impl<'p, 'tcx> Fields<'p, 'tcx> {
13791371 let pats: & [ _ ] = cx. pattern_arena . alloc_from_iter ( pats) ;
13801372
13811373 match self {
1382- Fields :: Filtered { fields, kept_count } => {
1374+ Fields :: Filtered { fields, len } => {
13831375 let mut pats = pats. iter ( ) ;
13841376 let mut fields = fields. clone ( ) ;
13851377 for f in & mut fields {
@@ -1388,7 +1380,7 @@ impl<'p, 'tcx> Fields<'p, 'tcx> {
13881380 * p = pats. next ( ) . unwrap ( ) ;
13891381 }
13901382 }
1391- Fields :: Filtered { fields, kept_count : * kept_count }
1383+ Fields :: Filtered { fields, len : * len }
13921384 }
13931385 _ => Fields :: Slice ( pats) ,
13941386 }
0 commit comments