Skip to content

Commit b7080a1

Browse files
doc(style): add let-chain rules
1 parent 175dcc7 commit b7080a1

File tree

1 file changed

+72
-6
lines changed

1 file changed

+72
-6
lines changed

Diff for: src/doc/style-guide/src/expressions.md

+72-6
Original file line numberDiff line numberDiff line change
@@ -521,8 +521,11 @@ self.pre_comment.as_ref().map_or(
521521

522522
## Control flow expressions
523523

524-
This section covers `if`, `if let`, `loop`, `while`, `while let`, and `for`
525-
expressions.
524+
This section covers `for` and `loop` expressions, as well as `if` and `while`
525+
expressions with their sub-expression variants. This includes those with a
526+
single `let` sub-expression (i.e. `if let` and `while let`)
527+
as well as "let-chains": those with one or more `let` sub-expressions and
528+
one or more bool-type conditions (i.e. `if a && let Some(b) = c`).
526529

527530
Put the keyword, any initial clauses, and the opening brace of the block all on
528531
a single line, if they fit. Apply the usual rules for [block
@@ -548,10 +551,11 @@ if let ... {
548551
}
549552
```
550553

551-
If the control line needs to be broken, prefer to break before the `=` in `*
552-
let` expressions and before `in` in a `for` expression; block-indent the
553-
following line. If the control line is broken for any reason, put the opening
554-
brace on its own line, not indented. Examples:
554+
If the control line needs to be broken, then prefer breaking before the `=` for any
555+
`let` sub-expression in an `if` or `while` expression that does not fit,
556+
and before `in` in a `for` expression; the following line should be block indented.
557+
If the control line is broken for any reason, then the opening brace should be on its
558+
own line and not indented. Examples:
555559

556560
```rust
557561
while let Some(foo)
@@ -572,6 +576,68 @@ if a_long_expression
572576
{
573577
...
574578
}
579+
580+
if let Some(a) = b
581+
&& another_long_expression
582+
&& a_third_long_expression
583+
{
584+
// ...
585+
}
586+
587+
if let Some(relatively_long_thing)
588+
= a_long_expression
589+
&& another_long_expression
590+
&& a_third_long_expression
591+
{
592+
// ...
593+
}
594+
595+
if some_expr
596+
&& another_long_expression
597+
&& let Some(relatively_long_thing) =
598+
a_long_long_long_long_long_long_really_reallllllllllyyyyyyy_long_expression
599+
&& a_third_long_expression
600+
{
601+
// ...
602+
}
603+
```
604+
605+
A let-chain control line is allowed to be formatted on a single line provided
606+
it only consists of two clauses, with the first, left-hand side operand being a literal or an
607+
`ident` (which can optionally be preceded by any number of unary prefix operators),
608+
and the second, right-hand side operand being a single-line `let` clause. Otherwise,
609+
the control line must be broken and formatted according to the above rules. For example:
610+
611+
```rust
612+
if a && let Some(b) = foo() {
613+
// ...
614+
}
615+
616+
if true && let Some(b) = foo() {
617+
// ...
618+
}
619+
620+
let operator = if !from_hir_call && let Some(p) = parent {
621+
// ...
622+
};
623+
624+
if let Some(b) = foo()
625+
&& a
626+
{
627+
// ..
628+
}
629+
630+
if foo()
631+
&& let Some(b) = bar
632+
{
633+
// ...
634+
}
635+
636+
if gen_pos != GenericArgPosition::Type
637+
&& let Some(b) = gen_args.bindings.first()
638+
{
639+
// ..
640+
}
575641
```
576642

577643
Where the initial clause spans multiple lines and ends with one or more closing

0 commit comments

Comments
 (0)