@@ -1105,14 +1105,20 @@ impl<'p, Cx: PatCx> fmt::Debug for PatStack<'p, Cx> {
11051105/// A row of the matrix.
11061106#[ derive( Clone ) ]
11071107struct MatrixRow < ' p , Cx : PatCx > {
1108- // The patterns in the row.
1108+ /// The patterns in the row.
11091109 pats : PatStack < ' p , Cx > ,
1110+ /// A (sub)pattern this row comes from. When expanding or-patterns, this tracks the last
1111+ /// alternative expanded, e.g. in `(0|1, 2|3)` we'd keep `3` for the last row. Used only for
1112+ /// diagnostics.
1113+ origin : & ' p DeconstructedPat < Cx > ,
11101114 /// Whether the original arm had a guard. This is inherited when specializing.
11111115 is_under_guard : bool ,
11121116 /// When we specialize, we remember which row of the original matrix produced a given row of the
11131117 /// specialized matrix. When we unspecialize, we use this to propagate usefulness back up the
11141118 /// callstack. On creation, this stores the index of the original match arm.
11151119 parent_row : usize ,
1120+ /// Remember the match arm this came from.
1121+ arm_id : usize ,
11161122 /// False when the matrix is just built. This is set to `true` by
11171123 /// [`compute_exhaustiveness_and_usefulness`] if the arm is found to be useful.
11181124 /// This is reset to `false` when specializing.
@@ -1142,7 +1148,9 @@ impl<'p, Cx: PatCx> MatrixRow<'p, Cx> {
11421148 fn new ( arm : & MatchArm < ' p , Cx > , arm_id : usize ) -> Self {
11431149 MatrixRow {
11441150 pats : PatStack :: from_pattern ( arm. pat ) ,
1151+ origin : arm. pat ,
11451152 parent_row : arm_id,
1153+ arm_id,
11461154 is_under_guard : arm. has_guard ,
11471155 useful : false ,
11481156 intersects_at_least : DenseBitSet :: new_empty ( 0 ) , // Initialized in `Matrix::push`.
@@ -1167,8 +1175,10 @@ impl<'p, Cx: PatCx> MatrixRow<'p, Cx> {
11671175 fn expand_or_pat ( & self , parent_row : usize ) -> impl Iterator < Item = MatrixRow < ' p , Cx > > {
11681176 let is_or_pat = self . pats . head ( ) . is_or_pat ( ) ;
11691177 self . pats . expand_or_pat ( ) . map ( move |patstack| MatrixRow {
1178+ origin : if is_or_pat { patstack. head ( ) . as_pat ( ) . unwrap ( ) } else { self . origin } ,
11701179 pats : patstack,
11711180 parent_row,
1181+ arm_id : self . arm_id ,
11721182 is_under_guard : self . is_under_guard ,
11731183 useful : false ,
11741184 intersects_at_least : DenseBitSet :: new_empty ( 0 ) , // Initialized in `Matrix::push`.
@@ -1188,7 +1198,9 @@ impl<'p, Cx: PatCx> MatrixRow<'p, Cx> {
11881198 ) -> Result < MatrixRow < ' p , Cx > , Cx :: Error > {
11891199 Ok ( MatrixRow {
11901200 pats : self . pats . pop_head_constructor ( cx, ctor, ctor_arity, ctor_is_relevant) ?,
1201+ origin : self . origin ,
11911202 parent_row,
1203+ arm_id : self . arm_id ,
11921204 is_under_guard : self . is_under_guard ,
11931205 useful : false ,
11941206 intersects_at_least : DenseBitSet :: new_empty ( 0 ) , // Initialized in `Matrix::push`.
@@ -1724,6 +1736,11 @@ fn compute_exhaustiveness_and_usefulness<'a, 'p, Cx: PatCx>(
17241736 // The next rows stays useful if this one is under a guard.
17251737 useful &= row. is_under_guard ;
17261738 }
1739+ for ( row1, row2) in matrix. rows ( ) . zip ( matrix. rows ( ) . skip ( 1 ) ) {
1740+ if row1. arm_id == row2. arm_id && row1. is_under_guard {
1741+ mcx. tycx . lint_overlapping_alternatives_under_guard ( row1. origin , row2. origin ) ;
1742+ }
1743+ }
17271744 return if useful && matrix. wildcard_row_is_relevant {
17281745 // The wildcard row is useful; the match is non-exhaustive.
17291746 Ok ( WitnessMatrix :: unit_witness ( ) )
0 commit comments