Skip to content

Commit 10b95e0

Browse files
authored
Changes for #4394 - Support preserving block wrapping of closure bodies (#4519)
* Changes for #4394 - Support preserving block wrapping of closure bodies * Add preserve_closure_block_wrapping config option support * Code purifying based on the discussion in PR #4519 * Further purifying code * Cosmetic comment change
1 parent a96e706 commit 10b95e0

File tree

5 files changed

+118
-1
lines changed

5 files changed

+118
-1
lines changed

Diff for: Configurations.md

+27
Original file line numberDiff line numberDiff line change
@@ -1836,6 +1836,33 @@ fn say_hi() {
18361836
}
18371837
```
18381838

1839+
## `preserve_closure_block_wrapping`
1840+
1841+
Preserves block wraping arround closures. For example, useful when the closure `||` can be
1842+
confused with OR.
1843+
1844+
- **Default value**: `false`
1845+
- **Possible values**: `true`, `false`
1846+
- **Stable**: No
1847+
1848+
#### `true`:
1849+
Original block wrapping is preserved:
1850+
```rust
1851+
fn main() {
1852+
let explicit_conversion_preserves_semantics =
1853+
|| { !is_mod || (is_mod && attrs.map_or(true, |a| a.is_empty())) };
1854+
}
1855+
```
1856+
1857+
#### `false` (default):
1858+
Block is not preserved:
1859+
```rust
1860+
fn main() {
1861+
let explicit_conversion_preserves_semantics =
1862+
|| !is_mod || (is_mod && attrs.map_or(true, |a| a.is_empty()));
1863+
}
1864+
```
1865+
18391866
## `overflow_delimited_expr`
18401867

18411868
When structs, slices, arrays, and block/array-like macros are used as the last

Diff for: src/config.rs

+2
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@ create_config! {
136136
format_generated_files: bool, false, false, "Format generated files";
137137
preserve_block_start_blank_lines: bool, false, false, "Preserve blank lines at the start of \
138138
blocks.";
139+
preserve_closure_block_wrapping: bool, false , false, "Preserve block wrapping around closures";
139140

140141
// Options that can change the source code beyond whitespace/blocks (somewhat linty things)
141142
merge_derives: bool, true, true, "Merge multiple `#[derive(...)]` into a single one";
@@ -626,6 +627,7 @@ edition = "2018"
626627
inline_attribute_width = 0
627628
format_generated_files = false
628629
preserve_block_start_blank_lines = false
630+
preserve_closure_block_wrapping = false
629631
merge_derives = true
630632
use_try_shorthand = false
631633
use_field_init_shorthand = false

Diff for: src/formatting/closures.rs

+12-1
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,19 @@ pub(crate) fn rewrite_closure(
5555
.map(|s| format!("{} {}", prefix, s));
5656
}
5757

58+
// Whether a closure block wrapping may not be preserved (#4394).
59+
let can_try_rewrite_without_block = if context.inside_macro() {
60+
false
61+
} else if context.config.preserve_closure_block_wrapping()
62+
&& context.snippet(body.span).trim_start().starts_with('{')
63+
{
64+
false
65+
} else {
66+
true
67+
};
68+
5869
let result = match fn_decl.output {
59-
ast::FnRetTy::Default(_) if !context.inside_macro() => {
70+
ast::FnRetTy::Default(_) if can_try_rewrite_without_block => {
6071
try_rewrite_without_block(body, &prefix, capture, context, shape, body_shape)
6172
}
6273
_ => None,

Diff for: tests/source/preserve_closure_block_wrapping.rs

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// rustfmt-preserve_closure_block_wrapping: true
2+
3+
fn main() {
4+
let explicit_conversion_preserves_semantics =
5+
|| { !is_mod || (is_mod && attrs.map_or(true, |a| a.is_empty())) };
6+
}
7+
8+
fn main() {
9+
|| {{}};
10+
}
11+
12+
fn issue1524() {
13+
let f = |x| {{{{x}}}};
14+
let f = |x| {{{x}}};
15+
let f = |x| {{x}};
16+
let f = |x| {x};
17+
let f = |x| x;
18+
}
19+
20+
fn main() {
21+
let arg_test2 = |big_argument_name, test123| {looooooooooooooooooong_function_naaaaaaaaaaaaaaaaame()};
22+
}
23+
24+
impl Foo {
25+
pub fn bar(&self) {
26+
Some(SomeType {
27+
push_closure_out_to_100_chars: iter(otherwise_it_works_ok.into_iter().map(|f| {
28+
Ok(f)
29+
})),
30+
})
31+
}
32+
}

Diff for: tests/target/preserve_closure_block_wrapping.rs

+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// rustfmt-preserve_closure_block_wrapping: true
2+
3+
fn main() {
4+
let explicit_conversion_preserves_semantics =
5+
|| { !is_mod || (is_mod && attrs.map_or(true, |a| a.is_empty())) };
6+
}
7+
8+
fn main() {
9+
|| { {} };
10+
}
11+
12+
fn issue1524() {
13+
let f = |x| {
14+
{
15+
{
16+
{ x }
17+
}
18+
}
19+
};
20+
let f = |x| {
21+
{
22+
{ x }
23+
}
24+
};
25+
let f = |x| {
26+
{ x }
27+
};
28+
let f = |x| { x };
29+
let f = |x| x;
30+
}
31+
32+
fn main() {
33+
let arg_test2 =
34+
|big_argument_name, test123| { looooooooooooooooooong_function_naaaaaaaaaaaaaaaaame() };
35+
}
36+
37+
impl Foo {
38+
pub fn bar(&self) {
39+
Some(SomeType {
40+
push_closure_out_to_100_chars: iter(
41+
otherwise_it_works_ok.into_iter().map(|f| { Ok(f) }),
42+
),
43+
})
44+
}
45+
}

0 commit comments

Comments
 (0)