Rollup merge of #145234 - dianne:1-tuple-witnesses, r=jackh726

match exhaustiveness diagnostics: show a trailing comma on singleton tuple consructors in witness patterns (and clean up a little)

Constructor patterns of type `(T,)` are written `(pat,)`, not `(pat)`. However, exhaustiveness/usefulness diagnostics would print them as `(pat)` when e.g. providing a witness of non-exhaustiveness and suggesting adding arms to make matches exhaustive; this would result in an error when applied.
rust-analyzer already prints the trailing comma, so it doesn't need changing.

This also includes some cleanup in the second commit, with justification in the commit message.
This commit is contained in:
Samuel Tardieu 2025-08-23 22:22:15 +02:00 committed by GitHub
commit 5a14685a63
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 13 additions and 25 deletions

View file

@ -101,23 +101,11 @@ pub(crate) fn write_struct_like<'tcx>(
let num_fields = variant_and_name.as_ref().map_or(subpatterns.len(), |(v, _)| v.fields.len());
if num_fields != 0 || variant_and_name.is_none() {
write!(f, "(")?;
for i in 0..num_fields {
write!(f, "{}", start_or_comma())?;
// Common case: the field is where we expect it.
if let Some(p) = subpatterns.get(i) {
if p.field.index() == i {
write!(f, "{}", p.pattern)?;
continue;
}
}
// Otherwise, we have to go looking for it.
if let Some(p) = subpatterns.iter().find(|p| p.field.index() == i) {
write!(f, "{}", p.pattern)?;
} else {
write!(f, "_")?;
}
for FieldPat { pattern, .. } in subpatterns {
write!(f, "{}{pattern}", start_or_comma())?;
}
if matches!(ty.kind(), ty::Tuple(..)) && num_fields == 1 {
write!(f, ",")?;
}
write!(f, ")")?;
}

View file

@ -7,11 +7,11 @@ fn main() {
(0 | 1, 2 | 3) => {}
}
match ((0u8,),) {
//~^ ERROR non-exhaustive patterns: `((4_u8..=u8::MAX))`
//~^ ERROR non-exhaustive patterns: `((4_u8..=u8::MAX,),)`
((0 | 1,) | (2 | 3,),) => {}
}
match (Some(0u8),) {
//~^ ERROR non-exhaustive patterns: `(Some(2_u8..=u8::MAX))`
//~^ ERROR non-exhaustive patterns: `(Some(2_u8..=u8::MAX),)`
(None | Some(0 | 1),) => {}
}
}

View file

@ -11,30 +11,30 @@ LL ~ (0 | 1, 2 | 3) => {},
LL + (2_u8..=u8::MAX, _) => todo!()
|
error[E0004]: non-exhaustive patterns: `((4_u8..=u8::MAX))` not covered
error[E0004]: non-exhaustive patterns: `((4_u8..=u8::MAX,),)` not covered
--> $DIR/exhaustiveness-non-exhaustive.rs:9:11
|
LL | match ((0u8,),) {
| ^^^^^^^^^ pattern `((4_u8..=u8::MAX))` not covered
| ^^^^^^^^^ pattern `((4_u8..=u8::MAX,),)` not covered
|
= note: the matched value is of type `((u8,),)`
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
|
LL ~ ((0 | 1,) | (2 | 3,),) => {},
LL + ((4_u8..=u8::MAX)) => todo!()
LL + ((4_u8..=u8::MAX,),) => todo!()
|
error[E0004]: non-exhaustive patterns: `(Some(2_u8..=u8::MAX))` not covered
error[E0004]: non-exhaustive patterns: `(Some(2_u8..=u8::MAX),)` not covered
--> $DIR/exhaustiveness-non-exhaustive.rs:13:11
|
LL | match (Some(0u8),) {
| ^^^^^^^^^^^^ pattern `(Some(2_u8..=u8::MAX))` not covered
| ^^^^^^^^^^^^ pattern `(Some(2_u8..=u8::MAX),)` not covered
|
= note: the matched value is of type `(Option<u8>,)`
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
|
LL ~ (None | Some(0 | 1),) => {},
LL + (Some(2_u8..=u8::MAX)) => todo!()
LL + (Some(2_u8..=u8::MAX),) => todo!()
|
error: aborting due to 3 previous errors