@@ -950,13 +950,6 @@ impl<'tcx> Constructor<'tcx> {
950950 }
951951}
952952
953- /// The fields of a struct, a tuple, or an enum variant. This hides away fields whose
954- /// uninhabitedness should not be visible to the user.
955- #[ derive( Debug , Clone ) ]
956- struct StructFields < ' p , ' tcx > {
957- fields : SmallVec < [ StructField < ' p , ' tcx > ; 2 ] > ,
958- }
959-
960953#[ derive( Debug , Copy , Clone ) ]
961954enum StructField < ' p , ' tcx > {
962955 Kept ( & ' p Pat < ' tcx > ) ,
@@ -984,97 +977,6 @@ impl<'p, 'tcx> StructField<'p, 'tcx> {
984977 }
985978}
986979
987- impl < ' p , ' tcx > StructFields < ' p , ' tcx > {
988- /// Creates a new list of wildcard fields for a given constructor. `constructor`
989- /// must be `Variant` or `Single`.
990- fn wildcards (
991- cx : & MatchCheckCtxt < ' p , ' tcx > ,
992- constructor : & Constructor < ' tcx > ,
993- ty : Ty < ' tcx > ,
994- ) -> Self {
995- let fields = match ty. kind {
996- ty:: Tuple ( ref fs) => fs
997- . into_iter ( )
998- . map ( |t| t. expect_ty ( ) )
999- . map ( |ty| StructField :: wildcard_from_ty ( cx, ty) )
1000- . collect ( ) ,
1001- ty:: Ref ( _, rty, _) => smallvec ! [ StructField :: wildcard_from_ty( cx, rty) ] ,
1002- ty:: Adt ( adt, substs) => {
1003- if adt. is_box ( ) {
1004- // Use T as the sub pattern type of Box<T>.
1005- smallvec ! [ StructField :: wildcard_from_ty( cx, substs. type_at( 0 ) ) ]
1006- } else {
1007- let variant = & adt. variants [ constructor. variant_index_for_adt ( cx, adt) ] ;
1008- // Whether we must not match the fields of this variant exhaustively.
1009- let is_non_exhaustive =
1010- variant. is_field_list_non_exhaustive ( ) && !adt. did . is_local ( ) ;
1011- variant
1012- . fields
1013- . iter ( )
1014- . map ( |field| {
1015- let field_ty = field. ty ( cx. tcx , substs) ;
1016- let is_visible =
1017- adt. is_enum ( ) || field. vis . is_accessible_from ( cx. module , cx. tcx ) ;
1018- let is_uninhabited = cx. is_uninhabited ( field_ty) ;
1019-
1020- // In the cases of either a `#[non_exhaustive]` field list or a non-public field, we hide
1021- // uninhabited fields in order not to reveal the uninhabitedness of the whole variant.
1022- if is_uninhabited && ( !is_visible || is_non_exhaustive) {
1023- StructField :: Hidden ( field_ty)
1024- } else {
1025- StructField :: wildcard_from_ty ( cx, field_ty)
1026- }
1027- } )
1028- . collect ( )
1029- }
1030- }
1031- _ => smallvec ! [ ] ,
1032- } ;
1033- StructFields { fields }
1034- }
1035-
1036- /// Number of (filtered) patterns contained.
1037- fn arity ( & self ) -> usize {
1038- self . fields . iter ( ) . filter ( |p| p. kept ( ) . is_some ( ) ) . count ( )
1039- }
1040-
1041- /// Overrides some of the fields with the provided patterns in the order provided.
1042- fn replace_fields ( & self , pats : impl IntoIterator < Item = & ' p Pat < ' tcx > > ) -> Self {
1043- // There should be `arity()` patterns in there.
1044- let mut pats_iter = pats. into_iter ( ) ;
1045- let mut fields = self . clone ( ) ;
1046- for f in & mut fields. fields {
1047- if let StructField :: Kept ( p) = f {
1048- // We take one input pattern for each `Kept` field, in order.
1049- let pat = pats_iter. next ( ) . unwrap ( ) ;
1050- * p = pat;
1051- }
1052- }
1053- fields
1054- }
1055-
1056- /// Overrides some of the fields with the provided patterns.
1057- fn replace_fields_indexed ( & self , pats : impl IntoIterator < Item = & ' p FieldPat < ' tcx > > ) -> Self {
1058- let mut res = self . clone ( ) ;
1059- for pat in pats {
1060- if let StructField :: Kept ( p) = & mut res. fields [ pat. field . index ( ) ] {
1061- * p = & pat. pattern
1062- }
1063- }
1064- res
1065- }
1066-
1067- /// Iterate over the exhaustive list of patterns.
1068- fn iter_all_patterns < ' a > ( & ' a self ) -> impl Iterator < Item = Pat < ' tcx > > + Captures < ' a > {
1069- self . fields . iter ( ) . map ( |p| p. to_pattern ( ) )
1070- }
1071-
1072- /// Returns the filtered list of patterns, to be stored in the matrix.
1073- fn filtered_patterns ( & self ) -> SmallVec < [ & ' p Pat < ' tcx > ; 2 ] > {
1074- self . fields . iter ( ) . filter_map ( |p| p. kept ( ) ) . collect ( )
1075- }
1076- }
1077-
1078980/// A value can be decomposed into a constructor applied to some fields. This struct represents
1079981/// those fields, generalized to allow patterns in each field. See also `Constructor`.
1080982///
@@ -1085,11 +987,11 @@ impl<'p, 'tcx> StructFields<'p, 'tcx> {
1085987/// full fields.
1086988#[ derive( Debug , Clone ) ]
1087989enum Fields < ' p , ' tcx > {
1088- /// Fields of a struct, with special handling of uninhabited types.
1089- Struct ( StructFields < ' p , ' tcx > ) ,
990+ /// Fields of a struct/tuple/variant , with special handling of uninhabited types.
991+ Struct ( SmallVec < [ StructField < ' p , ' tcx > ; 2 ] > ) ,
1090992 /// Non-struct list of patterns
1091993 Other ( SmallVec < [ & ' p Pat < ' tcx > ; 2 ] > ) ,
1092- /// Optimization for slices
994+ /// Optimization for slices of wildcards
1093995 WildcardSlice { arity : usize , wild : & ' p Pat < ' tcx > } ,
1094996}
1095997
@@ -1113,7 +1015,44 @@ impl<'p, 'tcx> Fields<'p, 'tcx> {
11131015 debug ! ( "Fields::wildcards({:#?}, {:?})" , constructor, ty) ;
11141016
11151017 match constructor {
1116- Single | Variant ( _) => Fields :: Struct ( StructFields :: wildcards ( cx, constructor, ty) ) ,
1018+ Single | Variant ( _) => Fields :: Struct ( match ty. kind {
1019+ ty:: Tuple ( ref fs) => fs
1020+ . into_iter ( )
1021+ . map ( |t| t. expect_ty ( ) )
1022+ . map ( |ty| StructField :: wildcard_from_ty ( cx, ty) )
1023+ . collect ( ) ,
1024+ ty:: Ref ( _, rty, _) => smallvec ! [ StructField :: wildcard_from_ty( cx, rty) ] ,
1025+ ty:: Adt ( adt, substs) => {
1026+ if adt. is_box ( ) {
1027+ // Use T as the sub pattern type of Box<T>.
1028+ smallvec ! [ StructField :: wildcard_from_ty( cx, substs. type_at( 0 ) ) ]
1029+ } else {
1030+ let variant = & adt. variants [ constructor. variant_index_for_adt ( cx, adt) ] ;
1031+ // Whether we must not match the fields of this variant exhaustively.
1032+ let is_non_exhaustive =
1033+ variant. is_field_list_non_exhaustive ( ) && !adt. did . is_local ( ) ;
1034+ variant
1035+ . fields
1036+ . iter ( )
1037+ . map ( |field| {
1038+ let field_ty = field. ty ( cx. tcx , substs) ;
1039+ let is_visible = adt. is_enum ( )
1040+ || field. vis . is_accessible_from ( cx. module , cx. tcx ) ;
1041+ let is_uninhabited = cx. is_uninhabited ( field_ty) ;
1042+
1043+ // In the cases of either a `#[non_exhaustive]` field list or a non-public field, we hide
1044+ // uninhabited fields in order not to reveal the uninhabitedness of the whole variant.
1045+ if is_uninhabited && ( !is_visible || is_non_exhaustive) {
1046+ StructField :: Hidden ( field_ty)
1047+ } else {
1048+ StructField :: wildcard_from_ty ( cx, field_ty)
1049+ }
1050+ } )
1051+ . collect ( )
1052+ }
1053+ }
1054+ _ => smallvec ! [ ] ,
1055+ } ) ,
11171056 Slice ( slice) => match ty. kind {
11181057 ty:: Slice ( ty) | ty:: Array ( ty, _) => {
11191058 let wild = & * cx. pattern_arena . alloc ( Pat :: wildcard_from_ty ( ty) ) ;
@@ -1128,7 +1067,18 @@ impl<'p, 'tcx> Fields<'p, 'tcx> {
11281067
11291068 /// Overrides some of the fields with the provided patterns. Panics if `self` is not `Struct`.
11301069 fn replace_fields_indexed ( & self , pats : impl IntoIterator < Item = & ' p FieldPat < ' tcx > > ) -> Self {
1131- Fields :: Struct ( self . as_structfields ( ) . unwrap ( ) . replace_fields_indexed ( pats) )
1070+ match self {
1071+ Fields :: Struct ( fields) => {
1072+ let mut fields = fields. clone ( ) ;
1073+ for pat in pats {
1074+ if let StructField :: Kept ( p) = & mut fields[ pat. field . index ( ) ] {
1075+ * p = & pat. pattern
1076+ }
1077+ }
1078+ Fields :: Struct ( fields)
1079+ }
1080+ _ => bug ! ( "`replace_fields_indexed` called on the wrong kind of `Fields`" ) ,
1081+ }
11321082 }
11331083
11341084 /// Replaces contained fields with the given filtered list of patterns, e.g. taken from the
@@ -1138,33 +1088,38 @@ impl<'p, 'tcx> Fields<'p, 'tcx> {
11381088 cx : & MatchCheckCtxt < ' p , ' tcx > ,
11391089 pats : impl IntoIterator < Item = Pat < ' tcx > > ,
11401090 ) -> Self {
1091+ // There should be `arity()` patterns in there.
11411092 let pats: & [ _ ] = cx. pattern_arena . alloc_from_iter ( pats) ;
1093+ let mut pats = pats. iter ( ) ;
1094+
11421095 match self {
1143- Fields :: Struct ( sf) => Fields :: Struct ( sf. replace_fields ( pats) ) ,
1144- _ => Fields :: Other ( pats. iter ( ) . collect ( ) ) ,
1096+ Fields :: Struct ( fields) => {
1097+ let mut fields = fields. clone ( ) ;
1098+ for f in & mut fields {
1099+ if let StructField :: Kept ( p) = f {
1100+ // We take one input pattern for each `Kept` field, in order.
1101+ * p = pats. next ( ) . unwrap ( ) ;
1102+ }
1103+ }
1104+ Fields :: Struct ( fields)
1105+ }
1106+ _ => Fields :: Other ( pats. collect ( ) ) ,
11451107 }
11461108 }
11471109
11481110 /// Number of (filtered) patterns contained.
11491111 fn arity ( & self ) -> usize {
11501112 match self {
1151- Fields :: Struct ( sf ) => sf . arity ( ) ,
1113+ Fields :: Struct ( fields ) => fields . iter ( ) . filter ( |p| p . kept ( ) . is_some ( ) ) . count ( ) ,
11521114 Fields :: Other ( pats) => pats. len ( ) ,
11531115 & Fields :: WildcardSlice { arity, .. } => arity,
11541116 }
11551117 }
11561118
1157- fn as_structfields ( & self ) -> Option < & StructFields < ' p , ' tcx > > {
1158- match self {
1159- Fields :: Struct ( sf) => Some ( sf) ,
1160- _ => None ,
1161- }
1162- }
1163-
11641119 /// Returns the exhaustive list of patterns.
11651120 fn all_patterns ( & self ) -> SmallVec < [ Pat < ' tcx > ; 2 ] > {
11661121 match self {
1167- Fields :: Struct ( sf ) => sf . iter_all_patterns ( ) . collect ( ) ,
1122+ Fields :: Struct ( fields ) => fields . iter ( ) . map ( |p| p . to_pattern ( ) ) . collect ( ) ,
11681123 Fields :: Other ( pats) => pats. iter ( ) . copied ( ) . cloned ( ) . collect ( ) ,
11691124 & Fields :: WildcardSlice { arity, wild } => ( 0 ..arity) . map ( |_| wild) . cloned ( ) . collect ( ) ,
11701125 }
@@ -1173,7 +1128,7 @@ impl<'p, 'tcx> Fields<'p, 'tcx> {
11731128 /// Returns the filtered list of patterns, to be stored in the matrix.
11741129 fn filtered_patterns ( self ) -> SmallVec < [ & ' p Pat < ' tcx > ; 2 ] > {
11751130 match self {
1176- Fields :: Struct ( sf ) => sf . filtered_patterns ( ) ,
1131+ Fields :: Struct ( fields ) => fields . into_iter ( ) . filter_map ( |p| p . kept ( ) ) . collect ( ) ,
11771132 Fields :: Other ( pats) => pats,
11781133 Fields :: WildcardSlice { arity, wild } => ( 0 ..arity) . map ( |_| wild) . collect ( ) ,
11791134 }
0 commit comments