about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Howell <michael@notriddle.com>2023-12-10 16:05:18 -0700
committerMichael Howell <michael@notriddle.com>2023-12-10 16:52:21 -0700
commit92b84f849a63af6454845452ee8a5567d6956302 (patch)
tree3d2b6474caa7017adfbe1ba58699099134e3d2b1
parentec4176167b964debee77015d0c67720639f9d673 (diff)
downloadrust-92b84f849a63af6454845452ee8a5567d6956302.tar.gz
rust-92b84f849a63af6454845452ee8a5567d6956302.zip
rustdoc-search: do not treat associated type names as types
Before: http://notriddle.com/rustdoc-html-demo-6/tor-before/tor_config/

After: http://notriddle.com/rustdoc-html-demo-6/tor-after/tor_config/

Profile: http://notriddle.com/rustdoc-html-demo-6/tor-profile/

As a bit of background information: in type-based queries, a type
name that does not exist gets treated as a generic type variable.

This causes a counterintuitive behavior in the `tor_config` crate,
which has a trait with an associated type variable called `T`.

This isn't a searchable concrete type, but its name still gets stored
in the typeNameIdMap, as a convenient way to intern its name.
-rw-r--r--src/librustdoc/html/static/js/search.js33
-rw-r--r--tests/rustdoc-js/enum-variant-not-type.js70
-rw-r--r--tests/rustdoc-js/enum-variant-not-type.rs14
3 files changed, 104 insertions, 13 deletions
diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js
index 8f68796ad26..832ac427112 100644
--- a/src/librustdoc/html/static/js/search.js
+++ b/src/librustdoc/html/static/js/search.js
@@ -243,7 +243,7 @@ function initSearch(rawSearchIndex) {
      * Map from normalized type names to integers. Used to make type search
      * more efficient.
      *
-     * @type {Map<string, integer>}
+     * @type {Map<string, {id: integer, assocOnly: boolean}>}
      */
     let typeNameIdMap;
     const ALIASES = new Map();
@@ -270,19 +270,22 @@ function initSearch(rawSearchIndex) {
      * get the same ID.
      *
      * @param {string} name
+     * @param {boolean} isAssocType - True if this is an assoc type
      *
      * @returns {integer}
      */
-    function buildTypeMapIndex(name) {
+    function buildTypeMapIndex(name, isAssocType) {
         if (name === "" || name === null) {
             return null;
         }
 
         if (typeNameIdMap.has(name)) {
-            return typeNameIdMap.get(name);
+            const obj = typeNameIdMap.get(name);
+            obj.assocOnly = isAssocType && obj.assocOnly;
+            return obj.id;
         } else {
             const id = typeNameIdMap.size;
-            typeNameIdMap.set(name, id);
+            typeNameIdMap.set(name, {id, assocOnly: isAssocType});
             return id;
         }
     }
@@ -2129,17 +2132,20 @@ function initSearch(rawSearchIndex) {
              * See `buildTypeMapIndex` for more information.
              *
              * @param {QueryElement} elem
+             * @param {boolean} isAssocType
              */
-            function convertNameToId(elem) {
-                if (typeNameIdMap.has(elem.pathLast)) {
-                    elem.id = typeNameIdMap.get(elem.pathLast);
+            function convertNameToId(elem, isAssocType) {
+                if (typeNameIdMap.has(elem.pathLast) &&
+                    (isAssocType || !typeNameIdMap.get(elem.pathLast).assocOnly)) {
+                    elem.id = typeNameIdMap.get(elem.pathLast).id;
                 } else if (!parsedQuery.literalSearch) {
                     let match = null;
                     let matchDist = maxEditDistance + 1;
                     let matchName = "";
-                    for (const [name, id] of typeNameIdMap) {
+                    for (const [name, {id, assocOnly}] of typeNameIdMap) {
                         const dist = editDistance(name, elem.pathLast, maxEditDistance);
-                        if (dist <= matchDist && dist <= maxEditDistance) {
+                        if (dist <= matchDist && dist <= maxEditDistance &&
+                            (isAssocType || !assocOnly)) {
                             if (dist === matchDist && matchName > name) {
                                 continue;
                             }
@@ -2206,12 +2212,13 @@ function initSearch(rawSearchIndex) {
                                 name,
                                 " does not exist",
                             ];
+                            return [null, []];
                         }
                         for (const elem2 of constraints) {
                             convertNameToId(elem2);
                         }
 
-                        return [typeNameIdMap.get(name), constraints];
+                        return [typeNameIdMap.get(name).id, constraints];
                     })
                 );
             }
@@ -2720,7 +2727,7 @@ ${item.displayPath}<span class="${type}">${name}</span>\
      *
      * @param {RawFunctionType} type
      */
-    function buildItemSearchType(type, lowercasePaths) {
+    function buildItemSearchType(type, lowercasePaths, isAssocType) {
         const PATH_INDEX_DATA = 0;
         const GENERICS_DATA = 1;
         const BINDINGS_DATA = 2;
@@ -2749,7 +2756,7 @@ ${item.displayPath}<span class="${type}">${name}</span>\
                     //
                     // As a result, the key should never have generics on it.
                     return [
-                        buildItemSearchType(assocType, lowercasePaths).id,
+                        buildItemSearchType(assocType, lowercasePaths, true).id,
                         buildItemSearchTypeAll(constraints, lowercasePaths),
                     ];
                 }));
@@ -2780,7 +2787,7 @@ ${item.displayPath}<span class="${type}">${name}</span>\
         }
         const item = lowercasePaths[pathIndex - 1];
         return {
-            id: buildTypeMapIndex(item.name),
+            id: buildTypeMapIndex(item.name, isAssocType),
             ty: item.ty,
             path: item.path,
             generics,
diff --git a/tests/rustdoc-js/enum-variant-not-type.js b/tests/rustdoc-js/enum-variant-not-type.js
new file mode 100644
index 00000000000..b0f1ec66658
--- /dev/null
+++ b/tests/rustdoc-js/enum-variant-not-type.js
@@ -0,0 +1,70 @@
+const EXPECTED = [
+    {
+        'query': 'T -> T',
+        'correction': null,
+        'others': [
+            {
+                'path': 'enum_variant_not_type',
+                'name': 'my_fn',
+            },
+            {
+                'path': 'enum_variant_not_type::AutoCorrectConfounder',
+                'name': 'assoc_type_acts_like_generic',
+            },
+        ],
+    },
+    {
+        'query': 'InsertUnnecessarilyLongTypeNameHere -> InsertUnnecessarilyLongTypeNameHere',
+        'correction': null,
+        'others': [
+            {
+                'path': 'enum_variant_not_type',
+                'name': 'my_fn',
+            },
+            {
+                'path': 'enum_variant_not_type::AutoCorrectConfounder',
+                'name': 'assoc_type_acts_like_generic',
+            },
+        ],
+    },
+    {
+        'query': 'InsertUnnecessarilyLongTypeNameHere',
+        'correction': null,
+        'others': [
+            {
+                'path': 'enum_variant_not_type::AutoCorrectConfounder',
+                'name': 'InsertUnnecessarilyLongTypeNameHere',
+            },
+        ],
+    },
+    {
+        'query': 'InsertUnnecessarilyLongTypeNameHereX',
+        'correction': null,
+        'others': [
+            {
+                'path': 'enum_variant_not_type::AutoCorrectConfounder',
+                'name': 'InsertUnnecessarilyLongTypeNameHere',
+            },
+        ],
+    },
+    {
+        'query': 'T',
+        'correction': null,
+        'others': [
+            {
+                'path': 'enum_variant_not_type::MyTrait',
+                'name': 'T',
+            },
+        ],
+    },
+    {
+        'query': 'T',
+        'correction': null,
+        'others': [
+            {
+                'path': 'enum_variant_not_type::MyTrait',
+                'name': 'T',
+            },
+        ],
+    },
+];
diff --git a/tests/rustdoc-js/enum-variant-not-type.rs b/tests/rustdoc-js/enum-variant-not-type.rs
new file mode 100644
index 00000000000..421bddf6289
--- /dev/null
+++ b/tests/rustdoc-js/enum-variant-not-type.rs
@@ -0,0 +1,14 @@
+pub trait MyTrait {
+    // Reduced from `arti` crate.
+    // https://tpo.pages.torproject.net/core/doc/rust/tor_config/list_builder/trait.DirectDefaultEmptyListBuilderAccessors.html#associatedtype.T
+    type T;
+    fn not_appearing(&self) -> Option<&Self::T>;
+}
+
+pub fn my_fn<X>(t: X) -> X { t }
+
+pub trait AutoCorrectConfounder {
+    type InsertUnnecessarilyLongTypeNameHere;
+    fn assoc_type_acts_like_generic(&self, x: &Self::InsertUnnecessarilyLongTypeNameHere)
+        -> Option<&Self::InsertUnnecessarilyLongTypeNameHere>;
+}