Skip to content

Commit e5f4bc0

Browse files
committed
Add new config option OverflowDensity
Through testing it was found that `Tall` as the default value for `fn_call_layout` was not backwards compatable and would lead to breaking formatting changes. Instead of version gating the new behavior, which would also lead to unexpected formatting changes for users who already set `version=Two`, it was decided that a new option should be add to encapsulate rustfmt's previous function argument behavior. In the context of `fn_call_layout` this new option has all the same variants as the `Density` option used for `fn_params_layout`.
1 parent 99f9475 commit e5f4bc0

File tree

13 files changed

+314
-14
lines changed

13 files changed

+314
-14
lines changed

Configurations.md

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -760,11 +760,33 @@ See also [`fn_params_layout`](#fn_params_layout)
760760

761761
Control the layout of arguments in function calls
762762

763-
- **Default value**: `"Tall"`
764-
- **Possible values**: `"Compressed"`, `"Tall"`, `"Vertical"`
763+
- **Default value**: `"Foo"`
764+
- **Possible values**: `"Foo"` `"Compressed"`, `"Tall"`, `"Vertical"`
765765
- **Stable**: No (tracking issue: N/A)
766766

767-
#### `"Tall"` (default):
767+
#### `"Foo"` (default):
768+
769+
```rust
770+
fn main() {
771+
lorem(ipsum, dolor, sit, amet);
772+
ipsum(
773+
dolor,
774+
sit,
775+
amet,
776+
consectetur,
777+
adipiscing,
778+
elit,
779+
vivamus,
780+
ipsum,
781+
orci,
782+
rhoncus,
783+
vel,
784+
imperdiet,
785+
);
786+
}
787+
```
788+
789+
#### `"Tall"`:
768790

769791
```rust
770792
fn main() {

src/config/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ create_config! {
127127
"(deprecated: use fn_params_layout instead)";
128128
fn_params_layout: Density, Density::Tall, true,
129129
"Control the layout of parameters in function signatures.";
130-
fn_call_layout: Density, Density::Tall, false,
130+
fn_call_layout: OverflowDensity, OverflowDensity::Foo, false,
131131
"Control the layout of arguments in a function call";
132132
brace_style: BraceStyle, BraceStyle::SameLineWhere, false, "Brace style for items";
133133
control_brace_style: ControlBraceStyle, ControlBraceStyle::AlwaysSameLine, false,
@@ -656,7 +656,7 @@ match_arm_blocks = true
656656
match_arm_leading_pipes = "Never"
657657
force_multiline_blocks = false
658658
fn_params_layout = "Tall"
659-
fn_call_layout = "Tall"
659+
fn_call_layout = "Foo"
660660
brace_style = "SameLineWhere"
661661
control_brace_style = "AlwaysSameLine"
662662
trailing_semicolon = true

src/config/options.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,22 @@ pub enum Density {
6969
Vertical,
7070
}
7171

72+
#[config_type]
73+
/// allows users to specify a density for list-like items.
74+
/// Currently only supports function arguments.
75+
pub enum OverflowDensity {
76+
/// To prevent breaking formatting changes, this option follows the default behavior for
77+
/// list-like items that can overflow.
78+
Foo,
79+
/// Fit as much on one line as possible before wrapping to the next line.
80+
Compressed,
81+
/// Items are placed horizontally as long as there is sufficient space and there aren't
82+
/// any line comments that would force a Vertical layout.
83+
Tall,
84+
/// Place every item on a separate line. There must be at least two items in the list.
85+
Vertical,
86+
}
87+
7288
#[config_type]
7389
/// Spacing around type combinators.
7490
pub enum TypeDensity {

src/expr.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use crate::comment::{
1212
combine_strs_with_missing_comments, contains_comment, recover_comment_removed, rewrite_comment,
1313
rewrite_missing_comment, CharClasses, FindUncommented,
1414
};
15-
use crate::config::{lists::*, Density};
15+
use crate::config::{lists::*, OverflowDensity};
1616
use crate::config::{Config, ControlBraceStyle, HexLiteralCase, IndentStyle, Version};
1717
use crate::lists::{
1818
definitive_tactic, itemize_list, shape_for_tactic, struct_lit_formatting, struct_lit_shape,
@@ -1272,7 +1272,7 @@ pub(crate) fn rewrite_call(
12721272
context: &RewriteContext<'_>,
12731273
callee: &str,
12741274
args: &[ptr::P<ast::Expr>],
1275-
force_list_tactic: Option<Density>,
1275+
force_list_tactic: Option<OverflowDensity>,
12761276
span: Span,
12771277
shape: Shape,
12781278
) -> Option<String> {

src/overflow.rs

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use rustc_span::Span;
99

1010
use crate::closures;
1111
use crate::config::Version;
12-
use crate::config::{lists::*, Density};
12+
use crate::config::{lists::*, OverflowDensity};
1313
use crate::expr::{
1414
can_be_overflowed_expr, is_every_expr_simple, is_method_call, is_nested_call, is_simple_expr,
1515
rewrite_cond,
@@ -252,7 +252,7 @@ pub(crate) fn rewrite_with_parens<'a, T: 'a + IntoOverflowableItem<'a>>(
252252
span: Span,
253253
item_max_width: usize,
254254
force_separator_tactic: Option<SeparatorTactic>,
255-
force_list_tactic: Option<Density>,
255+
force_list_tactic: Option<OverflowDensity>,
256256
) -> Option<String> {
257257
Context::new(
258258
context,
@@ -335,7 +335,7 @@ struct Context<'a> {
335335
item_max_width: usize,
336336
one_line_width: usize,
337337
force_separator_tactic: Option<SeparatorTactic>,
338-
force_list_tactic: Option<Density>,
338+
force_list_tactic: Option<OverflowDensity>,
339339
custom_delims: Option<(&'a str, &'a str)>,
340340
}
341341

@@ -350,7 +350,7 @@ impl<'a> Context<'a> {
350350
suffix: &'static str,
351351
item_max_width: usize,
352352
force_separator_tactic: Option<SeparatorTactic>,
353-
force_list_tactic: Option<Density>,
353+
force_list_tactic: Option<OverflowDensity>,
354354
custom_delims: Option<(&'a str, &'a str)>,
355355
) -> Context<'a> {
356356
let used_width = extra_offset(ident, shape);
@@ -599,23 +599,25 @@ impl<'a> Context<'a> {
599599
.any(|item| item.has_single_line_comment());
600600

601601
match self.force_list_tactic {
602-
Some(Density::Tall)
602+
Some(OverflowDensity::Tall)
603603
if tactic == DefinitiveListTactic::Mixed && any_but_last_contains_line_comment =>
604604
{
605605
// If we determined a `Mixed` layout, but we configured tall then force
606606
// the tactic to be vertical only if any of the items contain single line comments.
607607
// Otherwise, the tacitc was properly set above.
608608
tactic = DefinitiveListTactic::Vertical
609609
}
610-
Some(Density::Compressed) if tactic != DefinitiveListTactic::Horizontal => {
610+
Some(OverflowDensity::Compressed) if tactic != DefinitiveListTactic::Horizontal => {
611611
// Only force a mixed layout if we haven't already decided on going horizontal
612612
tactic = DefinitiveListTactic::Mixed
613613
}
614614
// If we need to force a `Vertical` layout, we should only do so if there are
615615
// at least 2 items for us to format. Otherwise, use the tactic already determined.
616-
Some(Density::Vertical) if self.items.len() > 1 => {
616+
Some(OverflowDensity::Vertical) if self.items.len() > 1 => {
617617
tactic = DefinitiveListTactic::Vertical;
618618
}
619+
// Default behavior for calls to match rustfmts pre `fn_call_layout` formatting.
620+
Some(OverflowDensity::Foo) => {}
619621
_ => {}
620622
};
621623

tests/source/configs/fn_call_layout/compressed.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,12 @@ fn main() {
3333
revoke_and_ack.is_some(),
3434
);
3535

36+
// line comment in the middle of the args
37+
CastCheck::new(
38+
&fn_ctxt, e, from_ty, to_ty,
39+
// We won't show any error to the user, so we don't care what the span is here.
40+
DUMMY_SP, DUMMY_SP,
41+
);
3642

3743
// other examples with more complex args
3844
more_complex_args(
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
// rustfmt-fn_call_layout: Foo
2+
3+
fn main() {
4+
empty_args();
5+
single_arg(ipsum);
6+
two_args(ipsum, dolor);
7+
8+
lorem(ipsum, dolor, sit, amet);
9+
lorem(ipsum, // some inine comment
10+
dolor, sit, amet);
11+
lorem(ipsum, /* some inine comment */
12+
dolor, sit, amet);
13+
ipsum(dolor, sit, amet, consectetur, adipiscing, elit, vivamus, ipsum, orci, rhoncus, vel, imperdiet);
14+
15+
// issue 2010
16+
let a = i8x32::new(
17+
0, 1, -1, 2,
18+
-2, 3, -3, 4,
19+
-4, 5, -5, std::i8::MAX,
20+
std::i8::MIN + 1, 100, -100, -32,
21+
0, 1, -1, 2,
22+
-2, 3, -3, 4,
23+
-4, 5, -5, std::i8::MAX,
24+
std::i8::MIN + 1, 100, -100, -32);
25+
26+
// issue 4146
27+
return_monitor_err(
28+
e,
29+
channel_state,
30+
chan,
31+
order,
32+
commitment_update.is_some(),
33+
revoke_and_ack.is_some(),
34+
);
35+
36+
// line comment in the middle of the args
37+
CastCheck::new(
38+
&fn_ctxt, e, from_ty, to_ty,
39+
// We won't show any error to the user, so we don't care what the span is here.
40+
DUMMY_SP, DUMMY_SP,
41+
);
42+
43+
// other examples with more complex args
44+
more_complex_args(
45+
|a, b, c| {if a == 998765390 {- b * 3 } else {c} },
46+
std::ops::Range { start: 3, end: 5 },
47+
std::i8::MAX, String::from(" hello world!!").as_bytes(),
48+
thread::Builder::new()
49+
.name("thread1".to_string())
50+
.spawn(move || {
51+
use std::sync::Arc;
52+
53+
let mut values = Arc::<[u32]>::new_uninit_slice(3);
54+
55+
// Deferred initialization:
56+
let data = Arc::get_mut(&mut values).unwrap();
57+
data[0].write(1);
58+
data[1].write(2);
59+
data[2].write(3);
60+
61+
let values = unsafe { values.assume_init() };
62+
}), "another argument"
63+
);
64+
65+
// nested calls
66+
ipsum(dolor(sit::amet(consectetur(aaaaaaaaaaaaaa, bbbbbbbbbbbb, ccccccccccccc, ddddddddddddd, eeeeeeeee))));
67+
68+
ipsum(dolor(sit::amet(consectetur(aaaaaaaaaaaaaa, bbbbbbbbbbbb, ccccccccccccc, ddddddddddddd, adipiscing(elit(|| ipsum(dolor(sit::amet(consectetur())))))))));
69+
70+
aaaaaaaaaaaaaaaaaa::bbbbbbbbbbbbbb::cccccccccc(ipsum(), dolor(sit::amet(consectetur, adipiscing), elit(vivamus::ipsum::orci(rhoncus()))));
71+
72+
ipsum(dolor(sit::amet(consectetur(adipiscing(elit(vivamus::ipsum::orci(rhoncus())))))));
73+
}

tests/source/configs/fn_call_layout/tall.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,12 @@ fn main() {
3333
revoke_and_ack.is_some(),
3434
);
3535

36+
// line comment in the middle of the args
37+
CastCheck::new(
38+
&fn_ctxt, e, from_ty, to_ty,
39+
// We won't show any error to the user, so we don't care what the span is here.
40+
DUMMY_SP, DUMMY_SP,
41+
);
3642

3743
// other examples with more complex args
3844
more_complex_args(

tests/source/configs/fn_call_layout/vertical.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,12 @@ fn main() {
3333
revoke_and_ack.is_some(),
3434
);
3535

36+
// line comment in the middle of the args
37+
CastCheck::new(
38+
&fn_ctxt, e, from_ty, to_ty,
39+
// We won't show any error to the user, so we don't care what the span is here.
40+
DUMMY_SP, DUMMY_SP,
41+
);
3642

3743
// other examples with more complex args
3844
more_complex_args(

tests/target/configs/fn_call_layout/compressed.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,13 @@ fn main() {
2727
e, channel_state, chan, order, commitment_update.is_some(), revoke_and_ack.is_some(),
2828
);
2929

30+
// line comment in the middle of the args
31+
CastCheck::new(
32+
&fn_ctxt, e, from_ty, to_ty,
33+
// We won't show any error to the user, so we don't care what the span is here.
34+
DUMMY_SP, DUMMY_SP,
35+
);
36+
3037
// other examples with more complex args
3138
more_complex_args(
3239
|a, b, c| {

0 commit comments

Comments
 (0)