Skip to content

Improve docs for single_line_if_else_max_width & add tests #5509

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
62 changes: 62 additions & 0 deletions Configurations.md
Original file line number Diff line number Diff line change
Expand Up @@ -2381,12 +2381,74 @@ Don't reformat out of line modules

Maximum line length for single line if-else expressions. A value of `0` (zero) results in if-else expressions always being broken into multiple lines. Note this occurs when `use_small_heuristics` is set to `Off`.

Common if-else expressions that may be formatted on a single line are:
* Expressions on the right hand side of an equals (`=`) sign. e.g. `let x = if y == 1 { 0 } else { 1 };`
* Conditional expression in function calls. e.g. `f(if x== 0 { 10 } else { 0 })`
* Single expression closures. e.g. `let x = |y| if y == 0 { 0 } else { 10 };`

In the following scenarios the if-else expression will be formatted over multiple lines.
* Empty if-else blocks.
* An outer if-else expression when if-else expression are nested.
* If-else blocks that contain statements (e.g. `let x = a;`), comments, or attributes (e.g. `let _ = if true { #[must_use] 1 } else { 2 };`).

When `version=One` is set (the default) an if-else expression at the end of a block is treated as a statement and is not formatted on a single line. When using `version=Two` the if-else expression may be formatted on a single line if it meets the criteria described above.

Comment on lines +2384 to +2395
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have some reservations about any attempts to reference, or perhaps to some readers, codify formatting behavior here. The Style Guide is what articulates the rules for the formatting behavior, and the exact prescriptions for when if-else can/can't be single lined can be found here.

This option exists as the mechanism to control the value used as the "small" threshold as described in the Guide, and I don't think we should have much more than that here.

Basically, the Config docs, and any particular option within them, isn't really the right place to try to explain the broader formatting rules for a given syntax construct

- **Default value**: `50`
- **Possible values**: any positive integer that is less than or equal to the value specified for [`max_width`](#max_width)
- **Stable**: Yes

By default this option is set as a percentage of [`max_width`](#max_width) provided by [`use_small_heuristics`](#use_small_heuristics), but a value set directly for `single_line_if_else_max_width` will take precedence.

#### `50` (default):

```rust
fn foo() -> usize {
fun(if some_long_name && some_other_long_name {
0
} else {
10
});

closure(|super_long_closure_variable| {
if super_long_closure_variable == 0 {
0
} else {
10
}
});

let bar = if some_long_name && some_other_long_name {
baz()
} else {
buzz()
};

if some_long_name && some_other_long_name {
1
} else {
2
}
}
```

#### `70`:

```rust
fn foo() -> usize {
fun(if some_long_name && some_other_long_name { 0 } else { 10 });

closure(|super_long_closure_variable| if super_long_closure_variable == 0 { 0 } else { 10 });

let bar = if some_long_name && some_other_long_name { baz() } else { buzz() };

if some_long_name && some_other_long_name {
1
} else {
2
}
}
```

See also [`max_width`](#max_width) and [`use_small_heuristics`](#use_small_heuristics)

## `space_after_colon`
Expand Down
8 changes: 8 additions & 0 deletions tests/source/issue-5496/70.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// rustfmt-version: One
// rustfmt-single_line_if_else_max_width: 70
fn foo() -> usize {
let some_long_name = true;
let some_other_long_name = false;
let bar = if some_long_name && some_other_long_name { baz() } else { buzz() };
if some_long_name && some_other_long_name { 1 } else { 2 }
}
12 changes: 12 additions & 0 deletions tests/source/issue-5496/70_version_two.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// rustfmt-version: Two
// rustfmt-single_line_if_else_max_width: 70
fn foo() -> usize {
let some_long_name = true;
let some_other_long_name = false;
let bar = if some_long_name && some_other_long_name { baz() } else { buzz() };
if some_long_name && some_other_long_name {
1
} else {
2
}
}
6 changes: 6 additions & 0 deletions tests/source/issue-5496/default.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
fn foo() -> usize {
let some_long_name = true;
let some_other_long_name = false;
let bar = if some_long_name && some_other_long_name { baz() } else { buzz() };
if some_long_name && some_other_long_name { 1 } else { 2 }
}
10 changes: 10 additions & 0 deletions tests/source/issue-5496/nested_if_one.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// rustfmt-version: One
// rustfmt-single_line_if_else_max_width: 75
fn foo() -> usize {
// nested
let _ = if true { if false { 1 } else { 2 } } else { 3 };
let _ = if true { 3 } else { if false { 1 } else { 2 } };
let _ = if true { if false { 1 } else { 2 } } else { if false { 3 } else { 4 } };

1
}
22 changes: 22 additions & 0 deletions tests/source/issue-5496/nested_if_two.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// rustfmt-version: Two
// rustfmt-single_line_if_else_max_width: 75
fn foo() -> usize {
// nested
let _ = if true {
if false { 1 } else { 2 }
} else {
3
};
let _ = if true {
3
} else {
if false { 1 } else { 2 }
};
let _ = if true {
if false { 1 } else { 2 }
} else {
if false { 3 } else { 4 }
};

1
}
24 changes: 24 additions & 0 deletions tests/source/issue-5496/simple_one.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// rustfmt-version: One
fn foo() -> usize {
// empty
let _ = if true { 1 } else { };
let _ = if true { } else { 2 };
let _ = if true { } else { };

// attribute
let _ = if true { #[must_use] 1 } else { 2 };
let _ = if true { 1 } else { #[must_use] 2 };
let _ = if true { #[must_use] 1 } else { #[must_use] 2 };

// comment
let _ = if true { 1 /*1*/ } else { 2 };
let _ = if true { 1 } else { 2 /*2*/};
let _ = if true { 1 /*1*/} else { 2 /*2*/};

// a statement
let _ = if true { let a = 1; a } else { 2 };
let _ = if true { 1 } else { let b = 2; b };
let _ = if true { let a = 1; a } else { let b = 2; b };

1
}
24 changes: 24 additions & 0 deletions tests/source/issue-5496/simple_two.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// rustfmt-version: Two
fn foo() -> usize {
// empty
let _ = if true { 1 } else { };
let _ = if true { } else { 2 };
let _ = if true { } else { };

// attribute
let _ = if true { #[must_use] 1 } else { 2 };
let _ = if true { 1 } else { #[must_use] 2 };
let _ = if true { #[must_use] 1 } else { #[must_use] 2 };

// comment
let _ = if true { 1 /*1*/ } else { 2 };
let _ = if true { 1 } else { 2 /*2*/};
let _ = if true { 1 /*1*/} else { 2 /*2*/};

// a statement
let _ = if true { let a = 1; a } else { 2 };
let _ = if true { 1 } else { let b = 2; b };
let _ = if true { let a = 1; a } else { let b = 2; b };

1
}
12 changes: 12 additions & 0 deletions tests/target/issue-5496/70.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// rustfmt-version: One
// rustfmt-single_line_if_else_max_width: 70
fn foo() -> usize {
let some_long_name = true;
let some_other_long_name = false;
let bar = if some_long_name && some_other_long_name { baz() } else { buzz() };
if some_long_name && some_other_long_name {
1
} else {
2
}
}
8 changes: 8 additions & 0 deletions tests/target/issue-5496/70_version_two.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// rustfmt-version: Two
// rustfmt-single_line_if_else_max_width: 70
fn foo() -> usize {
let some_long_name = true;
let some_other_long_name = false;
let bar = if some_long_name && some_other_long_name { baz() } else { buzz() };
if some_long_name && some_other_long_name { 1 } else { 2 }
}
14 changes: 14 additions & 0 deletions tests/target/issue-5496/default.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
fn foo() -> usize {
let some_long_name = true;
let some_other_long_name = false;
let bar = if some_long_name && some_other_long_name {
baz()
} else {
buzz()
};
if some_long_name && some_other_long_name {
1
} else {
2
}
}
38 changes: 38 additions & 0 deletions tests/target/issue-5496/nested_if_one.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// rustfmt-version: One
// rustfmt-single_line_if_else_max_width: 75
fn foo() -> usize {
// nested
let _ = if true {
if false {
1
} else {
2
}
} else {
3
};
let _ = if true {
3
} else {
if false {
1
} else {
2
}
};
let _ = if true {
if false {
1
} else {
2
}
} else {
if false {
3
} else {
4
}
};

1
}
22 changes: 22 additions & 0 deletions tests/target/issue-5496/nested_if_two.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// rustfmt-version: Two
// rustfmt-single_line_if_else_max_width: 75
fn foo() -> usize {
// nested
let _ = if true {
if false { 1 } else { 2 }
} else {
3
};
let _ = if true {
3
} else {
if false { 1 } else { 2 }
};
let _ = if true {
if false { 1 } else { 2 }
} else {
if false { 3 } else { 4 }
};

1
}
76 changes: 76 additions & 0 deletions tests/target/issue-5496/simple_one.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
// rustfmt-version: One
fn foo() -> usize {
// empty
let _ = if true {
1
} else {
};
let _ = if true {
} else {
2
};
let _ = if true {
} else {
};

// attribute
let _ = if true {
#[must_use]
1
} else {
2
};
let _ = if true {
1
} else {
#[must_use]
2
};
let _ = if true {
#[must_use]
1
} else {
#[must_use]
2
};

// comment
let _ = if true {
1 /*1*/
} else {
2
};
let _ = if true {
1
} else {
2 /*2*/
};
let _ = if true {
1 /*1*/
} else {
2 /*2*/
};

// a statement
let _ = if true {
let a = 1;
a
} else {
2
};
let _ = if true {
1
} else {
let b = 2;
b
};
let _ = if true {
let a = 1;
a
} else {
let b = 2;
b
};

1
}
Loading