@@ -67,7 +67,7 @@ pub(crate) use self::context::*;
6767pub ( crate ) use self :: span_map:: { LinkFromSrc , collect_spans_and_sources} ;
6868pub ( crate ) use self :: write_shared:: * ;
6969use crate :: clean:: { self , ItemId , RenderedLink } ;
70- use crate :: display:: { Joined as _, MaybeDisplay as _} ;
70+ use crate :: display:: { Joined as _, MaybeDisplay as _, Wrapped } ;
7171use crate :: error:: Error ;
7272use crate :: formats:: Impl ;
7373use crate :: formats:: cache:: Cache ;
@@ -153,59 +153,35 @@ struct RenderType {
153153
154154impl RenderType {
155155 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 ( )
167163 }
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) ?;
203180 }
204- string. push ( '}' ) ;
205- } else {
206- write_optional_id ( self . id , string) ;
207- }
181+ Ok ( ( ) )
182+ } ) )
208183 }
184+
209185 fn read_from_bytes ( string : & [ u8 ] ) -> ( RenderType , usize ) {
210186 let mut i = 0 ;
211187 if string[ i] == b'{' {
@@ -264,6 +240,40 @@ impl RenderType {
264240 }
265241}
266242
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+
267277#[ derive( Clone , Copy , Debug , Eq , PartialEq ) ]
268278enum RenderTypeId {
269279 DefId ( DefId ) ,
@@ -274,7 +284,7 @@ enum RenderTypeId {
274284}
275285
276286impl RenderTypeId {
277- fn write_to_string ( & self , string : & mut String ) {
287+ fn write_to_string ( & self ) -> impl fmt :: Display + use < > {
278288 let id: i32 = match & self {
279289 // 0 is a sentinel, everything else is one-indexed
280290 // concrete type
@@ -283,7 +293,7 @@ impl RenderTypeId {
283293 RenderTypeId :: Index ( idx) => ( * idx) . try_into ( ) . unwrap ( ) ,
284294 _ => panic ! ( "must convert render types to indexes before serializing" ) ,
285295 } ;
286- search_index:: encode:: write_signed_vlqhex_to_string ( id, string ) ;
296+ search_index:: encode:: write_signed_vlqhex_to_string ( id)
287297 }
288298 fn read_from_bytes ( string : & [ u8 ] ) -> ( Option < RenderTypeId > , usize ) {
289299 let Some ( ( value, offset) ) = search_index:: encode:: read_signed_vlqhex_from_string ( string)
@@ -311,13 +321,13 @@ pub(crate) struct IndexItemFunctionType {
311321
312322impl IndexItemFunctionType {
313323 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 ( )
321331 }
322332 fn read_from_string_without_param_names ( string : & [ u8 ] ) -> ( IndexItemFunctionType , usize ) {
323333 let mut i = 0 ;
@@ -367,7 +377,7 @@ impl IndexItemFunctionType {
367377 i += 1 ;
368378 ( IndexItemFunctionType { inputs, output, where_clause, param_names : Vec :: new ( ) } , i)
369379 }
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 {
371381 // If we couldn't figure out a type, just write 0,
372382 // which is encoded as `` ` `` (see RenderTypeId::write_to_string).
373383 let has_missing = self
@@ -376,49 +386,26 @@ impl IndexItemFunctionType {
376386 . chain ( self . output . iter ( ) )
377387 . any ( |i| i. id . is_none ( ) && i. generics . is_none ( ) ) ;
378388 if has_missing {
379- string . push ( '`' ) ;
389+ Either :: Left ( '`' )
380390 } 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) )
392396 }
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) ?;
419401 }
420- }
421- string. push ( '}' ) ;
402+ self . where_clause
403+ . iter ( )
404+ . map ( |constraints| write_render_types ( constraints) )
405+ . joined ( "" , f) ?;
406+
407+ Ok ( ( ) )
408+ } ) )
422409 }
423410 }
424411}
0 commit comments