@@ -792,12 +792,82 @@ pub enum Usefulness<'tcx> {
792792}
793793
794794impl < ' tcx > Usefulness < ' tcx > {
795+ fn new_useful ( preference : WitnessPreference ) -> Self {
796+ match preference {
797+ ConstructWitness => UsefulWithWitness ( vec ! [ Witness ( vec![ ] ) ] ) ,
798+ LeaveOutWitness => Useful ,
799+ }
800+ }
801+
795802 fn is_useful ( & self ) -> bool {
796803 match * self {
797804 NotUseful => false ,
798805 _ => true ,
799806 }
800807 }
808+
809+ fn apply_constructor (
810+ self ,
811+ cx : & MatchCheckCtxt < ' _ , ' tcx > ,
812+ ctor : & Constructor < ' tcx > ,
813+ ty : Ty < ' tcx > ,
814+ ) -> Self {
815+ match self {
816+ UsefulWithWitness ( witnesses) => UsefulWithWitness (
817+ witnesses
818+ . into_iter ( )
819+ . map ( |witness| witness. apply_constructor ( cx, & ctor, ty) )
820+ . collect ( ) ,
821+ ) ,
822+ x => x,
823+ }
824+ }
825+
826+ fn apply_wildcard ( self , ty : Ty < ' tcx > ) -> Self {
827+ match self {
828+ UsefulWithWitness ( witnesses) => {
829+ let wild = Pat { ty, span : DUMMY_SP , kind : box PatKind :: Wild } ;
830+ UsefulWithWitness (
831+ witnesses
832+ . into_iter ( )
833+ . map ( |mut witness| {
834+ witness. 0 . push ( wild. clone ( ) ) ;
835+ witness
836+ } )
837+ . collect ( ) ,
838+ )
839+ }
840+ x => x,
841+ }
842+ }
843+
844+ fn apply_missing_ctors (
845+ self ,
846+ cx : & MatchCheckCtxt < ' _ , ' tcx > ,
847+ ty : Ty < ' tcx > ,
848+ missing_ctors : & MissingConstructors < ' tcx > ,
849+ ) -> Self {
850+ match self {
851+ UsefulWithWitness ( witnesses) => {
852+ let new_patterns: Vec < _ > =
853+ missing_ctors. iter ( ) . map ( |ctor| ctor. apply_wildcards ( cx, ty) ) . collect ( ) ;
854+ // Add the new patterns to each witness
855+ UsefulWithWitness (
856+ witnesses
857+ . into_iter ( )
858+ . flat_map ( |witness| {
859+ new_patterns. iter ( ) . map ( move |pat| {
860+ let mut witness = witness. clone ( ) ;
861+ witness. 0 . push ( pat. clone ( ) ) ;
862+ witness
863+ } )
864+ } )
865+ . collect ( ) ,
866+ )
867+ }
868+ x => x,
869+ }
870+ }
801871}
802872
803873#[ derive( Copy , Clone , Debug ) ]
@@ -1399,10 +1469,7 @@ pub fn is_useful<'p, 'a, 'tcx>(
13991469 // the type of the tuple we're checking is inhabited or not.
14001470 if v. is_empty ( ) {
14011471 return if rows. is_empty ( ) {
1402- match witness_preference {
1403- ConstructWitness => UsefulWithWitness ( vec ! [ Witness ( vec![ ] ) ] ) ,
1404- LeaveOutWitness => Useful ,
1405- }
1472+ Usefulness :: new_useful ( witness_preference)
14061473 } else {
14071474 NotUseful
14081475 } ;
@@ -1527,79 +1594,62 @@ pub fn is_useful<'p, 'a, 'tcx>(
15271594 } else {
15281595 let matrix = matrix. specialize_wildcard ( ) ;
15291596 let v = v. to_tail ( ) ;
1530- match is_useful ( cx, & matrix, & v, witness_preference, hir_id) {
1531- UsefulWithWitness ( witnesses) => {
1532- let cx = & * cx;
1533- // In this case, there's at least one "free"
1534- // constructor that is only matched against by
1535- // wildcard patterns.
1536- //
1537- // There are 2 ways we can report a witness here.
1538- // Commonly, we can report all the "free"
1539- // constructors as witnesses, e.g., if we have:
1540- //
1541- // ```
1542- // enum Direction { N, S, E, W }
1543- // let Direction::N = ...;
1544- // ```
1545- //
1546- // we can report 3 witnesses: `S`, `E`, and `W`.
1547- //
1548- // However, there are 2 cases where we don't want
1549- // to do this and instead report a single `_` witness:
1550- //
1551- // 1) If the user is matching against a non-exhaustive
1552- // enum, there is no point in enumerating all possible
1553- // variants, because the user can't actually match
1554- // against them themselves, e.g., in an example like:
1555- // ```
1556- // let err: io::ErrorKind = ...;
1557- // match err {
1558- // io::ErrorKind::NotFound => {},
1559- // }
1560- // ```
1561- // we don't want to show every possible IO error,
1562- // but instead have `_` as the witness (this is
1563- // actually *required* if the user specified *all*
1564- // IO errors, but is probably what we want in every
1565- // case).
1566- //
1567- // 2) If the user didn't actually specify a constructor
1568- // in this arm, e.g., in
1569- // ```
1570- // let x: (Direction, Direction, bool) = ...;
1571- // let (_, _, false) = x;
1572- // ```
1573- // we don't want to show all 16 possible witnesses
1574- // `(<direction-1>, <direction-2>, true)` - we are
1575- // satisfied with `(_, _, true)`. In this case,
1576- // `used_ctors` is empty.
1577- let new_patterns = if is_non_exhaustive || missing_ctors. all_ctors_are_missing ( )
1578- {
1579- // All constructors are unused. Add a wild pattern
1580- // rather than each individual constructor.
1581- vec ! [ Pat { ty: pcx. ty, span: DUMMY_SP , kind: box PatKind :: Wild } ]
1582- } else {
1583- // Construct for each missing constructor a "wild" version of this
1584- // constructor, that matches everything that can be built with
1585- // it. For example, if `ctor` is a `Constructor::Variant` for
1586- // `Option::Some`, we get the pattern `Some(_)`.
1587- missing_ctors. iter ( ) . map ( |ctor| ctor. apply_wildcards ( cx, pcx. ty ) ) . collect ( )
1588- } ;
1589- // Add the new patterns to each witness
1590- let new_witnesses = witnesses
1591- . into_iter ( )
1592- . flat_map ( |witness| {
1593- new_patterns. iter ( ) . map ( move |pat| {
1594- let mut witness = witness. clone ( ) ;
1595- witness. 0 . push ( pat. clone ( ) ) ;
1596- witness
1597- } )
1598- } )
1599- . collect ( ) ;
1600- UsefulWithWitness ( new_witnesses)
1601- }
1602- result => result,
1597+ let usefulness = is_useful ( cx, & matrix, & v, witness_preference, hir_id) ;
1598+
1599+ // In this case, there's at least one "free"
1600+ // constructor that is only matched against by
1601+ // wildcard patterns.
1602+ //
1603+ // There are 2 ways we can report a witness here.
1604+ // Commonly, we can report all the "free"
1605+ // constructors as witnesses, e.g., if we have:
1606+ //
1607+ // ```
1608+ // enum Direction { N, S, E, W }
1609+ // let Direction::N = ...;
1610+ // ```
1611+ //
1612+ // we can report 3 witnesses: `S`, `E`, and `W`.
1613+ //
1614+ // However, there are 2 cases where we don't want
1615+ // to do this and instead report a single `_` witness:
1616+ //
1617+ // 1) If the user is matching against a non-exhaustive
1618+ // enum, there is no point in enumerating all possible
1619+ // variants, because the user can't actually match
1620+ // against them themselves, e.g., in an example like:
1621+ // ```
1622+ // let err: io::ErrorKind = ...;
1623+ // match err {
1624+ // io::ErrorKind::NotFound => {},
1625+ // }
1626+ // ```
1627+ // we don't want to show every possible IO error,
1628+ // but instead have `_` as the witness (this is
1629+ // actually *required* if the user specified *all*
1630+ // IO errors, but is probably what we want in every
1631+ // case).
1632+ //
1633+ // 2) If the user didn't actually specify a constructor
1634+ // in this arm, e.g., in
1635+ // ```
1636+ // let x: (Direction, Direction, bool) = ...;
1637+ // let (_, _, false) = x;
1638+ // ```
1639+ // we don't want to show all 16 possible witnesses
1640+ // `(<direction-1>, <direction-2>, true)` - we are
1641+ // satisfied with `(_, _, true)`. In this case,
1642+ // `used_ctors` is empty.
1643+ if is_non_exhaustive || missing_ctors. all_ctors_are_missing ( ) {
1644+ // All constructors are unused. Add a wild pattern
1645+ // rather than each individual constructor.
1646+ usefulness. apply_wildcard ( pcx. ty )
1647+ } else {
1648+ // Construct for each missing constructor a "wild" version of this
1649+ // constructor, that matches everything that can be built with
1650+ // it. For example, if `ctor` is a `Constructor::Variant` for
1651+ // `Option::Some`, we get the pattern `Some(_)`.
1652+ usefulness. apply_missing_ctors ( cx, pcx. ty , & missing_ctors)
16031653 }
16041654 }
16051655 }
@@ -1621,18 +1671,10 @@ fn is_useful_specialized<'p, 'a, 'tcx>(
16211671 let ctor_wild_subpatterns_owned: Vec < _ > = ctor. wildcard_subpatterns ( cx, lty) . collect ( ) ;
16221672 let ctor_wild_subpatterns: Vec < _ > = ctor_wild_subpatterns_owned. iter ( ) . collect ( ) ;
16231673 let matrix = matrix. specialize_constructor ( cx, & ctor, & ctor_wild_subpatterns) ;
1624- match v. specialize_constructor ( cx, & ctor, & ctor_wild_subpatterns) {
1625- Some ( v) => match is_useful ( cx, & matrix, & v, witness_preference, hir_id) {
1626- UsefulWithWitness ( witnesses) => UsefulWithWitness (
1627- witnesses
1628- . into_iter ( )
1629- . map ( |witness| witness. apply_constructor ( cx, & ctor, lty) )
1630- . collect ( ) ,
1631- ) ,
1632- result => result,
1633- } ,
1634- None => NotUseful ,
1635- }
1674+ v. specialize_constructor ( cx, & ctor, & ctor_wild_subpatterns)
1675+ . map ( |v| is_useful ( cx, & matrix, & v, witness_preference, hir_id) )
1676+ . map ( |u| u. apply_constructor ( cx, & ctor, lty) )
1677+ . unwrap_or ( NotUseful )
16361678}
16371679
16381680/// Determines the constructors that the given pattern can be specialized to.
0 commit comments