@@ -67,7 +67,7 @@ pub(crate) use self::context::*;
67
67
pub ( crate ) use self :: span_map:: { LinkFromSrc , collect_spans_and_sources} ;
68
68
pub ( crate ) use self :: write_shared:: * ;
69
69
use crate :: clean:: { self , ItemId , RenderedLink } ;
70
- use crate :: display:: { Joined as _, MaybeDisplay as _} ;
70
+ use crate :: display:: { Joined as _, MaybeDisplay as _, Wrapped } ;
71
71
use crate :: error:: Error ;
72
72
use crate :: formats:: Impl ;
73
73
use crate :: formats:: cache:: Cache ;
@@ -153,59 +153,35 @@ struct RenderType {
153
153
154
154
impl RenderType {
155
155
fn size ( & self ) -> usize {
156
- let mut size = 1 ;
157
- if let Some ( generics) = & self . generics {
158
- size += generics. iter ( ) . map ( RenderType :: size) . sum :: < usize > ( ) ;
159
- }
160
- if let Some ( bindings) = & self . bindings {
161
- for ( _, constraints) in bindings. iter ( ) {
162
- size += 1 ;
163
- size += constraints. iter ( ) . map ( RenderType :: size) . sum :: < usize > ( ) ;
164
- }
165
- }
166
- size
156
+ self . bindings
157
+ . iter ( )
158
+ . flatten ( )
159
+ . map ( |( _, constraints) | constraints)
160
+ . chain ( self . generics . iter ( ) )
161
+ . map ( |constraints| constraints. iter ( ) . map ( RenderType :: size) . sum :: < usize > ( ) + 1 )
162
+ . sum ( )
167
163
}
168
- // Types are rendered as lists of lists, because that's pretty compact.
169
- // The contents of the lists are always integers in self-terminating hex
170
- // form, handled by `RenderTypeId::write_to_string`, so no commas are
171
- // needed to separate the items.
172
- fn write_to_string ( & self , string : & mut String ) {
173
- fn write_optional_id ( id : Option < RenderTypeId > , string : & mut String ) {
174
- // 0 is a sentinel, everything else is one-indexed
175
- match id {
176
- Some ( id) => id. write_to_string ( string) ,
177
- None => string. push ( '`' ) ,
178
- }
179
- }
180
- // Either just the type id, or `{type, generics, bindings?}`
181
- // where generics is a list of types,
182
- // and bindings is a list of `{id, typelist}` pairs.
183
- if self . generics . is_some ( ) || self . bindings . is_some ( ) {
184
- string. push ( '{' ) ;
185
- write_optional_id ( self . id , string) ;
186
- string. push ( '{' ) ;
187
- for generic in self . generics . as_deref ( ) . unwrap_or_default ( ) {
188
- generic. write_to_string ( string) ;
189
- }
190
- string. push ( '}' ) ;
191
- if self . bindings . is_some ( ) {
192
- string. push ( '{' ) ;
193
- for binding in self . bindings . as_deref ( ) . unwrap_or_default ( ) {
194
- string. push ( '{' ) ;
195
- binding. 0 . write_to_string ( string) ;
196
- string. push ( '{' ) ;
197
- for constraint in & binding. 1 [ ..] {
198
- constraint. write_to_string ( string) ;
199
- }
200
- string. push_str ( "}}" ) ;
201
- }
202
- string. push ( '}' ) ;
164
+
165
+ fn write_bindings ( & self ) -> Option < impl fmt:: Display > {
166
+ let Some ( bindings) = & self . bindings else {
167
+ return None ;
168
+ } ;
169
+
170
+ Some ( Wrapped :: with_curly_brackets ( ) . wrap_fn ( move |f| {
171
+ for ( binding, constraints) in bindings {
172
+ Wrapped :: with_curly_brackets ( )
173
+ . wrap_fn ( |f| {
174
+ binding. write_to_string ( ) . fmt ( f) ?;
175
+ Wrapped :: with_curly_brackets ( )
176
+ . wrap_fn ( |f| constraints. iter ( ) . joined ( "" , f) )
177
+ . fmt ( f)
178
+ } )
179
+ . fmt ( f) ?;
203
180
}
204
- string. push ( '}' ) ;
205
- } else {
206
- write_optional_id ( self . id , string) ;
207
- }
181
+ Ok ( ( ) )
182
+ } ) )
208
183
}
184
+
209
185
fn read_from_bytes ( string : & [ u8 ] ) -> ( RenderType , usize ) {
210
186
let mut i = 0 ;
211
187
if string[ i] == b'{' {
@@ -264,6 +240,40 @@ impl RenderType {
264
240
}
265
241
}
266
242
243
+ impl fmt:: Display for RenderType {
244
+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
245
+ // Types are rendered as lists of lists, because that's pretty compact.
246
+ // The contents of the lists are always integers in self-terminating hex
247
+ // form, handled by `RenderTypeId::write_to_string`, so no commas are
248
+ // needed to separate the items.
249
+
250
+ fn write_optional_id ( id : Option < RenderTypeId > ) -> impl fmt:: Display {
251
+ // 0 is a sentinel, everything else is one-indexed
252
+ match id {
253
+ Some ( id) => Either :: Left ( id. write_to_string ( ) ) ,
254
+ None => Either :: Right ( '`' ) ,
255
+ }
256
+ }
257
+
258
+ // Either just the type id, or `{type, generics, bindings?}`
259
+ // where generics is a list of types,
260
+ // and bindings is a list of `{id, typelist}` pairs.
261
+ if self . generics . is_some ( ) || self . bindings . is_some ( ) {
262
+ Wrapped :: with_curly_brackets ( )
263
+ . wrap_fn ( |f| {
264
+ let id = write_optional_id ( self . id ) ;
265
+ let generics = Wrapped :: with_curly_brackets ( )
266
+ . wrap_fn ( |f| self . generics . iter ( ) . flatten ( ) . joined ( "" , f) ) ;
267
+ let bindings = self . write_bindings ( ) . maybe_display ( ) ;
268
+ write ! ( f, "{id}{generics}{bindings}" )
269
+ } )
270
+ . fmt ( f)
271
+ } else {
272
+ write_optional_id ( self . id ) . fmt ( f)
273
+ }
274
+ }
275
+ }
276
+
267
277
#[ derive( Clone , Copy , Debug , Eq , PartialEq ) ]
268
278
enum RenderTypeId {
269
279
DefId ( DefId ) ,
@@ -274,7 +284,7 @@ enum RenderTypeId {
274
284
}
275
285
276
286
impl RenderTypeId {
277
- fn write_to_string ( & self , string : & mut String ) {
287
+ fn write_to_string ( & self ) -> impl fmt :: Display + use < > {
278
288
let id: i32 = match & self {
279
289
// 0 is a sentinel, everything else is one-indexed
280
290
// concrete type
@@ -283,7 +293,7 @@ impl RenderTypeId {
283
293
RenderTypeId :: Index ( idx) => ( * idx) . try_into ( ) . unwrap ( ) ,
284
294
_ => panic ! ( "must convert render types to indexes before serializing" ) ,
285
295
} ;
286
- search_index:: encode:: write_signed_vlqhex_to_string ( id, string ) ;
296
+ search_index:: encode:: write_signed_vlqhex_to_string ( id)
287
297
}
288
298
fn read_from_bytes ( string : & [ u8 ] ) -> ( Option < RenderTypeId > , usize ) {
289
299
let Some ( ( value, offset) ) = search_index:: encode:: read_signed_vlqhex_from_string ( string)
@@ -311,13 +321,13 @@ pub(crate) struct IndexItemFunctionType {
311
321
312
322
impl IndexItemFunctionType {
313
323
fn size ( & self ) -> usize {
314
- self . inputs . iter ( ) . map ( RenderType :: size ) . sum :: < usize > ( )
315
- + self . output . iter ( ) . map ( RenderType :: size ) . sum :: < usize > ( )
316
- + self
317
- . where_clause
318
- . iter ( )
319
- . map ( |constraints| constraints . iter ( ) . map ( RenderType :: size) . sum :: < usize > ( ) )
320
- . sum :: < usize > ( )
324
+ self . where_clause
325
+ . iter ( )
326
+ . flatten ( )
327
+ . chain ( & self . inputs )
328
+ . chain ( & self . output )
329
+ . map ( RenderType :: size)
330
+ . sum ( )
321
331
}
322
332
fn read_from_string_without_param_names ( string : & [ u8 ] ) -> ( IndexItemFunctionType , usize ) {
323
333
let mut i = 0 ;
@@ -367,7 +377,7 @@ impl IndexItemFunctionType {
367
377
i += 1 ;
368
378
( IndexItemFunctionType { inputs, output, where_clause, param_names : Vec :: new ( ) } , i)
369
379
}
370
- fn write_to_string_without_param_names < ' a > ( & ' a self , string : & mut String ) {
380
+ fn write_to_string_without_param_names < ' a > ( & ' a self ) -> impl fmt :: Display {
371
381
// If we couldn't figure out a type, just write 0,
372
382
// which is encoded as `` ` `` (see RenderTypeId::write_to_string).
373
383
let has_missing = self
@@ -376,49 +386,26 @@ impl IndexItemFunctionType {
376
386
. chain ( self . output . iter ( ) )
377
387
. any ( |i| i. id . is_none ( ) && i. generics . is_none ( ) ) ;
378
388
if has_missing {
379
- string . push ( '`' ) ;
389
+ Either :: Left ( '`' )
380
390
} else {
381
- string. push ( '{' ) ;
382
- match & self . inputs [ ..] {
383
- [ one] if one. generics . is_none ( ) && one. bindings . is_none ( ) => {
384
- one. write_to_string ( string) ;
385
- }
386
- _ => {
387
- string. push ( '{' ) ;
388
- for item in & self . inputs [ ..] {
389
- item. write_to_string ( string) ;
390
- }
391
- string. push ( '}' ) ;
391
+ Either :: Right ( Wrapped :: with_curly_brackets ( ) . wrap_fn ( |f| {
392
+ fn write_render_types ( types : & [ RenderType ] ) -> impl fmt:: Display {
393
+ Wrapped :: with_curly_brackets ( )
394
+ . when ( !matches ! ( types, [ one] if one. generics. is_none( ) && one. bindings. is_none( ) ) )
395
+ . wrap_fn ( |f| types. iter ( ) . joined ( "" , f) )
392
396
}
393
- }
394
- match & self . output [ ..] {
395
- [ ] if self . where_clause . is_empty ( ) => { }
396
- [ one] if one. generics . is_none ( ) && one. bindings . is_none ( ) => {
397
- one. write_to_string ( string) ;
398
- }
399
- _ => {
400
- string. push ( '{' ) ;
401
- for item in & self . output [ ..] {
402
- item. write_to_string ( string) ;
403
- }
404
- string. push ( '}' ) ;
405
- }
406
- }
407
- for constraint in & self . where_clause {
408
- if let [ one] = & constraint[ ..]
409
- && one. generics . is_none ( )
410
- && one. bindings . is_none ( )
411
- {
412
- one. write_to_string ( string) ;
413
- } else {
414
- string. push ( '{' ) ;
415
- for item in & constraint[ ..] {
416
- item. write_to_string ( string) ;
417
- }
418
- string. push ( '}' ) ;
397
+
398
+ write_render_types ( & self . inputs ) . fmt ( f) ?;
399
+ if !( self . output . is_empty ( ) && self . where_clause . is_empty ( ) ) {
400
+ write_render_types ( & self . output ) . fmt ( f) ?;
419
401
}
420
- }
421
- string. push ( '}' ) ;
402
+ self . where_clause
403
+ . iter ( )
404
+ . map ( |constraints| write_render_types ( constraints) )
405
+ . joined ( "" , f) ?;
406
+
407
+ Ok ( ( ) )
408
+ } ) )
422
409
}
423
410
}
424
411
}
0 commit comments