-
Notifications
You must be signed in to change notification settings - Fork 55
Description
Feature tracking issue: rust-lang/rust#53667
Should we introduce a new guideline for wrapping let-chains?
The rationale is that let-chains allow let bindings to be anywhere in a line of code. let is no longer consitently at the left side. It is good for let bindings to stand out and be easy to discover since they introduce new variables for the following scope. Oftentimes when reading code, I look backwards with the question "where did this variable come from?"
Possible answers
-
No change. Wrap
letexpressions the same as any other expression. -
Always wrap
letexpressions.letis only ever preceded by one token in the same line:if,while,&&,||, etc. -
Wrap
letexpressions if they begin N characters or more past the current indentation.For example, a
let-expression may be on the same line if it is 15 characters from the left margin. If it is 16 characters from the left margin, it must break to the next line. -
Wrap
letexpressions if there are 2 (?) or moreletexpressions in the condition -
Allow
single_identifier && leton one line (if it fits line length limits), but require a line break before the&&for any other expression. Always wrap after a let expression.
Potential concerns for each answer
- The introduction of
xmay be hard to find in this case:if my_long_condition(foo, bar, baz) && some_more && let Some(x) = foo() { // lots of code... use_x(x);
- Wrapping for this case seems a little unnecessary since it only shifts
letleftward by one character:if a && let Some(b) = foo() {
- Added complexity to formatting logic. Difficult to follow/verify the guideline without automated tooling. The subtlety of the logic may be surprising to users.
- This case is suboptimal (similar to 1):
if my_function(Some(get_thing()), variable, and_another) && let Some(x) = foo() {
Other considerations
The rules for if and while will be the same.
If a let expression wraps, it will cause all of the && or ||-separated expressions to be on separate lines.
if something
&& let Some(x) = foo() && something_else { // bad - `&& something_else` should be on its own lineIf there is just one let binding at the beginning, the condition may be on one line:
if let Some(foo) = do_something() && another_condition {