@@ -792,12 +792,82 @@ pub enum Usefulness<'tcx> {
792
792
}
793
793
794
794
impl < ' 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
+
795
802
fn is_useful ( & self ) -> bool {
796
803
match * self {
797
804
NotUseful => false ,
798
805
_ => true ,
799
806
}
800
807
}
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
+ }
801
871
}
802
872
803
873
#[ derive( Copy , Clone , Debug ) ]
@@ -1399,10 +1469,7 @@ pub fn is_useful<'p, 'a, 'tcx>(
1399
1469
// the type of the tuple we're checking is inhabited or not.
1400
1470
if v. is_empty ( ) {
1401
1471
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)
1406
1473
} else {
1407
1474
NotUseful
1408
1475
} ;
@@ -1527,79 +1594,62 @@ pub fn is_useful<'p, 'a, 'tcx>(
1527
1594
} else {
1528
1595
let matrix = matrix. specialize_wildcard ( ) ;
1529
1596
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)
1603
1653
}
1604
1654
}
1605
1655
}
@@ -1621,18 +1671,10 @@ fn is_useful_specialized<'p, 'a, 'tcx>(
1621
1671
let ctor_wild_subpatterns_owned: Vec < _ > = ctor. wildcard_subpatterns ( cx, lty) . collect ( ) ;
1622
1672
let ctor_wild_subpatterns: Vec < _ > = ctor_wild_subpatterns_owned. iter ( ) . collect ( ) ;
1623
1673
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 )
1636
1678
}
1637
1679
1638
1680
/// Determines the constructors that the given pattern can be specialized to.
0 commit comments