@@ -846,6 +846,9 @@ enum Constructor<'tcx> {
846
846
Opaque ,
847
847
/// Fake extra constructor for enums that aren't allowed to be matched exhaustively.
848
848
NonExhaustive ,
849
+ /// Fake constructor for those types for which we can't list constructors explicitely, like
850
+ /// `f64` and `&str`.
851
+ Unlistable ,
849
852
/// Wildcard pattern.
850
853
Wildcard ,
851
854
}
@@ -949,6 +952,9 @@ impl<'tcx> Constructor<'tcx> {
949
952
}
950
953
// This constructor is never covered by anything else
951
954
NonExhaustive => vec ! [ NonExhaustive ] ,
955
+ // This constructor is only covered by `Single`s
956
+ Unlistable if other_ctors. iter ( ) . any ( |c| * c == Single ) => vec ! [ ] ,
957
+ Unlistable => vec ! [ Unlistable ] ,
952
958
Opaque => bug ! ( "found unexpected opaque ctor in all_ctors" ) ,
953
959
Wildcard => bug ! ( "found unexpected wildcard ctor in all_ctors" ) ,
954
960
}
@@ -1068,6 +1074,11 @@ impl<'tcx> Constructor<'tcx> {
1068
1074
( Opaque , _) | ( _, Opaque ) => false ,
1069
1075
// Only a wildcard pattern can match the special extra constructor.
1070
1076
( NonExhaustive , _) => false ,
1077
+ // If we encounter a `Single` here, this means there was only one constructor for this
1078
+ // type after all.
1079
+ ( Unlistable , Single ) => true ,
1080
+ // Otherwise, only a wildcard pattern can match the special extra constructor.
1081
+ ( Unlistable , _) => false ,
1071
1082
1072
1083
_ => bug ! ( "trying to compare incompatible constructors {:?} and {:?}" , self , other) ,
1073
1084
}
@@ -1146,7 +1157,7 @@ impl<'tcx> Constructor<'tcx> {
1146
1157
& Str ( value) => PatKind :: Constant { value } ,
1147
1158
& FloatRange ( lo, hi, end) => PatKind :: Range ( PatRange { lo, hi, end } ) ,
1148
1159
IntRange ( range) => return range. to_pat ( pcx. cx . tcx ) ,
1149
- NonExhaustive => PatKind :: Wild ,
1160
+ NonExhaustive | Unlistable => PatKind :: Wild ,
1150
1161
Opaque => bug ! ( "we should not try to apply an opaque constructor" ) ,
1151
1162
Wildcard => bug ! (
1152
1163
"trying to apply a wildcard constructor; this should have been done in `apply_constructors`"
@@ -1286,7 +1297,7 @@ impl<'p, 'tcx> Fields<'p, 'tcx> {
1286
1297
}
1287
1298
}
1288
1299
}
1289
- _ => Fields :: empty ( ) ,
1300
+ _ => bug ! ( "Unexpected type for `Single` constructor: {:?}" , ty ) ,
1290
1301
} ,
1291
1302
Slice ( slice) => match * ty. kind ( ) {
1292
1303
ty:: Slice ( ty) | ty:: Array ( ty, _) => {
@@ -1295,9 +1306,8 @@ impl<'p, 'tcx> Fields<'p, 'tcx> {
1295
1306
}
1296
1307
_ => bug ! ( "bad slice pattern {:?} {:?}" , constructor, ty) ,
1297
1308
} ,
1298
- Str ( ..) | FloatRange ( ..) | IntRange ( ..) | NonExhaustive | Opaque | Wildcard => {
1299
- Fields :: empty ( )
1300
- }
1309
+ Str ( ..) | FloatRange ( ..) | IntRange ( ..) | NonExhaustive | Opaque | Unlistable
1310
+ | Wildcard => Fields :: empty ( ) ,
1301
1311
} ;
1302
1312
debug ! ( "Fields::wildcards({:?}, {:?}) = {:#?}" , constructor, ty, ret) ;
1303
1313
ret
@@ -1616,9 +1626,9 @@ fn all_constructors<'p, 'tcx>(pcx: PatCtxt<'_, 'p, 'tcx>) -> Vec<Constructor<'tc
1616
1626
. unwrap ( ) ,
1617
1627
)
1618
1628
} ;
1619
- match * pcx. ty . kind ( ) {
1629
+ match pcx. ty . kind ( ) {
1620
1630
ty:: Bool => vec ! [ make_range( 0 , 1 ) ] ,
1621
- ty:: Array ( ref sub_ty, len) if len. try_eval_usize ( cx. tcx , cx. param_env ) . is_some ( ) => {
1631
+ ty:: Array ( sub_ty, len) if len. try_eval_usize ( cx. tcx , cx. param_env ) . is_some ( ) => {
1622
1632
let len = len. eval_usize ( cx. tcx , cx. param_env ) ;
1623
1633
if len != 0 && cx. is_uninhabited ( sub_ty) {
1624
1634
vec ! [ ]
@@ -1627,26 +1637,11 @@ fn all_constructors<'p, 'tcx>(pcx: PatCtxt<'_, 'p, 'tcx>) -> Vec<Constructor<'tc
1627
1637
}
1628
1638
}
1629
1639
// Treat arrays of a constant but unknown length like slices.
1630
- ty:: Array ( ref sub_ty, _) | ty:: Slice ( ref sub_ty) => {
1640
+ ty:: Array ( sub_ty, _) | ty:: Slice ( sub_ty) => {
1631
1641
let kind = if cx. is_uninhabited ( sub_ty) { FixedLen ( 0 ) } else { VarLen ( 0 , 0 ) } ;
1632
1642
vec ! [ Slice ( Slice { array_len: None , kind } ) ]
1633
1643
}
1634
1644
ty:: Adt ( def, substs) if def. is_enum ( ) => {
1635
- let ctors: Vec < _ > = if cx. tcx . features ( ) . exhaustive_patterns {
1636
- // If `exhaustive_patterns` is enabled, we exclude variants known to be
1637
- // uninhabited.
1638
- def. variants
1639
- . iter ( )
1640
- . filter ( |v| {
1641
- !v. uninhabited_from ( cx. tcx , substs, def. adt_kind ( ) , cx. param_env )
1642
- . contains ( cx. tcx , cx. module )
1643
- } )
1644
- . map ( |v| Variant ( v. def_id ) )
1645
- . collect ( )
1646
- } else {
1647
- def. variants . iter ( ) . map ( |v| Variant ( v. def_id ) ) . collect ( )
1648
- } ;
1649
-
1650
1645
// If the enum is declared as `#[non_exhaustive]`, we treat it as if it had an
1651
1646
// additional "unknown" constructor.
1652
1647
// There is no point in enumerating all possible variants, because the user can't
@@ -1672,7 +1667,22 @@ fn all_constructors<'p, 'tcx>(pcx: PatCtxt<'_, 'p, 'tcx>) -> Vec<Constructor<'tc
1672
1667
let is_secretly_empty =
1673
1668
def. variants . is_empty ( ) && !cx. tcx . features ( ) . exhaustive_patterns ;
1674
1669
1675
- if is_secretly_empty || is_declared_nonexhaustive { vec ! [ NonExhaustive ] } else { ctors }
1670
+ if is_secretly_empty || is_declared_nonexhaustive {
1671
+ vec ! [ NonExhaustive ]
1672
+ } else if cx. tcx . features ( ) . exhaustive_patterns {
1673
+ // If `exhaustive_patterns` is enabled, we exclude variants known to be
1674
+ // uninhabited.
1675
+ def. variants
1676
+ . iter ( )
1677
+ . filter ( |v| {
1678
+ !v. uninhabited_from ( cx. tcx , substs, def. adt_kind ( ) , cx. param_env )
1679
+ . contains ( cx. tcx , cx. module )
1680
+ } )
1681
+ . map ( |v| Variant ( v. def_id ) )
1682
+ . collect ( )
1683
+ } else {
1684
+ def. variants . iter ( ) . map ( |v| Variant ( v. def_id ) ) . collect ( )
1685
+ }
1676
1686
}
1677
1687
ty:: Char => {
1678
1688
vec ! [
@@ -1690,24 +1700,22 @@ fn all_constructors<'p, 'tcx>(pcx: PatCtxt<'_, 'p, 'tcx>) -> Vec<Constructor<'tc
1690
1700
// `#[non_exhaustive]` enums by returning a special unmatcheable constructor.
1691
1701
vec ! [ NonExhaustive ]
1692
1702
}
1693
- ty:: Int ( ity) => {
1703
+ & ty:: Int ( ity) => {
1694
1704
let bits = Integer :: from_attr ( & cx. tcx , SignedInt ( ity) ) . size ( ) . bits ( ) as u128 ;
1695
1705
let min = 1u128 << ( bits - 1 ) ;
1696
1706
let max = min - 1 ;
1697
1707
vec ! [ make_range( min, max) ]
1698
1708
}
1699
- ty:: Uint ( uty) => {
1709
+ & ty:: Uint ( uty) => {
1700
1710
let size = Integer :: from_attr ( & cx. tcx , UnsignedInt ( uty) ) . size ( ) ;
1701
1711
let max = truncate ( u128:: MAX , size) ;
1702
1712
vec ! [ make_range( 0 , max) ]
1703
1713
}
1704
- _ => {
1705
- if cx. is_uninhabited ( pcx. ty ) {
1706
- vec ! [ ]
1707
- } else {
1708
- vec ! [ Single ]
1709
- }
1710
- }
1714
+ _ if cx. is_uninhabited ( pcx. ty ) => vec ! [ ] ,
1715
+ ty:: Adt ( ..) | ty:: Tuple ( ..) => vec ! [ Single ] ,
1716
+ ty:: Ref ( _, t, _) if !t. is_str ( ) => vec ! [ Single ] ,
1717
+ // This type is one for which we don't know how to list constructors, like &str of f64.
1718
+ _ => vec ! [ Unlistable ] ,
1711
1719
}
1712
1720
}
1713
1721
0 commit comments