It'd be nice to smartly hint about missing tuple parentheses in patterns, especially in positions where parentheses nesting is required.
Example of incorrect code:
fn main() {
match Some((1, 2)) {
Some(x, y) => {}
None => {}
}
}
The error:
error[E0023]: this pattern has 2 fields, but the corresponding tuple variant has 1 field
--> src/main.rs:3:9
|
3 | Some(x, y) => {}
| ^^^^^^^^^^ expected 1 field, found 2
This error is confusing, especially since Some is a "tuple pattern" which is confusable with its tuple field. An error that suggests missing tuple parentheses would be helpful.
This issue has been assigned to @sam09 via this comment.
I think the right approach here would be to check if the scrutinee type (expected type in this context) has a single field of a tuple type with as many fields as the tuple struct pattern has.
Place to change:
If you tackle this, first please also refactor the snippet highlighted above into a diagnostics-only method and then do your changes in there.
Can I pick up this one? Doesn't look like anybody working on this.
@sam09 Please do.
@rustbot assign @sam09
I think the right approach here would be to check if the scrutinee type (expected type in this context) has a single field of a tuple type with as many fields as the tuple struct pattern has.
variant.fields.len() gives me the number of fields of expected type, which should be 1 here. I have a condition, varaints.fields.len()==1. However I can't see how many fields varaints.field[0] has, when trying to compare to the fields the tuple struct pattern has (subpats.len() in this case)
Maybe I misunderstood it, or am missing something here
This https://github.com/rust-lang/rust/pull/64161 seems to have changed some things here. Is this issue still relevant?
cc @estebank
Ostensibly it is still relevant as we could emit a specific suggestion in this case.
Yes, that PR only adds a bit of context that should generally be useful, but this is about adding a structured suggestion for this case in particular. This is more focused and more useful for this case in particular :)
Looking forward to it!
Thanks @Centril @estebank. I have one more question though,
https://github.com/rust-lang/rust/blob/24d0a01b75c034d52bdca10cca08e69538e871ca/src/librustc_typeck/check/pat.rs#L686-L709
This fields parameter in the above function gives the number of fields of expected type, while subpats gives me the number of fields in the tuple pattern.
The condition to show a missing parenthesis message should be something like:
if fields.len() == 1 && subpats.len() == fields[0].len() {
parentheses_missing = true;
}
But fields[0] is not a vector and I cannot seem to figure out how to find the number of elements in the expected type
But fields[0] is not a vector and I cannot seem to figure out how to find the number of elements in the expected type
You'll need to look at expected: Ty<'tcx> to see that it resolves to an TyKind::Adt(adt_def, substs) and then you'll need to match up the variant with the right one in the AdtDef. Once you have the right variant, you'll need to check that it has one field and extract it. You'll need to check that the single field is also a tuple and match the length of that tuple up with subpats.len(). You'll also need to handle the possibility that the enum is generic, e.g. as in the case of Option<T> and use substs to account for this.
Most helpful comment
cc @estebank
Ostensibly it is still relevant as we could emit a specific suggestion in this case.