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 {
-}