@@ -590,13 +590,16 @@ enum Constructor<'tcx> {
590
590
FixedLenSlice ( u64 ) ,
591
591
/// Slice patterns. Captures any array constructor of `length >= i + j`.
592
592
VarLenSlice ( u64 , u64 ) ,
593
+ /// Fake extra constructor for enums that aren't allowed to be matched exhaustively.
594
+ NonExhaustive ,
593
595
}
594
596
595
597
// Ignore spans when comparing, they don't carry semantic information as they are only for lints.
596
598
impl < ' tcx > std:: cmp:: PartialEq for Constructor < ' tcx > {
597
599
fn eq ( & self , other : & Self ) -> bool {
598
600
match ( self , other) {
599
601
( Constructor :: Single , Constructor :: Single ) => true ,
602
+ ( Constructor :: NonExhaustive , Constructor :: NonExhaustive ) => true ,
600
603
( Constructor :: Variant ( a) , Constructor :: Variant ( b) ) => a == b,
601
604
( Constructor :: ConstantValue ( a, _) , Constructor :: ConstantValue ( b, _) ) => a == b,
602
605
(
@@ -771,6 +774,8 @@ impl<'tcx> Constructor<'tcx> {
771
774
// ranges have been omitted.
772
775
remaining_ctors
773
776
}
777
+ // This constructor is never covered by anything else
778
+ NonExhaustive => vec ! [ NonExhaustive ] ,
774
779
}
775
780
}
776
781
@@ -842,7 +847,7 @@ impl<'tcx> Constructor<'tcx> {
842
847
}
843
848
_ => bug ! ( "bad slice pattern {:?} {:?}" , self , ty) ,
844
849
} ,
845
- ConstantValue ( ..) | ConstantRange ( ..) => vec ! [ ] ,
850
+ ConstantValue ( ..) | ConstantRange ( ..) | NonExhaustive => vec ! [ ] ,
846
851
}
847
852
}
848
853
@@ -865,7 +870,7 @@ impl<'tcx> Constructor<'tcx> {
865
870
} ,
866
871
FixedLenSlice ( length) => * length,
867
872
VarLenSlice ( prefix, suffix) => prefix + suffix,
868
- ConstantValue ( ..) | ConstantRange ( ..) => 0 ,
873
+ ConstantValue ( ..) | ConstantRange ( ..) | NonExhaustive => 0 ,
869
874
}
870
875
}
871
876
@@ -932,6 +937,7 @@ impl<'tcx> Constructor<'tcx> {
932
937
hi : ty:: Const :: from_bits ( cx. tcx , hi, ty:: ParamEnv :: empty ( ) . and ( ty) ) ,
933
938
end,
934
939
} ) ,
940
+ NonExhaustive => PatKind :: Wild ,
935
941
} ;
936
942
937
943
Pat { ty, span : DUMMY_SP , kind : Box :: new ( pat) }
@@ -1193,6 +1199,36 @@ fn all_constructors<'a, 'tcx>(
1193
1199
}
1194
1200
}
1195
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
+
1196
1232
ctors
1197
1233
}
1198
1234
@@ -1591,48 +1627,22 @@ pub fn is_useful<'p, 'a, 'tcx>(
1591
1627
let all_ctors = all_constructors ( cx, pcx) ;
1592
1628
debug ! ( "all_ctors = {:#?}" , all_ctors) ;
1593
1629
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
-
1597
1630
// `missing_ctors` is the set of constructors from the same type as the
1598
1631
// first column of `matrix` that are matched only by wildcard patterns
1599
1632
// from the first column.
1600
1633
//
1601
1634
// Therefore, if there is some pattern that is unmatched by `matrix`,
1602
1635
// it will still be unmatched if the first constructor is replaced by
1603
1636
// 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) ;
1621
1637
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) ;
1628
1642
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( ) , ) ;
1634
1644
1635
- if missing_ctors. is_empty ( ) && !is_non_exhaustive {
1645
+ if missing_ctors. is_empty ( ) {
1636
1646
let ( all_ctors, _) = missing_ctors. into_inner ( ) ;
1637
1647
split_grouped_constructors ( cx. tcx , cx. param_env , pcx, all_ctors, matrix, DUMMY_SP , None )
1638
1648
. into_iter ( )
@@ -1661,26 +1671,9 @@ pub fn is_useful<'p, 'a, 'tcx>(
1661
1671
//
1662
1672
// we can report 3 witnesses: `S`, `E`, and `W`.
1663
1673
//
1664
- // However, there are 2 cases where we don't want
1674
+ // However, there is a case where we don't want
1665
1675
// 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
1684
1677
// in this arm, e.g., in
1685
1678
// ```
1686
1679
// let x: (Direction, Direction, bool) = ...;
@@ -1690,7 +1683,7 @@ pub fn is_useful<'p, 'a, 'tcx>(
1690
1683
// `(<direction-1>, <direction-2>, true)` - we are
1691
1684
// satisfied with `(_, _, true)`. In this case,
1692
1685
// `used_ctors` is empty.
1693
- if is_non_exhaustive || missing_ctors. all_ctors_are_missing ( ) {
1686
+ if missing_ctors. all_ctors_are_missing ( ) {
1694
1687
// All constructors are unused. Add a wild pattern
1695
1688
// rather than each individual constructor.
1696
1689
usefulness. apply_wildcard ( pcx. ty )
@@ -2217,13 +2210,21 @@ fn patterns_for_variant<'p, 'a: 'p, 'tcx>(
2217
2210
/// fields filled with wild patterns.
2218
2211
fn specialize_one_pattern < ' p , ' a : ' p , ' q : ' p , ' tcx > (
2219
2212
cx : & mut MatchCheckCtxt < ' a , ' tcx > ,
2220
- pat : & ' q Pat < ' tcx > ,
2213
+ mut pat : & ' q Pat < ' tcx > ,
2221
2214
constructor : & Constructor < ' tcx > ,
2222
2215
ctor_wild_subpatterns : & [ & ' p Pat < ' tcx > ] ,
2223
2216
) -> 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
+
2224
2226
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
2227
2228
2228
2229
PatKind :: Binding { .. } | PatKind :: Wild => {
2229
2230
Some ( PatStack :: from_slice ( ctor_wild_subpatterns) )
0 commit comments