@@ -1042,7 +1042,7 @@ struct MatrixRow<'p, Cx: PatCx> {
10421042 is_under_guard : bool ,
10431043 /// When we specialize, we remember which row of the original matrix produced a given row of the
10441044 /// 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.
10461046 parent_row : usize ,
10471047 /// False when the matrix is just built. This is set to `true` by
10481048 /// [`compute_exhaustiveness_and_usefulness`] if the arm is found to be useful.
@@ -1163,10 +1163,10 @@ impl<'p, Cx: PatCx> Matrix<'p, Cx> {
11631163 place_info : smallvec ! [ place_info] ,
11641164 wildcard_row_is_relevant : true ,
11651165 } ;
1166- for ( row_id , arm) in arms. iter ( ) . enumerate ( ) {
1166+ for ( arm_id , arm) in arms. iter ( ) . enumerate ( ) {
11671167 let v = MatrixRow {
11681168 pats : PatStack :: from_pattern ( arm. pat ) ,
1169- parent_row : row_id , // dummy, we don't read it
1169+ parent_row : arm_id ,
11701170 is_under_guard : arm. has_guard ,
11711171 useful : false ,
11721172 intersects : BitSet :: new_empty ( 0 ) , // Initialized in `Matrix::expand_and_push`.
@@ -1738,6 +1738,9 @@ pub struct UsefulnessReport<'p, Cx: PatCx> {
17381738 /// If the match is exhaustive, this is empty. If not, this contains witnesses for the lack of
17391739 /// exhaustiveness.
17401740 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 > > ,
17411744}
17421745
17431746/// 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>(
17691772 } )
17701773 . collect ( ) ;
17711774
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 } )
17731790}
0 commit comments