@@ -1042,7 +1042,7 @@ struct MatrixRow<'p, Cx: PatCx> {
1042
1042
is_under_guard : bool ,
1043
1043
/// When we specialize, we remember which row of the original matrix produced a given row of the
1044
1044
/// specialized matrix. When we unspecialize, we use this to propagate usefulness back up the
1045
- /// callstack.
1045
+ /// callstack. On creation, this stores the index of the original match arm.
1046
1046
parent_row : usize ,
1047
1047
/// False when the matrix is just built. This is set to `true` by
1048
1048
/// [`compute_exhaustiveness_and_usefulness`] if the arm is found to be useful.
@@ -1163,10 +1163,10 @@ impl<'p, Cx: PatCx> Matrix<'p, Cx> {
1163
1163
place_info : smallvec ! [ place_info] ,
1164
1164
wildcard_row_is_relevant : true ,
1165
1165
} ;
1166
- for ( row_id , arm) in arms. iter ( ) . enumerate ( ) {
1166
+ for ( arm_id , arm) in arms. iter ( ) . enumerate ( ) {
1167
1167
let v = MatrixRow {
1168
1168
pats : PatStack :: from_pattern ( arm. pat ) ,
1169
- parent_row : row_id , // dummy, we don't read it
1169
+ parent_row : arm_id ,
1170
1170
is_under_guard : arm. has_guard ,
1171
1171
useful : false ,
1172
1172
intersects : BitSet :: new_empty ( 0 ) , // Initialized in `Matrix::expand_and_push`.
@@ -1738,6 +1738,9 @@ pub struct UsefulnessReport<'p, Cx: PatCx> {
1738
1738
/// If the match is exhaustive, this is empty. If not, this contains witnesses for the lack of
1739
1739
/// exhaustiveness.
1740
1740
pub non_exhaustiveness_witnesses : Vec < WitnessPat < Cx > > ,
1741
+ /// For each arm, a set of indices of arms above it that have non-empty intersection, i.e. there
1742
+ /// is a value matched by both arms. This may miss real intersections.
1743
+ pub arm_intersections : Vec < BitSet < usize > > ,
1741
1744
}
1742
1745
1743
1746
/// Computes whether a match is exhaustive and which of its arms are useful.
@@ -1769,5 +1772,19 @@ pub fn compute_match_usefulness<'p, Cx: PatCx>(
1769
1772
} )
1770
1773
. collect ( ) ;
1771
1774
1772
- Ok ( UsefulnessReport { arm_usefulness, non_exhaustiveness_witnesses } )
1775
+ let mut arm_intersections: Vec < _ > =
1776
+ arms. iter ( ) . enumerate ( ) . map ( |( i, _) | BitSet :: new_empty ( i) ) . collect ( ) ;
1777
+ for row in matrix. rows ( ) {
1778
+ let arm_id = row. parent_row ;
1779
+ for intersection in row. intersects . iter ( ) {
1780
+ // Convert the matrix row ids into arm ids (they can differ because we expand or-patterns).
1781
+ let arm_intersection = matrix. rows [ intersection] . parent_row ;
1782
+ // Note: self-intersection can happen with or-patterns.
1783
+ if arm_intersection != arm_id {
1784
+ arm_intersections[ arm_id] . insert ( arm_intersection) ;
1785
+ }
1786
+ }
1787
+ }
1788
+
1789
+ Ok ( UsefulnessReport { arm_usefulness, non_exhaustiveness_witnesses, arm_intersections } )
1773
1790
}
0 commit comments