diff options
Diffstat (limited to 'src/tools/rustfmt/tests')
35 files changed, 1606 insertions, 6 deletions
diff --git a/src/tools/rustfmt/tests/rustfmt/main.rs b/src/tools/rustfmt/tests/rustfmt/main.rs index 7ff301e80..4936a7174 100644 --- a/src/tools/rustfmt/tests/rustfmt/main.rs +++ b/src/tools/rustfmt/tests/rustfmt/main.rs @@ -174,3 +174,15 @@ fn rustfmt_emits_error_on_line_overflow_true() { "line formatted, but exceeded maximum width (maximum: 100 (see `max_width` option)" )) } + +#[test] +#[allow(non_snake_case)] +fn dont_emit_ICE() { + let files = ["tests/target/issue_5728.rs", "tests/target/issue_5729.rs"]; + + for file in files { + let args = [file]; + let (_stdout, stderr) = rustfmt(&args); + assert!(!stderr.contains("thread 'main' panicked")); + } +} diff --git a/src/tools/rustfmt/tests/source/configs/single_line_let_else_max_width/100.rs b/src/tools/rustfmt/tests/source/configs/single_line_let_else_max_width/100.rs new file mode 100644 index 000000000..a73c9084b --- /dev/null +++ b/src/tools/rustfmt/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/src/tools/rustfmt/tests/source/configs/single_line_let_else_max_width/50.rs b/src/tools/rustfmt/tests/source/configs/single_line_let_else_max_width/50.rs new file mode 100644 index 000000000..87d0583c5 --- /dev/null +++ b/src/tools/rustfmt/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/src/tools/rustfmt/tests/source/configs/single_line_let_else_max_width/zero.rs b/src/tools/rustfmt/tests/source/configs/single_line_let_else_max_width/zero.rs new file mode 100644 index 000000000..afb9e5033 --- /dev/null +++ b/src/tools/rustfmt/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/src/tools/rustfmt/tests/source/configs/use_small_heuristics/default.rs b/src/tools/rustfmt/tests/source/configs/use_small_heuristics/default.rs index 68bc40271..95238c548 100644 --- a/src/tools/rustfmt/tests/source/configs/use_small_heuristics/default.rs +++ b/src/tools/rustfmt/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/src/tools/rustfmt/tests/source/configs/use_small_heuristics/max.rs b/src/tools/rustfmt/tests/source/configs/use_small_heuristics/max.rs index 8d30932e2..b79302e22 100644 --- a/src/tools/rustfmt/tests/source/configs/use_small_heuristics/max.rs +++ b/src/tools/rustfmt/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/src/tools/rustfmt/tests/source/configs/use_small_heuristics/off.rs b/src/tools/rustfmt/tests/source/configs/use_small_heuristics/off.rs index f76392d24..80bcdd898 100644 --- a/src/tools/rustfmt/tests/source/configs/use_small_heuristics/off.rs +++ b/src/tools/rustfmt/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/src/tools/rustfmt/tests/source/issue-4041.rs b/src/tools/rustfmt/tests/source/issue-4041.rs new file mode 100644 index 000000000..274b80f1b --- /dev/null +++ b/src/tools/rustfmt/tests/source/issue-4041.rs @@ -0,0 +1,5 @@ +// rustfmt-wrap_comments: true +//! List: +//! - Sub list: +//! + very long #1 blah blah blah blah blah blah blah blah blah blah blah blah foo baar baxxxxxxxx long line 1231421230912i3091238192038 +//! + very long #2 blah blah blah blah blah blah blah blah blah blah blah blah diff --git a/src/tools/rustfmt/tests/source/issue-5234.rs b/src/tools/rustfmt/tests/source/issue-5234.rs new file mode 100644 index 000000000..67266f485 --- /dev/null +++ b/src/tools/rustfmt/tests/source/issue-5234.rs @@ -0,0 +1,51 @@ +// rustfmt-format_code_in_doc_comments: true + +/// ``` +/// ``` +fn foo() {} + +/// ``` +///Something +/// ``` +fn foo() {} + +/// ``` +/// +/// ``` +fn foo() {} + + +/// /// ``` +fn foo() {} + +/// /// ``` +/// ``` +/// +/// ``` +/// ``` +fn foo() {} + +fn foo() { +/// ``` +/// +/// ``` +struct bar {} +} + +/// ``` +/// fn com(){ +/// let i = 5; +/// +/// let j = 6; +/// } +/// ``` +fn foo() {} + +fn foo() { +/// ``` +///fn com(){ +///let i = 5; +///} +/// ``` +struct bar {} +} diff --git a/src/tools/rustfmt/tests/source/issue-5488.rs b/src/tools/rustfmt/tests/source/issue-5488.rs new file mode 100644 index 000000000..d361632e2 --- /dev/null +++ b/src/tools/rustfmt/tests/source/issue-5488.rs @@ -0,0 +1,17 @@ +// rustfmt-use_field_init_shorthand: true + +struct MyStruct(u32); +struct AnotherStruct { + a: u32, +} + +fn main() { + // Since MyStruct is a tuple struct, it should not be shorthanded to + // MyStruct { 0 } even if use_field_init_shorthand is enabled. + let instance = MyStruct { 0: 0 }; + + // Since AnotherStruct is not a tuple struct, the shorthand should + // apply. + let a = 10; + let instance = AnotherStruct { a: a }; +} diff --git a/src/tools/rustfmt/tests/source/issue-5586.rs b/src/tools/rustfmt/tests/source/issue-5586.rs new file mode 100644 index 000000000..9cf6c1d58 --- /dev/null +++ b/src/tools/rustfmt/tests/source/issue-5586.rs @@ -0,0 +1,164 @@ +// rustfmt-version: Two +fn main() { + // sample 1 + { + { + { + { + { + let push_ident = + if let Some(&node_id) = subgraph_nodes.get(pull_to_push_idx) { + self.node_id_as_ident(node_id, false) + } else { + // Entire subgraph is pull (except for a single send/push handoff output). + assert_eq!( + 1, + send_ports.len(), + "If entire subgraph is pull, should have only one handoff output." +); + send_ports[0].clone() + }; + } + } + } + } + } + + // sample 2 + { + { + { + { + { + let push_ident = if let Some(&node_id) = + subgraph_nodes.get(pull_to_push_idx) + { + self.node_id_as_ident(node_id, false) + } else { + // Entire subgraph is pull (except for a single send/push handoff output). + assert_eq!( + 1, + send_ports.len(), + "If entire subgraph is pull, should have only one handoff output." + ); + send_ports[0].clone() + }; + } + } + } + } + } + + // sample 3 + { + { + { + { + { + let push_ident = + if let Some(&node_id) = subgraph_nodes.get(pull_to_push_idx) { + self.node_id_as_ident(node_id, false) + } else { + // Entire subgraph is pull (except for a single send/push handoff output). + assert_eq!( + 1, + send_ports.len(), + "If entire subgraph is pull, should have only one handoff output." + ); + send_ports[0].clone() + }; + } + } + } + } + } + + // sample 4 + {{{{{ + let push_ident = + if let Some(&node_id) = subgraph_nodes.get(pull_to_push_idx) { + self.node_id_as_ident(node_id, false) + } else { + // Entire subgraph is pull (except for a single send/push handoff output). + assert_eq!( + 1, + send_ports.len(), + "If entire subgraph is pull, should have only one handoff output." + ); + send_ports[0].clone() + }; + }}}}} + + // sample 5 + { + { + { + { + { + let push_ident = + if let Some(&node_id) = subgraph_nodes.get(pull_to_push_idx) { + self.node_id_as_ident(node_id, false) + } else { + // Entire subgraph is pull (except for a single send/push handoff output). + assert_eq!( + 1, + send_ports.len(), + "If entire subgraph is pull, should have only one handoff output." + ); + send_ports[0].clone() + }; + } + } + } + } + } + + // sample 6 + { + { + { + { + { + let push_ident = if let Some(&node_id) = + subgraph_nodes.get(pull_to_push_idx) + { + self.node_id_as_ident(node_id, false) + } else { + // Entire subgraph is pull (except for a single send/push handoff output). + assert_eq!( + 1, + send_ports.len(), + "If entire subgraph is pull, should have only one handoff output." + ); + send_ports[0].clone() + }; + } + } + } + } + } + + // sample 7 + { + { + { + { + { + let push_ident = + if let Some(&node_id) = subgraph_nodes.get(pull_to_push_idx) { + self.node_id_as_ident(node_id, false) + } else { + // Entire subgraph is pull (except for a single send/push handoff output). + assert_eq!( + 1, + send_ports.len(), + "If entire subgraph is pull, should have only one handoff output." + ); + send_ports[0].clone() + }; + } + } + } + } + } +} diff --git a/src/tools/rustfmt/tests/source/issue_5686.rs b/src/tools/rustfmt/tests/source/issue_5686.rs new file mode 100644 index 000000000..3bf96f73b --- /dev/null +++ b/src/tools/rustfmt/tests/source/issue_5686.rs @@ -0,0 +1,40 @@ +#[repr(u8)] +enum MyEnum { + UnitWithExplicitDiscriminant = 0, + EmptyStructSingleLineBlockComment { + /* Comment */ + } = 1, + EmptyStructMultiLineBlockComment { + /* + * Comment + */ + } = 2, + EmptyStructLineComment { + // comment + } = 3, + EmptyTupleSingleLineBlockComment( + /* Comment */ + ) = 4, + EmptyTupleMultiLineBlockComment( + /* + * Comment + */ + ) = 5, + EmptyTupleLineComment( + // comment + ) = 6, +} + +enum Animal { + Dog(/* tuple variant closer in comment -> ) */) = 1, + #[hello(world)] + Cat(/* tuple variant close in leading attribute */) = 2, + Bee(/* tuple variant closer on associated field attribute */ #[hello(world)] usize) = 3, + Fox(/* tuple variant closer on const fn call */) = some_const_fn(), + Ant(/* tuple variant closer on macro call */) = some_macro!(), + Snake {/* stuct variant closer in comment -> } */} = 6, + #[hell{world}] + Cobra {/* struct variant close in leading attribute */} = 6, + Eagle {/* struct variant closer on associated field attribute */ #[hell{world}]value: Sting} = 7, + Koala {/* struct variant closer on macro call */} = some_macro!{} +} diff --git a/src/tools/rustfmt/tests/source/itemized-blocks/no_wrap.rs b/src/tools/rustfmt/tests/source/itemized-blocks/no_wrap.rs index a7b6a10a0..e5699e766 100644 --- a/src/tools/rustfmt/tests/source/itemized-blocks/no_wrap.rs +++ b/src/tools/rustfmt/tests/source/itemized-blocks/no_wrap.rs @@ -1,7 +1,7 @@ // rustfmt-normalize_comments: true // rustfmt-format_code_in_doc_comments: true -//! This is a list: +//! This is an itemized markdown list (see also issue #3224): //! * Outer //! * Outer //! * Inner @@ -13,6 +13,40 @@ //! - when the log level is info, the level name is green and the rest of the line is white //! - when the log level is debug, the whole line is white //! - when the log level is trace, the whole line is gray ("bright black") +//! +//! This is a numbered markdown list (see also issue #5416): +//! 1. Long long long long long long long long long long long long long long long long long line +//! 2. Another very long long long long long long long long long long long long long long long line +//! 3. Nested list +//! 1. Long long long long long long long long long long long long long long long long line +//! 2. Another very long long long long long long long long long long long long long long line +//! 4. Last item +//! +//! Using the ')' instead of '.' character after the number: +//! 1) Long long long long long long long long long long long long long long long long long line +//! 2) Another very long long long long long long long long long long long long long long long line +//! +//! Deep list that mixes various bullet and number formats: +//! 1. First level with a long long long long long long long long long long long long long long +//! long long long line +//! 2. First level with another very long long long long long long long long long long long long +//! long long long line +//! * Second level with a long long long long long long long long long long long long long +//! long long long line +//! * Second level with another very long long long long long long long long long long long +//! long long long line +//! 1) Third level with a long long long long long long long long long long long long long +//! long long long line +//! 2) Third level with another very long long long long long long long long long long +//! long long long long line +//! - Forth level with a long long long long long long long long long long long long +//! long long long long line +//! - Forth level with another very long long long long long long long long long long +//! long long long long line +//! 3) One more item at the third level +//! 4) Last item of the third level +//! * Last item of second level +//! 3. Last item of first level /// All the parameters ***except for `from_theater`*** should be inserted as sent by the remote /// theater, i.e., as passed to [`Theater::send`] on the remote actor: diff --git a/src/tools/rustfmt/tests/source/itemized-blocks/wrap.rs b/src/tools/rustfmt/tests/source/itemized-blocks/wrap.rs index 955cc698b..768461a43 100644 --- a/src/tools/rustfmt/tests/source/itemized-blocks/wrap.rs +++ b/src/tools/rustfmt/tests/source/itemized-blocks/wrap.rs @@ -2,7 +2,7 @@ // rustfmt-format_code_in_doc_comments: true // rustfmt-max_width: 50 -//! This is a list: +//! This is an itemized markdown list (see also issue #3224): //! * Outer //! * Outer //! * Inner @@ -14,6 +14,40 @@ //! - when the log level is info, the level name is green and the rest of the line is white //! - when the log level is debug, the whole line is white //! - when the log level is trace, the whole line is gray ("bright black") +//! +//! This is a numbered markdown list (see also issue #5416): +//! 1. Long long long long long long long long long long long long long long long long long line +//! 2. Another very long long long long long long long long long long long long long long long line +//! 3. Nested list +//! 1. Long long long long long long long long long long long long long long long long line +//! 2. Another very long long long long long long long long long long long long long long line +//! 4. Last item +//! +//! Using the ')' instead of '.' character after the number: +//! 1) Long long long long long long long long long long long long long long long long long line +//! 2) Another very long long long long long long long long long long long long long long long line +//! +//! Deep list that mixes various bullet and number formats: +//! 1. First level with a long long long long long long long long long long long long long long +//! long long long line +//! 2. First level with another very long long long long long long long long long long long long +//! long long long line +//! * Second level with a long long long long long long long long long long long long long +//! long long long line +//! * Second level with another very long long long long long long long long long long long +//! long long long line +//! 1) Third level with a long long long long long long long long long long long long long +//! long long long line +//! 2) Third level with another very long long long long long long long long long long +//! long long long long line +//! - Forth level with a long long long long long long long long long long long long +//! long long long long line +//! - Forth level with another very long long long long long long long long long long +//! long long long long line +//! 3) One more item at the third level +//! 4) Last item of the third level +//! * Last item of second level +//! 3. Last item of first level // This example shows how to configure fern to output really nicely colored logs // - when the log level is error, the whole line is red diff --git a/src/tools/rustfmt/tests/source/let_else.rs b/src/tools/rustfmt/tests/source/let_else.rs index a6e816fb5..85b3604ad 100644 --- a/src/tools/rustfmt/tests/source/let_else.rs +++ b/src/tools/rustfmt/tests/source/let_else.rs @@ -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 }; } diff --git a/src/tools/rustfmt/tests/target/configs/single_line_let_else_max_width/100.rs b/src/tools/rustfmt/tests/target/configs/single_line_let_else_max_width/100.rs new file mode 100644 index 000000000..0409124a5 --- /dev/null +++ b/src/tools/rustfmt/tests/target/configs/single_line_let_else_max_width/100.rs @@ -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 (..) { .. })`", + )); + }; +} diff --git a/src/tools/rustfmt/tests/target/configs/single_line_let_else_max_width/50.rs b/src/tools/rustfmt/tests/target/configs/single_line_let_else_max_width/50.rs new file mode 100644 index 000000000..6afc2b6f2 --- /dev/null +++ b/src/tools/rustfmt/tests/target/configs/single_line_let_else_max_width/50.rs @@ -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 (..) { .. })`", + )); + }; +} diff --git a/src/tools/rustfmt/tests/target/configs/single_line_let_else_max_width/zero.rs b/src/tools/rustfmt/tests/target/configs/single_line_let_else_max_width/zero.rs new file mode 100644 index 000000000..b5fd0b9ed --- /dev/null +++ b/src/tools/rustfmt/tests/target/configs/single_line_let_else_max_width/zero.rs @@ -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 (..) { .. })`", + )); + }; +} diff --git a/src/tools/rustfmt/tests/target/configs/use_small_heuristics/default.rs b/src/tools/rustfmt/tests/target/configs/use_small_heuristics/default.rs index d67bd9aaf..ad4073923 100644 --- a/src/tools/rustfmt/tests/target/configs/use_small_heuristics/default.rs +++ b/src/tools/rustfmt/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/src/tools/rustfmt/tests/target/configs/use_small_heuristics/max.rs b/src/tools/rustfmt/tests/target/configs/use_small_heuristics/max.rs index 785dfbea0..fe57f853d 100644 --- a/src/tools/rustfmt/tests/target/configs/use_small_heuristics/max.rs +++ b/src/tools/rustfmt/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/src/tools/rustfmt/tests/target/configs/use_small_heuristics/off.rs b/src/tools/rustfmt/tests/target/configs/use_small_heuristics/off.rs index f76392d24..b0b4e4ee4 100644 --- a/src/tools/rustfmt/tests/target/configs/use_small_heuristics/off.rs +++ b/src/tools/rustfmt/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/src/tools/rustfmt/tests/target/doc-of-generic-item.rs b/src/tools/rustfmt/tests/target/doc-of-generic-item.rs index 2efc5e09a..80886e74f 100644 --- a/src/tools/rustfmt/tests/target/doc-of-generic-item.rs +++ b/src/tools/rustfmt/tests/target/doc-of-generic-item.rs @@ -12,3 +12,21 @@ struct Foo< /// doc of N const N: item, >; + +// Non-doc pre-comment of Foo +/// doc of Foo +// Non-doc post-comment of Foo +struct Foo< + // Non-doc pre-comment of 'a + /// doc of 'a + // Non-doc post-comment of 'a + 'a, + // Non-doc pre-comment of T + /// doc of T + // Non-doc post-comment of T + T, + // Non-doc pre-comment of N + /// doc of N + // Non-doc post-comment of N + const N: item, +>; diff --git a/src/tools/rustfmt/tests/target/issue-4041.rs b/src/tools/rustfmt/tests/target/issue-4041.rs new file mode 100644 index 000000000..e9c693836 --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue-4041.rs @@ -0,0 +1,6 @@ +// rustfmt-wrap_comments: true +//! List: +//! - Sub list: +//! + very long #1 blah blah blah blah blah blah blah blah blah blah blah blah +//! foo baar baxxxxxxxx long line 1231421230912i3091238192038 +//! + very long #2 blah blah blah blah blah blah blah blah blah blah blah blah diff --git a/src/tools/rustfmt/tests/target/issue-4210-disabled.rs b/src/tools/rustfmt/tests/target/issue-4210-disabled.rs new file mode 100644 index 000000000..3ba87aab8 --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue-4210-disabled.rs @@ -0,0 +1,15 @@ +// rustfmt-wrap_comments: false + +/// Table that is > 80 symbols: +/// +/// | table | xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx | +/// |-------|-----------------------------------------------------------------------------| +/// | val | x | +pub struct Item; + +/// Table value that is > 80 symbols: +/// +/// | table | heading +/// |----------|----------------------------------------------------------------------------- +/// | long val | Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. +pub struct Item2; diff --git a/src/tools/rustfmt/tests/target/issue-4210.rs b/src/tools/rustfmt/tests/target/issue-4210.rs new file mode 100644 index 000000000..3fd966390 --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue-4210.rs @@ -0,0 +1,15 @@ +// rustfmt-wrap_comments: true + +/// Table that is > 80 symbols: +/// +/// | table | xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx | +/// |-------|-----------------------------------------------------------------------------| +/// | val | x | +pub struct Item; + +/// Table value that is > 80 symbols: +/// +/// | table | heading +/// |----------|----------------------------------------------------------------------------- +/// | long val | Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. +pub struct Item2; diff --git a/src/tools/rustfmt/tests/target/issue-5234.rs b/src/tools/rustfmt/tests/target/issue-5234.rs new file mode 100644 index 000000000..7ee9e46d1 --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue-5234.rs @@ -0,0 +1,47 @@ +// rustfmt-format_code_in_doc_comments: true + +/// ``` +/// ``` +fn foo() {} + +/// ``` +/// Something +/// ``` +fn foo() {} + +/// ``` +/// ``` +fn foo() {} + +/// /// ``` +fn foo() {} + +/// /// ``` +/// ``` +/// ``` +/// ``` +fn foo() {} + +fn foo() { + /// ``` + /// ``` + struct bar {} +} + +/// ``` +/// fn com() { +/// let i = 5; +/// +/// let j = 6; +/// } +/// ``` +fn foo() {} + +fn foo() { + /// ``` + /// fn com() { + /// let i = 5; + /// } + /// ``` + struct bar {} +} diff --git a/src/tools/rustfmt/tests/target/issue-5488.rs b/src/tools/rustfmt/tests/target/issue-5488.rs new file mode 100644 index 000000000..0cb37c56f --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue-5488.rs @@ -0,0 +1,17 @@ +// rustfmt-use_field_init_shorthand: true + +struct MyStruct(u32); +struct AnotherStruct { + a: u32, +} + +fn main() { + // Since MyStruct is a tuple struct, it should not be shorthanded to + // MyStruct { 0 } even if use_field_init_shorthand is enabled. + let instance = MyStruct { 0: 0 }; + + // Since AnotherStruct is not a tuple struct, the shorthand should + // apply. + let a = 10; + let instance = AnotherStruct { a }; +} diff --git a/src/tools/rustfmt/tests/target/issue-5586.rs b/src/tools/rustfmt/tests/target/issue-5586.rs new file mode 100644 index 000000000..7033ae975 --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue-5586.rs @@ -0,0 +1,177 @@ +// rustfmt-version: Two +fn main() { + // sample 1 + { + { + { + { + { + let push_ident = if let Some(&node_id) = + subgraph_nodes.get(pull_to_push_idx) + { + self.node_id_as_ident(node_id, false) + } else { + // Entire subgraph is pull (except for a single send/push handoff output). + assert_eq!( + 1, + send_ports.len(), + "If entire subgraph is pull, should have only one handoff output." + ); + send_ports[0].clone() + }; + } + } + } + } + } + + // sample 2 + { + { + { + { + { + let push_ident = if let Some(&node_id) = + subgraph_nodes.get(pull_to_push_idx) + { + self.node_id_as_ident(node_id, false) + } else { + // Entire subgraph is pull (except for a single send/push handoff output). + assert_eq!( + 1, + send_ports.len(), + "If entire subgraph is pull, should have only one handoff output." + ); + send_ports[0].clone() + }; + } + } + } + } + } + + // sample 3 + { + { + { + { + { + let push_ident = if let Some(&node_id) = + subgraph_nodes.get(pull_to_push_idx) + { + self.node_id_as_ident(node_id, false) + } else { + // Entire subgraph is pull (except for a single send/push handoff output). + assert_eq!( + 1, + send_ports.len(), + "If entire subgraph is pull, should have only one handoff output." + ); + send_ports[0].clone() + }; + } + } + } + } + } + + // sample 4 + { + { + { + { + { + let push_ident = if let Some(&node_id) = + subgraph_nodes.get(pull_to_push_idx) + { + self.node_id_as_ident(node_id, false) + } else { + // Entire subgraph is pull (except for a single send/push handoff output). + assert_eq!( + 1, + send_ports.len(), + "If entire subgraph is pull, should have only one handoff output." + ); + send_ports[0].clone() + }; + } + } + } + } + } + + // sample 5 + { + { + { + { + { + let push_ident = if let Some(&node_id) = + subgraph_nodes.get(pull_to_push_idx) + { + self.node_id_as_ident(node_id, false) + } else { + // Entire subgraph is pull (except for a single send/push handoff output). + assert_eq!( + 1, + send_ports.len(), + "If entire subgraph is pull, should have only one handoff output." + ); + send_ports[0].clone() + }; + } + } + } + } + } + + // sample 6 + { + { + { + { + { + let push_ident = if let Some(&node_id) = + subgraph_nodes.get(pull_to_push_idx) + { + self.node_id_as_ident(node_id, false) + } else { + // Entire subgraph is pull (except for a single send/push handoff output). + assert_eq!( + 1, + send_ports.len(), + "If entire subgraph is pull, should have only one handoff output." + ); + send_ports[0].clone() + }; + } + } + } + } + } + + // sample 7 + { + { + { + { + { + let push_ident = if let Some(&node_id) = + subgraph_nodes.get(pull_to_push_idx) + { + self.node_id_as_ident(node_id, false) + } else { + // Entire subgraph is pull (except for a single send/push handoff output). + assert_eq!( + 1, + send_ports.len(), + "If entire subgraph is pull, should have only one handoff output." + ); + send_ports[0].clone() + }; + } + } + } + } + } +} diff --git a/src/tools/rustfmt/tests/target/issue_5686.rs b/src/tools/rustfmt/tests/target/issue_5686.rs new file mode 100644 index 000000000..993f12b53 --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue_5686.rs @@ -0,0 +1,42 @@ +#[repr(u8)] +enum MyEnum { + UnitWithExplicitDiscriminant = 0, + EmptyStructSingleLineBlockComment {/* Comment */} = 1, + EmptyStructMultiLineBlockComment { + /* + * Comment + */ + } = 2, + EmptyStructLineComment { + // comment + } = 3, + EmptyTupleSingleLineBlockComment(/* Comment */) = 4, + EmptyTupleMultiLineBlockComment( + /* + * Comment + */ + ) = 5, + EmptyTupleLineComment( + // comment + ) = 6, +} + +enum Animal { + Dog(/* tuple variant closer in comment -> ) */) = 1, + #[hello(world)] + Cat(/* tuple variant close in leading attribute */) = 2, + Bee( + /* tuple variant closer on associated field attribute */ #[hello(world)] usize, + ) = 3, + Fox(/* tuple variant closer on const fn call */) = some_const_fn(), + Ant(/* tuple variant closer on macro call */) = some_macro!(), + Snake {/* stuct variant closer in comment -> } */} = 6, + #[hell{world}] + Cobra {/* struct variant close in leading attribute */} = 6, + Eagle { + /* struct variant closer on associated field attribute */ + #[hell{world}] + value: Sting, + } = 7, + Koala {/* struct variant closer on macro call */} = some_macro! {}, +} diff --git a/src/tools/rustfmt/tests/target/issue_5691.rs b/src/tools/rustfmt/tests/target/issue_5691.rs new file mode 100644 index 000000000..e3aad15db --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue_5691.rs @@ -0,0 +1,16 @@ +struct S<const C: usize> +where + [(); { num_slots!(C) }]:, { + /* An asterisk-based, or a double-slash-prefixed, comment here is + required to trigger the fmt bug. + + A single-line triple-slash-prefixed comment (with a field following it) is not enough - it will not trigger the fmt bug. + + Side note: If you have a combination of two, or all three of the + above mentioned types of comments here, some of them disappear + after `cargo fmt`. + + The bug gets triggered even if a field definition following the + (asterisk-based, or a double-slash-prefixed) comment, too. + */ +} diff --git a/src/tools/rustfmt/tests/target/issue_5728.rs b/src/tools/rustfmt/tests/target/issue_5728.rs new file mode 100644 index 000000000..e1355416f --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue_5728.rs @@ -0,0 +1,5 @@ +cfg_if::cfg_if! { + if #[cfg(windows)] { + } else if #(&cpus) { + } else [libc::CTL_HW, libc::HW_NCPU, 0, 0] +} diff --git a/src/tools/rustfmt/tests/target/issue_5729.rs b/src/tools/rustfmt/tests/target/issue_5729.rs new file mode 100644 index 000000000..d63c83e88 --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue_5729.rs @@ -0,0 +1,5 @@ +cfg_if::cfg_if! { + if { + } else if #(&cpus) { + } else [libc::CTL_HW, libc::HW_NCPU, 0, 0] +} diff --git a/src/tools/rustfmt/tests/target/itemized-blocks/no_wrap.rs b/src/tools/rustfmt/tests/target/itemized-blocks/no_wrap.rs index de8856382..86818b447 100644 --- a/src/tools/rustfmt/tests/target/itemized-blocks/no_wrap.rs +++ b/src/tools/rustfmt/tests/target/itemized-blocks/no_wrap.rs @@ -1,7 +1,7 @@ // rustfmt-normalize_comments: true // rustfmt-format_code_in_doc_comments: true -//! This is a list: +//! This is an itemized markdown list (see also issue #3224): //! * Outer //! * Outer //! * Inner @@ -13,6 +13,40 @@ //! - when the log level is info, the level name is green and the rest of the line is white //! - when the log level is debug, the whole line is white //! - when the log level is trace, the whole line is gray ("bright black") +//! +//! This is a numbered markdown list (see also issue #5416): +//! 1. Long long long long long long long long long long long long long long long long long line +//! 2. Another very long long long long long long long long long long long long long long long line +//! 3. Nested list +//! 1. Long long long long long long long long long long long long long long long long line +//! 2. Another very long long long long long long long long long long long long long long line +//! 4. Last item +//! +//! Using the ')' instead of '.' character after the number: +//! 1) Long long long long long long long long long long long long long long long long long line +//! 2) Another very long long long long long long long long long long long long long long long line +//! +//! Deep list that mixes various bullet and number formats: +//! 1. First level with a long long long long long long long long long long long long long long +//! long long long line +//! 2. First level with another very long long long long long long long long long long long long +//! long long long line +//! * Second level with a long long long long long long long long long long long long long +//! long long long line +//! * Second level with another very long long long long long long long long long long long +//! long long long line +//! 1) Third level with a long long long long long long long long long long long long long +//! long long long line +//! 2) Third level with another very long long long long long long long long long long +//! long long long long line +//! - Forth level with a long long long long long long long long long long long long +//! long long long long line +//! - Forth level with another very long long long long long long long long long long +//! long long long long line +//! 3) One more item at the third level +//! 4) Last item of the third level +//! * Last item of second level +//! 3. Last item of first level /// All the parameters ***except for `from_theater`*** should be inserted as sent by the remote /// theater, i.e., as passed to [`Theater::send`] on the remote actor: diff --git a/src/tools/rustfmt/tests/target/itemized-blocks/wrap.rs b/src/tools/rustfmt/tests/target/itemized-blocks/wrap.rs index a4907303c..4826590ea 100644 --- a/src/tools/rustfmt/tests/target/itemized-blocks/wrap.rs +++ b/src/tools/rustfmt/tests/target/itemized-blocks/wrap.rs @@ -2,7 +2,8 @@ // rustfmt-format_code_in_doc_comments: true // rustfmt-max_width: 50 -//! This is a list: +//! This is an itemized markdown list (see also +//! issue #3224): //! * Outer //! * Outer //! * Inner @@ -23,6 +24,65 @@ //! is white //! - when the log level is trace, the whole line //! is gray ("bright black") +//! +//! This is a numbered markdown list (see also +//! issue #5416): +//! 1. Long long long long long long long long +//! long long long long long long long long +//! long line +//! 2. Another very long long long long long long +//! long long long long long long long long +//! long line +//! 3. Nested list +//! 1. Long long long long long long long long +//! long long long long long long long long +//! line +//! 2. Another very long long long long long +//! long long long long long long long long +//! long line +//! 4. Last item +//! +//! Using the ')' instead of '.' character after +//! the number: +//! 1) Long long long long long long long long +//! long long long long long long long long +//! long line +//! 2) Another very long long long long long long +//! long long long long long long long long +//! long line +//! +//! Deep list that mixes various bullet and number +//! formats: +//! 1. First level with a long long long long long +//! long long long long long long long long +//! long long long long line +//! 2. First level with another very long long +//! long long long long long long long long +//! long long long long long line +//! * Second level with a long long long long +//! long long long long long long long long +//! long long long long line +//! * Second level with another very long long +//! long long long long long long long long +//! long long long long line +//! 1) Third level with a long long long +//! long long long long long long long +//! long long long long long long line +//! 2) Third level with another very long +//! long long long long long long long +//! long long long long long long line +//! - Forth level with a long long +//! long long long long long long +//! long long long long long long +//! long long line +//! - Forth level with another very +//! long long long long long long +//! long long long long long long +//! long long line +//! 3) One more item at the third level +//! 4) Last item of the third level +//! * Last item of second level +//! 3. Last item of first level // This example shows how to configure fern to // output really nicely colored logs diff --git a/src/tools/rustfmt/tests/target/let_else.rs b/src/tools/rustfmt/tests/target/let_else.rs index a6e816fb5..6554a0961 100644 --- a/src/tools/rustfmt/tests/target/let_else.rs +++ b/src/tools/rustfmt/tests/target/let_else.rs @@ -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; + }; } |