about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/items.rs78
-rw-r--r--tests/source/type-alias-where-clauses.rs20
-rw-r--r--tests/target/type-alias-where-clauses.rs20
3 files changed, 99 insertions, 19 deletions
diff --git a/src/items.rs b/src/items.rs
index daa3df9e5d0..fc043a697e0 100644
--- a/src/items.rs
+++ b/src/items.rs
@@ -1712,6 +1712,9 @@ pub(crate) fn rewrite_type_alias<'a, 'b>(
         where_clauses,
     } = *ty_alias_kind;
     let ty_opt = ty.as_ref();
+    let rhs_hi = ty
+        .as_ref()
+        .map_or(where_clauses.before.span.hi(), |ty| ty.span.hi());
     let (ident, vis) = match visitor_kind {
         Item(i) => (i.ident, &i.vis),
         AssocTraitItem(i) | AssocImplItem(i) => (i.ident, &i.vis),
@@ -1726,17 +1729,23 @@ pub(crate) fn rewrite_type_alias<'a, 'b>(
     match (visitor_kind, &op_ty) {
         (Item(_) | AssocTraitItem(_) | ForeignItem(_), Some(op_bounds)) => {
             let op = OpaqueType { bounds: op_bounds };
-            rewrite_ty(rw_info, Some(bounds), Some(&op), vis)
+            rewrite_ty(rw_info, Some(bounds), Some(&op), rhs_hi, vis)
         }
         (Item(_) | AssocTraitItem(_) | ForeignItem(_), None) => {
-            rewrite_ty(rw_info, Some(bounds), ty_opt, vis)
+            rewrite_ty(rw_info, Some(bounds), ty_opt, rhs_hi, vis)
         }
         (AssocImplItem(_), _) => {
             let result = if let Some(op_bounds) = op_ty {
                 let op = OpaqueType { bounds: op_bounds };
-                rewrite_ty(rw_info, Some(bounds), Some(&op), &DEFAULT_VISIBILITY)
+                rewrite_ty(
+                    rw_info,
+                    Some(bounds),
+                    Some(&op),
+                    rhs_hi,
+                    &DEFAULT_VISIBILITY,
+                )
             } else {
-                rewrite_ty(rw_info, Some(bounds), ty_opt, vis)
+                rewrite_ty(rw_info, Some(bounds), ty_opt, rhs_hi, vis)
             }?;
             match defaultness {
                 ast::Defaultness::Default(..) => Ok(format!("default {result}")),
@@ -1750,6 +1759,8 @@ fn rewrite_ty<R: Rewrite>(
     rw_info: &TyAliasRewriteInfo<'_, '_>,
     generic_bounds_opt: Option<&ast::GenericBounds>,
     rhs: Option<&R>,
+    // the span of the end of the RHS (or the end of the generics, if there is no RHS)
+    rhs_hi: BytePos,
     vis: &ast::Visibility,
 ) -> RewriteResult {
     let mut result = String::with_capacity(128);
@@ -1758,9 +1769,6 @@ fn rewrite_ty<R: Rewrite>(
         .where_clause
         .predicates
         .split_at(where_clauses.split);
-    if !after_where_predicates.is_empty() {
-        return Err(RewriteError::Unknown);
-    }
     result.push_str(&format!("{}type ", format_visibility(context, vis)));
     let ident_str = rewrite_ident(context, ident);
 
@@ -1796,7 +1804,7 @@ fn rewrite_ty<R: Rewrite>(
     if rhs.is_none() {
         option.suppress_comma();
     }
-    let where_clause_str = rewrite_where_clause(
+    let before_where_clause_str = rewrite_where_clause(
         context,
         before_where_predicates,
         where_clauses.before.span,
@@ -1808,14 +1816,20 @@ fn rewrite_ty<R: Rewrite>(
         generics.span.hi(),
         option,
     )?;
-    result.push_str(&where_clause_str);
+    result.push_str(&before_where_clause_str);
 
-    if let Some(ty) = rhs {
-        // If there's a where clause, add a newline before the assignment. Otherwise just add a
-        // space.
-        let has_where = !before_where_predicates.is_empty();
-        if has_where {
+    let mut result = if let Some(ty) = rhs {
+        // If there are any where clauses, add a newline before the assignment.
+        // If there is a before where clause, do not indent, but if there is
+        // only an after where clause, additionally indent the type.
+        if !before_where_predicates.is_empty() {
             result.push_str(&indent.to_string_with_newline(context.config));
+        } else if !after_where_predicates.is_empty() {
+            result.push_str(
+                &indent
+                    .block_indent(context.config)
+                    .to_string_with_newline(context.config),
+            );
         } else {
             result.push(' ');
         }
@@ -1834,7 +1848,7 @@ fn rewrite_ty<R: Rewrite>(
                         .unknown_error()?,
                 ) =>
             {
-                let comment_shape = if has_where {
+                let comment_shape = if !before_where_predicates.is_empty() {
                     Shape::indented(indent, context.config)
                 } else {
                     let shape = Shape::indented(indent, context.config);
@@ -1855,13 +1869,39 @@ fn rewrite_ty<R: Rewrite>(
             _ => format!("{result}="),
         };
 
-        // 1 = `;`
+        // 1 = `;` unless there's a trailing where clause
         let shape = Shape::indented(indent, context.config);
-        let shape = shape.sub_width(1).max_width_error(shape.width, span)?;
-        rewrite_assign_rhs(context, lhs, &*ty, &RhsAssignKind::Ty, shape).map(|s| s + ";")
+        let shape = if after_where_predicates.is_empty() {
+            Shape::indented(indent, context.config)
+                .sub_width(1)
+                .max_width_error(shape.width, span)?
+        } else {
+            shape
+        };
+        rewrite_assign_rhs(context, lhs, &*ty, &RhsAssignKind::Ty, shape)?
     } else {
-        Ok(format!("{result};"))
+        result
+    };
+
+    if !after_where_predicates.is_empty() {
+        let option = WhereClauseOption::new(true, WhereClauseSpace::Newline);
+        let after_where_clause_str = rewrite_where_clause(
+            context,
+            after_where_predicates,
+            where_clauses.after.span,
+            context.config.brace_style(),
+            Shape::indented(indent, context.config),
+            false,
+            ";",
+            None,
+            rhs_hi,
+            option,
+        )?;
+        result.push_str(&after_where_clause_str);
     }
+
+    result += ";";
+    Ok(result)
 }
 
 fn type_annotation_spacing(config: &Config) -> (&str, &str) {
diff --git a/tests/source/type-alias-where-clauses.rs b/tests/source/type-alias-where-clauses.rs
new file mode 100644
index 00000000000..ad998caf308
--- /dev/null
+++ b/tests/source/type-alias-where-clauses.rs
@@ -0,0 +1,20 @@
+    type Foo
+    where
+    A: B,
+    C: D,
+    = E;
+
+    type Foo
+    where
+    A: B,
+    C: D,
+    = E
+    where
+    F: G,
+    H: I;
+
+    type Foo
+    = E
+    where
+    F: G,
+    H: I;
\ No newline at end of file
diff --git a/tests/target/type-alias-where-clauses.rs b/tests/target/type-alias-where-clauses.rs
new file mode 100644
index 00000000000..96d2d63bbb8
--- /dev/null
+++ b/tests/target/type-alias-where-clauses.rs
@@ -0,0 +1,20 @@
+type Foo
+where
+    A: B,
+    C: D,
+= E;
+
+type Foo
+where
+    A: B,
+    C: D,
+= E
+where
+    F: G,
+    H: I;
+
+type Foo
+    = E
+where
+    F: G,
+    H: I;