@@ -560,13 +560,6 @@ impl<'a, 'tcx> MatchCheckCtxt<'a, 'tcx> {
560
560
}
561
561
}
562
562
563
- fn is_non_exhaustive_enum ( & self , ty : Ty < ' tcx > ) -> bool {
564
- match ty. kind {
565
- ty:: Adt ( adt_def, ..) => adt_def. is_variant_list_non_exhaustive ( ) ,
566
- _ => false ,
567
- }
568
- }
569
-
570
563
fn is_local ( & self , ty : Ty < ' tcx > ) -> bool {
571
564
match ty. kind {
572
565
ty:: Adt ( adt_def, ..) => adt_def. did . is_local ( ) ,
@@ -1133,7 +1126,7 @@ fn all_constructors<'a, 'tcx>(
1133
1126
pcx : PatCtxt < ' tcx > ,
1134
1127
) -> Vec < Constructor < ' tcx > > {
1135
1128
debug ! ( "all_constructors({:?})" , pcx. ty) ;
1136
- let ctors = match pcx. ty . kind {
1129
+ match pcx. ty . kind {
1137
1130
ty:: Bool => [ true , false ]
1138
1131
. iter ( )
1139
1132
. map ( |& b| ConstantValue ( ty:: Const :: from_bool ( cx. tcx , b) , pcx. span ) )
@@ -1150,17 +1143,49 @@ fn all_constructors<'a, 'tcx>(
1150
1143
vec ! [ VarLenSlice ( 0 , 0 ) ]
1151
1144
}
1152
1145
}
1153
- ty:: Adt ( def, substs) if def. is_enum ( ) => def
1154
- . variants
1155
- . iter ( )
1156
- . filter ( |v| {
1157
- !cx. tcx . features ( ) . exhaustive_patterns
1158
- || !v
1159
- . uninhabited_from ( cx. tcx , substs, def. adt_kind ( ) )
1160
- . contains ( cx. tcx , cx. module )
1161
- } )
1162
- . map ( |v| Variant ( v. def_id ) )
1163
- . collect ( ) ,
1146
+ ty:: Adt ( def, substs) if def. is_enum ( ) => {
1147
+ let ctors: Vec < _ > = def
1148
+ . variants
1149
+ . iter ( )
1150
+ . filter ( |v| {
1151
+ !cx. tcx . features ( ) . exhaustive_patterns
1152
+ || !v
1153
+ . uninhabited_from ( cx. tcx , substs, def. adt_kind ( ) )
1154
+ . contains ( cx. tcx , cx. module )
1155
+ } )
1156
+ . map ( |v| Variant ( v. def_id ) )
1157
+ . collect ( ) ;
1158
+
1159
+ // If our scrutinee is *privately* an empty enum, we must treat it as though it had an
1160
+ // "unknown" constructor (in that case, all other patterns obviously can't be variants)
1161
+ // to avoid exposing its emptyness. See the `match_privately_empty` test for details.
1162
+ // FIXME: currently the only way I know of something can be a privately-empty enum is
1163
+ // when the exhaustive_patterns feature flag is not present, so this is only needed for
1164
+ // that case.
1165
+ let is_privately_empty = ctors. is_empty ( ) && !cx. is_uninhabited ( pcx. ty ) ;
1166
+ // If the enum is declared as `#[non_exhaustive]`, we treat it as if it had an
1167
+ // additionnal "unknown" constructor.
1168
+ let is_declared_nonexhaustive =
1169
+ def. is_variant_list_non_exhaustive ( ) && !cx. is_local ( pcx. ty ) ;
1170
+
1171
+ if is_privately_empty || is_declared_nonexhaustive {
1172
+ // There is no point in enumerating all possible variants, because the user can't
1173
+ // actually match against them themselves. So we return only the fictitious
1174
+ // constructor.
1175
+ // E.g., in an example like:
1176
+ // ```
1177
+ // let err: io::ErrorKind = ...;
1178
+ // match err {
1179
+ // io::ErrorKind::NotFound => {},
1180
+ // }
1181
+ // ```
1182
+ // we don't want to show every possible IO error, but instead have only `_` as the
1183
+ // witness.
1184
+ vec ! [ NonExhaustive ]
1185
+ } else {
1186
+ ctors
1187
+ }
1188
+ }
1164
1189
ty:: Char => {
1165
1190
vec ! [
1166
1191
// The valid Unicode Scalar Value ranges.
@@ -1180,6 +1205,15 @@ fn all_constructors<'a, 'tcx>(
1180
1205
) ,
1181
1206
]
1182
1207
}
1208
+ ty:: Int ( _) | ty:: Uint ( _)
1209
+ if pcx. ty . is_ptr_sized_integral ( )
1210
+ && !cx. tcx . features ( ) . precise_pointer_size_matching =>
1211
+ {
1212
+ // `usize`/`isize` are not allowed to be matched exhaustively unless the
1213
+ // `precise_pointer_size_matching` feature is enabled. So we treat those types like
1214
+ // `#[non_exhaustive]` enums by returning a special unmatcheable constructor.
1215
+ vec ! [ NonExhaustive ]
1216
+ }
1183
1217
ty:: Int ( ity) => {
1184
1218
let bits = Integer :: from_attr ( & cx. tcx , SignedInt ( ity) ) . size ( ) . bits ( ) as u128 ;
1185
1219
let min = 1u128 << ( bits - 1 ) ;
@@ -1198,38 +1232,7 @@ fn all_constructors<'a, 'tcx>(
1198
1232
vec ! [ Single ]
1199
1233
}
1200
1234
}
1201
- } ;
1202
-
1203
- // FIXME: currently the only way I know of something can
1204
- // be a privately-empty enum is when the exhaustive_patterns
1205
- // feature flag is not present, so this is only
1206
- // needed for that case.
1207
- let is_privately_empty = ctors. is_empty ( ) && !cx. is_uninhabited ( pcx. ty ) ;
1208
- let is_declared_nonexhaustive = cx. is_non_exhaustive_enum ( pcx. ty ) && !cx. is_local ( pcx. ty ) ;
1209
- let is_non_exhaustive = is_privately_empty
1210
- || is_declared_nonexhaustive
1211
- || ( pcx. ty . is_ptr_sized_integral ( ) && !cx. tcx . features ( ) . precise_pointer_size_matching ) ;
1212
- if is_non_exhaustive {
1213
- // If our scrutinee is *privately* an empty enum, we must treat it as though it had an
1214
- // "unknown" constructor (in that case, all other patterns obviously can't be variants) to
1215
- // avoid exposing its emptyness. See the `match_privately_empty` test for details.
1216
- //
1217
- // If the enum is declared as `#[non_exhaustive]`, we treat it as if it had an additionnal
1218
- // "unknown" constructor. However there is no point in enumerating all possible variants,
1219
- // because the user can't actually match against them themselves. So we return only the
1220
- // fictitious constructor.
1221
- // E.g., in an example like:
1222
- // ```
1223
- // let err: io::ErrorKind = ...;
1224
- // match err {
1225
- // io::ErrorKind::NotFound => {},
1226
- // }
1227
- // ```
1228
- // we don't want to show every possible IO error, but instead have only `_` as the witness.
1229
- return vec ! [ NonExhaustive ] ;
1230
- }
1231
-
1232
- ctors
1235
+ }
1233
1236
}
1234
1237
1235
1238
/// An inclusive interval, used for precise integer exhaustiveness checking.
0 commit comments