8
8
//! not be used external to this module.
9
9
10
10
use std:: borrow:: Cow ;
11
- use std:: cell:: Cell ;
12
11
use std:: cmp:: Ordering ;
13
12
use std:: fmt:: { self , Display , Write } ;
14
13
use std:: iter:: { self , once} ;
15
14
16
- use itertools:: Itertools ;
15
+ use itertools:: Either ;
17
16
use rustc_abi:: ExternAbi ;
18
17
use rustc_attr_parsing:: { ConstStability , StabilityLevel , StableSince } ;
19
18
use rustc_data_structures:: captures:: Captures ;
@@ -35,6 +34,7 @@ use crate::formats::cache::Cache;
35
34
use crate :: formats:: item_type:: ItemType ;
36
35
use crate :: html:: escape:: { Escape , EscapeBodyText } ;
37
36
use crate :: html:: render:: Context ;
37
+ use crate :: joined:: Joined as _;
38
38
use crate :: passes:: collect_intra_doc_links:: UrlFragment ;
39
39
40
40
pub ( crate ) trait Print {
@@ -146,36 +146,18 @@ impl Buffer {
146
146
}
147
147
}
148
148
149
- pub ( crate ) fn comma_sep < T : Display > (
150
- items : impl Iterator < Item = T > ,
151
- space_after_comma : bool ,
152
- ) -> impl Display {
153
- let items = Cell :: new ( Some ( items) ) ;
154
- fmt:: from_fn ( move |f| {
155
- for ( i, item) in items. take ( ) . unwrap ( ) . enumerate ( ) {
156
- if i != 0 {
157
- write ! ( f, ",{}" , if space_after_comma { " " } else { "" } ) ?;
158
- }
159
- item. fmt ( f) ?;
160
- }
161
- Ok ( ( ) )
162
- } )
163
- }
164
-
165
149
pub ( crate ) fn print_generic_bounds < ' a , ' tcx : ' a > (
166
150
bounds : & ' a [ clean:: GenericBound ] ,
167
151
cx : & ' a Context < ' tcx > ,
168
152
) -> impl Display + ' a + Captures < ' tcx > {
169
153
fmt:: from_fn ( move |f| {
170
154
let mut bounds_dup = FxHashSet :: default ( ) ;
171
155
172
- for ( i, bound) in bounds. iter ( ) . filter ( |b| bounds_dup. insert ( * b) ) . enumerate ( ) {
173
- if i > 0 {
174
- f. write_str ( " + " ) ?;
175
- }
176
- bound. print ( cx) . fmt ( f) ?;
177
- }
178
- Ok ( ( ) )
156
+ bounds
157
+ . iter ( )
158
+ . filter ( move |b| bounds_dup. insert ( * b) )
159
+ . map ( |bound| bound. print ( cx) )
160
+ . joined ( " + " , f)
179
161
} )
180
162
}
181
163
@@ -190,12 +172,7 @@ impl clean::GenericParamDef {
190
172
191
173
if !outlives. is_empty ( ) {
192
174
f. write_str ( ": " ) ?;
193
- for ( i, lt) in outlives. iter ( ) . enumerate ( ) {
194
- if i != 0 {
195
- f. write_str ( " + " ) ?;
196
- }
197
- write ! ( f, "{}" , lt. print( ) ) ?;
198
- }
175
+ outlives. iter ( ) . map ( |lt| lt. print ( ) ) . joined ( " + " , f) ?;
199
176
}
200
177
201
178
Ok ( ( ) )
@@ -245,10 +222,12 @@ impl clean::Generics {
245
222
return Ok ( ( ) ) ;
246
223
}
247
224
225
+ let real_params =
226
+ fmt:: from_fn ( |f| real_params. clone ( ) . map ( |g| g. print ( cx) ) . joined ( ", " , f) ) ;
248
227
if f. alternate ( ) {
249
- write ! ( f, "<{:#}>" , comma_sep ( real_params. map ( |g| g . print ( cx ) ) , true ) )
228
+ write ! ( f, "<{:#}>" , real_params)
250
229
} else {
251
- write ! ( f, "<{}>" , comma_sep ( real_params. map ( |g| g . print ( cx ) ) , true ) )
230
+ write ! ( f, "<{}>" , real_params)
252
231
}
253
232
} )
254
233
}
@@ -260,6 +239,42 @@ pub(crate) enum Ending {
260
239
NoNewline ,
261
240
}
262
241
242
+ fn print_where_predicate < ' a , ' tcx : ' a > (
243
+ predicate : & ' a clean:: WherePredicate ,
244
+ cx : & ' a Context < ' tcx > ,
245
+ ) -> impl Display + ' a + Captures < ' tcx > {
246
+ fmt:: from_fn ( move |f| {
247
+ match predicate {
248
+ clean:: WherePredicate :: BoundPredicate { ty, bounds, bound_params } => {
249
+ print_higher_ranked_params_with_space ( bound_params, cx, "for" ) . fmt ( f) ?;
250
+ ty. print ( cx) . fmt ( f) ?;
251
+ f. write_str ( ":" ) ?;
252
+ if !bounds. is_empty ( ) {
253
+ f. write_str ( " " ) ?;
254
+ print_generic_bounds ( bounds, cx) . fmt ( f) ?;
255
+ }
256
+ Ok ( ( ) )
257
+ }
258
+ clean:: WherePredicate :: RegionPredicate { lifetime, bounds } => {
259
+ // We don't need to check `alternate` since we can be certain that neither
260
+ // the lifetime nor the bounds contain any characters which need escaping.
261
+ write ! ( f, "{}:" , lifetime. print( ) ) ?;
262
+ if !bounds. is_empty ( ) {
263
+ write ! ( f, " {}" , print_generic_bounds( bounds, cx) ) ?;
264
+ }
265
+ Ok ( ( ) )
266
+ }
267
+ clean:: WherePredicate :: EqPredicate { lhs, rhs } => {
268
+ if f. alternate ( ) {
269
+ write ! ( f, "{:#} == {:#}" , lhs. print( cx) , rhs. print( cx) )
270
+ } else {
271
+ write ! ( f, "{} == {}" , lhs. print( cx) , rhs. print( cx) )
272
+ }
273
+ }
274
+ }
275
+ } )
276
+ }
277
+
263
278
/// * The Generics from which to emit a where-clause.
264
279
/// * The number of spaces to indent each line with.
265
280
/// * Whether the where-clause needs to add a comma and newline after the last bound.
@@ -270,55 +285,26 @@ pub(crate) fn print_where_clause<'a, 'tcx: 'a>(
270
285
ending : Ending ,
271
286
) -> impl Display + ' a + Captures < ' tcx > {
272
287
fmt:: from_fn ( move |f| {
273
- let mut where_predicates = gens
274
- . where_predicates
275
- . iter ( )
276
- . map ( |pred| {
277
- fmt:: from_fn ( move |f| {
278
- if f. alternate ( ) {
279
- f. write_str ( " " ) ?;
280
- } else {
281
- f. write_str ( "\n " ) ?;
282
- }
288
+ if gens. where_predicates . is_empty ( ) {
289
+ return Ok ( ( ) ) ;
290
+ }
283
291
284
- match pred {
285
- clean:: WherePredicate :: BoundPredicate { ty, bounds, bound_params } => {
286
- print_higher_ranked_params_with_space ( bound_params, cx, "for" )
287
- . fmt ( f) ?;
288
- ty. print ( cx) . fmt ( f) ?;
289
- f. write_str ( ":" ) ?;
290
- if !bounds. is_empty ( ) {
291
- f. write_str ( " " ) ?;
292
- print_generic_bounds ( bounds, cx) . fmt ( f) ?;
293
- }
294
- Ok ( ( ) )
295
- }
296
- clean:: WherePredicate :: RegionPredicate { lifetime, bounds } => {
297
- // We don't need to check `alternate` since we can be certain that neither
298
- // the lifetime nor the bounds contain any characters which need escaping.
299
- write ! ( f, "{}:" , lifetime. print( ) ) ?;
300
- if !bounds. is_empty ( ) {
301
- write ! ( f, " {}" , print_generic_bounds( bounds, cx) ) ?;
302
- }
303
- Ok ( ( ) )
304
- }
305
- clean:: WherePredicate :: EqPredicate { lhs, rhs } => {
306
- if f. alternate ( ) {
307
- write ! ( f, "{:#} == {:#}" , lhs. print( cx) , rhs. print( cx) )
308
- } else {
309
- write ! ( f, "{} == {}" , lhs. print( cx) , rhs. print( cx) )
310
- }
292
+ let where_preds = fmt:: from_fn ( |f| {
293
+ gens. where_predicates
294
+ . iter ( )
295
+ . map ( |predicate| {
296
+ fmt:: from_fn ( |f| {
297
+ if f. alternate ( ) {
298
+ f. write_str ( " " ) ?;
299
+ } else {
300
+ f. write_str ( "\n " ) ?;
311
301
}
312
- }
302
+ print_where_predicate ( predicate, cx) . fmt ( f)
303
+ } )
313
304
} )
314
- } )
315
- . peekable ( ) ;
316
-
317
- if where_predicates. peek ( ) . is_none ( ) {
318
- return Ok ( ( ) ) ;
319
- }
305
+ . joined ( "," , f)
306
+ } ) ;
320
307
321
- let where_preds = comma_sep ( where_predicates, false ) ;
322
308
let clause = if f. alternate ( ) {
323
309
if ending == Ending :: Newline {
324
310
format ! ( " where{where_preds}," )
@@ -415,12 +401,7 @@ impl clean::GenericBound {
415
401
} else {
416
402
f. write_str ( "use<" ) ?;
417
403
}
418
- for ( i, arg) in args. iter ( ) . enumerate ( ) {
419
- if i > 0 {
420
- write ! ( f, ", " ) ?;
421
- }
422
- arg. fmt ( f) ?;
423
- }
404
+ args. iter ( ) . joined ( ", " , f) ?;
424
405
if f. alternate ( ) { f. write_str ( ">" ) } else { f. write_str ( ">" ) }
425
406
}
426
407
} )
@@ -438,29 +419,18 @@ impl clean::GenericArgs {
438
419
} else {
439
420
f. write_str ( "<" ) ?;
440
421
}
441
- let mut comma = false ;
442
- for arg in args. iter ( ) {
443
- if comma {
444
- f. write_str ( ", " ) ?;
445
- }
446
- comma = true ;
447
- if f. alternate ( ) {
448
- write ! ( f, "{:#}" , arg. print( cx) ) ?;
449
- } else {
450
- write ! ( f, "{}" , arg. print( cx) ) ?;
451
- }
452
- }
453
- for constraint in constraints. iter ( ) {
454
- if comma {
455
- f. write_str ( ", " ) ?;
456
- }
457
- comma = true ;
458
- if f. alternate ( ) {
459
- write ! ( f, "{:#}" , constraint. print( cx) ) ?;
460
- } else {
461
- write ! ( f, "{}" , constraint. print( cx) ) ?;
462
- }
463
- }
422
+
423
+ [ Either :: Left ( args) , Either :: Right ( constraints) ]
424
+ . into_iter ( )
425
+ . flat_map ( Either :: factor_into_iter)
426
+ . map ( |either| {
427
+ either. map_either (
428
+ |arg| arg. print ( cx) ,
429
+ |constraint| constraint. print ( cx) ,
430
+ )
431
+ } )
432
+ . joined ( ", " , f) ?;
433
+
464
434
if f. alternate ( ) {
465
435
f. write_str ( ">" ) ?;
466
436
} else {
@@ -470,14 +440,7 @@ impl clean::GenericArgs {
470
440
}
471
441
clean:: GenericArgs :: Parenthesized { inputs, output } => {
472
442
f. write_str ( "(" ) ?;
473
- let mut comma = false ;
474
- for ty in inputs. iter ( ) {
475
- if comma {
476
- f. write_str ( ", " ) ?;
477
- }
478
- comma = true ;
479
- ty. print ( cx) . fmt ( f) ?;
480
- }
443
+ inputs. iter ( ) . map ( |ty| ty. print ( cx) ) . joined ( ", " , f) ?;
481
444
f. write_str ( ")" ) ?;
482
445
if let Some ( ref ty) = * output {
483
446
if f. alternate ( ) {
@@ -524,6 +487,7 @@ pub(crate) enum HrefError {
524
487
// Panics if `syms` is empty.
525
488
pub ( crate ) fn join_with_double_colon ( syms : & [ Symbol ] ) -> String {
526
489
let mut s = String :: with_capacity ( estimate_item_path_byte_length ( syms. len ( ) ) ) ;
490
+ // NOTE: using `Joined::joined` here causes a noticeable perf regression
527
491
s. push_str ( syms[ 0 ] . as_str ( ) ) ;
528
492
for sym in & syms[ 1 ..] {
529
493
s. push_str ( "::" ) ;
@@ -572,20 +536,20 @@ fn generate_macro_def_id_path(
572
536
}
573
537
574
538
if let Some ( last) = path. last_mut ( ) {
575
- * last = Symbol :: intern ( & format ! ( "macro.{}.html" , last . as_str ( ) ) ) ;
539
+ * last = Symbol :: intern ( & format ! ( "macro.{last }.html" ) ) ;
576
540
}
577
541
578
542
let url = match cache. extern_locations [ & def_id. krate ] {
579
543
ExternalLocation :: Remote ( ref s) => {
580
544
// `ExternalLocation::Remote` always end with a `/`.
581
- format ! ( "{s}{path}" , path = path . iter ( ) . map ( |p| p . as_str ( ) ) . join ( "/" ) )
545
+ format ! ( "{s}{path}" , path = fmt :: from_fn ( |f| path . iter ( ) . joined ( "/" , f ) ) )
582
546
}
583
547
ExternalLocation :: Local => {
584
548
// `root_path` always end with a `/`.
585
549
format ! (
586
550
"{root_path}{path}" ,
587
551
root_path = root_path. unwrap_or( "" ) ,
588
- path = path . iter ( ) . map ( |p| p . as_str ( ) ) . join ( "/" )
552
+ path = fmt :: from_fn ( |f| path . iter ( ) . joined ( "/" , f ) )
589
553
)
590
554
}
591
555
ExternalLocation :: Unknown => {
@@ -682,9 +646,8 @@ fn make_href(
682
646
url_parts. push ( "index.html" ) ;
683
647
}
684
648
_ => {
685
- let prefix = shortty. as_str ( ) ;
686
649
let last = fqp. last ( ) . unwrap ( ) ;
687
- url_parts. push_fmt ( format_args ! ( "{prefix }.{last}.html" ) ) ;
650
+ url_parts. push_fmt ( format_args ! ( "{shortty }.{last}.html" ) ) ;
688
651
}
689
652
}
690
653
Ok ( ( url_parts. finish ( ) , shortty, fqp. to_vec ( ) ) )
@@ -950,12 +913,7 @@ fn tybounds<'a, 'tcx: 'a>(
950
913
cx : & ' a Context < ' tcx > ,
951
914
) -> impl Display + ' a + Captures < ' tcx > {
952
915
fmt:: from_fn ( move |f| {
953
- for ( i, bound) in bounds. iter ( ) . enumerate ( ) {
954
- if i > 0 {
955
- write ! ( f, " + " ) ?;
956
- }
957
- bound. print ( cx) . fmt ( f) ?;
958
- }
916
+ bounds. iter ( ) . map ( |bound| bound. print ( cx) ) . joined ( " + " , f) ?;
959
917
if let Some ( lt) = lt {
960
918
// We don't need to check `alternate` since we can be certain that
961
919
// the lifetime doesn't contain any characters which need escaping.
@@ -974,7 +932,7 @@ fn print_higher_ranked_params_with_space<'a, 'tcx: 'a>(
974
932
if !params. is_empty ( ) {
975
933
f. write_str ( keyword) ?;
976
934
f. write_str ( if f. alternate ( ) { "<" } else { "<" } ) ?;
977
- comma_sep ( params. iter ( ) . map ( |lt| lt. print ( cx) ) , true ) . fmt ( f) ?;
935
+ params. iter ( ) . map ( |lt| lt. print ( cx) ) . joined ( ", " , f) ?;
978
936
f. write_str ( if f. alternate ( ) { "> " } else { "> " } ) ?;
979
937
}
980
938
Ok ( ( ) )
@@ -1025,9 +983,7 @@ fn fmt_type(
1025
983
clean:: Primitive ( clean:: PrimitiveType :: Never ) => {
1026
984
primitive_link ( f, PrimitiveType :: Never , format_args ! ( "!" ) , cx)
1027
985
}
1028
- clean:: Primitive ( prim) => {
1029
- primitive_link ( f, prim, format_args ! ( "{}" , prim. as_sym( ) . as_str( ) ) , cx)
1030
- }
986
+ clean:: Primitive ( prim) => primitive_link ( f, prim, format_args ! ( "{}" , prim. as_sym( ) ) , cx) ,
1031
987
clean:: BareFunction ( ref decl) => {
1032
988
print_higher_ranked_params_with_space ( & decl. generic_params , cx, "for" ) . fmt ( f) ?;
1033
989
decl. safety . print_with_space ( ) . fmt ( f) ?;
@@ -1067,18 +1023,16 @@ fn fmt_type(
1067
1023
primitive_link (
1068
1024
f,
1069
1025
PrimitiveType :: Tuple ,
1070
- format_args ! ( "({})" , generic_names. iter( ) . map( |s| s. as_str( ) ) . join( ", " ) ) ,
1026
+ format_args ! (
1027
+ "({})" ,
1028
+ fmt:: from_fn( |f| generic_names. iter( ) . joined( ", " , f) )
1029
+ ) ,
1071
1030
cx,
1072
1031
)
1073
1032
} else {
1074
- write ! ( f, "(" ) ?;
1075
- for ( i, item) in many. iter ( ) . enumerate ( ) {
1076
- if i != 0 {
1077
- write ! ( f, ", " ) ?;
1078
- }
1079
- item. print ( cx) . fmt ( f) ?;
1080
- }
1081
- write ! ( f, ")" )
1033
+ f. write_str ( "(" ) ?;
1034
+ many. iter ( ) . map ( |item| item. print ( cx) ) . joined ( ", " , f) ?;
1035
+ f. write_str ( ")" )
1082
1036
}
1083
1037
}
1084
1038
} ,
@@ -1407,14 +1361,15 @@ impl clean::Arguments {
1407
1361
cx : & ' a Context < ' tcx > ,
1408
1362
) -> impl Display + ' a + Captures < ' tcx > {
1409
1363
fmt:: from_fn ( move |f| {
1410
- for ( i, input) in self . values . iter ( ) . enumerate ( ) {
1411
- write ! ( f, "{}: " , input. name) ?;
1412
- input. type_ . print ( cx) . fmt ( f) ?;
1413
- if i + 1 < self . values . len ( ) {
1414
- write ! ( f, ", " ) ?;
1415
- }
1416
- }
1417
- Ok ( ( ) )
1364
+ self . values
1365
+ . iter ( )
1366
+ . map ( |input| {
1367
+ fmt:: from_fn ( |f| {
1368
+ write ! ( f, "{}: " , input. name) ?;
1369
+ input. type_ . print ( cx) . fmt ( f)
1370
+ } )
1371
+ } )
1372
+ . joined ( ", " , f)
1418
1373
} )
1419
1374
}
1420
1375
}
@@ -1723,12 +1678,7 @@ impl clean::ImportSource {
1723
1678
}
1724
1679
let name = self . path . last ( ) ;
1725
1680
if let hir:: def:: Res :: PrimTy ( p) = self . path . res {
1726
- primitive_link (
1727
- f,
1728
- PrimitiveType :: from ( p) ,
1729
- format_args ! ( "{}" , name. as_str( ) ) ,
1730
- cx,
1731
- ) ?;
1681
+ primitive_link ( f, PrimitiveType :: from ( p) , format_args ! ( "{name}" ) , cx) ?;
1732
1682
} else {
1733
1683
f. write_str ( name. as_str ( ) ) ?;
1734
1684
}
0 commit comments