about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Howell <michael@notriddle.com>2023-02-28 18:17:59 -0700
committerMichael Howell <michael@notriddle.com>2023-03-20 22:41:57 -0700
commite600c0ba0e0b8153e68c4cead3d92b2c52ca8914 (patch)
tree2edcba6db60fd0dd0580249843ae57fc37c67de9
parent3ff4d56650bf5f7a57d11f3666fb429f0b00b18f (diff)
downloadrust-e600c0ba0e0b8153e68c4cead3d92b2c52ca8914.tar.gz
rust-e600c0ba0e0b8153e68c4cead3d92b2c52ca8914.zip
rustdoc: add support for type filters in arguments and generics
This makes sense, since the search index has the information in it,
and it's more useful for function signature searches since a
function signature search's item type is, by definition, some type
of function (there's more than one, but not very many).
-rw-r--r--src/librustdoc/html/static/js/search.js164
-rw-r--r--src/tools/rustdoc-js/tester.js11
-rw-r--r--tests/rustdoc-js-std/parser-errors.js58
-rw-r--r--tests/rustdoc-js-std/parser-filter.js96
-rw-r--r--tests/rustdoc-js-std/parser-generics.js6
-rw-r--r--tests/rustdoc-js-std/parser-ident.js10
-rw-r--r--tests/rustdoc-js-std/parser-literal.js2
-rw-r--r--tests/rustdoc-js-std/parser-paths.js10
-rw-r--r--tests/rustdoc-js-std/parser-quote.js9
-rw-r--r--tests/rustdoc-js-std/parser-returned.js11
-rw-r--r--tests/rustdoc-js-std/parser-separators.js18
-rw-r--r--tests/rustdoc-js-std/parser-weird-queries.js17
-rw-r--r--tests/rustdoc-js/generics-impl.js13
-rw-r--r--tests/rustdoc-js/generics.js16
-rw-r--r--tests/rustdoc-js/primitive.js10
15 files changed, 301 insertions, 150 deletions
diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js
index 36ff20e299e..840ed8e1080 100644
--- a/src/librustdoc/html/static/js/search.js
+++ b/src/librustdoc/html/static/js/search.js
@@ -354,12 +354,15 @@ function initSearch(rawSearchIndex) {
         if (isInGenerics) {
             parserState.genericsElems += 1;
         }
+        const typeFilter = parserState.typeFilter;
+        parserState.typeFilter = null;
         return {
             name: name,
             fullPath: pathSegments,
             pathWithoutLast: pathSegments.slice(0, pathSegments.length - 1),
             pathLast: pathSegments[pathSegments.length - 1],
             generics: generics,
+            typeFilter,
         };
     }
 
@@ -495,6 +498,11 @@ function initSearch(rawSearchIndex) {
      */
     function getItemsBefore(query, parserState, elems, endChar) {
         let foundStopChar = true;
+        let start = parserState.pos;
+
+        // If this is a generic, keep the outer item's type filter around.
+        const oldTypeFilter = parserState.typeFilter;
+        parserState.typeFilter = null;
 
         while (parserState.pos < parserState.length) {
             const c = parserState.userQuery[parserState.pos];
@@ -506,7 +514,25 @@ function initSearch(rawSearchIndex) {
                 continue;
             } else if (c === ":" && isPathStart(parserState)) {
                 throw ["Unexpected ", "::", ": paths cannot start with ", "::"];
-            } else if (c === ":" || isEndCharacter(c)) {
+            }  else if (c === ":") {
+                if (parserState.typeFilter !== null) {
+                    throw ["Unexpected ", ":"];
+                }
+                if (elems.length === 0) {
+                    throw ["Expected type filter before ", ":"];
+                } else if (query.literalSearch) {
+                    throw ["You cannot use quotes on type filter"];
+                }
+                // The type filter doesn't count as an element since it's a modifier.
+                const typeFilterElem = elems.pop();
+                checkExtraTypeFilterCharacters(start, parserState);
+                parserState.typeFilter = typeFilterElem.name;
+                parserState.pos += 1;
+                parserState.totalElems -= 1;
+                query.literalSearch = false;
+                foundStopChar = true;
+                continue;
+            } else if (isEndCharacter(c)) {
                 let extra = "";
                 if (endChar === ">") {
                     extra = "<";
@@ -540,15 +566,10 @@ function initSearch(rawSearchIndex) {
                 ];
             }
             const posBefore = parserState.pos;
+            start = parserState.pos;
             getNextElem(query, parserState, elems, endChar === ">");
-            if (endChar !== "") {
-                if (parserState.pos >= parserState.length) {
-                    throw ["Unclosed ", "<"];
-                }
-                const c2 = parserState.userQuery[parserState.pos];
-                if (!isSeparatorCharacter(c2) && c2 !== endChar) {
-                    throw ["Expected ", endChar, ", found ", c2];
-                }
+            if (endChar !== "" && parserState.pos >= parserState.length) {
+                throw ["Unclosed ", "<"];
             }
             // This case can be encountered if `getNextElem` encountered a "stop character" right
             // from the start. For example if you have `,,` or `<>`. In this case, we simply move up
@@ -564,6 +585,8 @@ function initSearch(rawSearchIndex) {
         // We are either at the end of the string or on the `endChar` character, let's move forward
         // in any case.
         parserState.pos += 1;
+
+        parserState.typeFilter = oldTypeFilter;
     }
 
     /**
@@ -572,10 +595,10 @@ function initSearch(rawSearchIndex) {
      *
      * @param {ParserState} parserState
      */
-    function checkExtraTypeFilterCharacters(parserState) {
+    function checkExtraTypeFilterCharacters(start, parserState) {
         const query = parserState.userQuery;
 
-        for (let pos = 0; pos < parserState.pos; ++pos) {
+        for (let pos = start; pos < parserState.pos; ++pos) {
             if (!isIdentCharacter(query[pos]) && !isWhitespaceCharacter(query[pos])) {
                 throw ["Unexpected ", query[pos], " in type filter"];
             }
@@ -591,6 +614,7 @@ function initSearch(rawSearchIndex) {
      */
     function parseInput(query, parserState) {
         let foundStopChar = true;
+        let start = parserState.pos;
 
         while (parserState.pos < parserState.length) {
             const c = parserState.userQuery[parserState.pos];
@@ -612,16 +636,15 @@ function initSearch(rawSearchIndex) {
                 }
                 if (query.elems.length === 0) {
                     throw ["Expected type filter before ", ":"];
-                } else if (query.elems.length !== 1 || parserState.totalElems !== 1) {
-                    throw ["Unexpected ", ":"];
                 } else if (query.literalSearch) {
                     throw ["You cannot use quotes on type filter"];
                 }
-                checkExtraTypeFilterCharacters(parserState);
                 // The type filter doesn't count as an element since it's a modifier.
-                parserState.typeFilter = query.elems.pop().name;
+                const typeFilterElem = query.elems.pop();
+                checkExtraTypeFilterCharacters(start, parserState);
+                parserState.typeFilter = typeFilterElem.name;
                 parserState.pos += 1;
-                parserState.totalElems = 0;
+                parserState.totalElems -= 1;
                 query.literalSearch = false;
                 foundStopChar = true;
                 continue;
@@ -653,6 +676,7 @@ function initSearch(rawSearchIndex) {
                 ];
             }
             const before = query.elems.length;
+            start = parserState.pos;
             getNextElem(query, parserState, query.elems, false);
             if (query.elems.length === before) {
                 // Nothing was added, weird... Let's increase the position to not remain stuck.
@@ -660,6 +684,9 @@ function initSearch(rawSearchIndex) {
             }
             foundStopChar = false;
         }
+        if (parserState.typeFilter !== null) {
+            throw ["Unexpected ", ":", " (expected path after type filter)"];
+        }
         while (parserState.pos < parserState.length) {
             if (isReturnArrow(parserState)) {
                 parserState.pos += 2;
@@ -687,7 +714,6 @@ function initSearch(rawSearchIndex) {
         return {
             original: userQuery,
             userQuery: userQuery.toLowerCase(),
-            typeFilter: NO_TYPE_FILTER,
             elems: [],
             returned: [],
             // Total number of "top" elements (does not include generics).
@@ -738,8 +764,8 @@ function initSearch(rawSearchIndex) {
      *
      * ident = *(ALPHA / DIGIT / "_")
      * path = ident *(DOUBLE-COLON ident) [!]
-     * arg = path [generics]
-     * arg-without-generic = path
+     * arg = [type-filter *WS COLON *WS] path [generics]
+     * arg-without-generic = [type-filter *WS COLON *WS] path
      * type-sep = COMMA/WS *(COMMA/WS)
      * nonempty-arg-list = *(type-sep) arg *(type-sep arg) *(type-sep)
      * nonempty-arg-list-without-generics = *(type-sep) arg-without-generic
@@ -749,7 +775,7 @@ function initSearch(rawSearchIndex) {
      * return-args = RETURN-ARROW *(type-sep) nonempty-arg-list
      *
      * exact-search = [type-filter *WS COLON] [ RETURN-ARROW ] *WS QUOTE ident QUOTE [ generics ]
-     * type-search = [type-filter *WS COLON] [ nonempty-arg-list ] [ return-args ]
+     * type-search = [ nonempty-arg-list ] [ return-args ]
      *
      * query = *WS (exact-search / type-search) *WS
      *
@@ -798,6 +824,20 @@ function initSearch(rawSearchIndex) {
      * @return {ParsedQuery}    - The parsed query
      */
     function parseQuery(userQuery) {
+        function convertTypeFilterOnElem(elem) {
+            if (elem.typeFilter !== null) {
+                let typeFilter = elem.typeFilter;
+                if (typeFilter === "const") {
+                    typeFilter = "constant";
+                }
+                elem.typeFilter = itemTypeFromName(typeFilter);
+            } else {
+                elem.typeFilter = NO_TYPE_FILTER;
+            }
+            for (const elem2 of elem.generics) {
+                convertTypeFilterOnElem(elem2);
+            }
+        }
         userQuery = userQuery.trim();
         const parserState = {
             length: userQuery.length,
@@ -812,17 +852,15 @@ function initSearch(rawSearchIndex) {
 
         try {
             parseInput(query, parserState);
-            if (parserState.typeFilter !== null) {
-                let typeFilter = parserState.typeFilter;
-                if (typeFilter === "const") {
-                    typeFilter = "constant";
-                }
-                query.typeFilter = itemTypeFromName(typeFilter);
+            for (const elem of query.elems) {
+                convertTypeFilterOnElem(elem);
+            }
+            for (const elem of query.returned) {
+                convertTypeFilterOnElem(elem);
             }
         } catch (err) {
             query = newParsedQuery(userQuery);
             query.error = err;
-            query.typeFilter = -1;
             return query;
         }
 
@@ -1057,12 +1095,10 @@ function initSearch(rawSearchIndex) {
             }
             // The names match, but we need to be sure that all generics kinda
             // match as well.
-            let elem_name;
             if (elem.generics.length > 0 && row.generics.length >= elem.generics.length) {
                 const elems = Object.create(null);
                 for (const entry of row.generics) {
-                    elem_name = entry.name;
-                    if (elem_name === "") {
+                    if (entry.name === "") {
                         // Pure generic, needs to check into it.
                         if (checkGenerics(entry, elem, maxEditDistance + 1, maxEditDistance)
                             !== 0) {
@@ -1070,19 +1106,19 @@ function initSearch(rawSearchIndex) {
                         }
                         continue;
                     }
-                    if (elems[elem_name] === undefined) {
-                        elems[elem_name] = 0;
+                    if (elems[entry.name] === undefined) {
+                        elems[entry.name] = [];
                     }
-                    elems[elem_name] += 1;
+                    elems[entry.name].push(entry.ty);
                 }
                 // We need to find the type that matches the most to remove it in order
                 // to move forward.
-                for (const generic of elem.generics) {
+                const handleGeneric = generic => {
                     let match = null;
                     if (elems[generic.name]) {
                         match = generic.name;
                     } else {
-                        for (elem_name in elems) {
+                        for (const elem_name in elems) {
                             if (!hasOwnPropertyRustdoc(elems, elem_name)) {
                                 continue;
                             }
@@ -1093,12 +1129,32 @@ function initSearch(rawSearchIndex) {
                         }
                     }
                     if (match === null) {
-                        return maxEditDistance + 1;
+                        return false;
                     }
-                    elems[match] -= 1;
-                    if (elems[match] === 0) {
+                    const matchIdx = elems[match].findIndex(tmp_elem =>
+                        typePassesFilter(generic.typeFilter, tmp_elem));
+                    if (matchIdx === -1) {
+                        return false;
+                    }
+                    elems[match].splice(matchIdx, 1);
+                    if (elems[match].length === 0) {
                         delete elems[match];
                     }
+                    return true;
+                };
+                // To do the right thing with type filters, we first process generics
+                // that have them, removing matching ones from the "bag," then do the
+                // ones with no type filter, which can match any entry regardless of its
+                // own type.
+                for (const generic of elem.generics) {
+                    if (generic.typeFilter !== -1 && !handleGeneric(generic)) {
+                        return maxEditDistance + 1;
+                    }
+                }
+                for (const generic of elem.generics) {
+                    if (generic.typeFilter === -1 && !handleGeneric(generic)) {
+                        return maxEditDistance + 1;
+                    }
                 }
                 return 0;
             }
@@ -1145,14 +1201,20 @@ function initSearch(rawSearchIndex) {
                 return maxEditDistance + 1;
             }
 
-            let dist = editDistance(row.name, elem.name, maxEditDistance);
+            let dist;
+            if (typePassesFilter(elem.typeFilter, row.ty)) {
+                dist = editDistance(row.name, elem.name, maxEditDistance);
+            } else {
+                dist = maxEditDistance + 1;
+            }
             if (literalSearch) {
                 if (dist !== 0) {
                     // The name didn't match, let's try to check if the generics do.
                     if (elem.generics.length === 0) {
                         const checkGeneric = row.generics.length > 0;
                         if (checkGeneric && row.generics
-                            .findIndex(tmp_elem => tmp_elem.name === elem.name) !== -1) {
+                            .findIndex(tmp_elem => tmp_elem.name === elem.name &&
+                                typePassesFilter(elem.typeFilter, tmp_elem.ty)) !== -1) {
                             return 0;
                         }
                     }
@@ -1201,22 +1263,21 @@ function initSearch(rawSearchIndex) {
          *
          * @param {Row} row
          * @param {QueryElement} elem    - The element from the parsed query.
-         * @param {integer} typeFilter
+         * @param {integer} maxEditDistance
          * @param {Array<integer>} skipPositions - Do not return one of these positions.
          *
          * @return {dist: integer, position: integer} - Returns an edit distance to the best match.
          *                                              If there is no match, returns
          *                                              `maxEditDistance + 1` and position: -1.
          */
-        function findArg(row, elem, typeFilter, maxEditDistance, skipPositions) {
+        function findArg(row, elem, maxEditDistance, skipPositions) {
             let dist = maxEditDistance + 1;
             let position = -1;
 
             if (row && row.type && row.type.inputs && row.type.inputs.length > 0) {
                 let i = 0;
                 for (const input of row.type.inputs) {
-                    if (!typePassesFilter(typeFilter, input.ty) ||
-                        skipPositions.indexOf(i) !== -1) {
+                    if (skipPositions.indexOf(i) !== -1) {
                         i += 1;
                         continue;
                     }
@@ -1245,14 +1306,14 @@ function initSearch(rawSearchIndex) {
          *
          * @param {Row} row
          * @param {QueryElement} elem   - The element from the parsed query.
-         * @param {integer} typeFilter
+         * @param {integer} maxEditDistance
          * @param {Array<integer>} skipPositions - Do not return one of these positions.
          *
          * @return {dist: integer, position: integer} - Returns an edit distance to the best match.
          *                                              If there is no match, returns
          *                                              `maxEditDistance + 1` and position: -1.
          */
-        function checkReturned(row, elem, typeFilter, maxEditDistance, skipPositions) {
+        function checkReturned(row, elem, maxEditDistance, skipPositions) {
             let dist = maxEditDistance + 1;
             let position = -1;
 
@@ -1260,8 +1321,7 @@ function initSearch(rawSearchIndex) {
                 const ret = row.type.output;
                 let i = 0;
                 for (const ret_ty of ret) {
-                    if (!typePassesFilter(typeFilter, ret_ty.ty) ||
-                        skipPositions.indexOf(i) !== -1) {
+                    if (skipPositions.indexOf(i) !== -1) {
                         i += 1;
                         continue;
                     }
@@ -1483,15 +1543,15 @@ function initSearch(rawSearchIndex) {
             const fullId = row.id;
             const searchWord = searchWords[pos];
 
-            const in_args = findArg(row, elem, parsedQuery.typeFilter, maxEditDistance, []);
-            const returned = checkReturned(row, elem, parsedQuery.typeFilter, maxEditDistance, []);
+            const in_args = findArg(row, elem, maxEditDistance, []);
+            const returned = checkReturned(row, elem, maxEditDistance, []);
 
             // path_dist is 0 because no parent path information is currently stored
             // in the search index
             addIntoResults(results_in_args, fullId, pos, -1, in_args.dist, 0, maxEditDistance);
             addIntoResults(results_returned, fullId, pos, -1, returned.dist, 0, maxEditDistance);
 
-            if (!typePassesFilter(parsedQuery.typeFilter, row.ty)) {
+            if (!typePassesFilter(elem.typeFilter, row.ty)) {
                 return;
             }
 
@@ -1568,7 +1628,6 @@ function initSearch(rawSearchIndex) {
                     const { dist, position } = callback(
                         row,
                         elem,
-                        NO_TYPE_FILTER,
                         maxEditDistance,
                         skipPositions
                     );
@@ -1632,7 +1691,6 @@ function initSearch(rawSearchIndex) {
                         in_returned = checkReturned(
                             row,
                             elem,
-                            parsedQuery.typeFilter,
                             maxEditDistance,
                             []
                         );
diff --git a/src/tools/rustdoc-js/tester.js b/src/tools/rustdoc-js/tester.js
index 8d46a8ce7f1..6b9a9b66a7d 100644
--- a/src/tools/rustdoc-js/tester.js
+++ b/src/tools/rustdoc-js/tester.js
@@ -79,11 +79,18 @@ function checkNeededFields(fullPath, expected, error_text, queryName, position)
             "foundElems",
             "original",
             "returned",
-            "typeFilter",
             "userQuery",
             "error",
         ];
-    } else if (fullPath.endsWith("elems") || fullPath.endsWith("generics")) {
+    } else if (fullPath.endsWith("elems") || fullPath.endsWith("returned")) {
+        fieldsToCheck = [
+            "name",
+            "fullPath",
+            "pathWithoutLast",
+            "pathLast",
+            "generics",
+        ];
+    } else if (fullPath.endsWith("generics")) {
         fieldsToCheck = [
             "name",
             "fullPath",
diff --git a/tests/rustdoc-js-std/parser-errors.js b/tests/rustdoc-js-std/parser-errors.js
index 98c6f27ca61..d1aa840ab08 100644
--- a/tests/rustdoc-js-std/parser-errors.js
+++ b/tests/rustdoc-js-std/parser-errors.js
@@ -17,6 +17,7 @@ const QUERY = [
     "a b:",
     "a (b:",
     "_:",
+    "_:a",
     "a-bb",
     "a>bb",
     "ab'",
@@ -48,7 +49,6 @@ const PARSED = [
         foundElems: 0,
         original: "<P>",
         returned: [],
-        typeFilter: -1,
         userQuery: "<p>",
         error: "Found generics without a path",
     },
@@ -57,7 +57,6 @@ const PARSED = [
         foundElems: 0,
         original: "-> <P>",
         returned: [],
-        typeFilter: -1,
         userQuery: "-> <p>",
         error: "Found generics without a path",
     },
@@ -66,7 +65,6 @@ const PARSED = [
         foundElems: 0,
         original: "a<\"P\">",
         returned: [],
-        typeFilter: -1,
         userQuery: "a<\"p\">",
         error: "Unexpected `\"` in generics",
     },
@@ -75,7 +73,6 @@ const PARSED = [
         foundElems: 0,
         original: "\"P\" \"P\"",
         returned: [],
-        typeFilter: -1,
         userQuery: "\"p\" \"p\"",
         error: "Cannot have more than one literal search element",
     },
@@ -84,7 +81,6 @@ const PARSED = [
         foundElems: 0,
         original: "P \"P\"",
         returned: [],
-        typeFilter: -1,
         userQuery: "p \"p\"",
         error: "Cannot use literal search when there is more than one element",
     },
@@ -93,7 +89,6 @@ const PARSED = [
         foundElems: 0,
         original: "\"p\" p",
         returned: [],
-        typeFilter: -1,
         userQuery: "\"p\" p",
         error: "You cannot have more than one element if you use quotes",
     },
@@ -102,7 +97,6 @@ const PARSED = [
         foundElems: 0,
         original: "\"const\": p",
         returned: [],
-        typeFilter: -1,
         userQuery: "\"const\": p",
         error: "You cannot use quotes on type filter",
     },
@@ -111,16 +105,14 @@ const PARSED = [
         foundElems: 0,
         original: "a<:a>",
         returned: [],
-        typeFilter: -1,
         userQuery: "a<:a>",
-        error: "Unexpected `:` after `<`",
+        error: "Expected type filter before `:`",
     },
     {
         elems: [],
         foundElems: 0,
         original: "a<::a>",
         returned: [],
-        typeFilter: -1,
         userQuery: "a<::a>",
         error: "Unexpected `::`: paths cannot start with `::`",
     },
@@ -129,7 +121,6 @@ const PARSED = [
         foundElems: 0,
         original: "((a))",
         returned: [],
-        typeFilter: -1,
         userQuery: "((a))",
         error: "Unexpected `(`",
     },
@@ -138,7 +129,6 @@ const PARSED = [
         foundElems: 0,
         original: "(p -> p",
         returned: [],
-        typeFilter: -1,
         userQuery: "(p -> p",
         error: "Unexpected `(`",
     },
@@ -147,7 +137,6 @@ const PARSED = [
         foundElems: 0,
         original: "::a::b",
         returned: [],
-        typeFilter: -1,
         userQuery: "::a::b",
         error: "Paths cannot start with `::`",
     },
@@ -156,7 +145,6 @@ const PARSED = [
         foundElems: 0,
         original: "a::::b",
         returned: [],
-        typeFilter: -1,
         userQuery: "a::::b",
         error: "Unexpected `::::`",
     },
@@ -165,7 +153,6 @@ const PARSED = [
         foundElems: 0,
         original: "a::b::",
         returned: [],
-        typeFilter: -1,
         userQuery: "a::b::",
         error: "Paths cannot end with `::`",
     },
@@ -174,7 +161,6 @@ const PARSED = [
         foundElems: 0,
         original: ":a",
         returned: [],
-        typeFilter: -1,
         userQuery: ":a",
         error: "Expected type filter before `:`",
     },
@@ -183,16 +169,14 @@ const PARSED = [
         foundElems: 0,
         original: "a b:",
         returned: [],
-        typeFilter: -1,
         userQuery: "a b:",
-        error: "Unexpected `:`",
+        error: "Unexpected `:` (expected path after type filter)",
     },
     {
         elems: [],
         foundElems: 0,
         original: "a (b:",
         returned: [],
-        typeFilter: -1,
         userQuery: "a (b:",
         error: "Unexpected `(`",
     },
@@ -201,8 +185,15 @@ const PARSED = [
         foundElems: 0,
         original: "_:",
         returned: [],
-        typeFilter: -1,
         userQuery: "_:",
+        error: "Unexpected `:` (expected path after type filter)",
+    },
+    {
+        elems: [],
+        foundElems: 0,
+        original: "_:a",
+        returned: [],
+        userQuery: "_:a",
         error: "Unknown type filter `_`",
     },
     {
@@ -210,7 +201,6 @@ const PARSED = [
         foundElems: 0,
         original: "a-bb",
         returned: [],
-        typeFilter: -1,
         userQuery: "a-bb",
         error: "Unexpected `-` (did you mean `->`?)",
     },
@@ -219,7 +209,6 @@ const PARSED = [
         foundElems: 0,
         original: "a>bb",
         returned: [],
-        typeFilter: -1,
         userQuery: "a>bb",
         error: "Unexpected `>` (did you mean `->`?)",
     },
@@ -228,7 +217,6 @@ const PARSED = [
         foundElems: 0,
         original: "ab'",
         returned: [],
-        typeFilter: -1,
         userQuery: "ab'",
         error: "Unexpected `'`",
     },
@@ -237,7 +225,6 @@ const PARSED = [
         foundElems: 0,
         original: "a->",
         returned: [],
-        typeFilter: -1,
         userQuery: "a->",
         error: "Expected at least one item after `->`",
     },
@@ -246,7 +233,6 @@ const PARSED = [
         foundElems: 0,
         original: '"p" <a>',
         returned: [],
-        typeFilter: -1,
         userQuery: '"p" <a>',
         error: "Found generics without a path",
     },
@@ -255,7 +241,6 @@ const PARSED = [
         foundElems: 0,
         original: '"p" a<a>',
         returned: [],
-        typeFilter: -1,
         userQuery: '"p" a<a>',
         error: "You cannot have more than one element if you use quotes",
     },
@@ -264,7 +249,6 @@ const PARSED = [
         foundElems: 0,
         original: 'a,<',
         returned: [],
-        typeFilter: -1,
         userQuery: 'a,<',
         error: 'Found generics without a path',
     },
@@ -273,7 +257,6 @@ const PARSED = [
         foundElems: 0,
         original: 'aaaaa<>b',
         returned: [],
-        typeFilter: -1,
         userQuery: 'aaaaa<>b',
         error: 'Expected `,`, ` `, `:` or `->`, found `b`',
     },
@@ -282,16 +265,14 @@ const PARSED = [
         foundElems: 0,
         original: 'fn:aaaaa<>b',
         returned: [],
-        typeFilter: -1,
         userQuery: 'fn:aaaaa<>b',
-        error: 'Expected `,`, ` ` or `->`, found `b`',
+        error: 'Expected `,`, ` `, `:` or `->`, found `b`',
     },
     {
         elems: [],
         foundElems: 0,
         original: '->a<>b',
         returned: [],
-        typeFilter: -1,
         userQuery: '->a<>b',
         error: 'Expected `,` or ` `, found `b`',
     },
@@ -300,7 +281,6 @@ const PARSED = [
         foundElems: 0,
         original: 'a<->',
         returned: [],
-        typeFilter: -1,
         userQuery: 'a<->',
         error: 'Unexpected `-` after `<`',
     },
@@ -309,7 +289,6 @@ const PARSED = [
         foundElems: 0,
         original: 'a:: a',
         returned: [],
-        typeFilter: -1,
         userQuery: 'a:: a',
         error: 'Paths cannot end with `::`',
     },
@@ -318,7 +297,6 @@ const PARSED = [
         foundElems: 0,
         original: 'a ::a',
         returned: [],
-        typeFilter: -1,
         userQuery: 'a ::a',
         error: 'Paths cannot start with `::`',
     },
@@ -327,16 +305,14 @@ const PARSED = [
         foundElems: 0,
         original: "a<a>:",
         returned: [],
-        typeFilter: -1,
         userQuery: "a<a>:",
-        error: 'Unexpected `:`',
+        error: 'Unexpected `<` in type filter',
     },
     {
         elems: [],
         foundElems: 0,
         original: "a<>:",
         returned: [],
-        typeFilter: -1,
         userQuery: "a<>:",
         error: 'Unexpected `<` in type filter',
     },
@@ -345,7 +321,6 @@ const PARSED = [
         foundElems: 0,
         original: "a,:",
         returned: [],
-        typeFilter: -1,
         userQuery: "a,:",
         error: 'Unexpected `,` in type filter',
     },
@@ -354,7 +329,6 @@ const PARSED = [
         foundElems: 0,
         original: "a<>  :",
         returned: [],
-        typeFilter: -1,
         userQuery: "a<>  :",
         error: 'Unexpected `<` in type filter',
     },
@@ -363,7 +337,6 @@ const PARSED = [
         foundElems: 0,
         original: "mod : :",
         returned: [],
-        typeFilter: -1,
         userQuery: "mod : :",
         error: 'Unexpected `:`',
     },
@@ -372,7 +345,6 @@ const PARSED = [
         foundElems: 0,
         original: "a!a",
         returned: [],
-        typeFilter: -1,
         userQuery: "a!a",
         error: 'Unexpected `!`: it can only be at the end of an ident',
     },
@@ -381,7 +353,6 @@ const PARSED = [
         foundElems: 0,
         original: "a!!",
         returned: [],
-        typeFilter: -1,
         userQuery: "a!!",
         error: 'Cannot have more than one `!` in an ident',
     },
@@ -390,7 +361,6 @@ const PARSED = [
         foundElems: 0,
         original: "mod:a!",
         returned: [],
-        typeFilter: -1,
         userQuery: "mod:a!",
         error: 'Invalid search type: macro `!` and `mod` both specified',
     },
@@ -399,7 +369,6 @@ const PARSED = [
         foundElems: 0,
         original: "a!::a",
         returned: [],
-        typeFilter: -1,
         userQuery: "a!::a",
         error: 'Cannot have associated items in macros',
     },
@@ -408,7 +377,6 @@ const PARSED = [
         foundElems: 0,
         original: "a<",
         returned: [],
-        typeFilter: -1,
         userQuery: "a<",
         error: "Unclosed `<`",
     },
diff --git a/tests/rustdoc-js-std/parser-filter.js b/tests/rustdoc-js-std/parser-filter.js
index 01f65b478f8..e23447ab75d 100644
--- a/tests/rustdoc-js-std/parser-filter.js
+++ b/tests/rustdoc-js-std/parser-filter.js
@@ -1,4 +1,14 @@
-const QUERY = ['fn:foo', 'enum : foo', 'macro<f>:foo', 'macro!', 'macro:mac!', 'a::mac!'];
+const QUERY = [
+    'fn:foo',
+    'enum : foo',
+    'macro<f>:foo',
+    'macro!',
+    'macro:mac!',
+    'a::mac!',
+    '-> fn:foo',
+    '-> fn:foo<fn:bar>',
+    '-> fn:foo<fn:bar, enum : baz::fuzz>',
+];
 
 const PARSED = [
     {
@@ -8,11 +18,11 @@ const PARSED = [
             pathWithoutLast: [],
             pathLast: "foo",
             generics: [],
+            typeFilter: 5,
         }],
         foundElems: 1,
         original: "fn:foo",
         returned: [],
-        typeFilter: 5,
         userQuery: "fn:foo",
         error: null,
     },
@@ -23,11 +33,11 @@ const PARSED = [
             pathWithoutLast: [],
             pathLast: "foo",
             generics: [],
+            typeFilter: 4,
         }],
         foundElems: 1,
         original: "enum : foo",
         returned: [],
-        typeFilter: 4,
         userQuery: "enum : foo",
         error: null,
     },
@@ -36,9 +46,8 @@ const PARSED = [
         foundElems: 0,
         original: "macro<f>:foo",
         returned: [],
-        typeFilter: -1,
         userQuery: "macro<f>:foo",
-        error: "Unexpected `:`",
+        error: "Unexpected `<` in type filter",
     },
     {
         elems: [{
@@ -47,11 +56,11 @@ const PARSED = [
             pathWithoutLast: [],
             pathLast: "macro",
             generics: [],
+            typeFilter: 14,
         }],
         foundElems: 1,
         original: "macro!",
         returned: [],
-        typeFilter: 14,
         userQuery: "macro!",
         error: null,
     },
@@ -62,11 +71,11 @@ const PARSED = [
             pathWithoutLast: [],
             pathLast: "mac",
             generics: [],
+            typeFilter: 14,
         }],
         foundElems: 1,
         original: "macro:mac!",
         returned: [],
-        typeFilter: 14,
         userQuery: "macro:mac!",
         error: null,
     },
@@ -77,12 +86,83 @@ const PARSED = [
             pathWithoutLast: ["a"],
             pathLast: "mac",
             generics: [],
+            typeFilter: 14,
         }],
         foundElems: 1,
         original: "a::mac!",
         returned: [],
-        typeFilter: 14,
         userQuery: "a::mac!",
         error: null,
     },
+    {
+        elems: [],
+        foundElems: 1,
+        original: "-> fn:foo",
+        returned: [{
+            name: "foo",
+            fullPath: ["foo"],
+            pathWithoutLast: [],
+            pathLast: "foo",
+            generics: [],
+            typeFilter: 5,
+        }],
+        userQuery: "-> fn:foo",
+        error: null,
+    },
+    {
+        elems: [],
+        foundElems: 1,
+        original: "-> fn:foo<fn:bar>",
+        returned: [{
+            name: "foo",
+            fullPath: ["foo"],
+            pathWithoutLast: [],
+            pathLast: "foo",
+            generics: [
+                {
+                    name: "bar",
+                    fullPath: ["bar"],
+                    pathWithoutLast: [],
+                    pathLast: "bar",
+                    generics: [],
+                    typeFilter: 5,
+                }
+            ],
+            typeFilter: 5,
+        }],
+        userQuery: "-> fn:foo<fn:bar>",
+        error: null,
+    },
+    {
+        elems: [],
+        foundElems: 1,
+        original: "-> fn:foo<fn:bar, enum : baz::fuzz>",
+        returned: [{
+            name: "foo",
+            fullPath: ["foo"],
+            pathWithoutLast: [],
+            pathLast: "foo",
+            generics: [
+                {
+                    name: "bar",
+                    fullPath: ["bar"],
+                    pathWithoutLast: [],
+                    pathLast: "bar",
+                    generics: [],
+                    typeFilter: 5,
+                },
+                {
+                    name: "baz::fuzz",
+                    fullPath: ["baz", "fuzz"],
+                    pathWithoutLast: ["baz"],
+                    pathLast: "fuzz",
+                    generics: [],
+                    typeFilter: 4,
+                },
+            ],
+            typeFilter: 5,
+        }],
+        userQuery: "-> fn:foo<fn:bar, enum : baz::fuzz>",
+        error: null,
+    },
 ];
diff --git a/tests/rustdoc-js-std/parser-generics.js b/tests/rustdoc-js-std/parser-generics.js
index 0cf7f5019aa..c448d845acb 100644
--- a/tests/rustdoc-js-std/parser-generics.js
+++ b/tests/rustdoc-js-std/parser-generics.js
@@ -6,7 +6,6 @@ const PARSED = [
         foundElems: 0,
         original: 'A<B<C<D>,  E>',
         returned: [],
-        typeFilter: -1,
         userQuery: 'a<b<c<d>,  e>',
         error: 'Unexpected `<` after `<`',
     },
@@ -18,6 +17,7 @@ const PARSED = [
                 pathWithoutLast: [],
                 pathLast: "p",
                 generics: [],
+                typeFilter: -1,
             },
             {
                 name: "u8",
@@ -25,12 +25,12 @@ const PARSED = [
                 pathWithoutLast: [],
                 pathLast: "u8",
                 generics: [],
+                typeFilter: -1,
             },
         ],
         foundElems: 2,
         original: "p<> u8",
         returned: [],
-        typeFilter: -1,
         userQuery: "p<> u8",
         error: null,
     },
@@ -50,12 +50,12 @@ const PARSED = [
                         generics: [],
                     },
                 ],
+                typeFilter: -1,
             },
         ],
         foundElems: 1,
         original: '"p"<a>',
         returned: [],
-        typeFilter: -1,
         userQuery: '"p"<a>',
         error: null,
     },
diff --git a/tests/rustdoc-js-std/parser-ident.js b/tests/rustdoc-js-std/parser-ident.js
index 6c17d00f16e..be42b7aa463 100644
--- a/tests/rustdoc-js-std/parser-ident.js
+++ b/tests/rustdoc-js-std/parser-ident.js
@@ -23,11 +23,11 @@ const PARSED = [
                     generics: [],
                 },
             ],
+            typeFilter: -1,
         }],
         foundElems: 1,
         original: "R<!>",
         returned: [],
-        typeFilter: -1,
         userQuery: "r<!>",
         error: null,
     },
@@ -38,11 +38,11 @@ const PARSED = [
             pathWithoutLast: [],
             pathLast: "!",
             generics: [],
+            typeFilter: -1,
         }],
         foundElems: 1,
         original: "!",
         returned: [],
-        typeFilter: -1,
         userQuery: "!",
         error: null,
     },
@@ -53,11 +53,11 @@ const PARSED = [
             pathWithoutLast: [],
             pathLast: "a",
             generics: [],
+            typeFilter: 14,
         }],
         foundElems: 1,
         original: "a!",
         returned: [],
-        typeFilter: 14,
         userQuery: "a!",
         error: null,
     },
@@ -66,7 +66,6 @@ const PARSED = [
         foundElems: 0,
         original: "a!::b",
         returned: [],
-        typeFilter: -1,
         userQuery: "a!::b",
         error: "Cannot have associated items in macros",
     },
@@ -77,11 +76,11 @@ const PARSED = [
             pathWithoutLast: ["!"],
             pathLast: "b",
             generics: [],
+            typeFilter: -1,
         }],
         foundElems: 1,
         original: "!::b",
         returned: [],
-        typeFilter: -1,
         userQuery: "!::b",
         error: null,
     },
@@ -90,7 +89,6 @@ const PARSED = [
         foundElems: 0,
         original: "a!::b!",
         returned: [],
-        typeFilter: -1,
         userQuery: "a!::b!",
         error: "Cannot have associated items in macros",
     },
diff --git a/tests/rustdoc-js-std/parser-literal.js b/tests/rustdoc-js-std/parser-literal.js
index 87b3baff1e2..3a31d1bddff 100644
--- a/tests/rustdoc-js-std/parser-literal.js
+++ b/tests/rustdoc-js-std/parser-literal.js
@@ -16,11 +16,11 @@ const PARSED = [
                     generics: [],
                 },
             ],
+            typeFilter: -1,
         }],
         foundElems: 1,
         original: "R<P>",
         returned: [],
-        typeFilter: -1,
         userQuery: "r<p>",
         error: null,
     }
diff --git a/tests/rustdoc-js-std/parser-paths.js b/tests/rustdoc-js-std/parser-paths.js
index 9f823f9336a..f3e421f5ffa 100644
--- a/tests/rustdoc-js-std/parser-paths.js
+++ b/tests/rustdoc-js-std/parser-paths.js
@@ -8,11 +8,11 @@ const PARSED = [
             pathWithoutLast: ["a"],
             pathLast: "b",
             generics: [],
+            typeFilter: -1,
         }],
         foundElems: 1,
         original: "A::B",
         returned: [],
-        typeFilter: -1,
         userQuery: "a::b",
         error: null,
     },
@@ -24,6 +24,7 @@ const PARSED = [
                 pathWithoutLast: ["a"],
                 pathLast: "b",
                 generics: [],
+                typeFilter: -1,
             },
             {
                 name: "c",
@@ -31,12 +32,12 @@ const PARSED = [
                 pathWithoutLast: [],
                 pathLast: "c",
                 generics: [],
+                typeFilter: -1,
             },
         ],
         foundElems: 2,
         original: 'A::B,C',
         returned: [],
-        typeFilter: -1,
         userQuery: 'a::b,c',
         error: null,
     },
@@ -56,6 +57,7 @@ const PARSED = [
                         generics: [],
                     },
                 ],
+                typeFilter: -1,
             },
             {
                 name: "c",
@@ -63,12 +65,12 @@ const PARSED = [
                 pathWithoutLast: [],
                 pathLast: "c",
                 generics: [],
+                typeFilter: -1,
             },
         ],
         foundElems: 2,
         original: 'A::B<f>,C',
         returned: [],
-        typeFilter: -1,
         userQuery: 'a::b<f>,c',
         error: null,
     },
@@ -79,11 +81,11 @@ const PARSED = [
             pathWithoutLast: ["mod"],
             pathLast: "a",
             generics: [],
+            typeFilter: -1,
         }],
         foundElems: 1,
         original: "mod::a",
         returned: [],
-        typeFilter: -1,
         userQuery: "mod::a",
         error: null,
     },
diff --git a/tests/rustdoc-js-std/parser-quote.js b/tests/rustdoc-js-std/parser-quote.js
index 1e16c90de5e..d5d67cac892 100644
--- a/tests/rustdoc-js-std/parser-quote.js
+++ b/tests/rustdoc-js-std/parser-quote.js
@@ -19,8 +19,8 @@ const PARSED = [
             pathWithoutLast: [],
             pathLast: "p",
             generics: [],
+            typeFilter: -1,
         }],
-        typeFilter: -1,
         userQuery: '-> "p"',
         error: null,
     },
@@ -31,11 +31,11 @@ const PARSED = [
             pathWithoutLast: [],
             pathLast: "p",
             generics: [],
+            typeFilter: -1,
         }],
         foundElems: 1,
         original: '"p",',
         returned: [],
-        typeFilter: -1,
         userQuery: '"p",',
         error: null,
     },
@@ -44,7 +44,6 @@ const PARSED = [
         foundElems: 0,
         original: '"p" -> a',
         returned: [],
-        typeFilter: -1,
         userQuery: '"p" -> a',
         error: "You cannot have more than one element if you use quotes",
     },
@@ -53,7 +52,6 @@ const PARSED = [
         foundElems: 0,
         original: '"a" -> "p"',
         returned: [],
-        typeFilter: -1,
         userQuery: '"a" -> "p"',
         error: "Cannot have more than one literal search element",
     },
@@ -62,7 +60,6 @@ const PARSED = [
         foundElems: 0,
         original: '->"-"',
         returned: [],
-        typeFilter: -1,
         userQuery: '->"-"',
         error: 'Unexpected `-` in a string element',
     },
@@ -71,7 +68,6 @@ const PARSED = [
         foundElems: 0,
         original: '"a',
         returned: [],
-        typeFilter: -1,
         userQuery: '"a',
         error: 'Unclosed `"`',
     },
@@ -80,7 +76,6 @@ const PARSED = [
         foundElems: 0,
         original: '""',
         returned: [],
-        typeFilter: -1,
         userQuery: '""',
         error: 'Cannot have empty string element',
     },
diff --git a/tests/rustdoc-js-std/parser-returned.js b/tests/rustdoc-js-std/parser-returned.js
index 6fce17dcabd..c2981319055 100644
--- a/tests/rustdoc-js-std/parser-returned.js
+++ b/tests/rustdoc-js-std/parser-returned.js
@@ -25,8 +25,8 @@ const PARSED = [
                     generics: [],
                 },
             ],
+            typeFilter: -1,
         }],
-        typeFilter: -1,
         userQuery: "-> f<p>",
         error: null,
     },
@@ -40,8 +40,8 @@ const PARSED = [
             pathWithoutLast: [],
             pathLast: "p",
             generics: [],
+            typeFilter: -1,
         }],
-        typeFilter: -1,
         userQuery: "-> p",
         error: null,
     },
@@ -55,8 +55,8 @@ const PARSED = [
             pathWithoutLast: [],
             pathLast: "a",
             generics: [],
+            typeFilter: -1,
         }],
-        typeFilter: -1,
         userQuery: "->,a",
         error: null,
     },
@@ -67,6 +67,7 @@ const PARSED = [
             pathWithoutLast: [],
             pathLast: "aaaaa",
             generics: [],
+            typeFilter: -1,
         }],
         foundElems: 2,
         original: "aaaaa->a",
@@ -76,8 +77,8 @@ const PARSED = [
             pathWithoutLast: [],
             pathLast: "a",
             generics: [],
+            typeFilter: -1,
         }],
-        typeFilter: -1,
         userQuery: "aaaaa->a",
         error: null,
     },
@@ -91,8 +92,8 @@ const PARSED = [
             pathWithoutLast: [],
             pathLast: "!",
             generics: [],
+            typeFilter: -1,
         }],
-        typeFilter: -1,
         userQuery: "-> !",
         error: null,
     },
diff --git a/tests/rustdoc-js-std/parser-separators.js b/tests/rustdoc-js-std/parser-separators.js
index 5b7abdfa8d6..fc8c5114c4e 100644
--- a/tests/rustdoc-js-std/parser-separators.js
+++ b/tests/rustdoc-js-std/parser-separators.js
@@ -19,6 +19,7 @@ const PARSED = [
                 pathWithoutLast: [],
                 pathLast: 'aaaaaa',
                 generics: [],
+                typeFilter: -1,
             },
             {
                 name: 'b',
@@ -26,12 +27,12 @@ const PARSED = [
                 pathWithoutLast: [],
                 pathLast: 'b',
                 generics: [],
+                typeFilter: -1,
             },
         ],
         foundElems: 2,
         original: "aaaaaa	b",
         returned: [],
-        typeFilter: -1,
         userQuery: "aaaaaa	b",
         error: null,
     },
@@ -43,6 +44,7 @@ const PARSED = [
                 pathWithoutLast: [],
                 pathLast: 'a',
                 generics: [],
+                typeFilter: -1,
             },
             {
                 name: 'b',
@@ -50,12 +52,12 @@ const PARSED = [
                 pathWithoutLast: [],
                 pathLast: 'b',
                 generics: [],
+                typeFilter: -1,
             },
         ],
         foundElems: 2,
         original: "a b",
         returned: [],
-        typeFilter: -1,
         userQuery: "a b",
         error: null,
     },
@@ -67,6 +69,7 @@ const PARSED = [
                 pathWithoutLast: [],
                 pathLast: 'a',
                 generics: [],
+                typeFilter: -1,
             },
             {
                 name: 'b',
@@ -74,12 +77,12 @@ const PARSED = [
                 pathWithoutLast: [],
                 pathLast: 'b',
                 generics: [],
+                typeFilter: -1,
             },
         ],
         foundElems: 2,
         original: "a,b",
         returned: [],
-        typeFilter: -1,
         userQuery: "a,b",
         error: null,
     },
@@ -91,6 +94,7 @@ const PARSED = [
                 pathWithoutLast: [],
                 pathLast: 'a',
                 generics: [],
+                typeFilter: -1,
             },
             {
                 name: 'b',
@@ -98,12 +102,12 @@ const PARSED = [
                 pathWithoutLast: [],
                 pathLast: 'b',
                 generics: [],
+                typeFilter: -1,
             },
         ],
         foundElems: 2,
         original: "a\tb",
         returned: [],
-        typeFilter: -1,
         userQuery: "a\tb",
         error: null,
     },
@@ -130,12 +134,12 @@ const PARSED = [
                         generics: [],
                     },
                 ],
+                typeFilter: -1,
             },
         ],
         foundElems: 1,
         original: "a<b c>",
         returned: [],
-        typeFilter: -1,
         userQuery: "a<b c>",
         error: null,
     },
@@ -162,12 +166,12 @@ const PARSED = [
                         generics: [],
                     },
                 ],
+                typeFilter: -1,
             },
         ],
         foundElems: 1,
         original: "a<b,c>",
         returned: [],
-        typeFilter: -1,
         userQuery: "a<b,c>",
         error: null,
     },
@@ -194,12 +198,12 @@ const PARSED = [
                         generics: [],
                     },
                 ],
+                typeFilter: -1,
             },
         ],
         foundElems: 1,
         original: "a<b\tc>",
         returned: [],
-        typeFilter: -1,
         userQuery: "a<b\tc>",
         error: null,
     },
diff --git a/tests/rustdoc-js-std/parser-weird-queries.js b/tests/rustdoc-js-std/parser-weird-queries.js
index a3d85aeca5e..dc1049a70bc 100644
--- a/tests/rustdoc-js-std/parser-weird-queries.js
+++ b/tests/rustdoc-js-std/parser-weird-queries.js
@@ -20,6 +20,7 @@ const PARSED = [
                 pathWithoutLast: [],
                 pathLast: "a",
                 generics: [],
+                typeFilter: -1,
             },
             {
                 name: "b",
@@ -27,12 +28,12 @@ const PARSED = [
                 pathWithoutLast: [],
                 pathLast: "b",
                 generics: [],
+                typeFilter: -1,
             },
         ],
         foundElems: 2,
         original: "a b",
         returned: [],
-        typeFilter: -1,
         userQuery: "a b",
         error: null,
     },
@@ -44,6 +45,7 @@ const PARSED = [
                 pathWithoutLast: [],
                 pathLast: "a",
                 generics: [],
+                typeFilter: -1,
             },
             {
                 name: "b",
@@ -51,12 +53,12 @@ const PARSED = [
                 pathWithoutLast: [],
                 pathLast: "b",
                 generics: [],
+                typeFilter: -1,
             },
         ],
         foundElems: 2,
         original: "a   b",
         returned: [],
-        typeFilter: -1,
         userQuery: "a   b",
         error: null,
     },
@@ -65,7 +67,6 @@ const PARSED = [
         foundElems: 0,
         original: "a,b(c)",
         returned: [],
-        typeFilter: -1,
         userQuery: "a,b(c)",
         error: "Unexpected `(`",
     },
@@ -77,6 +78,7 @@ const PARSED = [
                 pathWithoutLast: [],
                 pathLast: "aaa",
                 generics: [],
+                typeFilter: -1,
             },
             {
                 name: "a",
@@ -84,12 +86,12 @@ const PARSED = [
                 pathWithoutLast: [],
                 pathLast: "a",
                 generics: [],
+                typeFilter: -1,
             },
         ],
         foundElems: 2,
         original: "aaa,a",
         returned: [],
-        typeFilter: -1,
         userQuery: "aaa,a",
         error: null,
     },
@@ -98,7 +100,6 @@ const PARSED = [
         foundElems: 0,
         original: ",,,,",
         returned: [],
-        typeFilter: -1,
         userQuery: ",,,,",
         error: null,
     },
@@ -107,17 +108,15 @@ const PARSED = [
         foundElems: 0,
         original: 'mod    :',
         returned: [],
-        typeFilter: 0,
         userQuery: 'mod    :',
-        error: null,
+        error: "Unexpected `:` (expected path after type filter)",
     },
     {
         elems: [],
         foundElems: 0,
         original: 'mod\t:',
         returned: [],
-        typeFilter: 0,
         userQuery: 'mod\t:',
-        error: null,
+        error: "Unexpected `:` (expected path after type filter)",
     },
 ];
diff --git a/tests/rustdoc-js/generics-impl.js b/tests/rustdoc-js/generics-impl.js
index bb6e0041db5..5051743bda2 100644
--- a/tests/rustdoc-js/generics-impl.js
+++ b/tests/rustdoc-js/generics-impl.js
@@ -5,6 +5,8 @@ const QUERY = [
     'Aaaaaaa -> bool',
     'Aaaaaaa -> usize',
     'Read -> u64',
+    'trait:Read -> u64',
+    'struct:Read -> u64',
     'bool -> u64',
     'Ddddddd -> u64',
     '-> Ddddddd'
@@ -37,6 +39,17 @@ const EXPECTED = [
         ],
     },
     {
+        // trait:Read -> u64
+        'others': [
+            { 'path': 'generics_impl::Ddddddd', 'name': 'eeeeeee' },
+            { 'path': 'generics_impl::Ddddddd', 'name': 'ggggggg' },
+        ],
+    },
+    {
+        // struct:Read -> u64
+        'others': [],
+    },
+    {
         // bool -> u64
         'others': [
             { 'path': 'generics_impl::Ddddddd', 'name': 'fffffff' },
diff --git a/tests/rustdoc-js/generics.js b/tests/rustdoc-js/generics.js
index 5e5ba7cd9ac..f79c709ad6c 100644
--- a/tests/rustdoc-js/generics.js
+++ b/tests/rustdoc-js/generics.js
@@ -2,6 +2,8 @@
 
 const QUERY = [
     'R<P>',
+    'R<struct:P>',
+    'R<enum:P>',
     '"P"',
     'P',
     'ExtraCreditStructMulti<ExtraCreditInnerMulti, ExtraCreditInnerMulti>',
@@ -21,6 +23,20 @@ const EXPECTED = [
         ],
     },
     {
+        // R<struct:P>
+        'returned': [
+            { 'path': 'generics', 'name': 'alef' },
+        ],
+        'in_args': [
+            { 'path': 'generics', 'name': 'alpha' },
+        ],
+    },
+    {
+        // R<enum:P>
+        'returned': [],
+        'in_args': [],
+    },
+    {
         // "P"
         'others': [
             { 'path': 'generics', 'name': 'P' },
diff --git a/tests/rustdoc-js/primitive.js b/tests/rustdoc-js/primitive.js
index 918f7099918..4aec98c3403 100644
--- a/tests/rustdoc-js/primitive.js
+++ b/tests/rustdoc-js/primitive.js
@@ -3,6 +3,8 @@
 const QUERY = [
     "i32",
     "str",
+    "primitive:str",
+    "struct:str",
     "TotoIsSomewhere",
 ];
 
@@ -18,6 +20,14 @@ const EXPECTED = [
         ],
     },
     {
+        'returned': [
+            { 'path': 'primitive', 'name': 'foo' },
+        ],
+    },
+    {
+        'returned': [],
+    },
+    {
         'others': [],
         'in_args': [],
         'returned': [],