gated the handling of comment in types list
diff --git a/src/items.rs b/src/items.rs index 2f12801..20b0cda 100644 --- a/src/items.rs +++ b/src/items.rs
@@ -991,16 +991,28 @@ result.push_str(&generics_str); if !generic_bounds.is_empty() { - let comment_span = mk_sp(generics.span.hi(), generic_bounds[0].span().lo()); - let after_colon = context.snippet_provider.span_after(comment_span, ":"); - let comment = recover_missing_comment_in_span( - mk_sp(after_colon, comment_span.hi()), - shape, - context, - // 1 = ":" - last_line_width(&result) + 1, - ) - .unwrap_or_default(); + let comment = if context.config.version() == Version::Two { + let comment_span = mk_sp(generics.span.hi(), generic_bounds[0].span().lo()); + let after_colon = context.snippet_provider.span_after(comment_span, ":"); + recover_missing_comment_in_span( + mk_sp(after_colon, comment_span.hi()), + shape, + context, + // 1 = ":" + last_line_width(&result) + 1, + ) + .unwrap_or_default() + } else { + let ident_hi = context + .snippet_provider + .span_after(item.span, &item.ident.as_str()); + let bound_hi = generic_bounds.last().unwrap().span().hi(); + let snippet = context.snippet(mk_sp(ident_hi, bound_hi)); + if contains_comment(snippet) { + return None; + } + String::new() + }; result = rewrite_assign_rhs_with( context, format!("{}:{}", result, comment),
diff --git a/src/types.rs b/src/types.rs index b0369a0..4fb745f 100644 --- a/src/types.rs +++ b/src/types.rs
@@ -499,7 +499,11 @@ "{}{}{}", result, colon, - join_bounds(context, shape.sub_width(overhead)?, bounds, true)? + if context.config.version() == Version::One { + join_bounds_v1(context, shape.sub_width(overhead)?, bounds, true)? + } else { + join_bounds_v2(context, shape.sub_width(overhead)?, bounds, true)? + } ); Some(result) } @@ -542,7 +546,11 @@ return Some(String::new()); } - join_bounds(context, shape, self, true) + if context.config.version() == Version::One { + join_bounds_v1(context, shape, self, true) + } else { + join_bounds_v2(context, shape, self, true) + } } } @@ -748,7 +756,7 @@ let rw = if context.config.version() == Version::One { it.rewrite(context, shape) } else { - join_bounds(context, shape, it, false) + join_bounds_v2(context, shape, it, false) }; rw.map(|it_str| { let space = if it_str.is_empty() { "" } else { " " }; @@ -827,7 +835,66 @@ } } -fn join_bounds( +fn join_bounds_v1( + context: &RewriteContext<'_>, + shape: Shape, + items: &[ast::GenericBound], + need_indent: bool, +) -> Option<String> { + debug_assert!(!items.is_empty()); + + // Try to join types in a single line + let joiner = match context.config.type_punctuation_density() { + TypeDensity::Compressed => "+", + TypeDensity::Wide => " + ", + }; + let type_strs = items + .iter() + .map(|item| item.rewrite(context, shape)) + .collect::<Option<Vec<_>>>()?; + let result = type_strs.join(joiner); + if items.len() <= 1 || (!result.contains('\n') && result.len() <= shape.width) { + return Some(result); + } + + // We need to use multiple lines. + let (type_strs, offset) = if need_indent { + // Rewrite with additional indentation. + let nested_shape = shape + .block_indent(context.config.tab_spaces()) + .with_max_width(context.config); + let type_strs = items + .iter() + .map(|item| item.rewrite(context, nested_shape)) + .collect::<Option<Vec<_>>>()?; + (type_strs, nested_shape.indent) + } else { + (type_strs, shape.indent) + }; + + let is_bound_extendable = |s: &str, b: &ast::GenericBound| match b { + ast::GenericBound::Outlives(..) => true, + ast::GenericBound::Trait(..) => last_line_extendable(s), + }; + let mut result = String::with_capacity(128); + result.push_str(&type_strs[0]); + let mut can_be_put_on_the_same_line = is_bound_extendable(&result, &items[0]); + let generic_bounds_in_order = is_generic_bounds_in_order(items); + for (bound, bound_str) in items[1..].iter().zip(type_strs[1..].iter()) { + if generic_bounds_in_order && can_be_put_on_the_same_line { + result.push_str(joiner); + } else { + result.push_str(&offset.to_string_with_newline(context.config)); + result.push_str("+ "); + } + result.push_str(bound_str); + can_be_put_on_the_same_line = is_bound_extendable(bound_str, bound); + } + + Some(result) +} + +fn join_bounds_v2( context: &RewriteContext<'_>, shape: Shape, items: &[ast::GenericBound],
diff --git a/tests/source/types_compressed.rs b/tests/source/issue-3669/type_compressed-one.rs similarity index 93% copy from tests/source/types_compressed.rs copy to tests/source/issue-3669/type_compressed-one.rs index 4254842..a6a4a91 100644 --- a/tests/source/types_compressed.rs +++ b/tests/source/issue-3669/type_compressed-one.rs
@@ -1,3 +1,4 @@ +// rustfmt-version: One // rustfmt-type_punctuation_density: Compressed pub fn do_something<'a, T: Trait1 + Trait2 + 'a>(
diff --git a/tests/source/types_compressed.rs b/tests/source/issue-3669/type_compressed-two.rs similarity index 93% rename from tests/source/types_compressed.rs rename to tests/source/issue-3669/type_compressed-two.rs index 4254842..ce4a5c8 100644 --- a/tests/source/types_compressed.rs +++ b/tests/source/issue-3669/type_compressed-two.rs
@@ -1,3 +1,4 @@ +// rustfmt-version: Two // rustfmt-type_punctuation_density: Compressed pub fn do_something<'a, T: Trait1 + Trait2 + 'a>(
diff --git a/tests/source/issue-3669.rs b/tests/source/issue-3669/version-one.rs similarity index 98% rename from tests/source/issue-3669.rs rename to tests/source/issue-3669/version-one.rs index f9046c3..f2f1956 100644 --- a/tests/source/issue-3669.rs +++ b/tests/source/issue-3669/version-one.rs
@@ -1,3 +1,5 @@ +// rustfmt-version: One + pub trait PCG: self::sealed::Sealed // comment1 + Sized // comment2 + Eq // comment3
diff --git a/tests/source/issue-3669.rs b/tests/source/issue-3669/version-two.rs similarity index 96% copy from tests/source/issue-3669.rs copy to tests/source/issue-3669/version-two.rs index f9046c3..c8e873d 100644 --- a/tests/source/issue-3669.rs +++ b/tests/source/issue-3669/version-two.rs
@@ -1,3 +1,5 @@ +// rustfmt-version: Two + pub trait PCG: self::sealed::Sealed // comment1 + Sized // comment2 + Eq // comment3 @@ -72,3 +74,11 @@ + Serialize + for<'a> Deserialize<'a>; } + +// #2055 +pub trait Foo: +// A and C +A + C +// and B + + B +{}
diff --git a/tests/target/issue-3669/type_compressed-one.rs b/tests/target/issue-3669/type_compressed-one.rs new file mode 100644 index 0000000..46e4a2e --- /dev/null +++ b/tests/target/issue-3669/type_compressed-one.rs
@@ -0,0 +1,45 @@ +// rustfmt-version: One +// rustfmt-type_punctuation_density: Compressed + +pub fn do_something<'a, T: Trait1+Trait2+'a>( + &fooo: u32, +) -> impl Foo + + Foo + + Foo + + Foo + + Foo + + Foo + + Foo + + Foo + + Foo + + Foo + + Foo + + Foo + + Foo + + Foo + + Foo + + Foo + + Foo + + Foo + + Foo + + Foo + + Foo + + Foo + + Foo + + Foo + + Foo + + Foo + + Foo + + Foo + + Foo + + Foo + + Foo + + Foo + + Foo + + Foo + + Foo + + Foo + + Foo + + Foo + + 'a+'a+'a+'a+'a { +}
diff --git a/tests/target/issue-3669/type_compressed-two.rs b/tests/target/issue-3669/type_compressed-two.rs new file mode 100644 index 0000000..224293f --- /dev/null +++ b/tests/target/issue-3669/type_compressed-two.rs
@@ -0,0 +1,45 @@ +// rustfmt-version: Two +// rustfmt-type_punctuation_density: Compressed + +pub fn do_something<'a, T: Trait1+Trait2+'a>( + &fooo: u32, +) -> impl Foo ++Foo ++Foo ++Foo ++Foo ++Foo ++Foo ++Foo ++Foo ++Foo ++Foo ++Foo ++Foo ++Foo ++Foo ++Foo ++Foo ++Foo ++Foo ++Foo ++Foo ++Foo ++Foo ++Foo ++Foo ++Foo ++Foo ++Foo ++Foo ++Foo ++Foo ++Foo ++Foo ++Foo ++Foo ++Foo ++Foo ++Foo ++'a+'a+'a+'a+'a { +}
diff --git a/tests/source/issue-3669.rs b/tests/target/issue-3669/version-one.rs similarity index 86% copy from tests/source/issue-3669.rs copy to tests/target/issue-3669/version-one.rs index f9046c3..173ec09 100644 --- a/tests/source/issue-3669.rs +++ b/tests/target/issue-3669/version-one.rs
@@ -1,3 +1,5 @@ +// rustfmt-version: One + pub trait PCG: self::sealed::Sealed // comment1 + Sized // comment2 + Eq // comment3 @@ -48,21 +50,22 @@ for<'a> Deserialize<'a>; // Note(Evrey): Because Rust is drunk. 13 } -pub trait Foo: self::sealed::Sealed - + Sized - + Eq - + Hash - + Debug - + Clone - + Default - + Serialize - + for<'a> Deserialize<'a> +pub trait Foo: + self::sealed::Sealed + + Sized + + Eq + + Hash + + Debug + + Clone + + Default + + Serialize + + for<'a> Deserialize<'a> { type DoubleState: Copy - + ShrAssign<u8> - + Shl<u8, Output = Self::DoubleState> -+ BitAnd<Output = Self::DoubleState> -+ BitOrAssign + + ShrAssign<u8> + + Shl<u8, Output = Self::DoubleState> + + BitAnd<Output = Self::DoubleState> + + BitOrAssign + Sub<Output = Self::DoubleState> + Into<u128> + Debug
diff --git a/tests/target/issue-3669.rs b/tests/target/issue-3669/version-two.rs similarity index 96% rename from tests/target/issue-3669.rs rename to tests/target/issue-3669/version-two.rs index 06e42ad..082fa81 100644 --- a/tests/target/issue-3669.rs +++ b/tests/target/issue-3669/version-two.rs
@@ -1,3 +1,5 @@ +// rustfmt-version: Two + pub trait PCG: self::sealed::Sealed // comment1 + Sized // comment2 @@ -75,3 +77,12 @@ + Serialize + for<'a> Deserialize<'a>; } + +// #2055 +pub trait Foo: +// A and C + A + + C // and B + + B +{ +}
diff --git a/tests/target/trait.rs b/tests/target/trait.rs index 57e0975..620046a 100644 --- a/tests/target/trait.rs +++ b/tests/target/trait.rs
@@ -87,11 +87,10 @@ // #2055 pub trait Foo: // A and C - A - + C // and B +A + C +// and B + B -{ -} +{} // #2158 trait Foo {
diff --git a/tests/target/types_compressed.rs b/tests/target/types_compressed.rs deleted file mode 100644 index ff3bcf6..0000000 --- a/tests/target/types_compressed.rs +++ /dev/null
@@ -1,44 +0,0 @@ -// rustfmt-type_punctuation_density: Compressed - -pub fn do_something<'a, T: Trait1+Trait2+'a>( - &fooo: u32, -) -> impl Foo - +Foo - +Foo - +Foo - +Foo - +Foo - +Foo - +Foo - +Foo - +Foo - +Foo - +Foo - +Foo - +Foo - +Foo - +Foo - +Foo - +Foo - +Foo - +Foo - +Foo - +Foo - +Foo - +Foo - +Foo - +Foo - +Foo - +Foo - +Foo - +Foo - +Foo - +Foo - +Foo - +Foo - +Foo - +Foo - +Foo - +Foo - +'a+'a+'a+'a+'a { -}