@@ -7,6 +7,7 @@ use regex::Regex;
7
7
use rustc_ast:: visit;
8
8
use rustc_ast:: { ast, ptr} ;
9
9
use rustc_span:: { symbol, BytePos , Span , DUMMY_SP } ;
10
+ use unicode_width:: UnicodeWidthStr ;
10
11
11
12
use crate :: attr:: filter_inline_attrs;
12
13
use crate :: comment:: {
@@ -1132,6 +1133,56 @@ fn format_struct(
1132
1133
}
1133
1134
}
1134
1135
1136
+ fn rewrite_bounds (
1137
+ result : & mut String ,
1138
+ context : & RewriteContext < ' _ > ,
1139
+ bounds : & ast:: GenericBounds ,
1140
+ terminator : & str ,
1141
+ shape : Shape ,
1142
+ span : Span ,
1143
+ ) -> Option < ( ) > {
1144
+ let indented = shape. block_indent ( context. config . tab_spaces ( ) ) ;
1145
+ let items = itemize_list (
1146
+ context. snippet_provider ,
1147
+ bounds. iter ( ) ,
1148
+ terminator,
1149
+ "+" ,
1150
+ |bound| bound. span ( ) . lo ( ) ,
1151
+ |bound| bound. span ( ) . hi ( ) ,
1152
+ |bound| bound. rewrite ( context, indented) ,
1153
+ span. lo ( ) ,
1154
+ span. hi ( ) ,
1155
+ false ,
1156
+ )
1157
+ . collect :: < Vec < _ > > ( ) ;
1158
+
1159
+ let tactic = definitive_tactic (
1160
+ & items,
1161
+ ListTactic :: LimitedHorizontalVertical ( shape. width ) ,
1162
+ Separator :: Plus ,
1163
+ context. config . max_width ( ) ,
1164
+ ) ;
1165
+
1166
+ let fmt = ListFormatting :: new ( indented, context. config )
1167
+ . tactic ( tactic)
1168
+ . trailing_separator ( SeparatorTactic :: Never )
1169
+ . separator ( "+" )
1170
+ . separator_place ( SeparatorPlace :: Front )
1171
+ . align_comments ( false ) ;
1172
+
1173
+ let item_str = write_list ( items, & fmt) ?;
1174
+
1175
+ let space = if tactic == DefinitiveListTactic :: Horizontal {
1176
+ Cow :: from ( " " )
1177
+ } else {
1178
+ indented. indent . to_string_with_newline ( & context. config )
1179
+ } ;
1180
+ result. push ( ':' ) ;
1181
+ result. push_str ( & space) ;
1182
+ result. push_str ( & item_str) ;
1183
+ Some ( ( ) )
1184
+ }
1185
+
1135
1186
pub ( crate ) fn format_trait (
1136
1187
context : & RewriteContext < ' _ > ,
1137
1188
item : & ast:: Item ,
@@ -1164,25 +1215,40 @@ pub(crate) fn format_trait(
1164
1215
rewrite_generics ( context, rewrite_ident ( context, item. ident ) , generics, shape) ?;
1165
1216
result. push_str ( & generics_str) ;
1166
1217
1167
- // FIXME(#2055): rustfmt fails to format when there are comments between trait bounds.
1168
1218
if !bounds. is_empty ( ) {
1169
- // Retrieve *unnormalized* ident (See #6069)
1170
- let source_ident = context. snippet ( item. ident . span ) ;
1171
- let ident_hi = context. snippet_provider . span_after ( item. span , source_ident) ;
1172
- let bound_hi = bounds. last ( ) . unwrap ( ) . span ( ) . hi ( ) ;
1173
- let snippet = context. snippet ( mk_sp ( ident_hi, bound_hi) ) ;
1174
- if contains_comment ( snippet) {
1175
- return None ;
1176
- }
1219
+ if context. config . version ( ) == Version :: Two {
1220
+ let after_colon = context
1221
+ . snippet_provider
1222
+ . span_after ( item. span . with_lo ( item. ident . span . hi ( ) ) , ":" ) ;
1177
1223
1178
- result = rewrite_assign_rhs_with (
1179
- context,
1180
- result + ":" ,
1181
- bounds,
1182
- shape,
1183
- & RhsAssignKind :: Bounds ,
1184
- RhsTactics :: ForceNextLineWithoutIndent ,
1185
- ) ?;
1224
+ let span = mk_sp ( after_colon, body_lo) ;
1225
+ let shape = if result. contains ( '\n' ) {
1226
+ shape
1227
+ } else {
1228
+ // `offset_left` takes into account what we've rewritten already + 1 for `:`
1229
+ // `sub_width` take into account the trailing `{`
1230
+ shape. offset_left ( header. width ( ) + 1 ) ?. sub_width ( 1 ) ?
1231
+ } ;
1232
+ rewrite_bounds ( & mut result, context, bounds, "{" , shape, span) ?;
1233
+ } else {
1234
+ // Retrieve *unnormalized* ident (See #6069)
1235
+ let source_ident = context. snippet ( item. ident . span ) ;
1236
+ let ident_hi = context. snippet_provider . span_after ( item. span , source_ident) ;
1237
+ let bound_hi = bounds. last ( ) . unwrap ( ) . span ( ) . hi ( ) ;
1238
+ let snippet = context. snippet ( mk_sp ( ident_hi, bound_hi) ) ;
1239
+ if contains_comment ( snippet) {
1240
+ return None ;
1241
+ }
1242
+
1243
+ result = rewrite_assign_rhs_with (
1244
+ context,
1245
+ result + ":" ,
1246
+ bounds,
1247
+ shape,
1248
+ & RhsAssignKind :: Bounds ,
1249
+ RhsTactics :: ForceNextLineWithoutIndent ,
1250
+ ) ?;
1251
+ }
1186
1252
}
1187
1253
1188
1254
// Rewrite where-clause.
@@ -1219,7 +1285,9 @@ pub(crate) fn format_trait(
1219
1285
result. push_str ( & where_indent. to_string_with_newline ( context. config ) ) ;
1220
1286
}
1221
1287
result. push_str ( & where_clause_str) ;
1222
- } else {
1288
+ }
1289
+
1290
+ if generics. where_clause . predicates . is_empty ( ) && bounds. is_empty ( ) {
1223
1291
let item_snippet = context. snippet ( item. span ) ;
1224
1292
if let Some ( lo) = item_snippet. find ( '/' ) {
1225
1293
// 1 = `{`
0 commit comments