Rust: Hint on missing tuple parens in pattern

Created on 27 Aug 2019  路  9Comments  路  Source: rust-lang/rust

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.


A-diagnostics A-suggestion-diagnostics C-enhancement E-help-wanted E-medium E-mentor T-compiler

Most helpful comment

cc @estebank

Ostensibly it is still relevant as we could emit a specific suggestion in this case.

All 9 comments

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:

https://github.com/rust-lang/rust/blob/53df91a9b24ad999e7ca896447af6f5f74fe43bc/src/librustc_typeck/check/pat.rs#L678-L688

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.

Was this page helpful?
0 / 5 - 0 ratings