Code change:
The match remains exhaustive with highlighted pattern removed, but it does not produce any warnings: <!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOTEND --
I know where the problem comes from: this bit of code tries to handle unreachable sub-or-patterns diagnostics, but it's a bit of a hack. What remains is to come up with a better solution. claim

Related discussion:
text: //     (false | true, false | true) => {} // } // ``` <del> let mut unreachable_subpats = FxHashSet::default(); // Whether any branch at all is useful. </del> <ins> // If however the sub-branches come from the current column, they come from the inside of // the current or-pattern, and we want to keep them all. Eg. in the following, we _do_ want // to lint that the last `false` is unreachable. // ``` // match None { //     Some(false) => {} //     None | Some(true | false) => {} // } // ``` let mut matrix = matrix.clone(); // We keep track of sub-branches separately depending on whether they come from this column // or from others. let mut unreachables_this_column: FxHashSet<Span> = FxHashSet::default(); let mut unreachables_other_columns: Vec<FxHashSet<Span>> = Vec::default(); // Whether at least one branch is reachable. </ins> let mut any_is_useful = false; for v in vs { let res = is_useful(cx, &matrix, &v, witness_preference, hir_id, is_under_guard, false); match res { <del> Useful(pats) => { if !any_is_useful { any_is_useful = true; // Initialize with the first set of unreachable subpatterns encountered. unreachable_subpats = pats.into_iter().collect(); } else { // Keep the patterns unreachable from both this and previous branches. unreachable_subpats = pats.into_iter().filter(|p| unreachable_subpats.contains(p)).collect(); </del> <ins> Useful(unreachables) => { if let Some((this_column, other_columns)) = unreachables.split_last() { // We keep the union of unreachables found in the first column. unreachables_this_column.extend(this_column); // We keep the intersection of unreachables found in other columns. if unreachables_other_columns.is_empty() { unreachables_other_columns = other_columns.to_vec(); } else { unreachables_other_columns = unreachables_other_columns .into_iter() .zip(other_columns) .map(|(x, y)| x.intersection(&y).copied().collect()) .collect(); } </ins> } <ins> any_is_useful = true; </ins> } <del> NotUseful => unreachable_branches.push(v.head().span), UsefulWithWitness(_) => { bug!("Encountered or-pat in `v` during exhaustiveness checking") </del> <ins> NotUseful => { unreachables_this_column.insert(v.head().span); </ins> } <ins> UsefulWithWitness(_) => bug!( "encountered or-pat in the expansion of `_` during exhaustiveness checking" ), </ins> } <del> // If pattern has a guard don't add it to the matrix </del> <ins> // If pattern has a guard don't add it to the matrix. </ins> if !is_under_guard { <ins> // We push the already-seen patterns into the matrix in order to detect redundant // branches like `Some(_) | Some(0)`. </ins> matrix.push(v); } } <del> if any_is_useful { // Collect all the unreachable patterns. unreachable_branches.extend(unreachable_subpats); return Useful(unreachable_branches); </del> <ins> return if any_is_useful { let mut unreachables = if unreachables_other_columns.is_empty() { let n_columns = v.len(); (0..n_columns - 1).map(|_| FxHashSet::default()).collect() } else { unreachables_other_columns }; unreachables.push(unreachables_this_column); Useful(unreachables) </ins> } else { <del> return NotUseful; } </del> <ins> NotUseful }; </ins> } // FIXME(Nadrieril): Hack to work around type normalization issues (see #72476).