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