From fe8b72d98e58e05420be9c1227ebdbe7a742dcf9 Mon Sep 17 00:00:00 2001 From: Yacin Tmimi Date: Sun, 9 Apr 2023 02:13:11 -0400 Subject: [PATCH] implement single_line_let_else_max_width This allows users to configure the maximum length of a single line `let-else` statements. `let-else` statements that otherwise meet the requirements to be formatted on a single line will have their divergent `else` block formatted over multiple lines if they exceed this length. **Note**: `single_line_let_else_max_widt` will be introduced as a stable configuration option. --- Configurations.md | 77 +++++++++++++++++++ src/config/config_type.rs | 10 +++ src/config/mod.rs | 7 ++ src/config/options.rs | 6 ++ src/items.rs | 27 +++++-- .../single_line_let_else_max_width/100.rs | 40 ++++++++++ .../single_line_let_else_max_width/50.rs | 40 ++++++++++ .../single_line_let_else_max_width/zero.rs | 40 ++++++++++ .../configs/use_small_heuristics/default.rs | 10 +++ .../configs/use_small_heuristics/max.rs | 10 +++ .../configs/use_small_heuristics/off.rs | 10 +++ tests/source/let_else.rs | 11 +++ .../single_line_let_else_max_width/100.rs | 59 ++++++++++++++ .../single_line_let_else_max_width/50.rs | 61 +++++++++++++++ .../single_line_let_else_max_width/zero.rs | 65 ++++++++++++++++ .../configs/use_small_heuristics/default.rs | 12 +++ .../configs/use_small_heuristics/max.rs | 10 +++ .../configs/use_small_heuristics/off.rs | 16 ++++ tests/target/let_else.rs | 24 ++++++ 19 files changed, 528 insertions(+), 7 deletions(-) create mode 100644 tests/source/configs/single_line_let_else_max_width/100.rs create mode 100644 tests/source/configs/single_line_let_else_max_width/50.rs create mode 100644 tests/source/configs/single_line_let_else_max_width/zero.rs create mode 100644 tests/target/configs/single_line_let_else_max_width/100.rs create mode 100644 tests/target/configs/single_line_let_else_max_width/50.rs create mode 100644 tests/target/configs/single_line_let_else_max_width/zero.rs diff --git a/Configurations.md b/Configurations.md index ac638ff91e6..ac5747800b2 100644 --- a/Configurations.md +++ b/Configurations.md @@ -2392,6 +2392,78 @@ By default this option is set as a percentage of [`max_width`](#max_width) provi See also [`max_width`](#max_width) and [`use_small_heuristics`](#use_small_heuristics) +## `single_line_let_else_max_width` + +Maximum line length for single line let-else statements. +See the [let-else statement section of the Rust Style Guide](https://github.com/rust-lang/rust/blob/master/src/doc/style-guide/src/statements.md#else-blocks-let-else-statements) for more details on when a let-else statement may be written on a single line. +A value of `0` (zero) means the divergent `else` block will always be formatted over multiple lines. +Note this occurs when `use_small_heuristics` is set to `Off`. + +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_let_else_max_width` will take precedence. + +- **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 + +#### `50` (default): + +```rust +fn main() { + let Some(w) = opt else { return Ok(()) }; + + let Some(x) = opt else { return }; + + let Some(y) = opt else { + return; + }; + + let Some(z) = some_very_very_very_very_long_name else { + return; + }; +} +``` + +#### `0`: + +```rust +fn main() { + let Some(w) = opt else { + return Ok(()); + }; + + let Some(x) = opt else { + return; + }; + + let Some(y) = opt else { + return; + }; + + let Some(z) = some_very_very_very_very_long_name else { + return; + }; +} +``` + +#### `100`: + +```rust +fn main() { + let Some(w) = opt else { return Ok(()) }; + + let Some(x) = opt else { return }; + + let Some(y) = opt else { + return; + }; + + let Some(z) = some_very_very_very_very_long_name else { return }; +} +``` + +See also [`max_width`](#max_width) and [`use_small_heuristics`](#use_small_heuristics) + + ## `space_after_colon` Leave a space after the colon. @@ -2804,6 +2876,7 @@ The ratios are: * [`array_width`](#array_width) - `60%` * [`chain_width`](#chain_width) - `60%` * [`single_line_if_else_max_width`](#single_line_if_else_max_width) - `50%` +* [`single_line_let_else_max_width`](#single_line_let_else_max_width) - `50%` For example when `max_width` is set to `100`, the width settings are: * `fn_call_width=60` @@ -2813,6 +2886,7 @@ For example when `max_width` is set to `100`, the width settings are: * `array_width=60` * `chain_width=60` * `single_line_if_else_max_width=50` +* `single_line_let_else_max_width=50` and when `max_width` is set to `200`: * `fn_call_width=120` @@ -2822,6 +2896,7 @@ and when `max_width` is set to `200`: * `array_width=120` * `chain_width=120` * `single_line_if_else_max_width=100` +* `single_line_let_else_max_width=100` ```rust enum Lorem { @@ -2891,6 +2966,7 @@ So if `max_width` is set to `200`, then all the width settings are also set to ` * `array_width=200` * `chain_width=200` * `single_line_if_else_max_width=200` +* `single_line_let_else_max_width=200` ```rust enum Lorem { @@ -2918,6 +2994,7 @@ See also: * [`array_width`](#array_width) * [`chain_width`](#chain_width) * [`single_line_if_else_max_width`](#single_line_if_else_max_width) +* [`single_line_let_else_max_width`](#single_line_let_else_max_width) ## `use_try_shorthand` diff --git a/src/config/config_type.rs b/src/config/config_type.rs index 54ca7676dfc..c836b4bbb78 100644 --- a/src/config/config_type.rs +++ b/src/config/config_type.rs @@ -121,6 +121,7 @@ macro_rules! create_config { | "use_small_heuristics" | "fn_call_width" | "single_line_if_else_max_width" + | "single_line_let_else_max_width" | "attr_fn_like_width" | "struct_lit_width" | "struct_variant_width" @@ -269,6 +270,7 @@ macro_rules! create_config { | "use_small_heuristics" | "fn_call_width" | "single_line_if_else_max_width" + | "single_line_let_else_max_width" | "attr_fn_like_width" | "struct_lit_width" | "struct_variant_width" @@ -407,6 +409,14 @@ macro_rules! create_config { "single_line_if_else_max_width", ); self.single_line_if_else_max_width.2 = single_line_if_else_max_width; + + let single_line_let_else_max_width = get_width_value( + self.was_set().single_line_let_else_max_width(), + self.single_line_let_else_max_width.2, + heuristics.single_line_let_else_max_width, + "single_line_let_else_max_width", + ); + self.single_line_let_else_max_width.2 = single_line_let_else_max_width; } fn set_heuristics(&mut self) { diff --git a/src/config/mod.rs b/src/config/mod.rs index 14f27f3f8b6..6f41b299e87 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -58,6 +58,9 @@ create_config! { chain_width: usize, 60, true, "Maximum length of a chain to fit on a single line."; single_line_if_else_max_width: usize, 50, true, "Maximum line length for single line if-else \ expressions. A value of zero means always break if-else expressions."; + single_line_let_else_max_width: usize, 50, true, "Maximum line length for single line \ + let-else statements. A value of zero means always format the divergent `else` block \ + over multiple lines."; // Comments. macros, and strings wrap_comments: bool, false, false, "Break comments to fit on the line"; @@ -473,6 +476,9 @@ mod test { chain_width: usize, 60, true, "Maximum length of a chain to fit on a single line."; single_line_if_else_max_width: usize, 50, true, "Maximum line length for single \ line if-else expressions. A value of zero means always break if-else expressions."; + single_line_let_else_max_width: usize, 50, false, "Maximum line length for single \ + line let-else statements. A value of zero means always format the divergent \ + `else` block over multiple lines."; // Options that are used by the tests stable_option: bool, false, true, "A stable option"; @@ -619,6 +625,7 @@ struct_variant_width = 35 array_width = 60 chain_width = 60 single_line_if_else_max_width = 50 +single_line_let_else_max_width = 50 wrap_comments = false format_code_in_doc_comments = false doc_comment_code_block_width = 100 diff --git a/src/config/options.rs b/src/config/options.rs index 408017d2432..3aa1a4de99d 100644 --- a/src/config/options.rs +++ b/src/config/options.rs @@ -236,6 +236,9 @@ pub struct WidthHeuristics { // Maximum line length for single line if-else expressions. A value // of zero means always break if-else expressions. pub(crate) single_line_if_else_max_width: usize, + // Maximum line length for single line let-else statements. A value of zero means + // always format the divergent `else` block over multiple lines. + pub(crate) single_line_let_else_max_width: usize, } impl fmt::Display for WidthHeuristics { @@ -255,6 +258,7 @@ impl WidthHeuristics { array_width: usize::max_value(), chain_width: usize::max_value(), single_line_if_else_max_width: 0, + single_line_let_else_max_width: 0, } } @@ -267,6 +271,7 @@ impl WidthHeuristics { array_width: max_width, chain_width: max_width, single_line_if_else_max_width: max_width, + single_line_let_else_max_width: max_width, } } @@ -288,6 +293,7 @@ impl WidthHeuristics { array_width: (60.0 * max_width_ratio).round() as usize, chain_width: (60.0 * max_width_ratio).round() as usize, single_line_if_else_max_width: (50.0 * max_width_ratio).round() as usize, + single_line_let_else_max_width: (50.0 * max_width_ratio).round() as usize, } } } diff --git a/src/items.rs b/src/items.rs index 97a76f6bb32..157ae931a24 100644 --- a/src/items.rs +++ b/src/items.rs @@ -138,17 +138,30 @@ impl Rewrite for ast::Local { ); result.push_str(&else_kw); - let allow_single_line = allow_single_line_let_else_block(&result, block); + // At this point we've written `let {pat} = {expr} else' into the buffer, and we + // want to calculate up front if there's room to write the divergent block on the + // same line. The available space varies based on indentation so we clamp the width + // on the smaller of `shape.width` and `single_line_let_else_max_width`. + let max_width = + std::cmp::min(shape.width, context.config.single_line_let_else_max_width()); + + // If available_space hits zero we know for sure this will be a multi-lined block + let available_space = max_width.saturating_sub(result.len()); + + let allow_single_line = !force_newline_else + && available_space > 0 + && allow_single_line_let_else_block(&result, block); let mut rw_else_block = rewrite_let_else_block(block, allow_single_line, context, shape)?; - if allow_single_line && !rw_else_block.contains('\n') { - let available_space = shape.width.saturating_sub(result.len()); - if available_space <= rw_else_block.len() { - // writing this on one line would exceed the available width - rw_else_block = rewrite_let_else_block(block, false, context, shape)?; - } + let single_line_else = !rw_else_block.contains('\n'); + let else_block_exceeds_width = available_space <= rw_else_block.len(); + + if allow_single_line && single_line_else && else_block_exceeds_width { + // writing this on one line would exceed the available width + // so rewrite the else block over multiple lines. + rw_else_block = rewrite_let_else_block(block, false, context, shape)?; } result.push_str(&rw_else_block); diff --git a/tests/source/configs/single_line_let_else_max_width/100.rs b/tests/source/configs/single_line_let_else_max_width/100.rs new file mode 100644 index 00000000000..a73c9084bf2 --- /dev/null +++ b/tests/source/configs/single_line_let_else_max_width/100.rs @@ -0,0 +1,40 @@ +// rustfmt-single_line_let_else_max_width: 100 + +fn main() { + let Some(a) = opt else {}; + + let Some(b) = opt else { return }; + + let Some(c) = opt else { + return + }; + + let Some(c) = opt else { + // a comment should always force the block to be multi-lined + return + }; + + let Some(c) = opt else { /* a comment should always force the block to be multi-lined */ return }; + + let Some(d) = some_very_very_very_very_long_name else { return }; + + let Expr::Slice(ast::ExprSlice { lower, upper, step, range: _ }) = slice.as_ref() else { + return + }; + + let Some((base_place, current)) = self.lower_expr_as_place(current, *base, true)? else { + return Ok(None) + }; + + let Some(doc_attr) = variant.attrs.iter().find(|attr| attr.path().is_ident("doc")) else { + return Err(Error::new(variant.span(), r#"expected a doc comment"#)) + }; + + let Some((base_place, current)) = self.lower_expr_as_place(current, *base, true) else { + return Ok(None) + }; + + let Stmt::Expr(Expr::Call(ExprCall { args: some_args, .. }), _) = last_stmt else { + return Err(Error::new(last_stmt.span(), "expected last expression to be `Some(match (..) { .. })`")) + }; +} diff --git a/tests/source/configs/single_line_let_else_max_width/50.rs b/tests/source/configs/single_line_let_else_max_width/50.rs new file mode 100644 index 00000000000..87d0583c552 --- /dev/null +++ b/tests/source/configs/single_line_let_else_max_width/50.rs @@ -0,0 +1,40 @@ +// rustfmt-single_line_let_else_max_width: 50 + +fn main() { + let Some(a) = opt else {}; + + let Some(b) = opt else { return }; + + let Some(c) = opt else { + return + }; + + let Some(c) = opt else { + // a comment should always force the block to be multi-lined + return + }; + + let Some(c) = opt else { /* a comment should always force the block to be multi-lined */ return }; + + let Some(d) = some_very_very_very_very_long_name else { return }; + + let Expr::Slice(ast::ExprSlice { lower, upper, step, range: _ }) = slice.as_ref() else { + return + }; + + let Some((base_place, current)) = self.lower_expr_as_place(current, *base, true)? else { + return Ok(None) + }; + + let Some(doc_attr) = variant.attrs.iter().find(|attr| attr.path().is_ident("doc")) else { + return Err(Error::new(variant.span(), r#"expected a doc comment"#)) + }; + + let Some((base_place, current)) = self.lower_expr_as_place(current, *base, true) else { + return Ok(None) + }; + + let Stmt::Expr(Expr::Call(ExprCall { args: some_args, .. }), _) = last_stmt else { + return Err(Error::new(last_stmt.span(), "expected last expression to be `Some(match (..) { .. })`")) + }; +} diff --git a/tests/source/configs/single_line_let_else_max_width/zero.rs b/tests/source/configs/single_line_let_else_max_width/zero.rs new file mode 100644 index 00000000000..afb9e503307 --- /dev/null +++ b/tests/source/configs/single_line_let_else_max_width/zero.rs @@ -0,0 +1,40 @@ +// rustfmt-single_line_let_else_max_width: 0 + +fn main() { + let Some(a) = opt else {}; + + let Some(b) = opt else { return }; + + let Some(c) = opt else { + return + }; + + let Some(c) = opt else { + // a comment should always force the block to be multi-lined + return + }; + + let Some(c) = opt else { /* a comment should always force the block to be multi-lined */ return }; + + let Some(d) = some_very_very_very_very_long_name else { return }; + + let Expr::Slice(ast::ExprSlice { lower, upper, step, range: _ }) = slice.as_ref() else { + return + }; + + let Some((base_place, current)) = self.lower_expr_as_place(current, *base, true)? else { + return Ok(None) + }; + + let Some(doc_attr) = variant.attrs.iter().find(|attr| attr.path().is_ident("doc")) else { + return Err(Error::new(variant.span(), r#"expected a doc comment"#)) + }; + + let Some((base_place, current)) = self.lower_expr_as_place(current, *base, true) else { + return Ok(None) + }; + + let Stmt::Expr(Expr::Call(ExprCall { args: some_args, .. }), _) = last_stmt else { + return Err(Error::new(last_stmt.span(), "expected last expression to be `Some(match (..) { .. })`")) + }; +} diff --git a/tests/source/configs/use_small_heuristics/default.rs b/tests/source/configs/use_small_heuristics/default.rs index 68bc40271a1..95238c54844 100644 --- a/tests/source/configs/use_small_heuristics/default.rs +++ b/tests/source/configs/use_small_heuristics/default.rs @@ -23,3 +23,13 @@ fn main() { sit }; } + +fn format_let_else() { + let Some(a) = opt else {}; + + let Some(b) = opt else { return }; + + let Some(c) = opt else { return }; + + let Some(d) = some_very_very_very_very_long_name else { return }; +} diff --git a/tests/source/configs/use_small_heuristics/max.rs b/tests/source/configs/use_small_heuristics/max.rs index 8d30932e2c2..b79302e22ab 100644 --- a/tests/source/configs/use_small_heuristics/max.rs +++ b/tests/source/configs/use_small_heuristics/max.rs @@ -23,3 +23,13 @@ fn main() { sit }; } + +fn format_let_else() { + let Some(a) = opt else {}; + + let Some(b) = opt else { return }; + + let Some(c) = opt else { return }; + + let Some(d) = some_very_very_very_very_long_name else { return }; +} diff --git a/tests/source/configs/use_small_heuristics/off.rs b/tests/source/configs/use_small_heuristics/off.rs index f76392d2404..80bcdd89896 100644 --- a/tests/source/configs/use_small_heuristics/off.rs +++ b/tests/source/configs/use_small_heuristics/off.rs @@ -23,3 +23,13 @@ fn main() { sit }; } + +fn format_let_else() { + let Some(a) = opt else {}; + + let Some(b) = opt else { return }; + + let Some(c) = opt else { return }; + + let Some(d) = some_very_very_very_very_long_name else { return }; +} diff --git a/tests/source/let_else.rs b/tests/source/let_else.rs index 9c02117c6e8..85b3604ad3c 100644 --- a/tests/source/let_else.rs +++ b/tests/source/let_else.rs @@ -1,3 +1,5 @@ +// rustfmt-single_line_let_else_max_width: 100 + fn main() { // Although this won't compile it still parses so make sure we can format empty else blocks let Some(x) = opt else {}; @@ -149,3 +151,12 @@ fn long_patterns() { return; }; } + +fn with_trailing_try_operator() { + // Currently the trailing ? forces the else on the next line + // This may be revisited in style edition 2024 + let Some(next_bucket) = ranking_rules[cur_ranking_rule_index].next_bucket(ctx, logger, &ranking_rule_universes[cur_ranking_rule_index])? else { return }; + + // Maybe this is a workaround? + let Ok(Some(next_bucket)) = ranking_rules[cur_ranking_rule_index].next_bucket(ctx, logger, &ranking_rule_universes[cur_ranking_rule_index]) else { return }; +} diff --git a/tests/target/configs/single_line_let_else_max_width/100.rs b/tests/target/configs/single_line_let_else_max_width/100.rs new file mode 100644 index 00000000000..2310ff8a228 --- /dev/null +++ b/tests/target/configs/single_line_let_else_max_width/100.rs @@ -0,0 +1,59 @@ +// rustfmt-single_line_let_else_max_width: 100 + +fn main() { + let Some(a) = opt else {}; + + let Some(b) = opt else { return }; + + let Some(c) = opt else { return }; + + let Some(c) = opt else { + // a comment should always force the block to be multi-lined + return; + }; + + let Some(c) = opt else { + /* a comment should always force the block to be multi-lined */ + return; + }; + + let Some(d) = some_very_very_very_very_long_name else { return }; + + let Expr::Slice(ast::ExprSlice { + lower, + upper, + step, + range: _, + }) = slice.as_ref() else { + return; + }; + + let Some((base_place, current)) = self.lower_expr_as_place(current, *base, true)? else { + return Ok(None); + }; + + let Some(doc_attr) = variant + .attrs + .iter() + .find(|attr| attr.path().is_ident("doc")) + else { + return Err(Error::new(variant.span(), r#"expected a doc comment"#)); + }; + + let Some((base_place, current)) = self.lower_expr_as_place(current, *base, true) else { + return Ok(None); + }; + + let Stmt::Expr( + Expr::Call(ExprCall { + args: some_args, .. + }), + _, + ) = last_stmt + else { + return Err(Error::new( + last_stmt.span(), + "expected last expression to be `Some(match (..) { .. })`", + )); + }; +} diff --git a/tests/target/configs/single_line_let_else_max_width/50.rs b/tests/target/configs/single_line_let_else_max_width/50.rs new file mode 100644 index 00000000000..df2c40d72d6 --- /dev/null +++ b/tests/target/configs/single_line_let_else_max_width/50.rs @@ -0,0 +1,61 @@ +// rustfmt-single_line_let_else_max_width: 50 + +fn main() { + let Some(a) = opt else {}; + + let Some(b) = opt else { return }; + + let Some(c) = opt else { return }; + + let Some(c) = opt else { + // a comment should always force the block to be multi-lined + return; + }; + + let Some(c) = opt else { + /* a comment should always force the block to be multi-lined */ + return; + }; + + let Some(d) = some_very_very_very_very_long_name else { + return; + }; + + let Expr::Slice(ast::ExprSlice { + lower, + upper, + step, + range: _, + }) = slice.as_ref() else { + return; + }; + + let Some((base_place, current)) = self.lower_expr_as_place(current, *base, true)? else { + return Ok(None); + }; + + let Some(doc_attr) = variant + .attrs + .iter() + .find(|attr| attr.path().is_ident("doc")) + else { + return Err(Error::new(variant.span(), r#"expected a doc comment"#)); + }; + + let Some((base_place, current)) = self.lower_expr_as_place(current, *base, true) else { + return Ok(None); + }; + + let Stmt::Expr( + Expr::Call(ExprCall { + args: some_args, .. + }), + _, + ) = last_stmt + else { + return Err(Error::new( + last_stmt.span(), + "expected last expression to be `Some(match (..) { .. })`", + )); + }; +} diff --git a/tests/target/configs/single_line_let_else_max_width/zero.rs b/tests/target/configs/single_line_let_else_max_width/zero.rs new file mode 100644 index 00000000000..f4d26ad3757 --- /dev/null +++ b/tests/target/configs/single_line_let_else_max_width/zero.rs @@ -0,0 +1,65 @@ +// rustfmt-single_line_let_else_max_width: 0 + +fn main() { + let Some(a) = opt else {}; + + let Some(b) = opt else { + return; + }; + + let Some(c) = opt else { + return; + }; + + let Some(c) = opt else { + // a comment should always force the block to be multi-lined + return; + }; + + let Some(c) = opt else { + /* a comment should always force the block to be multi-lined */ + return; + }; + + let Some(d) = some_very_very_very_very_long_name else { + return; + }; + + let Expr::Slice(ast::ExprSlice { + lower, + upper, + step, + range: _, + }) = slice.as_ref() else { + return; + }; + + let Some((base_place, current)) = self.lower_expr_as_place(current, *base, true)? else { + return Ok(None); + }; + + let Some(doc_attr) = variant + .attrs + .iter() + .find(|attr| attr.path().is_ident("doc")) + else { + return Err(Error::new(variant.span(), r#"expected a doc comment"#)); + }; + + let Some((base_place, current)) = self.lower_expr_as_place(current, *base, true) else { + return Ok(None); + }; + + let Stmt::Expr( + Expr::Call(ExprCall { + args: some_args, .. + }), + _, + ) = last_stmt + else { + return Err(Error::new( + last_stmt.span(), + "expected last expression to be `Some(match (..) { .. })`", + )); + }; +} diff --git a/tests/target/configs/use_small_heuristics/default.rs b/tests/target/configs/use_small_heuristics/default.rs index d67bd9aafaf..ad40739233e 100644 --- a/tests/target/configs/use_small_heuristics/default.rs +++ b/tests/target/configs/use_small_heuristics/default.rs @@ -24,3 +24,15 @@ fn main() { let lorem = if ipsum { dolor } else { sit }; } + +fn format_let_else() { + let Some(a) = opt else {}; + + let Some(b) = opt else { return }; + + let Some(c) = opt else { return }; + + let Some(d) = some_very_very_very_very_long_name else { + return; + }; +} diff --git a/tests/target/configs/use_small_heuristics/max.rs b/tests/target/configs/use_small_heuristics/max.rs index 785dfbea014..fe57f853d9d 100644 --- a/tests/target/configs/use_small_heuristics/max.rs +++ b/tests/target/configs/use_small_heuristics/max.rs @@ -13,3 +13,13 @@ fn main() { let lorem = if ipsum { dolor } else { sit }; } + +fn format_let_else() { + let Some(a) = opt else {}; + + let Some(b) = opt else { return }; + + let Some(c) = opt else { return }; + + let Some(d) = some_very_very_very_very_long_name else { return }; +} diff --git a/tests/target/configs/use_small_heuristics/off.rs b/tests/target/configs/use_small_heuristics/off.rs index f76392d2404..b0b4e4ee49f 100644 --- a/tests/target/configs/use_small_heuristics/off.rs +++ b/tests/target/configs/use_small_heuristics/off.rs @@ -23,3 +23,19 @@ fn main() { sit }; } + +fn format_let_else() { + let Some(a) = opt else {}; + + let Some(b) = opt else { + return; + }; + + let Some(c) = opt else { + return; + }; + + let Some(d) = some_very_very_very_very_long_name else { + return; + }; +} diff --git a/tests/target/let_else.rs b/tests/target/let_else.rs index 88115d129aa..6554a0961c0 100644 --- a/tests/target/let_else.rs +++ b/tests/target/let_else.rs @@ -1,3 +1,5 @@ +// rustfmt-single_line_let_else_max_width: 100 + fn main() { // Although this won't compile it still parses so make sure we can format empty else blocks let Some(x) = opt else {}; @@ -228,3 +230,25 @@ fn long_patterns() { return; }; } + +fn with_trailing_try_operator() { + // Currently the trailing ? forces the else on the next line + // This may be revisited in style edition 2024 + let Some(next_bucket) = ranking_rules[cur_ranking_rule_index].next_bucket( + ctx, + logger, + &ranking_rule_universes[cur_ranking_rule_index], + )? + else { + return; + }; + + // Maybe this is a workaround? + let Ok(Some(next_bucket)) = ranking_rules[cur_ranking_rule_index].next_bucket( + ctx, + logger, + &ranking_rule_universes[cur_ranking_rule_index], + ) else { + return; + }; +}