Skip to content

match #34

@nrc

Description

@nrc

basics

match $discr {
    $arm1
    $arm2
    ...
}

Spaces and newlines as shown. In particular, prefer not to line-break the discriminant if possible; each match arm must have its own line; arms are block indented.

simple arms

Short arm:

$pat if $expr => $expr,

Prefer the above form if the arm fits on one line.

Avoid single line blocks:

$pat if $expr => { $expr }   // No

The last match arm should have a comma if the body is not a block:

match $expr {
    $expr => foo,
    $expr => bar,
}

Block body:

$pat if $expr => {
    ...
}

Note no comma if using a block, prefer not to line-break pattern or if clause, block indentation of arm body.

Empty blocks:

$pat if $expr => {}

Note {} not (), no comma, no space in the block.

Question - multi-line single expressions

Should a block be required?

E.g.,

match foo {
    bar => 42,
    baz => a_very_long_expr(dsfsdfsdfa,
                            dsafdfa,
                            dsfsfdsfdsfsd),
}

// vs

match foo {
    bar => 42,
    baz => {
        a_very_long_expr(dsfsdfsdfa,
                         dsafdfa,
                         dsfsfdsfdsfsd)
    }
}

Rustfmt currently does the latter, I found that it sometimes makes it easier to read, helps prevent rightward drift, and gets around the slightly unfortunate issue of expressions with blocks needing a comma:

match foo {
    bar => 42,
    baz => if qux {
        ...
    },  // comma needed here :-(
}

I'm no longer 100% convinced this is worth the extra vertical space however. We might want to leave this question unanswered for a while since the benefit in preventing rightward drift would not be so important if we pick a style which other wise prevents it (e.g., by using two space indent, or using more block indentation):

match foo {
  bar => 42,
  baz => a_very_long_expr(dsfsdfsdfa,
    dsafdfa,
    dsfsfdsfdsfsd),
}

Breaking the arm

Prefer breaking before the body:

$pat =>
    $expr,

or

$pat => {
    ...
}

Then prefer breaking before the if (if present, see below).

Then prefer breaking the pattern at |s (if there are multiple sub-patterns, see below). If breaking the pattern, the rest of the arm should only be broken as necessary. E.g., the following are ok:

pat1 |
pat2 |
pat3 if $expr => {
    ...
}
pat1 |
pat2 |
pat3 => $expr,
pat1 |
pat2 |
pat3 if $expr => $expr,

Finally, break each pattern if necessary.

Breaking before if

If necessary to break before the if, it should be block indented, a block is required for the arm body, and the { of the block should be on a newline. This helps prevent the if clause be distinguished from the arm body. Never break after the if:

$pat
    if $expr =>
{
    ...
}

If $expr does not fit on one line, break it according to the rules for expressions.

large patterns

If using a compound pattern (pat1 | pat2), prefer to put the whole pattern on one line. If it does not fit, put each sub-pattern on a new line, with the line terminated by |:

pat1 |
pat2 |
pat3 => {
    ...
}

If any sub-pattern does not on the line, break it according to the rules for patterns.

Question - blank lines between arms

These are sometimes useful for indicating groups of arms, I propose Rustfmt leaves single blank lines where the user writes them and coalesces multiple blank lines into one. E.g.,

match $expr {
    $expr => foo,

    $expr => bar,
}

Question - consistency between arms

Should we allow a mix of block arms and single expression arms? Or should we use blocks for every arm if any arm requires it? The second alternative is more consistent, but wastes some space. It also looks odd in the relatively common case where there is a single large arm and many small arms.

Question - exhaustiveness

Should we offer any guidance about using _ in match arms? I feel there are strong idioms for using this or not depending on desired backwards compatibility. However, it may be beyond the remit of the style guide/process.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions