Skip to content

Commit

Permalink
Prevent structs with ".." from being rewritten with alignment
Browse files Browse the repository at this point in the history
 rustfmt should only support rewriting a struct in an expression
 position with alignment (non-default behavior) when there is no rest
 (with or without a base) and all of the fields are non-shorthand.
  • Loading branch information
ytmimi authored and calebcartwright committed Oct 13, 2021
1 parent 8b58cce commit d418057
Show file tree
Hide file tree
Showing 15 changed files with 458 additions and 7 deletions.
11 changes: 4 additions & 7 deletions src/expr.rs
Expand Up @@ -1528,12 +1528,12 @@ fn rewrite_struct_lit<'a>(
let path_shape = shape.sub_width(2)?;
let path_str = rewrite_path(context, PathContext::Expr, None, path, path_shape)?;

let has_base = match struct_rest {
let has_base_or_rest = match struct_rest {
ast::StructRest::None if fields.is_empty() => return Some(format!("{} {{}}", path_str)),
ast::StructRest::Rest(_) if fields.is_empty() => {
return Some(format!("{} {{ .. }}", path_str));
}
ast::StructRest::Base(_) => true,
ast::StructRest::Rest(_) | ast::StructRest::Base(_) => true,
_ => false,
};

Expand All @@ -1542,7 +1542,7 @@ fn rewrite_struct_lit<'a>(

let one_line_width = h_shape.map_or(0, |shape| shape.width);
let body_lo = context.snippet_provider.span_after(span, "{");
let fields_str = if struct_lit_can_be_aligned(fields, has_base)
let fields_str = if struct_lit_can_be_aligned(fields, has_base_or_rest)
&& context.config.struct_field_align_threshold() > 0
{
rewrite_with_alignment(
Expand Down Expand Up @@ -1614,10 +1614,7 @@ fn rewrite_struct_lit<'a>(
nested_shape,
tactic,
context,
force_no_trailing_comma
|| has_base
|| !context.use_block_indent()
|| matches!(struct_rest, ast::StructRest::Rest(_)),
force_no_trailing_comma || has_base_or_rest || !context.use_block_indent(),
);

write_list(&item_vec, &fmt)?
Expand Down
35 changes: 35 additions & 0 deletions tests/source/issue-4926/deeply_nested_struct.rs
@@ -0,0 +1,35 @@

// rustfmt-struct_field_align_threshold: 30

struct X {
a: i32,
b: i32,
c: i32,
}

fn test(x: X) {
let d = {
let e = {
let f = {
let g = {
let h = {
let i = {
let j = {
matches!(
x,
X { a: 1_000, b: 1_000, .. }
)
};
j
};
i
};
h
};
g
};
f
};
e
};
}
@@ -0,0 +1,43 @@
// rustfmt-struct_field_align_threshold: 30

struct X {
really_really_long_field_a: i32,
really_really_really_long_field_b: i32,
really_really_really_really_long_field_c: i32,
really_really_really_really_really_long_field_d: i32,
really_really_really_really_really_really_long_field_e: i32,
f: i32,
}

fn test(x: X) {
let d = {
let e = {
let f = {
let g = {
let h = {
let i = {
let j = {
matches!(
x,
X {
really_really_long_field_a: 10,
really_really_really_long_field_b: 10,
really_really_really_really_long_field_c: 10,
really_really_really_really_really_long_field_d: 10,
really_really_really_really_really_really_long_field_e: 10, ..
}
)
};
j
};
i
};
h
};
g
};
f
};
e
};
}
44 changes: 44 additions & 0 deletions tests/source/issue-4926/deeply_nested_struct_with_many_fields.rs
@@ -0,0 +1,44 @@
// rustfmt-struct_field_align_threshold: 30

struct X {
a: i32,
b: i32,
c: i32,
d: i32,
e: i32,
f: i32,
g: i32,
h: i32,
i: i32,
j: i32,
k: i32,
}

fn test(x: X) {
let d = {
let e = {
let f = {
let g = {
let h = {
let i = {
let j = {
matches!(
x,
X {
a: 1_000, b: 1_000, c: 1_000, d: 1_000, e: 1_000, f: 1_000, g: 1_000, h: 1_000, i: 1_000, j: 1_000, ..
}
)
};
j
};
i
};
h
};
g
};
f
};
e
};
}
35 changes: 35 additions & 0 deletions tests/source/issue-4926/enum_struct_field.rs
@@ -0,0 +1,35 @@
// rustfmt-struct_field_align_threshold: 30
// rustfmt-enum_discrim_align_threshold: 30
// rustfmt-imports_layout: HorizontalVertical

#[derive(Default)]
struct InnerStructA { bbbbbbbbb: i32, cccccccc: i32 }

enum SomeEnumNamedD {
E(InnerStructA),
F {
ggggggggggggggggggggggggg: bool,
h: bool,
}
}

impl SomeEnumNamedD {
fn f_variant() -> Self {
Self::F { ggggggggggggggggggggggggg: true, h: true }
}
}

fn main() {
let kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk = SomeEnumNamedD::f_variant();
let something_we_care_about = matches!(
kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk,
SomeEnumNamedD::F {
ggggggggggggggggggggggggg: true,
..
}
);

if something_we_care_about {
println!("Yup it happened");
}
}
10 changes: 10 additions & 0 deletions tests/source/issue-4926/minimum_example.rs
@@ -0,0 +1,10 @@
// rustfmt-struct_field_align_threshold: 30

struct X { a: i32, b: i32 }

fn test(x: X) {
let y = matches!(x, X {
a: 1,
..
});
}
21 changes: 21 additions & 0 deletions tests/source/issue-4926/struct_with_long_field_names.rs
@@ -0,0 +1,21 @@
// rustfmt-struct_field_align_threshold: 30

struct X {
really_really_long_field_a: i32,
really_really_really_long_field_b: i32,
really_really_really_really_long_field_c: i32,
really_really_really_really_really_long_field_d: i32,
really_really_really_really_really_really_long_field_e: i32,
f: i32,
}

fn test(x: X) {
let y = matches!(x, X {
really_really_long_field_a: 10,
really_really_really_long_field_b: 10,
really_really_really_really_long_field_c: 10,
really_really_really_really_really_long_field_d: 10,
really_really_really_really_really_really_long_field_e: 10,
..
});
}
21 changes: 21 additions & 0 deletions tests/source/issue-4926/struct_with_many_fields.rs
@@ -0,0 +1,21 @@
// rustfmt-struct_field_align_threshold: 30

struct X {
a: i32,
b: i32,
c: i32,
d: i32,
e: i32,
f: i32,
g: i32,
h: i32,
i: i32,
j: i32,
k: i32,
}

fn test(x: X) {
let y = matches!(x, X {
a: 1_000, b: 1_000, c: 1_000, d: 1_000, e: 1_000, f: 1_000, g: 1_000, h: 1_000, i: 1_000, j: 1_000, ..
});
}
38 changes: 38 additions & 0 deletions tests/target/issue-4926/deeply_nested_struct.rs
@@ -0,0 +1,38 @@
// rustfmt-struct_field_align_threshold: 30

struct X {
a: i32,
b: i32,
c: i32,
}

fn test(x: X) {
let d = {
let e = {
let f = {
let g = {
let h = {
let i = {
let j = {
matches!(
x,
X {
a: 1_000,
b: 1_000,
..
}
)
};
j
};
i
};
h
};
g
};
f
};
e
};
}
@@ -0,0 +1,44 @@
// rustfmt-struct_field_align_threshold: 30

struct X {
really_really_long_field_a: i32,
really_really_really_long_field_b: i32,
really_really_really_really_long_field_c: i32,
really_really_really_really_really_long_field_d: i32,
really_really_really_really_really_really_long_field_e: i32,
f: i32,
}

fn test(x: X) {
let d = {
let e = {
let f = {
let g = {
let h = {
let i = {
let j = {
matches!(
x,
X {
really_really_long_field_a: 10,
really_really_really_long_field_b: 10,
really_really_really_really_long_field_c: 10,
really_really_really_really_really_long_field_d: 10,
really_really_really_really_really_really_long_field_e: 10,
..
}
)
};
j
};
i
};
h
};
g
};
f
};
e
};
}
54 changes: 54 additions & 0 deletions tests/target/issue-4926/deeply_nested_struct_with_many_fields.rs
@@ -0,0 +1,54 @@
// rustfmt-struct_field_align_threshold: 30

struct X {
a: i32,
b: i32,
c: i32,
d: i32,
e: i32,
f: i32,
g: i32,
h: i32,
i: i32,
j: i32,
k: i32,
}

fn test(x: X) {
let d = {
let e = {
let f = {
let g = {
let h = {
let i = {
let j = {
matches!(
x,
X {
a: 1_000,
b: 1_000,
c: 1_000,
d: 1_000,
e: 1_000,
f: 1_000,
g: 1_000,
h: 1_000,
i: 1_000,
j: 1_000,
..
}
)
};
j
};
i
};
h
};
g
};
f
};
e
};
}

0 comments on commit d418057

Please sign in to comment.