@@ -1106,14 +1106,20 @@ impl<'p, Cx: PatCx> fmt::Debug for PatStack<'p, Cx> {
11061106/// A row of the matrix.
11071107#[ derive( Clone ) ]
11081108struct MatrixRow < ' p , Cx : PatCx > {
1109- // The patterns in the row.
1109+ /// The patterns in the row.
11101110 pats : PatStack < ' p , Cx > ,
1111+ /// A (sub)pattern this row comes from. When expanding or-patterns, this tracks the last
1112+ /// alternative expanded, e.g. in `(0|1, 2|3)` we'd keep `3` for the last row. Used only for
1113+ /// diagnostics.
1114+ origin : & ' p DeconstructedPat < Cx > ,
11111115 /// Whether the original arm had a guard. This is inherited when specializing.
11121116 is_under_guard : bool ,
11131117 /// When we specialize, we remember which row of the original matrix produced a given row of the
11141118 /// specialized matrix. When we unspecialize, we use this to propagate usefulness back up the
11151119 /// callstack. On creation, this stores the index of the original match arm.
11161120 parent_row : usize ,
1121+ /// Remember the match arm this came from.
1122+ arm_id : usize ,
11171123 /// False when the matrix is just built. This is set to `true` by
11181124 /// [`compute_exhaustiveness_and_usefulness`] if the arm is found to be useful.
11191125 /// This is reset to `false` when specializing.
@@ -1143,7 +1149,9 @@ impl<'p, Cx: PatCx> MatrixRow<'p, Cx> {
11431149 fn new ( arm : & MatchArm < ' p , Cx > , arm_id : usize ) -> Self {
11441150 MatrixRow {
11451151 pats : PatStack :: from_pattern ( arm. pat ) ,
1152+ origin : arm. pat ,
11461153 parent_row : arm_id,
1154+ arm_id,
11471155 is_under_guard : arm. has_guard ,
11481156 useful : false ,
11491157 intersects_at_least : DenseBitSet :: new_empty ( 0 ) , // Initialized in `Matrix::push`.
@@ -1168,8 +1176,10 @@ impl<'p, Cx: PatCx> MatrixRow<'p, Cx> {
11681176 fn expand_or_pat ( & self , parent_row : usize ) -> impl Iterator < Item = MatrixRow < ' p , Cx > > {
11691177 let is_or_pat = self . pats . head ( ) . is_or_pat ( ) ;
11701178 self . pats . expand_or_pat ( ) . map ( move |patstack| MatrixRow {
1179+ origin : if is_or_pat { patstack. head ( ) . as_pat ( ) . unwrap ( ) } else { self . origin } ,
11711180 pats : patstack,
11721181 parent_row,
1182+ arm_id : self . arm_id ,
11731183 is_under_guard : self . is_under_guard ,
11741184 useful : false ,
11751185 intersects_at_least : DenseBitSet :: new_empty ( 0 ) , // Initialized in `Matrix::push`.
@@ -1189,7 +1199,9 @@ impl<'p, Cx: PatCx> MatrixRow<'p, Cx> {
11891199 ) -> Result < MatrixRow < ' p , Cx > , Cx :: Error > {
11901200 Ok ( MatrixRow {
11911201 pats : self . pats . pop_head_constructor ( cx, ctor, ctor_arity, ctor_is_relevant) ?,
1202+ origin : self . origin ,
11921203 parent_row,
1204+ arm_id : self . arm_id ,
11931205 is_under_guard : self . is_under_guard ,
11941206 useful : false ,
11951207 intersects_at_least : DenseBitSet :: new_empty ( 0 ) , // Initialized in `Matrix::push`.
@@ -1725,6 +1737,11 @@ fn compute_exhaustiveness_and_usefulness<'a, 'p, Cx: PatCx>(
17251737 // The next rows stays useful if this one is under a guard.
17261738 useful &= row. is_under_guard ;
17271739 }
1740+ for ( row1, row2) in matrix. rows ( ) . zip ( matrix. rows ( ) . skip ( 1 ) ) {
1741+ if row1. arm_id == row2. arm_id && row1. is_under_guard {
1742+ mcx. tycx . lint_overlapping_alternatives_under_guard ( row1. origin , row2. origin ) ;
1743+ }
1744+ }
17281745 return if useful && matrix. wildcard_row_is_relevant {
17291746 // The wildcard row is useful; the match is non-exhaustive.
17301747 Ok ( WitnessMatrix :: unit_witness ( ) )
0 commit comments