@@ -950,13 +950,6 @@ impl<'tcx> Constructor<'tcx> {
950
950
}
951
951
}
952
952
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
-
960
953
#[ derive( Debug , Copy , Clone ) ]
961
954
enum StructField < ' p , ' tcx > {
962
955
Kept ( & ' p Pat < ' tcx > ) ,
@@ -984,97 +977,6 @@ impl<'p, 'tcx> StructField<'p, 'tcx> {
984
977
}
985
978
}
986
979
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
-
1078
980
/// A value can be decomposed into a constructor applied to some fields. This struct represents
1079
981
/// those fields, generalized to allow patterns in each field. See also `Constructor`.
1080
982
///
@@ -1085,11 +987,11 @@ impl<'p, 'tcx> StructFields<'p, 'tcx> {
1085
987
/// full fields.
1086
988
#[ derive( Debug , Clone ) ]
1087
989
enum 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 ] > ) ,
1090
992
/// Non-struct list of patterns
1091
993
Other ( SmallVec < [ & ' p Pat < ' tcx > ; 2 ] > ) ,
1092
- /// Optimization for slices
994
+ /// Optimization for slices of wildcards
1093
995
WildcardSlice { arity : usize , wild : & ' p Pat < ' tcx > } ,
1094
996
}
1095
997
@@ -1113,7 +1015,44 @@ impl<'p, 'tcx> Fields<'p, 'tcx> {
1113
1015
debug ! ( "Fields::wildcards({:#?}, {:?})" , constructor, ty) ;
1114
1016
1115
1017
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
+ } ) ,
1117
1056
Slice ( slice) => match ty. kind {
1118
1057
ty:: Slice ( ty) | ty:: Array ( ty, _) => {
1119
1058
let wild = & * cx. pattern_arena . alloc ( Pat :: wildcard_from_ty ( ty) ) ;
@@ -1128,7 +1067,18 @@ impl<'p, 'tcx> Fields<'p, 'tcx> {
1128
1067
1129
1068
/// Overrides some of the fields with the provided patterns. Panics if `self` is not `Struct`.
1130
1069
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
+ }
1132
1082
}
1133
1083
1134
1084
/// 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> {
1138
1088
cx : & MatchCheckCtxt < ' p , ' tcx > ,
1139
1089
pats : impl IntoIterator < Item = Pat < ' tcx > > ,
1140
1090
) -> Self {
1091
+ // There should be `arity()` patterns in there.
1141
1092
let pats: & [ _ ] = cx. pattern_arena . alloc_from_iter ( pats) ;
1093
+ let mut pats = pats. iter ( ) ;
1094
+
1142
1095
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 ( ) ) ,
1145
1107
}
1146
1108
}
1147
1109
1148
1110
/// Number of (filtered) patterns contained.
1149
1111
fn arity ( & self ) -> usize {
1150
1112
match self {
1151
- Fields :: Struct ( sf ) => sf . arity ( ) ,
1113
+ Fields :: Struct ( fields ) => fields . iter ( ) . filter ( |p| p . kept ( ) . is_some ( ) ) . count ( ) ,
1152
1114
Fields :: Other ( pats) => pats. len ( ) ,
1153
1115
& Fields :: WildcardSlice { arity, .. } => arity,
1154
1116
}
1155
1117
}
1156
1118
1157
- fn as_structfields ( & self ) -> Option < & StructFields < ' p , ' tcx > > {
1158
- match self {
1159
- Fields :: Struct ( sf) => Some ( sf) ,
1160
- _ => None ,
1161
- }
1162
- }
1163
-
1164
1119
/// Returns the exhaustive list of patterns.
1165
1120
fn all_patterns ( & self ) -> SmallVec < [ Pat < ' tcx > ; 2 ] > {
1166
1121
match self {
1167
- Fields :: Struct ( sf ) => sf . iter_all_patterns ( ) . collect ( ) ,
1122
+ Fields :: Struct ( fields ) => fields . iter ( ) . map ( |p| p . to_pattern ( ) ) . collect ( ) ,
1168
1123
Fields :: Other ( pats) => pats. iter ( ) . copied ( ) . cloned ( ) . collect ( ) ,
1169
1124
& Fields :: WildcardSlice { arity, wild } => ( 0 ..arity) . map ( |_| wild) . cloned ( ) . collect ( ) ,
1170
1125
}
@@ -1173,7 +1128,7 @@ impl<'p, 'tcx> Fields<'p, 'tcx> {
1173
1128
/// Returns the filtered list of patterns, to be stored in the matrix.
1174
1129
fn filtered_patterns ( self ) -> SmallVec < [ & ' p Pat < ' tcx > ; 2 ] > {
1175
1130
match self {
1176
- Fields :: Struct ( sf ) => sf . filtered_patterns ( ) ,
1131
+ Fields :: Struct ( fields ) => fields . into_iter ( ) . filter_map ( |p| p . kept ( ) ) . collect ( ) ,
1177
1132
Fields :: Other ( pats) => pats,
1178
1133
Fields :: WildcardSlice { arity, wild } => ( 0 ..arity) . map ( |_| wild) . collect ( ) ,
1179
1134
}
0 commit comments