@@ -590,13 +590,16 @@ enum Constructor<'tcx> {
590590 FixedLenSlice ( u64 ) ,
591591 /// Slice patterns. Captures any array constructor of `length >= i + j`.
592592 VarLenSlice ( u64 , u64 ) ,
593+ /// Fake extra constructor for enums that aren't allowed to be matched exhaustively.
594+ NonExhaustive ,
593595}
594596
595597// Ignore spans when comparing, they don't carry semantic information as they are only for lints.
596598impl < ' tcx > std:: cmp:: PartialEq for Constructor < ' tcx > {
597599 fn eq ( & self , other : & Self ) -> bool {
598600 match ( self , other) {
599601 ( Constructor :: Single , Constructor :: Single ) => true ,
602+ ( Constructor :: NonExhaustive , Constructor :: NonExhaustive ) => true ,
600603 ( Constructor :: Variant ( a) , Constructor :: Variant ( b) ) => a == b,
601604 ( Constructor :: ConstantValue ( a, _) , Constructor :: ConstantValue ( b, _) ) => a == b,
602605 (
@@ -771,6 +774,8 @@ impl<'tcx> Constructor<'tcx> {
771774 // ranges have been omitted.
772775 remaining_ctors
773776 }
777+ // This constructor is never covered by anything else
778+ NonExhaustive => vec ! [ NonExhaustive ] ,
774779 }
775780 }
776781
@@ -842,7 +847,7 @@ impl<'tcx> Constructor<'tcx> {
842847 }
843848 _ => bug ! ( "bad slice pattern {:?} {:?}" , self , ty) ,
844849 } ,
845- ConstantValue ( ..) | ConstantRange ( ..) => vec ! [ ] ,
850+ ConstantValue ( ..) | ConstantRange ( ..) | NonExhaustive => vec ! [ ] ,
846851 }
847852 }
848853
@@ -865,7 +870,7 @@ impl<'tcx> Constructor<'tcx> {
865870 } ,
866871 FixedLenSlice ( length) => * length,
867872 VarLenSlice ( prefix, suffix) => prefix + suffix,
868- ConstantValue ( ..) | ConstantRange ( ..) => 0 ,
873+ ConstantValue ( ..) | ConstantRange ( ..) | NonExhaustive => 0 ,
869874 }
870875 }
871876
@@ -932,6 +937,7 @@ impl<'tcx> Constructor<'tcx> {
932937 hi : ty:: Const :: from_bits ( cx. tcx , hi, ty:: ParamEnv :: empty ( ) . and ( ty) ) ,
933938 end,
934939 } ) ,
940+ NonExhaustive => PatKind :: Wild ,
935941 } ;
936942
937943 Pat { ty, span : DUMMY_SP , kind : Box :: new ( pat) }
@@ -1193,6 +1199,36 @@ fn all_constructors<'a, 'tcx>(
11931199 }
11941200 }
11951201 } ;
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+
11961232 ctors
11971233}
11981234
@@ -1591,48 +1627,22 @@ pub fn is_useful<'p, 'a, 'tcx>(
15911627 let all_ctors = all_constructors ( cx, pcx) ;
15921628 debug ! ( "all_ctors = {:#?}" , all_ctors) ;
15931629
1594- let is_privately_empty = all_ctors. is_empty ( ) && !cx. is_uninhabited ( pcx. ty ) ;
1595- let is_declared_nonexhaustive = cx. is_non_exhaustive_enum ( pcx. ty ) && !cx. is_local ( pcx. ty ) ;
1596-
15971630 // `missing_ctors` is the set of constructors from the same type as the
15981631 // first column of `matrix` that are matched only by wildcard patterns
15991632 // from the first column.
16001633 //
16011634 // Therefore, if there is some pattern that is unmatched by `matrix`,
16021635 // it will still be unmatched if the first constructor is replaced by
16031636 // any of the constructors in `missing_ctors`
1604- //
1605- // However, if our scrutinee is *privately* an empty enum, we
1606- // must treat it as though it had an "unknown" constructor (in
1607- // that case, all other patterns obviously can't be variants)
1608- // to avoid exposing its emptyness. See the `match_privately_empty`
1609- // test for details.
1610- //
1611- // FIXME: currently the only way I know of something can
1612- // be a privately-empty enum is when the exhaustive_patterns
1613- // feature flag is not present, so this is only
1614- // needed for that case.
1615-
1616- // Missing constructors are those that are not matched by any
1617- // non-wildcard patterns in the current column. To determine if
1618- // the set is empty, we can check that `.peek().is_none()`, so
1619- // we only fully construct them on-demand, because they're rarely used and can be big.
1620- let missing_ctors = MissingConstructors :: new ( cx. tcx , cx. param_env , all_ctors, used_ctors) ;
16211637
1622- debug ! (
1623- "missing_ctors.empty()={:#?} is_privately_empty={:#?} is_declared_nonexhaustive={:#?}" ,
1624- missing_ctors. is_empty( ) ,
1625- is_privately_empty,
1626- is_declared_nonexhaustive
1627- ) ;
1638+ // Missing constructors are those that are not matched by any non-wildcard patterns in the
1639+ // current column. We only fully construct them on-demand, because they're rarely used and
1640+ // can be big.
1641+ let missing_ctors = MissingConstructors :: new ( cx. tcx , cx. param_env , all_ctors, used_ctors) ;
16281642
1629- // For privately empty and non-exhaustive enums, we work as if there were an "extra"
1630- // `_` constructor for the type, so we can never match over all constructors.
1631- let is_non_exhaustive = is_privately_empty
1632- || is_declared_nonexhaustive
1633- || ( pcx. ty . is_ptr_sized_integral ( ) && !cx. tcx . features ( ) . precise_pointer_size_matching ) ;
1643+ debug ! ( "missing_ctors.empty()={:#?}" , missing_ctors. is_empty( ) , ) ;
16341644
1635- if missing_ctors. is_empty ( ) && !is_non_exhaustive {
1645+ if missing_ctors. is_empty ( ) {
16361646 let ( all_ctors, _) = missing_ctors. into_inner ( ) ;
16371647 split_grouped_constructors ( cx. tcx , cx. param_env , pcx, all_ctors, matrix, DUMMY_SP , None )
16381648 . into_iter ( )
@@ -1661,26 +1671,9 @@ pub fn is_useful<'p, 'a, 'tcx>(
16611671 //
16621672 // we can report 3 witnesses: `S`, `E`, and `W`.
16631673 //
1664- // However, there are 2 cases where we don't want
1674+ // However, there is a case where we don't want
16651675 // to do this and instead report a single `_` witness:
1666- //
1667- // 1) If the user is matching against a non-exhaustive
1668- // enum, there is no point in enumerating all possible
1669- // variants, because the user can't actually match
1670- // against them themselves, e.g., in an example like:
1671- // ```
1672- // let err: io::ErrorKind = ...;
1673- // match err {
1674- // io::ErrorKind::NotFound => {},
1675- // }
1676- // ```
1677- // we don't want to show every possible IO error,
1678- // but instead have `_` as the witness (this is
1679- // actually *required* if the user specified *all*
1680- // IO errors, but is probably what we want in every
1681- // case).
1682- //
1683- // 2) If the user didn't actually specify a constructor
1676+ // if the user didn't actually specify a constructor
16841677 // in this arm, e.g., in
16851678 // ```
16861679 // let x: (Direction, Direction, bool) = ...;
@@ -1690,7 +1683,7 @@ pub fn is_useful<'p, 'a, 'tcx>(
16901683 // `(<direction-1>, <direction-2>, true)` - we are
16911684 // satisfied with `(_, _, true)`. In this case,
16921685 // `used_ctors` is empty.
1693- if is_non_exhaustive || missing_ctors. all_ctors_are_missing ( ) {
1686+ if missing_ctors. all_ctors_are_missing ( ) {
16941687 // All constructors are unused. Add a wild pattern
16951688 // rather than each individual constructor.
16961689 usefulness. apply_wildcard ( pcx. ty )
@@ -2217,13 +2210,21 @@ fn patterns_for_variant<'p, 'a: 'p, 'tcx>(
22172210/// fields filled with wild patterns.
22182211fn specialize_one_pattern < ' p , ' a : ' p , ' q : ' p , ' tcx > (
22192212 cx : & mut MatchCheckCtxt < ' a , ' tcx > ,
2220- pat : & ' q Pat < ' tcx > ,
2213+ mut pat : & ' q Pat < ' tcx > ,
22212214 constructor : & Constructor < ' tcx > ,
22222215 ctor_wild_subpatterns : & [ & ' p Pat < ' tcx > ] ,
22232216) -> Option < PatStack < ' p , ' tcx > > {
2217+ while let PatKind :: AscribeUserType { ref subpattern, .. } = * pat. kind {
2218+ pat = subpattern;
2219+ }
2220+
2221+ if let NonExhaustive = constructor {
2222+ // Only a wildcard pattern can match the special extra constructor
2223+ return if pat. is_wildcard ( ) { Some ( PatStack :: default ( ) ) } else { None } ;
2224+ }
2225+
22242226 let result = match * pat. kind {
2225- PatKind :: AscribeUserType { ref subpattern, .. } => PatStack :: from_pattern ( subpattern)
2226- . specialize_constructor ( cx, constructor, ctor_wild_subpatterns) ,
2227+ PatKind :: AscribeUserType { .. } => bug ! ( ) , // Handled above
22272228
22282229 PatKind :: Binding { .. } | PatKind :: Wild => {
22292230 Some ( PatStack :: from_slice ( ctor_wild_subpatterns) )
0 commit comments