about summary refs log tree commit diff
path: root/src/librustdoc
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2024-01-09 14:50:14 +0000
committerbors <bors@rust-lang.org>2024-01-09 14:50:14 +0000
commit5876c8cdfd3df742c334d6447d44d760c77103b6 (patch)
treeb2437656721ba0a5f4068566975525a9bab87974 /src/librustdoc
parentbe00c5a9b89161b7f45ba80340f709e8e41122f9 (diff)
parentf41d7739880e72743a74722ae6fcc1be9f7b4e5c (diff)
downloadrust-5876c8cdfd3df742c334d6447d44d760c77103b6.tar.gz
rust-5876c8cdfd3df742c334d6447d44d760c77103b6.zip
Auto merge of #119767 - GuillaumeGomez:rollup-fbp26yb, r=GuillaumeGomez
Rollup of 9 pull requests

Successful merges:

 - #117556 (Disallow reference to `static mut` and adding `static_mut_ref` lint)
 - #118748 (std: getrandom simplification for freebsd.)
 - #119282 (Rework and improve the unstable documentation of check-cfg)
 - #119527 (don't reexport atomic::ordering via rustc_data_structures, use std import)
 - #119668 (Simplify implementation of MIR promotion)
 - #119699 (Merge dead bb pruning and unreachable bb deduplication.)
 - #119723 (Remove `-Zdont-buffer-diagnostics`.)
 - #119756 (rustdoc-search: reuse individual types in function signatures)
 - #119758 (GNU/Hurd: unconditionally use inline stack probes)

r? `@ghost`
`@rustbot` modify labels: rollup
Diffstat (limited to 'src/librustdoc')
-rw-r--r--src/librustdoc/html/static/js/search.js111
1 files changed, 91 insertions, 20 deletions
diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js
index a5e2bc1c7af..7995a33f09f 100644
--- a/src/librustdoc/html/static/js/search.js
+++ b/src/librustdoc/html/static/js/search.js
@@ -2717,10 +2717,34 @@ ${item.displayPath}<span class="${type}">${name}</span>\
      * @return {Array<FunctionSearchType>}
      */
     function buildItemSearchTypeAll(types, lowercasePaths) {
-        return types.map(type => buildItemSearchType(type, lowercasePaths));
+        return types.length > 0 ?
+            types.map(type => buildItemSearchType(type, lowercasePaths)) :
+            EMPTY_GENERICS_ARRAY;
     }
 
     /**
+     * Empty, immutable map used in item search types with no bindings.
+     *
+     * @type {Map<number, Array<FunctionType>>}
+     */
+    const EMPTY_BINDINGS_MAP = new Map();
+
+    /**
+     * Empty, immutable map used in item search types with no bindings.
+     *
+     * @type {Array<FunctionType>}
+     */
+    const EMPTY_GENERICS_ARRAY = [];
+
+    /**
+     * Object pool for function types with no bindings or generics.
+     * This is reset after loading the index.
+     *
+     * @type {Map<number|null, FunctionType>}
+     */
+    let TYPES_POOL = new Map();
+
+    /**
      * Converts a single type.
      *
      * @param {RawFunctionType} type
@@ -2732,15 +2756,15 @@ ${item.displayPath}<span class="${type}">${name}</span>\
         let pathIndex, generics, bindings;
         if (typeof type === "number") {
             pathIndex = type;
-            generics = [];
-            bindings = new Map();
+            generics = EMPTY_GENERICS_ARRAY;
+            bindings = EMPTY_BINDINGS_MAP;
         } else {
             pathIndex = type[PATH_INDEX_DATA];
             generics = buildItemSearchTypeAll(
                 type[GENERICS_DATA],
                 lowercasePaths
             );
-            if (type.length > BINDINGS_DATA) {
+            if (type.length > BINDINGS_DATA && type[BINDINGS_DATA].length > 0) {
                 bindings = new Map(type[BINDINGS_DATA].map(binding => {
                     const [assocType, constraints] = binding;
                     // Associated type constructors are represented sloppily in rustdoc's
@@ -2759,38 +2783,83 @@ ${item.displayPath}<span class="${type}">${name}</span>\
                     ];
                 }));
             } else {
-                bindings = new Map();
+                bindings = EMPTY_BINDINGS_MAP;
             }
         }
+        /**
+         * @type {FunctionType}
+         */
+        let result;
         if (pathIndex < 0) {
             // types less than 0 are generic parameters
             // the actual names of generic parameters aren't stored, since they aren't API
-            return {
+            result = {
                 id: pathIndex,
                 ty: TY_GENERIC,
                 path: null,
                 generics,
                 bindings,
             };
-        }
-        if (pathIndex === 0) {
+        } else if (pathIndex === 0) {
             // `0` is used as a sentinel because it's fewer bytes than `null`
-            return {
+            result = {
                 id: null,
                 ty: null,
                 path: null,
                 generics,
                 bindings,
             };
+        } else {
+            const item = lowercasePaths[pathIndex - 1];
+            result = {
+                id: buildTypeMapIndex(item.name, isAssocType),
+                ty: item.ty,
+                path: item.path,
+                generics,
+                bindings,
+            };
         }
-        const item = lowercasePaths[pathIndex - 1];
-        return {
-            id: buildTypeMapIndex(item.name, isAssocType),
-            ty: item.ty,
-            path: item.path,
-            generics,
-            bindings,
-        };
+        const cr = TYPES_POOL.get(result.id);
+        if (cr) {
+            // Shallow equality check. Since this function is used
+            // to construct every type object, this should be mostly
+            // equivalent to a deep equality check, except if there's
+            // a conflict, we don't keep the old one around, so it's
+            // not a fully precise implementation of hashcons.
+            if (cr.generics.length === result.generics.length &&
+                cr.generics !== result.generics &&
+                cr.generics.every((x, i) => result.generics[i] === x)
+            ) {
+                result.generics = cr.generics;
+            }
+            if (cr.bindings.size === result.bindings.size && cr.bindings !== result.bindings) {
+                let ok = true;
+                for (const [k, v] of cr.bindings.entries()) {
+                    const v2 = result.bindings.get(v);
+                    if (!v2) {
+                        ok = false;
+                        break;
+                    }
+                    if (v !== v2 && v.length === v2.length && v.every((x, i) => v2[i] === x)) {
+                        result.bindings.set(k, v);
+                    } else if (v !== v2) {
+                        ok = false;
+                        break;
+                    }
+                }
+                if (ok) {
+                    result.bindings = cr.bindings;
+                }
+            }
+            if (cr.ty === result.ty && cr.path === result.path
+                && cr.bindings === result.bindings && cr.generics === result.generics
+                && cr.ty === result.ty
+            ) {
+                return cr;
+            }
+        }
+        TYPES_POOL.set(result.id, result);
+        return result;
     }
 
     /**
@@ -2801,7 +2870,7 @@ ${item.displayPath}<span class="${type}">${name}</span>\
      * object-based encoding so that the actual search code is more readable and easier to debug.
      *
      * The raw function search type format is generated using serde in
-     * librustdoc/html/render/mod.rs: impl Serialize for IndexItemFunctionType
+     * librustdoc/html/render/mod.rs: IndexItemFunctionType::write_to_string
      *
      * @param {{
      *  string: string,
@@ -2970,8 +3039,8 @@ ${item.displayPath}<span class="${type}">${name}</span>\
         const fb = {
             id: null,
             ty: 0,
-            generics: [],
-            bindings: new Map(),
+            generics: EMPTY_GENERICS_ARRAY,
+            bindings: EMPTY_BINDINGS_MAP,
         };
         for (const [k, v] of type.bindings.entries()) {
             fb.id = k;
@@ -3199,6 +3268,8 @@ ${item.displayPath}<span class="${type}">${name}</span>\
             }
             currentIndex += itemTypes.length;
         }
+        // Drop the (rather large) hash table used for reusing function items
+        TYPES_POOL = new Map();
     }
 
     /**