@@ -61,13 +61,15 @@ use rustc_middle::ty::print::PrintTraitRefExt;
6161use rustc_middle:: ty:: { self , TyCtxt } ;
6262use rustc_span:: symbol:: { Symbol , sym} ;
6363use rustc_span:: { BytePos , DUMMY_SP , FileName , RealFileName } ;
64+ use serde:: ser:: SerializeSeq as _;
65+ use serde:: { Deserialize , Serialize } ;
6466use tracing:: { debug, info} ;
6567
6668pub ( crate ) use self :: context:: * ;
6769pub ( crate ) use self :: span_map:: { LinkFromSrc , collect_spans_and_sources} ;
6870pub ( crate ) use self :: write_shared:: * ;
6971use crate :: clean:: { self , ItemId , RenderedLink } ;
70- use crate :: display:: { Joined as _, MaybeDisplay as _} ;
72+ use crate :: display:: { Joined as _, MaybeDisplay as _, Wrapped } ;
7173use crate :: error:: Error ;
7274use crate :: formats:: Impl ;
7375use crate :: formats:: cache:: Cache ;
@@ -144,7 +146,7 @@ pub(crate) struct IndexItem {
144146}
145147
146148/// A type used for the search index.
147- #[ derive( Debug , Eq , PartialEq ) ]
149+ #[ derive( Clone , Debug , Eq , PartialEq ) ]
148150struct RenderType {
149151 id : Option < RenderTypeId > ,
150152 generics : Option < Vec < RenderType > > ,
@@ -153,59 +155,35 @@ struct RenderType {
153155
154156impl RenderType {
155157 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
158+ self . bindings
159+ . iter ( )
160+ . flatten ( )
161+ . map ( |( _, constraints) | constraints)
162+ . chain ( self . generics . iter ( ) )
163+ . map ( |constraints| constraints. iter ( ) . map ( RenderType :: size) . sum :: < usize > ( ) + 1 )
164+ . sum ( )
167165 }
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 ( '}' ) ;
166+
167+ fn write_bindings ( & self ) -> Option < impl fmt:: Display > {
168+ let Some ( bindings) = & self . bindings else {
169+ return None ;
170+ } ;
171+
172+ Some ( Wrapped :: with_curly_brackets ( ) . wrap_fn ( move |f| {
173+ for ( binding, constraints) in bindings {
174+ Wrapped :: with_curly_brackets ( )
175+ . wrap_fn ( |f| {
176+ binding. write_to_string ( ) . fmt ( f) ?;
177+ Wrapped :: with_curly_brackets ( )
178+ . wrap_fn ( |f| constraints. iter ( ) . joined ( "" , f) )
179+ . fmt ( f)
180+ } )
181+ . fmt ( f) ?;
203182 }
204- string. push ( '}' ) ;
205- } else {
206- write_optional_id ( self . id , string) ;
207- }
183+ Ok ( ( ) )
184+ } ) )
208185 }
186+
209187 fn read_from_bytes ( string : & [ u8 ] ) -> ( RenderType , usize ) {
210188 let mut i = 0 ;
211189 if string[ i] == b'{' {
@@ -264,6 +242,40 @@ impl RenderType {
264242 }
265243}
266244
245+ impl fmt:: Display for RenderType {
246+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
247+ // Types are rendered as lists of lists, because that's pretty compact.
248+ // The contents of the lists are always integers in self-terminating hex
249+ // form, handled by `RenderTypeId::write_to_string`, so no commas are
250+ // needed to separate the items.
251+
252+ fn write_optional_id ( id : Option < RenderTypeId > ) -> impl fmt:: Display {
253+ // 0 is a sentinel, everything else is one-indexed
254+ match id {
255+ Some ( id) => Either :: Left ( id. write_to_string ( ) ) ,
256+ None => Either :: Right ( '`' ) ,
257+ }
258+ }
259+
260+ // Either just the type id, or `{type, generics, bindings?}`
261+ // where generics is a list of types,
262+ // and bindings is a list of `{id, typelist}` pairs.
263+ if self . generics . is_some ( ) || self . bindings . is_some ( ) {
264+ Wrapped :: with_curly_brackets ( )
265+ . wrap_fn ( |f| {
266+ let id = write_optional_id ( self . id ) ;
267+ let generics = Wrapped :: with_curly_brackets ( )
268+ . wrap_fn ( |f| self . generics . iter ( ) . flatten ( ) . joined ( "" , f) ) ;
269+ let bindings = self . write_bindings ( ) . maybe_display ( ) ;
270+ write ! ( f, "{id}{generics}{bindings}" )
271+ } )
272+ . fmt ( f)
273+ } else {
274+ write_optional_id ( self . id ) . fmt ( f)
275+ }
276+ }
277+ }
278+
267279#[ derive( Clone , Copy , Debug , Eq , PartialEq ) ]
268280enum RenderTypeId {
269281 DefId ( DefId ) ,
@@ -274,7 +286,7 @@ enum RenderTypeId {
274286}
275287
276288impl RenderTypeId {
277- fn write_to_string ( & self , string : & mut String ) {
289+ fn write_to_string ( & self ) -> impl fmt :: Display + use < > {
278290 let id: i32 = match & self {
279291 // 0 is a sentinel, everything else is one-indexed
280292 // concrete type
@@ -283,7 +295,7 @@ impl RenderTypeId {
283295 RenderTypeId :: Index ( idx) => ( * idx) . try_into ( ) . unwrap ( ) ,
284296 _ => panic ! ( "must convert render types to indexes before serializing" ) ,
285297 } ;
286- search_index:: encode:: write_signed_vlqhex_to_string ( id, string ) ;
298+ search_index:: encode:: write_signed_vlqhex_to_string ( id)
287299 }
288300 fn read_from_bytes ( string : & [ u8 ] ) -> ( Option < RenderTypeId > , usize ) {
289301 let Some ( ( value, offset) ) = search_index:: encode:: read_signed_vlqhex_from_string ( string)
@@ -301,7 +313,7 @@ impl RenderTypeId {
301313}
302314
303315/// Full type of functions/methods in the search index.
304- #[ derive( Debug , Eq , PartialEq ) ]
316+ #[ derive( Clone , Debug , Eq , PartialEq ) ]
305317pub ( crate ) struct IndexItemFunctionType {
306318 inputs : Vec < RenderType > ,
307319 output : Vec < RenderType > ,
@@ -311,13 +323,13 @@ pub(crate) struct IndexItemFunctionType {
311323
312324impl IndexItemFunctionType {
313325 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 > ( )
326+ self . where_clause
327+ . iter ( )
328+ . flatten ( )
329+ . chain ( & self . inputs )
330+ . chain ( & self . output )
331+ . map ( RenderType :: size)
332+ . sum ( )
321333 }
322334 fn read_from_string_without_param_names ( string : & [ u8 ] ) -> ( IndexItemFunctionType , usize ) {
323335 let mut i = 0 ;
@@ -367,7 +379,7 @@ impl IndexItemFunctionType {
367379 i += 1 ;
368380 ( IndexItemFunctionType { inputs, output, where_clause, param_names : Vec :: new ( ) } , i)
369381 }
370- fn write_to_string_without_param_names < ' a > ( & ' a self , string : & mut String ) {
382+ fn write_to_string_without_param_names < ' a > ( & ' a self ) -> impl fmt :: Display {
371383 // If we couldn't figure out a type, just write 0,
372384 // which is encoded as `` ` `` (see RenderTypeId::write_to_string).
373385 let has_missing = self
@@ -376,50 +388,94 @@ impl IndexItemFunctionType {
376388 . chain ( self . output . iter ( ) )
377389 . any ( |i| i. id . is_none ( ) && i. generics . is_none ( ) ) ;
378390 if has_missing {
379- string . push ( '`' ) ;
391+ Either :: Left ( '`' )
380392 } 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) ;
393+ Either :: Right ( Wrapped :: with_curly_brackets ( ) . wrap_fn ( |f| {
394+ fn write_render_types ( types : & [ RenderType ] ) -> impl fmt:: Display {
395+ Wrapped :: with_curly_brackets ( )
396+ . when ( !matches ! ( types, [ one] if one. generics. is_none( ) && one. bindings. is_none( ) ) )
397+ . wrap_fn ( |f| types. iter ( ) . joined ( "" , f) )
385398 }
386- _ => {
387- string. push ( '{' ) ;
388- for item in & self . inputs [ ..] {
389- item. write_to_string ( string) ;
390- }
391- string. push ( '}' ) ;
399+
400+ write_render_types ( & self . inputs ) . fmt ( f) ?;
401+ if !( self . output . is_empty ( ) && self . where_clause . is_empty ( ) ) {
402+ write_render_types ( & self . output ) . fmt ( f) ?;
392403 }
404+ self . where_clause
405+ . iter ( )
406+ . map ( |constraints| write_render_types ( constraints) )
407+ . joined ( "" , f) ?;
408+
409+ Ok ( ( ) )
410+ } ) )
411+ }
412+ }
413+ }
414+
415+ impl Serialize for IndexItemFunctionType {
416+ fn serialize < S > ( & self , serializer : S ) -> Result < S :: Ok , S :: Error >
417+ where
418+ S : serde:: Serializer ,
419+ {
420+ let mut seq = serializer. serialize_seq ( Some ( 2 ) ) ?;
421+ seq. serialize_element ( & self . write_to_string_without_param_names ( ) . to_string ( ) ) ?;
422+
423+ struct ParamNames < ' a > ( & ' a [ Option < Symbol > ] ) ;
424+
425+ impl < ' a > Serialize for ParamNames < ' a > {
426+ fn serialize < S > ( & self , serializer : S ) -> Result < S :: Ok , S :: Error >
427+ where
428+ S : serde:: Serializer ,
429+ {
430+ serializer. collect_seq (
431+ self . 0
432+ . iter ( )
433+ . map ( |symbol| symbol. as_ref ( ) . map ( ToString :: to_string) . unwrap_or_default ( ) ) ,
434+ )
393435 }
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- }
436+ }
437+
438+ seq. serialize_element ( & ParamNames ( & self . param_names ) ) ?;
439+ seq. end ( )
440+ }
441+ }
442+
443+ impl < ' de > Deserialize < ' de > for IndexItemFunctionType {
444+ fn deserialize < D > ( deserializer : D ) -> Result < Self , D :: Error >
445+ where
446+ D : serde:: Deserializer < ' de > ,
447+ {
448+ use serde:: de:: { self , Error as _} ;
449+
450+ struct FunctionDataVisitor ;
451+ impl < ' de > de:: Visitor < ' de > for FunctionDataVisitor {
452+ type Value = IndexItemFunctionType ;
453+ fn expecting ( & self , formatter : & mut std:: fmt:: Formatter < ' _ > ) -> fmt:: Result {
454+ write ! ( formatter, "fn data" )
406455 }
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 ( '}' ) ;
419- }
456+ fn visit_seq < A : de:: SeqAccess < ' de > > ( self , mut v : A ) -> Result < Self :: Value , A :: Error > {
457+ let ( mut function_signature, _) = v
458+ . next_element ( ) ?
459+ . map ( |fn_ : String | {
460+ IndexItemFunctionType :: read_from_string_without_param_names ( fn_. as_bytes ( ) )
461+ } )
462+ . ok_or_else ( || A :: Error :: missing_field ( "function_signature" ) ) ?;
463+ let param_names: Vec < Option < Symbol > > = v
464+ . next_element ( ) ?
465+ . map ( |param_names : Vec < String > | {
466+ param_names
467+ . into_iter ( )
468+ . map ( |symbol| {
469+ if symbol. is_empty ( ) { None } else { Some ( Symbol :: intern ( & symbol) ) }
470+ } )
471+ . collect ( )
472+ } )
473+ . ok_or_else ( || A :: Error :: missing_field ( "param_names" ) ) ?;
474+ function_signature. param_names = param_names;
475+ Ok ( function_signature)
420476 }
421- string. push ( '}' ) ;
422477 }
478+ deserializer. deserialize_any ( FunctionDataVisitor )
423479 }
424480}
425481
0 commit comments