diff --git a/src/librustdoc/html/render/search_index.rs b/src/librustdoc/html/render/search_index.rs
index f9192a5e648..d672f0bb599 100644
--- a/src/librustdoc/html/render/search_index.rs
+++ b/src/librustdoc/html/render/search_index.rs
@@ -234,7 +234,33 @@ pub(crate) fn build_index<'tcx>(
)?;
crate_data.serialize_field(
"f",
- &self.items.iter().map(|item| &item.search_type).collect::>(),
+ &self
+ .items
+ .iter()
+ .map(|item| {
+ // Fake option to get `0` out as a sentinel instead of `null`.
+ // We want to use `0` because it's three less bytes.
+ enum FunctionOption<'a> {
+ Function(&'a IndexItemFunctionType),
+ None,
+ }
+ impl<'a> Serialize for FunctionOption<'a> {
+ fn serialize(&self, serializer: S) -> Result
+ where
+ S: Serializer,
+ {
+ match self {
+ FunctionOption::None => 0.serialize(serializer),
+ FunctionOption::Function(ty) => ty.serialize(serializer),
+ }
+ }
+ }
+ match &item.search_type {
+ Some(ty) => FunctionOption::Function(ty),
+ None => FunctionOption::None,
+ }
+ })
+ .collect::>(),
)?;
crate_data.serialize_field(
"p",
diff --git a/src/librustdoc/html/static/js/externs.js b/src/librustdoc/html/static/js/externs.js
index 23947d002ab..ecbe15a59da 100644
--- a/src/librustdoc/html/static/js/externs.js
+++ b/src/librustdoc/html/static/js/externs.js
@@ -86,6 +86,9 @@ let Results;
* A pair of [inputs, outputs], or 0 for null. This is stored in the search index.
* The JavaScript deserializes this into FunctionSearchType.
*
+ * Numeric IDs are *ONE-indexed* into the paths array (`p`). Zero is used as a sentinel for `null`
+ * because `null` is four bytes while `0` is one byte.
+ *
* An input or output can be encoded as just a number if there is only one of them, AND
* it has no generics. The no generics rule exists to avoid ambiguity: imagine if you had
* a function with a single output, and that output had a single generic:
@@ -114,6 +117,9 @@ let RawFunctionSearchType;
* A single function input or output type. This is either a single path ID, or a pair of
* [path ID, generics].
*
+ * Numeric IDs are *ONE-indexed* into the paths array (`p`). Zero is used as a sentinel for `null`
+ * because `null` is four bytes while `0` is one byte.
+ *
* @typedef {number | [number, Array]}
*/
let RawFunctionType;
diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js
index 46fab7ee57b..75c7bd45a29 100644
--- a/src/librustdoc/html/static/js/search.js
+++ b/src/librustdoc/html/static/js/search.js
@@ -1846,9 +1846,6 @@ function initSearch(rawSearchIndex) {
function buildItemSearchTypeAll(types, lowercasePaths) {
const PATH_INDEX_DATA = 0;
const GENERICS_DATA = 1;
- if (types === null) {
- return [];
- }
return types.map(type => {
let pathIndex, generics;
if (typeof type === "number") {
@@ -1859,6 +1856,7 @@ function initSearch(rawSearchIndex) {
generics = buildItemSearchTypeAll(type[GENERICS_DATA], lowercasePaths);
}
return {
+ // `0` is used as a sentinel because it's fewer bytes than `null`
name: pathIndex === 0 ? null : lowercasePaths[pathIndex - 1].name,
ty: pathIndex === 0 ? null : lowercasePaths[pathIndex - 1].ty,
generics: generics,
@@ -1884,7 +1882,8 @@ function initSearch(rawSearchIndex) {
function buildFunctionSearchType(functionSearchType, lowercasePaths) {
const INPUTS_DATA = 0;
const OUTPUT_DATA = 1;
- if (functionSearchType === 0 || functionSearchType === null) {
+ // `0` is used as a sentinel because it's fewer bytes than `null`
+ if (functionSearchType === 0) {
return null;
}
let inputs, output;