Merge commit 'dca1cf90ad6b8e45afbed2061803befbb2d159e9' into sync-rustfmt
This commit is contained in:
parent
80bf3ea542
commit
78331eefaf
11
CHANGELOG.md
11
CHANGELOG.md
@ -2,6 +2,17 @@
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
|
||||
## [1.6.0] 2023-07-02
|
||||
|
||||
### Added
|
||||
|
||||
- Support for formatting let-else statements [#5690]
|
||||
- New config option, `single_line_let_else_max_width`, that allows users to configure the maximum length of 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 [#5684]
|
||||
|
||||
[#5690]: (https://github.com/rust-lang/rustfmt/pulls/5690)
|
||||
[#5684]: https://github.com/rust-lang/rustfmt/issues/5684
|
||||
|
||||
## [1.5.3] 2023-06-20
|
||||
|
||||
### Fixed
|
||||
|
6
Cargo.lock
generated
6
Cargo.lock
generated
@ -481,9 +481,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.56"
|
||||
version = "1.0.63"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2b63bdb0cd06f1f4dedf69b254734f9b45af66e4a031e42a7480257d9898b435"
|
||||
checksum = "7b368fba921b0dce7e60f5e04ec15e565b3303972b42bcfde1d0713b881959eb"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
@ -545,7 +545,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rustfmt-nightly"
|
||||
version = "1.5.3"
|
||||
version = "1.6.0"
|
||||
dependencies = [
|
||||
"annotate-snippets",
|
||||
"anyhow",
|
||||
|
@ -1,7 +1,7 @@
|
||||
[package]
|
||||
|
||||
name = "rustfmt-nightly"
|
||||
version = "1.5.3"
|
||||
version = "1.6.0"
|
||||
description = "Tool to find and fix Rust formatting issues"
|
||||
repository = "https://github.com/rust-lang/rustfmt"
|
||||
readme = "README.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`
|
||||
|
||||
|
4
config_proc_macro/Cargo.lock
generated
4
config_proc_macro/Cargo.lock
generated
@ -4,9 +4,9 @@ version = 3
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.56"
|
||||
version = "1.0.63"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2b63bdb0cd06f1f4dedf69b254734f9b45af66e4a031e42a7480257d9898b435"
|
||||
checksum = "7b368fba921b0dce7e60f5e04ec15e565b3303972b42bcfde1d0713b881959eb"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
@ -1,3 +1,3 @@
|
||||
[toolchain]
|
||||
channel = "nightly-2023-06-19"
|
||||
channel = "nightly-2023-07-01"
|
||||
components = ["llvm-tools", "rustc-dev"]
|
||||
|
@ -121,6 +121,7 @@ pub fn $i(&mut self, value: $ty) {
|
||||
| "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 @@ pub fn override_value(&mut self, key: &str, val: &str)
|
||||
| "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 @@ fn set_width_heuristics(&mut self, heuristics: WidthHeuristics) {
|
||||
"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) {
|
||||
|
@ -58,6 +58,9 @@
|
||||
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 @@ pub(crate) enum PartiallyUnstableOption {
|
||||
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 @@ fn test_dump_default_config() {
|
||||
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
|
||||
|
@ -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 @@ pub fn null() -> 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 @@ pub fn set(max_width: usize) -> 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 @@ pub fn scaled(max_width: usize) -> 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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
107
src/expr.rs
107
src/expr.rs
@ -576,6 +576,17 @@ fn rewrite_block(
|
||||
label: Option<ast::Label>,
|
||||
context: &RewriteContext<'_>,
|
||||
shape: Shape,
|
||||
) -> Option<String> {
|
||||
rewrite_block_inner(block, attrs, label, true, context, shape)
|
||||
}
|
||||
|
||||
fn rewrite_block_inner(
|
||||
block: &ast::Block,
|
||||
attrs: Option<&[ast::Attribute]>,
|
||||
label: Option<ast::Label>,
|
||||
allow_single_line: bool,
|
||||
context: &RewriteContext<'_>,
|
||||
shape: Shape,
|
||||
) -> Option<String> {
|
||||
let prefix = block_prefix(context, block, shape)?;
|
||||
|
||||
@ -587,7 +598,7 @@ fn rewrite_block(
|
||||
|
||||
let result = rewrite_block_with_visitor(context, &prefix, block, attrs, label, shape, true);
|
||||
if let Some(ref result_str) = result {
|
||||
if result_str.lines().count() <= 3 {
|
||||
if allow_single_line && result_str.lines().count() <= 3 {
|
||||
if let rw @ Some(_) =
|
||||
rewrite_single_line_block(context, &prefix, block, attrs, label, shape)
|
||||
{
|
||||
@ -599,6 +610,16 @@ fn rewrite_block(
|
||||
result
|
||||
}
|
||||
|
||||
/// Rewrite the divergent block of a `let-else` statement.
|
||||
pub(crate) fn rewrite_let_else_block(
|
||||
block: &ast::Block,
|
||||
allow_single_line: bool,
|
||||
context: &RewriteContext<'_>,
|
||||
shape: Shape,
|
||||
) -> Option<String> {
|
||||
rewrite_block_inner(block, None, None, allow_single_line, context, shape)
|
||||
}
|
||||
|
||||
// Rewrite condition if the given expression has one.
|
||||
pub(crate) fn rewrite_cond(
|
||||
context: &RewriteContext<'_>,
|
||||
@ -1005,6 +1026,49 @@ fn rewrite_cond(
|
||||
}
|
||||
}
|
||||
|
||||
/// Rewrite the `else` keyword with surrounding comments.
|
||||
///
|
||||
/// force_newline_else: whether or not to rewrite the `else` keyword on a newline.
|
||||
/// is_last: true if this is an `else` and `false` if this is an `else if` block.
|
||||
/// context: rewrite context
|
||||
/// span: Span between the end of the last expression and the start of the else block,
|
||||
/// which contains the `else` keyword
|
||||
/// shape: Shape
|
||||
pub(crate) fn rewrite_else_kw_with_comments(
|
||||
force_newline_else: bool,
|
||||
is_last: bool,
|
||||
context: &RewriteContext<'_>,
|
||||
span: Span,
|
||||
shape: Shape,
|
||||
) -> String {
|
||||
let else_kw_lo = context.snippet_provider.span_before(span, "else");
|
||||
let before_else_kw = mk_sp(span.lo(), else_kw_lo);
|
||||
let before_else_kw_comment = extract_comment(before_else_kw, context, shape);
|
||||
|
||||
let else_kw_hi = context.snippet_provider.span_after(span, "else");
|
||||
let after_else_kw = mk_sp(else_kw_hi, span.hi());
|
||||
let after_else_kw_comment = extract_comment(after_else_kw, context, shape);
|
||||
|
||||
let newline_sep = &shape.indent.to_string_with_newline(context.config);
|
||||
let before_sep = match context.config.control_brace_style() {
|
||||
_ if force_newline_else => newline_sep.as_ref(),
|
||||
ControlBraceStyle::AlwaysNextLine | ControlBraceStyle::ClosingNextLine => {
|
||||
newline_sep.as_ref()
|
||||
}
|
||||
ControlBraceStyle::AlwaysSameLine => " ",
|
||||
};
|
||||
let after_sep = match context.config.control_brace_style() {
|
||||
ControlBraceStyle::AlwaysNextLine if is_last => newline_sep.as_ref(),
|
||||
_ => " ",
|
||||
};
|
||||
|
||||
format!(
|
||||
"{}else{}",
|
||||
before_else_kw_comment.as_ref().map_or(before_sep, |s| &**s),
|
||||
after_else_kw_comment.as_ref().map_or(after_sep, |s| &**s),
|
||||
)
|
||||
}
|
||||
|
||||
impl<'a> Rewrite for ControlFlow<'a> {
|
||||
fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> {
|
||||
debug!("ControlFlow::rewrite {:?} {:?}", self, shape);
|
||||
@ -1071,41 +1135,14 @@ fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String>
|
||||
}
|
||||
};
|
||||
|
||||
let between_kwd_else_block = mk_sp(
|
||||
self.block.span.hi(),
|
||||
context
|
||||
.snippet_provider
|
||||
.span_before(mk_sp(self.block.span.hi(), else_block.span.lo()), "else"),
|
||||
let else_kw = rewrite_else_kw_with_comments(
|
||||
false,
|
||||
last_in_chain,
|
||||
context,
|
||||
self.block.span.between(else_block.span),
|
||||
shape,
|
||||
);
|
||||
let between_kwd_else_block_comment =
|
||||
extract_comment(between_kwd_else_block, context, shape);
|
||||
|
||||
let after_else = mk_sp(
|
||||
context
|
||||
.snippet_provider
|
||||
.span_after(mk_sp(self.block.span.hi(), else_block.span.lo()), "else"),
|
||||
else_block.span.lo(),
|
||||
);
|
||||
let after_else_comment = extract_comment(after_else, context, shape);
|
||||
|
||||
let between_sep = match context.config.control_brace_style() {
|
||||
ControlBraceStyle::AlwaysNextLine | ControlBraceStyle::ClosingNextLine => {
|
||||
&*alt_block_sep
|
||||
}
|
||||
ControlBraceStyle::AlwaysSameLine => " ",
|
||||
};
|
||||
let after_sep = match context.config.control_brace_style() {
|
||||
ControlBraceStyle::AlwaysNextLine if last_in_chain => &*alt_block_sep,
|
||||
_ => " ",
|
||||
};
|
||||
|
||||
result.push_str(&format!(
|
||||
"{}else{}",
|
||||
between_kwd_else_block_comment
|
||||
.as_ref()
|
||||
.map_or(between_sep, |s| &**s),
|
||||
after_else_comment.as_ref().map_or(after_sep, |s| &**s),
|
||||
));
|
||||
result.push_str(&else_kw);
|
||||
result.push_str(&rewrite?);
|
||||
}
|
||||
|
||||
|
108
src/items.rs
108
src/items.rs
@ -18,7 +18,8 @@
|
||||
use crate::config::{BraceStyle, Config, IndentStyle, Version};
|
||||
use crate::expr::{
|
||||
is_empty_block, is_simple_block_stmt, rewrite_assign_rhs, rewrite_assign_rhs_with,
|
||||
rewrite_assign_rhs_with_comments, RhsAssignKind, RhsTactics,
|
||||
rewrite_assign_rhs_with_comments, rewrite_else_kw_with_comments, rewrite_let_else_block,
|
||||
RhsAssignKind, RhsTactics,
|
||||
};
|
||||
use crate::lists::{definitive_tactic, itemize_list, write_list, ListFormatting, Separator};
|
||||
use crate::macros::{rewrite_macro, MacroPosition};
|
||||
@ -44,7 +45,7 @@ fn type_annotation_separator(config: &Config) -> &str {
|
||||
}
|
||||
|
||||
// Statements of the form
|
||||
// let pat: ty = init;
|
||||
// let pat: ty = init; or let pat: ty = init else { .. };
|
||||
impl Rewrite for ast::Local {
|
||||
fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> {
|
||||
debug!(
|
||||
@ -54,7 +55,7 @@ fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String>
|
||||
|
||||
skip_out_of_file_lines_range!(context, self.span);
|
||||
|
||||
if contains_skip(&self.attrs) || matches!(self.kind, ast::LocalKind::InitElse(..)) {
|
||||
if contains_skip(&self.attrs) {
|
||||
return None;
|
||||
}
|
||||
|
||||
@ -112,7 +113,7 @@ fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String>
|
||||
|
||||
result.push_str(&infix);
|
||||
|
||||
if let Some((init, _els)) = self.kind.init_else_opt() {
|
||||
if let Some((init, else_block)) = self.kind.init_else_opt() {
|
||||
// 1 = trailing semicolon;
|
||||
let nested_shape = shape.sub_width(1)?;
|
||||
|
||||
@ -123,7 +124,49 @@ fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String>
|
||||
&RhsAssignKind::Expr(&init.kind, init.span),
|
||||
nested_shape,
|
||||
)?;
|
||||
// todo else
|
||||
|
||||
if let Some(block) = else_block {
|
||||
let else_kw_span = init.span.between(block.span);
|
||||
let force_newline_else = pat_str.contains('\n')
|
||||
|| !same_line_else_kw_and_brace(&result, context, else_kw_span, nested_shape);
|
||||
let else_kw = rewrite_else_kw_with_comments(
|
||||
force_newline_else,
|
||||
true,
|
||||
context,
|
||||
else_kw_span,
|
||||
shape,
|
||||
);
|
||||
result.push_str(&else_kw);
|
||||
|
||||
// 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)?;
|
||||
|
||||
let single_line_else = !rw_else_block.contains('\n');
|
||||
// +1 for the trailing `;`
|
||||
let else_block_exceeds_width = rw_else_block.len() + 1 > available_space;
|
||||
|
||||
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);
|
||||
};
|
||||
}
|
||||
|
||||
result.push(';');
|
||||
@ -131,6 +174,61 @@ fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String>
|
||||
}
|
||||
}
|
||||
|
||||
/// When the initializer expression is multi-lined, then the else keyword and opening brace of the
|
||||
/// block ( i.e. "else {") should be put on the same line as the end of the initializer expression
|
||||
/// if all the following are true:
|
||||
///
|
||||
/// 1. The initializer expression ends with one or more closing parentheses, square brackets,
|
||||
/// or braces
|
||||
/// 2. There is nothing else on that line
|
||||
/// 3. That line is not indented beyond the indent on the first line of the let keyword
|
||||
fn same_line_else_kw_and_brace(
|
||||
init_str: &str,
|
||||
context: &RewriteContext<'_>,
|
||||
else_kw_span: Span,
|
||||
init_shape: Shape,
|
||||
) -> bool {
|
||||
if !init_str.contains('\n') {
|
||||
// initializer expression is single lined. The "else {" can only be placed on the same line
|
||||
// as the initializer expression if there is enough room for it.
|
||||
// 7 = ` else {`
|
||||
return init_shape.width.saturating_sub(init_str.len()) >= 7;
|
||||
}
|
||||
|
||||
// 1. The initializer expression ends with one or more `)`, `]`, `}`.
|
||||
if !init_str.ends_with([')', ']', '}']) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 2. There is nothing else on that line
|
||||
// For example, there are no comments
|
||||
let else_kw_snippet = context.snippet(else_kw_span).trim();
|
||||
if else_kw_snippet != "else" {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 3. The last line of the initializer expression is not indented beyond the `let` keyword
|
||||
let indent = init_shape.indent.to_string(context.config);
|
||||
init_str
|
||||
.lines()
|
||||
.last()
|
||||
.expect("initializer expression is multi-lined")
|
||||
.strip_prefix(indent.as_ref())
|
||||
.map_or(false, |l| !l.starts_with(char::is_whitespace))
|
||||
}
|
||||
|
||||
fn allow_single_line_let_else_block(result: &str, block: &ast::Block) -> bool {
|
||||
if result.contains('\n') {
|
||||
return false;
|
||||
}
|
||||
|
||||
if block.stmts.len() <= 1 {
|
||||
return true;
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
|
||||
// FIXME convert to using rewrite style rather than visitor
|
||||
// FIXME format modules in this style
|
||||
#[allow(dead_code)]
|
||||
|
40
tests/source/configs/single_line_let_else_max_width/100.rs
Normal file
40
tests/source/configs/single_line_let_else_max_width/100.rs
Normal file
@ -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 (..) { .. })`"))
|
||||
};
|
||||
}
|
40
tests/source/configs/single_line_let_else_max_width/50.rs
Normal file
40
tests/source/configs/single_line_let_else_max_width/50.rs
Normal file
@ -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 (..) { .. })`"))
|
||||
};
|
||||
}
|
40
tests/source/configs/single_line_let_else_max_width/zero.rs
Normal file
40
tests/source/configs/single_line_let_else_max_width/zero.rs
Normal file
@ -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 (..) { .. })`"))
|
||||
};
|
||||
}
|
@ -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 };
|
||||
}
|
||||
|
@ -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 };
|
||||
}
|
||||
|
@ -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 };
|
||||
}
|
||||
|
@ -1,3 +1,162 @@
|
||||
// rustfmt-single_line_let_else_max_width: 100
|
||||
|
||||
fn main() {
|
||||
let Some(1) = Some(1) else { return };
|
||||
// Although this won't compile it still parses so make sure we can format empty else blocks
|
||||
let Some(x) = opt else {};
|
||||
|
||||
// let-else may be formatted on a single line if they are "short"
|
||||
// and only contain a single expression
|
||||
let Some(x) = opt else { return };
|
||||
|
||||
let Some(x) = opt else {
|
||||
return
|
||||
};
|
||||
|
||||
let Some(x) = opt else { return; };
|
||||
|
||||
let Some(x) = opt else {
|
||||
// nope
|
||||
return;
|
||||
};
|
||||
|
||||
let Some(x) = opt else { let y = 1; return y };
|
||||
|
||||
let Some(x) = y.foo("abc", fairly_long_identifier, "def", "123456", "string", "cheese") else { bar() };
|
||||
|
||||
let Some(x) = abcdef().foo("abc", some_really_really_really_long_ident, "ident", "123456").bar().baz().qux("fffffffffffffffff") else { foo_bar() };
|
||||
}
|
||||
|
||||
fn with_comments_around_else_keyword() {
|
||||
let Some(x) = opt /* pre else keyword block-comment */ else { return };
|
||||
|
||||
let Some(x) = opt else /* post else keyword block-comment */ { return };
|
||||
|
||||
let Some(x) = opt /* pre else keyword block-comment */ else /* post else keyword block-comment */ { return };
|
||||
|
||||
let Some(x) = opt // pre else keyword line-comment
|
||||
else { return };
|
||||
|
||||
let Some(x) = opt else
|
||||
// post else keyword line-comment
|
||||
{ return };
|
||||
|
||||
let Some(x) = opt // pre else keyword line-comment
|
||||
else
|
||||
// post else keyword line-comment
|
||||
{ return };
|
||||
|
||||
}
|
||||
|
||||
fn unbreakable_initializer_expr_pre_formatting_let_else_length_near_max_width() {
|
||||
// Pre Formatting:
|
||||
// The length of `(indent)let pat = init else block;` is 100 (max_width)
|
||||
// Post Formatting:
|
||||
// The formatting is left unchanged!
|
||||
let Some(x) = some_really_really_really_really_really_really_really_long_name_A else { return };
|
||||
|
||||
// Pre Formatting:
|
||||
// The length of `(indent)let pat = init else block;` is 100 (max_width)
|
||||
// Post Formatting:
|
||||
// The else keyword and opening brace remain on the same line as the initializer expr,
|
||||
// and the else block is formatted over multiple lines because we can't fit the
|
||||
// else block on the same line as the initializer expr.
|
||||
let Some(x) = some_really_really_really_really_really_really_really_long_name___B else {return};
|
||||
|
||||
// Pre Formatting:
|
||||
// The length of `(indent)let pat = init else block;` is 100 (max_width)
|
||||
// Post Formatting:
|
||||
// The else keyword and opening brace remain on the same line as the initializer expr,
|
||||
// and the else block is formatted over multiple lines because we can't fit the
|
||||
// else block on the same line as the initializer expr.
|
||||
let Some(x) = some_really_really_really_really_long_name_____C else {some_divergent_function()};
|
||||
|
||||
// Pre Formatting:
|
||||
// The length of `(indent)let pat = init else block;` is 101 (> max_width)
|
||||
// Post Formatting:
|
||||
// The else keyword and opening brace remain on the same line as the initializer expr,
|
||||
// and the else block is formatted over multiple lines because we can't fit the
|
||||
// else block on the same line as the initializer expr.
|
||||
let Some(x) = some_really_really_really_really_really_really_really_long_name__D else { return };
|
||||
}
|
||||
|
||||
fn unbreakable_initializer_expr_pre_formatting_length_up_to_opening_brace_near_max_width() {
|
||||
// Pre Formatting:
|
||||
// The length of `(indent)let pat = init else {` is 99 (< max_width)
|
||||
// Post Formatting:
|
||||
// The else keyword and opening brace remain on the same line as the initializer expr,
|
||||
// and the else block is formatted over multiple lines because we can't fit the
|
||||
// else block on the same line as the initializer expr.
|
||||
let Some(x) = some_really_really_really_really_really_really_really_really_long_name___E else {return};
|
||||
|
||||
// Pre Formatting:
|
||||
// The length of `(indent)let pat = init else {` is 101 (> max_width)
|
||||
// Post Formatting:
|
||||
// The else keyword and opening brace cannot fit on the same line as the initializer expr.
|
||||
// They are formatted on the next line.
|
||||
let Some(x) = some_really_really_really_really_really_really_really_really_long_name_____F else {return};
|
||||
}
|
||||
|
||||
fn unbreakable_initializer_expr_pre_formatting_length_through_initializer_expr_near_max_width() {
|
||||
// Pre Formatting:
|
||||
// The length of `(indent)let pat = init` is 99 (< max_width)
|
||||
// Post Formatting:
|
||||
// The else keyword and opening brace cannot fit on the same line as the initializer expr.
|
||||
// They are formatted on the next line.
|
||||
let Some(x) = some_really_really_really_really_really_really_really_really_really_long_name___G else {return};
|
||||
|
||||
// Pre Formatting:
|
||||
// The length of `(indent)let pat = init` is 100 (max_width)
|
||||
// Post Formatting:
|
||||
// Break after the `=` and put the initializer expr on it's own line.
|
||||
// Because the initializer expr is multi-lined the else is placed on it's own line.
|
||||
let Some(x) = some_really_really_really_really_really_really_really_really_really_long_name____H else {return};
|
||||
|
||||
// Pre Formatting:
|
||||
// The length of `(indent)let pat = init` is 109 (> max_width)
|
||||
// Post Formatting:
|
||||
// Break after the `=` and put the initializer expr on it's own line.
|
||||
// Because the initializer expr is multi-lined the else is placed on it's own line.
|
||||
// The initializer expr has a length of 91, which when indented on the next line
|
||||
// The `(indent)init` line has a lengh of 99. This is the max length that the `init` can be
|
||||
// before we start running into max_width issues. I suspect this is becuase the shape is
|
||||
// accounting for the `;` at the end of the `let-else` statement.
|
||||
let Some(x) = some_really_really_really_really_really_really_really_really_really_really_long_name______I else {return};
|
||||
|
||||
// Pre Formatting:
|
||||
// The length of `(indent)let pat = init` is 110 (> max_width)
|
||||
// Post Formatting:
|
||||
// Max length issues prevent us from formatting.
|
||||
// The initializer expr has a length of 92, which if it would be indented on the next line
|
||||
// the `(indent)init` line has a lengh of 100 which == max_width of 100.
|
||||
// One might expect formatting to succeed, but I suspect the reason we hit max_width issues is
|
||||
// because the Shape is accounting for the `;` at the end of the `let-else` statement.
|
||||
let Some(x) = some_really_really_really_really_really_really_really_really_really_really_really_long_nameJ else {return};
|
||||
}
|
||||
|
||||
fn long_patterns() {
|
||||
let Foo {x: Bar(..), y: FooBar(..), z: Baz(..)} = opt else {
|
||||
return;
|
||||
};
|
||||
|
||||
// with version=One we don't wrap long array patterns
|
||||
let [aaaaaaaaaaaaaaaa, bbbbbbbbbbbbbbb, cccccccccccccccccc, dddddddddddddddddd] = opt else {
|
||||
return;
|
||||
};
|
||||
|
||||
let ("aaaaaaaaaaaaaaaaaaa" | "bbbbbbbbbbbbbbbbb" | "cccccccccccccccccccccccc" | "dddddddddddddddd" | "eeeeeeeeeeeeeeee") = opt else {
|
||||
return;
|
||||
};
|
||||
|
||||
let Some(Ok((Message::ChangeColor(super::color::Color::Rgb(r, g, b)), Point { x, y, z }))) = opt else {
|
||||
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 };
|
||||
}
|
||||
|
60
tests/target/configs/single_line_let_else_max_width/100.rs
Normal file
60
tests/target/configs/single_line_let_else_max_width/100.rs
Normal file
@ -0,0 +1,60 @@
|
||||
// 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 (..) { .. })`",
|
||||
));
|
||||
};
|
||||
}
|
62
tests/target/configs/single_line_let_else_max_width/50.rs
Normal file
62
tests/target/configs/single_line_let_else_max_width/50.rs
Normal file
@ -0,0 +1,62 @@
|
||||
// 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 (..) { .. })`",
|
||||
));
|
||||
};
|
||||
}
|
66
tests/target/configs/single_line_let_else_max_width/zero.rs
Normal file
66
tests/target/configs/single_line_let_else_max_width/zero.rs
Normal file
@ -0,0 +1,66 @@
|
||||
// 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 (..) { .. })`",
|
||||
));
|
||||
};
|
||||
}
|
@ -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;
|
||||
};
|
||||
}
|
||||
|
@ -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 };
|
||||
}
|
||||
|
@ -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;
|
||||
};
|
||||
}
|
||||
|
@ -1,3 +1,254 @@
|
||||
// rustfmt-single_line_let_else_max_width: 100
|
||||
|
||||
fn main() {
|
||||
let Some(1) = Some(1) else { return };
|
||||
// Although this won't compile it still parses so make sure we can format empty else blocks
|
||||
let Some(x) = opt else {};
|
||||
|
||||
// let-else may be formatted on a single line if they are "short"
|
||||
// and only contain a single expression
|
||||
let Some(x) = opt else { return };
|
||||
|
||||
let Some(x) = opt else { return };
|
||||
|
||||
let Some(x) = opt else {
|
||||
return;
|
||||
};
|
||||
|
||||
let Some(x) = opt else {
|
||||
// nope
|
||||
return;
|
||||
};
|
||||
|
||||
let Some(x) = opt else {
|
||||
let y = 1;
|
||||
return y;
|
||||
};
|
||||
|
||||
let Some(x) = y.foo(
|
||||
"abc",
|
||||
fairly_long_identifier,
|
||||
"def",
|
||||
"123456",
|
||||
"string",
|
||||
"cheese",
|
||||
) else {
|
||||
bar()
|
||||
};
|
||||
|
||||
let Some(x) = abcdef()
|
||||
.foo(
|
||||
"abc",
|
||||
some_really_really_really_long_ident,
|
||||
"ident",
|
||||
"123456",
|
||||
)
|
||||
.bar()
|
||||
.baz()
|
||||
.qux("fffffffffffffffff")
|
||||
else {
|
||||
foo_bar()
|
||||
};
|
||||
}
|
||||
|
||||
fn with_comments_around_else_keyword() {
|
||||
let Some(x) = opt
|
||||
/* pre else keyword block-comment */
|
||||
else {
|
||||
return;
|
||||
};
|
||||
|
||||
let Some(x) = opt else
|
||||
/* post else keyword block-comment */
|
||||
{
|
||||
return;
|
||||
};
|
||||
|
||||
let Some(x) = opt
|
||||
/* pre else keyword block-comment */
|
||||
else
|
||||
/* post else keyword block-comment */
|
||||
{
|
||||
return;
|
||||
};
|
||||
|
||||
let Some(x) = opt
|
||||
// pre else keyword line-comment
|
||||
else {
|
||||
return;
|
||||
};
|
||||
|
||||
let Some(x) = opt else
|
||||
// post else keyword line-comment
|
||||
{
|
||||
return;
|
||||
};
|
||||
|
||||
let Some(x) = opt
|
||||
// pre else keyword line-comment
|
||||
else
|
||||
// post else keyword line-comment
|
||||
{
|
||||
return;
|
||||
};
|
||||
}
|
||||
|
||||
fn unbreakable_initializer_expr_pre_formatting_let_else_length_near_max_width() {
|
||||
// Pre Formatting:
|
||||
// The length of `(indent)let pat = init else block;` is 100 (max_width)
|
||||
// Post Formatting:
|
||||
// The formatting is left unchanged!
|
||||
let Some(x) = some_really_really_really_really_really_really_really_long_name_A else { return };
|
||||
|
||||
// Pre Formatting:
|
||||
// The length of `(indent)let pat = init else block;` is 100 (max_width)
|
||||
// Post Formatting:
|
||||
// The else keyword and opening brace remain on the same line as the initializer expr,
|
||||
// and the else block is formatted over multiple lines because we can't fit the
|
||||
// else block on the same line as the initializer expr.
|
||||
let Some(x) = some_really_really_really_really_really_really_really_long_name___B else {
|
||||
return;
|
||||
};
|
||||
|
||||
// Pre Formatting:
|
||||
// The length of `(indent)let pat = init else block;` is 100 (max_width)
|
||||
// Post Formatting:
|
||||
// The else keyword and opening brace remain on the same line as the initializer expr,
|
||||
// and the else block is formatted over multiple lines because we can't fit the
|
||||
// else block on the same line as the initializer expr.
|
||||
let Some(x) = some_really_really_really_really_long_name_____C else {
|
||||
some_divergent_function()
|
||||
};
|
||||
|
||||
// Pre Formatting:
|
||||
// The length of `(indent)let pat = init else block;` is 101 (> max_width)
|
||||
// Post Formatting:
|
||||
// The else keyword and opening brace remain on the same line as the initializer expr,
|
||||
// and the else block is formatted over multiple lines because we can't fit the
|
||||
// else block on the same line as the initializer expr.
|
||||
let Some(x) = some_really_really_really_really_really_really_really_long_name__D else {
|
||||
return;
|
||||
};
|
||||
}
|
||||
|
||||
fn unbreakable_initializer_expr_pre_formatting_length_up_to_opening_brace_near_max_width() {
|
||||
// Pre Formatting:
|
||||
// The length of `(indent)let pat = init else {` is 99 (< max_width)
|
||||
// Post Formatting:
|
||||
// The else keyword and opening brace remain on the same line as the initializer expr,
|
||||
// and the else block is formatted over multiple lines because we can't fit the
|
||||
// else block on the same line as the initializer expr.
|
||||
let Some(x) = some_really_really_really_really_really_really_really_really_long_name___E else {
|
||||
return;
|
||||
};
|
||||
|
||||
// Pre Formatting:
|
||||
// The length of `(indent)let pat = init else {` is 101 (> max_width)
|
||||
// Post Formatting:
|
||||
// The else keyword and opening brace cannot fit on the same line as the initializer expr.
|
||||
// They are formatted on the next line.
|
||||
let Some(x) = some_really_really_really_really_really_really_really_really_long_name_____F
|
||||
else {
|
||||
return;
|
||||
};
|
||||
}
|
||||
|
||||
fn unbreakable_initializer_expr_pre_formatting_length_through_initializer_expr_near_max_width() {
|
||||
// Pre Formatting:
|
||||
// The length of `(indent)let pat = init` is 99 (< max_width)
|
||||
// Post Formatting:
|
||||
// The else keyword and opening brace cannot fit on the same line as the initializer expr.
|
||||
// They are formatted on the next line.
|
||||
let Some(x) = some_really_really_really_really_really_really_really_really_really_long_name___G
|
||||
else {
|
||||
return;
|
||||
};
|
||||
|
||||
// Pre Formatting:
|
||||
// The length of `(indent)let pat = init` is 100 (max_width)
|
||||
// Post Formatting:
|
||||
// Break after the `=` and put the initializer expr on it's own line.
|
||||
// Because the initializer expr is multi-lined the else is placed on it's own line.
|
||||
let Some(x) =
|
||||
some_really_really_really_really_really_really_really_really_really_long_name____H
|
||||
else {
|
||||
return;
|
||||
};
|
||||
|
||||
// Pre Formatting:
|
||||
// The length of `(indent)let pat = init` is 109 (> max_width)
|
||||
// Post Formatting:
|
||||
// Break after the `=` and put the initializer expr on it's own line.
|
||||
// Because the initializer expr is multi-lined the else is placed on it's own line.
|
||||
// The initializer expr has a length of 91, which when indented on the next line
|
||||
// The `(indent)init` line has a lengh of 99. This is the max length that the `init` can be
|
||||
// before we start running into max_width issues. I suspect this is becuase the shape is
|
||||
// accounting for the `;` at the end of the `let-else` statement.
|
||||
let Some(x) =
|
||||
some_really_really_really_really_really_really_really_really_really_really_long_name______I
|
||||
else {
|
||||
return;
|
||||
};
|
||||
|
||||
// Pre Formatting:
|
||||
// The length of `(indent)let pat = init` is 110 (> max_width)
|
||||
// Post Formatting:
|
||||
// Max length issues prevent us from formatting.
|
||||
// The initializer expr has a length of 92, which if it would be indented on the next line
|
||||
// the `(indent)init` line has a lengh of 100 which == max_width of 100.
|
||||
// One might expect formatting to succeed, but I suspect the reason we hit max_width issues is
|
||||
// because the Shape is accounting for the `;` at the end of the `let-else` statement.
|
||||
let Some(x) = some_really_really_really_really_really_really_really_really_really_really_really_long_nameJ else {return};
|
||||
}
|
||||
|
||||
fn long_patterns() {
|
||||
let Foo {
|
||||
x: Bar(..),
|
||||
y: FooBar(..),
|
||||
z: Baz(..),
|
||||
} = opt
|
||||
else {
|
||||
return;
|
||||
};
|
||||
|
||||
// with version=One we don't wrap long array patterns
|
||||
let [aaaaaaaaaaaaaaaa, bbbbbbbbbbbbbbb, cccccccccccccccccc, dddddddddddddddddd] = opt else {
|
||||
return;
|
||||
};
|
||||
|
||||
let ("aaaaaaaaaaaaaaaaaaa"
|
||||
| "bbbbbbbbbbbbbbbbb"
|
||||
| "cccccccccccccccccccccccc"
|
||||
| "dddddddddddddddd"
|
||||
| "eeeeeeeeeeeeeeee") = opt
|
||||
else {
|
||||
return;
|
||||
};
|
||||
|
||||
let Some(Ok((Message::ChangeColor(super::color::Color::Rgb(r, g, b)), Point { x, y, z }))) =
|
||||
opt
|
||||
else {
|
||||
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;
|
||||
};
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user