@@ -846,6 +846,9 @@ enum Constructor<'tcx> {
846846 Opaque ,
847847 /// Fake extra constructor for enums that aren't allowed to be matched exhaustively.
848848 NonExhaustive ,
849+ /// Fake constructor for those types for which we can't list constructors explicitely, like
850+ /// `f64` and `&str`.
851+ Unlistable ,
849852 /// Wildcard pattern.
850853 Wildcard ,
851854}
@@ -949,6 +952,9 @@ impl<'tcx> Constructor<'tcx> {
949952 }
950953 // This constructor is never covered by anything else
951954 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 ] ,
952958 Opaque => bug ! ( "found unexpected opaque ctor in all_ctors" ) ,
953959 Wildcard => bug ! ( "found unexpected wildcard ctor in all_ctors" ) ,
954960 }
@@ -1068,6 +1074,11 @@ impl<'tcx> Constructor<'tcx> {
10681074 ( Opaque , _) | ( _, Opaque ) => false ,
10691075 // Only a wildcard pattern can match the special extra constructor.
10701076 ( 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 ,
10711082
10721083 _ => bug ! ( "trying to compare incompatible constructors {:?} and {:?}" , self , other) ,
10731084 }
@@ -1146,7 +1157,7 @@ impl<'tcx> Constructor<'tcx> {
11461157 & Str ( value) => PatKind :: Constant { value } ,
11471158 & FloatRange ( lo, hi, end) => PatKind :: Range ( PatRange { lo, hi, end } ) ,
11481159 IntRange ( range) => return range. to_pat ( pcx. cx . tcx ) ,
1149- NonExhaustive => PatKind :: Wild ,
1160+ NonExhaustive | Unlistable => PatKind :: Wild ,
11501161 Opaque => bug ! ( "we should not try to apply an opaque constructor" ) ,
11511162 Wildcard => bug ! (
11521163 "trying to apply a wildcard constructor; this should have been done in `apply_constructors`"
@@ -1286,7 +1297,7 @@ impl<'p, 'tcx> Fields<'p, 'tcx> {
12861297 }
12871298 }
12881299 }
1289- _ => Fields :: empty ( ) ,
1300+ _ => bug ! ( "Unexpected type for `Single` constructor: {:?}" , ty ) ,
12901301 } ,
12911302 Slice ( slice) => match * ty. kind ( ) {
12921303 ty:: Slice ( ty) | ty:: Array ( ty, _) => {
@@ -1295,9 +1306,8 @@ impl<'p, 'tcx> Fields<'p, 'tcx> {
12951306 }
12961307 _ => bug ! ( "bad slice pattern {:?} {:?}" , constructor, ty) ,
12971308 } ,
1298- Str ( ..) | FloatRange ( ..) | IntRange ( ..) | NonExhaustive | Opaque | Wildcard => {
1299- Fields :: empty ( )
1300- }
1309+ Str ( ..) | FloatRange ( ..) | IntRange ( ..) | NonExhaustive | Opaque | Unlistable
1310+ | Wildcard => Fields :: empty ( ) ,
13011311 } ;
13021312 debug ! ( "Fields::wildcards({:?}, {:?}) = {:#?}" , constructor, ty, ret) ;
13031313 ret
@@ -1616,9 +1626,9 @@ fn all_constructors<'p, 'tcx>(pcx: PatCtxt<'_, 'p, 'tcx>) -> Vec<Constructor<'tc
16161626 . unwrap ( ) ,
16171627 )
16181628 } ;
1619- match * pcx. ty . kind ( ) {
1629+ match pcx. ty . kind ( ) {
16201630 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 ( ) => {
16221632 let len = len. eval_usize ( cx. tcx , cx. param_env ) ;
16231633 if len != 0 && cx. is_uninhabited ( sub_ty) {
16241634 vec ! [ ]
@@ -1627,26 +1637,11 @@ fn all_constructors<'p, 'tcx>(pcx: PatCtxt<'_, 'p, 'tcx>) -> Vec<Constructor<'tc
16271637 }
16281638 }
16291639 // 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) => {
16311641 let kind = if cx. is_uninhabited ( sub_ty) { FixedLen ( 0 ) } else { VarLen ( 0 , 0 ) } ;
16321642 vec ! [ Slice ( Slice { array_len: None , kind } ) ]
16331643 }
16341644 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-
16501645 // If the enum is declared as `#[non_exhaustive]`, we treat it as if it had an
16511646 // additional "unknown" constructor.
16521647 // 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
16721667 let is_secretly_empty =
16731668 def. variants . is_empty ( ) && !cx. tcx . features ( ) . exhaustive_patterns ;
16741669
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+ }
16761686 }
16771687 ty:: Char => {
16781688 vec ! [
@@ -1690,24 +1700,22 @@ fn all_constructors<'p, 'tcx>(pcx: PatCtxt<'_, 'p, 'tcx>) -> Vec<Constructor<'tc
16901700 // `#[non_exhaustive]` enums by returning a special unmatcheable constructor.
16911701 vec ! [ NonExhaustive ]
16921702 }
1693- ty:: Int ( ity) => {
1703+ & ty:: Int ( ity) => {
16941704 let bits = Integer :: from_attr ( & cx. tcx , SignedInt ( ity) ) . size ( ) . bits ( ) as u128 ;
16951705 let min = 1u128 << ( bits - 1 ) ;
16961706 let max = min - 1 ;
16971707 vec ! [ make_range( min, max) ]
16981708 }
1699- ty:: Uint ( uty) => {
1709+ & ty:: Uint ( uty) => {
17001710 let size = Integer :: from_attr ( & cx. tcx , UnsignedInt ( uty) ) . size ( ) ;
17011711 let max = truncate ( u128:: MAX , size) ;
17021712 vec ! [ make_range( 0 , max) ]
17031713 }
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 ] ,
17111719 }
17121720}
17131721
0 commit comments