@@ -131,6 +131,10 @@ pub(crate) struct RenderType {
131
131
}
132
132
133
133
impl RenderType {
134
+ // Types are rendered as lists of lists, because that's pretty compact.
135
+ // The contents of the lists are always integers in self-terminating hex
136
+ // form, handled by `RenderTypeId::write_to_string`, so no commas are
137
+ // needed to separate the items.
134
138
pub fn write_to_string ( & self , string : & mut String ) {
135
139
fn write_optional_id ( id : Option < RenderTypeId > , string : & mut String ) {
136
140
// 0 is a sentinel, everything else is one-indexed
@@ -139,6 +143,9 @@ impl RenderType {
139
143
None => string. push ( '`' ) ,
140
144
}
141
145
}
146
+ // Either just the type id, or `{type, generics, bindings?}`
147
+ // where generics is a list of types,
148
+ // and bindings is a list of `{id, typelist}` pairs.
142
149
if self . generics . is_some ( ) || self . bindings . is_some ( ) {
143
150
string. push ( '{' ) ;
144
151
write_optional_id ( self . id , string) ;
@@ -186,10 +193,19 @@ impl RenderTypeId {
186
193
RenderTypeId :: Index ( idx) => ( true , ( -* idx) . try_into ( ) . unwrap ( ) ) ,
187
194
_ => panic ! ( "must convert render types to indexes before serializing" ) ,
188
195
} ;
189
- // zig-zag notation
196
+ // zig-zag encoding
190
197
let value: u32 = ( id << 1 ) | ( if sign { 1 } else { 0 } ) ;
191
- // encode
192
- // Documented in https://rust-lang.github.io/rustc-dev-guide/rustdoc-internals/search.html
198
+ // Self-terminating hex use capital letters for everything but the
199
+ // least significant digit, which is lowercase. For example, decimal 17
200
+ // would be `` Aa `` if zig-zag encoding weren't used.
201
+ //
202
+ // Zig-zag encoding, however, stores the sign bit as the last bit.
203
+ // This means, in the last hexit, 1 is actually `c`, -1 is `b`
204
+ // (`a` is the imaginary -0), and, because all the bits are shifted
205
+ // by one, `` A` `` is actually 8 and `` Aa `` is -8.
206
+ //
207
+ // https://rust-lang.github.io/rustc-dev-guide/rustdoc-internals/search.html
208
+ // describes the encoding in more detail.
193
209
let mut shift: u32 = 28 ;
194
210
let mut mask: u32 = 0xF0_00_00_00 ;
195
211
while shift < 32 {
@@ -219,8 +235,9 @@ impl IndexItemFunctionType {
219
235
string : & mut String ,
220
236
backref_queue : & mut VecDeque < & ' a IndexItemFunctionType > ,
221
237
) {
222
- assert ! ( backref_queue. len( ) < 16 ) ;
223
- // If we couldn't figure out a type, just write `0`.
238
+ assert ! ( backref_queue. len( ) <= 16 ) ;
239
+ // If we couldn't figure out a type, just write 0,
240
+ // which is encoded as `` ` `` (see RenderTypeId::write_to_string).
224
241
let has_missing = self
225
242
. inputs
226
243
. iter ( )
@@ -229,13 +246,15 @@ impl IndexItemFunctionType {
229
246
if has_missing {
230
247
string. push ( '`' ) ;
231
248
} else if let Some ( idx) = backref_queue. iter ( ) . position ( |other| * other == self ) {
249
+ // The backref queue has 16 items, so backrefs use
250
+ // a single hexit, disjoint from the ones used for numbers.
232
251
string. push (
233
252
char:: try_from ( '0' as u32 + u32:: try_from ( idx) . unwrap ( ) )
234
253
. expect ( "last possible value is '?'" ) ,
235
254
) ;
236
255
} else {
237
256
backref_queue. push_front ( self ) ;
238
- if backref_queue. len ( ) >= 16 {
257
+ if backref_queue. len ( ) > 16 {
239
258
backref_queue. pop_back ( ) ;
240
259
}
241
260
string. push ( '{' ) ;
0 commit comments