@@ -560,13 +560,6 @@ impl<'a, 'tcx> MatchCheckCtxt<'a, 'tcx> {
560560 }
561561 }
562562
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-
570563 fn is_local ( & self , ty : Ty < ' tcx > ) -> bool {
571564 match ty. kind {
572565 ty:: Adt ( adt_def, ..) => adt_def. did . is_local ( ) ,
@@ -1133,7 +1126,7 @@ fn all_constructors<'a, 'tcx>(
11331126 pcx : PatCtxt < ' tcx > ,
11341127) -> Vec < Constructor < ' tcx > > {
11351128 debug ! ( "all_constructors({:?})" , pcx. ty) ;
1136- let ctors = match pcx. ty . kind {
1129+ match pcx. ty . kind {
11371130 ty:: Bool => [ true , false ]
11381131 . iter ( )
11391132 . map ( |& b| ConstantValue ( ty:: Const :: from_bool ( cx. tcx , b) , pcx. span ) )
@@ -1150,17 +1143,49 @@ fn all_constructors<'a, 'tcx>(
11501143 vec ! [ VarLenSlice ( 0 , 0 ) ]
11511144 }
11521145 }
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+ }
11641189 ty:: Char => {
11651190 vec ! [
11661191 // The valid Unicode Scalar Value ranges.
@@ -1180,6 +1205,15 @@ fn all_constructors<'a, 'tcx>(
11801205 ) ,
11811206 ]
11821207 }
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+ }
11831217 ty:: Int ( ity) => {
11841218 let bits = Integer :: from_attr ( & cx. tcx , SignedInt ( ity) ) . size ( ) . bits ( ) as u128 ;
11851219 let min = 1u128 << ( bits - 1 ) ;
@@ -1198,38 +1232,7 @@ fn all_constructors<'a, 'tcx>(
11981232 vec ! [ Single ]
11991233 }
12001234 }
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+ }
12331236}
12341237
12351238/// An inclusive interval, used for precise integer exhaustiveness checking.
0 commit comments