@@ -1105,14 +1105,20 @@ impl<'p, Cx: PatCx> fmt::Debug for PatStack<'p, Cx> {
1105
1105
/// A row of the matrix.
1106
1106
#[ derive( Clone ) ]
1107
1107
struct MatrixRow < ' p , Cx : PatCx > {
1108
- // The patterns in the row.
1108
+ /// The patterns in the row.
1109
1109
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 > ,
1110
1114
/// Whether the original arm had a guard. This is inherited when specializing.
1111
1115
is_under_guard : bool ,
1112
1116
/// When we specialize, we remember which row of the original matrix produced a given row of the
1113
1117
/// specialized matrix. When we unspecialize, we use this to propagate usefulness back up the
1114
1118
/// callstack. On creation, this stores the index of the original match arm.
1115
1119
parent_row : usize ,
1120
+ /// Remember the match arm this came from.
1121
+ arm_id : usize ,
1116
1122
/// False when the matrix is just built. This is set to `true` by
1117
1123
/// [`compute_exhaustiveness_and_usefulness`] if the arm is found to be useful.
1118
1124
/// This is reset to `false` when specializing.
@@ -1142,7 +1148,9 @@ impl<'p, Cx: PatCx> MatrixRow<'p, Cx> {
1142
1148
fn new ( arm : & MatchArm < ' p , Cx > , arm_id : usize ) -> Self {
1143
1149
MatrixRow {
1144
1150
pats : PatStack :: from_pattern ( arm. pat ) ,
1151
+ origin : arm. pat ,
1145
1152
parent_row : arm_id,
1153
+ arm_id,
1146
1154
is_under_guard : arm. has_guard ,
1147
1155
useful : false ,
1148
1156
intersects_at_least : DenseBitSet :: new_empty ( 0 ) , // Initialized in `Matrix::push`.
@@ -1167,8 +1175,10 @@ impl<'p, Cx: PatCx> MatrixRow<'p, Cx> {
1167
1175
fn expand_or_pat ( & self , parent_row : usize ) -> impl Iterator < Item = MatrixRow < ' p , Cx > > {
1168
1176
let is_or_pat = self . pats . head ( ) . is_or_pat ( ) ;
1169
1177
self . pats . expand_or_pat ( ) . map ( move |patstack| MatrixRow {
1178
+ origin : if is_or_pat { patstack. head ( ) . as_pat ( ) . unwrap ( ) } else { self . origin } ,
1170
1179
pats : patstack,
1171
1180
parent_row,
1181
+ arm_id : self . arm_id ,
1172
1182
is_under_guard : self . is_under_guard ,
1173
1183
useful : false ,
1174
1184
intersects_at_least : DenseBitSet :: new_empty ( 0 ) , // Initialized in `Matrix::push`.
@@ -1188,7 +1198,9 @@ impl<'p, Cx: PatCx> MatrixRow<'p, Cx> {
1188
1198
) -> Result < MatrixRow < ' p , Cx > , Cx :: Error > {
1189
1199
Ok ( MatrixRow {
1190
1200
pats : self . pats . pop_head_constructor ( cx, ctor, ctor_arity, ctor_is_relevant) ?,
1201
+ origin : self . origin ,
1191
1202
parent_row,
1203
+ arm_id : self . arm_id ,
1192
1204
is_under_guard : self . is_under_guard ,
1193
1205
useful : false ,
1194
1206
intersects_at_least : DenseBitSet :: new_empty ( 0 ) , // Initialized in `Matrix::push`.
@@ -1724,6 +1736,11 @@ fn compute_exhaustiveness_and_usefulness<'a, 'p, Cx: PatCx>(
1724
1736
// The next rows stays useful if this one is under a guard.
1725
1737
useful &= row. is_under_guard ;
1726
1738
}
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
+ }
1727
1744
return if useful && matrix. wildcard_row_is_relevant {
1728
1745
// The wildcard row is useful; the match is non-exhaustive.
1729
1746
Ok ( WitnessMatrix :: unit_witness ( ) )
0 commit comments