diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs
index 8afeec81d8731..bea5ccd7c860d 100644
--- a/src/librustdoc/html/render/mod.rs
+++ b/src/librustdoc/html/render/mod.rs
@@ -131,6 +131,10 @@ pub(crate) struct RenderType {
}
impl RenderType {
+ // Types are rendered as lists of lists, because that's pretty compact.
+ // The contents of the lists are always integers in self-terminating hex
+ // form, handled by `RenderTypeId::write_to_string`, so no commas are
+ // needed to separate the items.
pub fn write_to_string(&self, string: &mut String) {
fn write_optional_id(id: Option, string: &mut String) {
// 0 is a sentinel, everything else is one-indexed
@@ -139,6 +143,9 @@ impl RenderType {
None => string.push('`'),
}
}
+ // Either just the type id, or `{type, generics, bindings?}`
+ // where generics is a list of types,
+ // and bindings is a list of `{id, typelist}` pairs.
if self.generics.is_some() || self.bindings.is_some() {
string.push('{');
write_optional_id(self.id, string);
@@ -186,10 +193,19 @@ impl RenderTypeId {
RenderTypeId::Index(idx) => (true, (-*idx).try_into().unwrap()),
_ => panic!("must convert render types to indexes before serializing"),
};
- // zig-zag notation
+ // zig-zag encoding
let value: u32 = (id << 1) | (if sign { 1 } else { 0 });
- // encode
- // Documented in https://rust-lang.github.io/rustc-dev-guide/rustdoc-internals/search.html
+ // Self-terminating hex use capital letters for everything but the
+ // least significant digit, which is lowercase. For example, decimal 17
+ // would be `` Aa `` if zig-zag encoding weren't used.
+ //
+ // Zig-zag encoding, however, stores the sign bit as the last bit.
+ // This means, in the last hexit, 1 is actually `c`, -1 is `b`
+ // (`a` is the imaginary -0), and, because all the bits are shifted
+ // by one, `` A` `` is actually 8 and `` Aa `` is -8.
+ //
+ // https://rust-lang.github.io/rustc-dev-guide/rustdoc-internals/search.html
+ // describes the encoding in more detail.
let mut shift: u32 = 28;
let mut mask: u32 = 0xF0_00_00_00;
while shift < 32 {
@@ -219,8 +235,9 @@ impl IndexItemFunctionType {
string: &mut String,
backref_queue: &mut VecDeque<&'a IndexItemFunctionType>,
) {
- assert!(backref_queue.len() < 16);
- // If we couldn't figure out a type, just write `0`.
+ assert!(backref_queue.len() <= 16);
+ // If we couldn't figure out a type, just write 0,
+ // which is encoded as `` ` `` (see RenderTypeId::write_to_string).
let has_missing = self
.inputs
.iter()
@@ -229,13 +246,15 @@ impl IndexItemFunctionType {
if has_missing {
string.push('`');
} else if let Some(idx) = backref_queue.iter().position(|other| *other == self) {
+ // The backref queue has 16 items, so backrefs use
+ // a single hexit, disjoint from the ones used for numbers.
string.push(
char::try_from('0' as u32 + u32::try_from(idx).unwrap())
.expect("last possible value is '?'"),
);
} else {
backref_queue.push_front(self);
- if backref_queue.len() >= 16 {
+ if backref_queue.len() > 16 {
backref_queue.pop_back();
}
string.push('{');
diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js
index 6fb92d8fbb123..e0708485fc058 100644
--- a/src/librustdoc/html/static/js/search.js
+++ b/src/librustdoc/html/static/js/search.js
@@ -2858,7 +2858,7 @@ ${item.displayPath}${name}\
inputs, output, where_clause,
};
itemFunctionDecoder.backrefQueue.unshift(ret);
- if (itemFunctionDecoder.backrefQueue.length >= 16) {
+ if (itemFunctionDecoder.backrefQueue.length > 16) {
itemFunctionDecoder.backrefQueue.pop();
}
return ret;