From a8c0b3bfff36c5b7dbd429891b7fd2093e25a9ad Mon Sep 17 00:00:00 2001 From: binarycat Date: Mon, 3 Mar 2025 23:36:12 -0600 Subject: [PATCH 01/14] rustdoc search: increase strictness of typechecking --- src/librustdoc/html/static/js/rustdoc.d.ts | 10 ++++++++-- src/librustdoc/html/static/js/search.js | 7 +++---- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/librustdoc/html/static/js/rustdoc.d.ts b/src/librustdoc/html/static/js/rustdoc.d.ts index acea7828e86a9..c7b7a46808f1b 100644 --- a/src/librustdoc/html/static/js/rustdoc.d.ts +++ b/src/librustdoc/html/static/js/rustdoc.d.ts @@ -123,7 +123,7 @@ declare namespace rustdoc { * Same as QueryElement, but bindings and typeFilter support strings */ interface ParserQueryElement { - name: string, + name: string|null, id: number|null, fullPath: Array, pathWithoutLast: Array, @@ -131,10 +131,16 @@ declare namespace rustdoc { normalizedPathLast: string, generics: Array, bindings: Map>, - bindingName: {name: string, generics: ParserQueryElement[]}|null, + bindingName: {name: string|null, generics: ParserQueryElement[]}|null, typeFilter: string|null, } + /** + * Same as ParserQueryElement, but all fields are optional. + */ + type ParserQueryElementFields = { + [K in keyof ParserQueryElement]?: ParserQueryElement[T] + } /** * Intermediate parser state. Discarded when parsing is done. */ diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js index ccbd6811b0712..4073bb389c069 100644 --- a/src/librustdoc/html/static/js/search.js +++ b/src/librustdoc/html/static/js/search.js @@ -638,7 +638,6 @@ function getNextElem(query, parserState, elems, isInGenerics) { getFilteredNextElem(query, parserState, generics, isInGenerics); generics[generics.length - 1].bindingName = makePrimitiveElement("output"); } else { - // @ts-expect-error generics.push(makePrimitiveElement(null, { bindingName: makePrimitiveElement("output"), typeFilter: null, @@ -791,7 +790,7 @@ function createQueryElement(query, parserState, name, generics, isInGenerics) { generics: generics.filter(gen => { // Syntactically, bindings are parsed as generics, // but the query engine treats them differently. - if (gen.bindingName !== null) { + if (gen.bindingName !== null && gen.bindingName.name !== null) { if (gen.name !== null) { gen.bindingName.generics.unshift(gen); } @@ -811,8 +810,8 @@ function createQueryElement(query, parserState, name, generics, isInGenerics) { /** * - * @param {string} name - * @param {Object=} extra + * @param {string|null} name + * @param {rustdoc.ParserQueryElementFields=} extra * @returns {rustdoc.ParserQueryElement} */ function makePrimitiveElement(name, extra) { From 2f9ea8a55ad6397bae7d97f653bbe02915017f03 Mon Sep 17 00:00:00 2001 From: binarycat Date: Tue, 4 Mar 2025 00:27:27 -0600 Subject: [PATCH 02/14] rustdoc search: give buildTypeMapIndex a conditional return type we encode "if the argument is a non-empty string, this will never return null" into the type signature. --- src/librustdoc/html/static/js/search.js | 26 ++++++++++--------------- 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js index 4073bb389c069..bd0dab97f0184 100644 --- a/src/librustdoc/html/static/js/search.js +++ b/src/librustdoc/html/static/js/search.js @@ -1477,73 +1477,61 @@ class DocSearch { * Special type name IDs for searching by array. * @type {number} */ - // @ts-expect-error this.typeNameIdOfArray = this.buildTypeMapIndex("array"); /** * Special type name IDs for searching by slice. * @type {number} */ - // @ts-expect-error this.typeNameIdOfSlice = this.buildTypeMapIndex("slice"); /** * Special type name IDs for searching by both array and slice (`[]` syntax). * @type {number} */ - // @ts-expect-error this.typeNameIdOfArrayOrSlice = this.buildTypeMapIndex("[]"); /** * Special type name IDs for searching by tuple. * @type {number} */ - // @ts-expect-error this.typeNameIdOfTuple = this.buildTypeMapIndex("tuple"); /** * Special type name IDs for searching by unit. * @type {number} */ - // @ts-expect-error this.typeNameIdOfUnit = this.buildTypeMapIndex("unit"); /** * Special type name IDs for searching by both tuple and unit (`()` syntax). * @type {number} */ - // @ts-expect-error this.typeNameIdOfTupleOrUnit = this.buildTypeMapIndex("()"); /** * Special type name IDs for searching `fn`. * @type {number} */ - // @ts-expect-error this.typeNameIdOfFn = this.buildTypeMapIndex("fn"); /** * Special type name IDs for searching `fnmut`. * @type {number} */ - // @ts-expect-error this.typeNameIdOfFnMut = this.buildTypeMapIndex("fnmut"); /** * Special type name IDs for searching `fnonce`. * @type {number} */ - // @ts-expect-error this.typeNameIdOfFnOnce = this.buildTypeMapIndex("fnonce"); /** * Special type name IDs for searching higher order functions (`->` syntax). * @type {number} */ - // @ts-expect-error this.typeNameIdOfHof = this.buildTypeMapIndex("->"); /** * Special type name IDs the output assoc type. * @type {number} */ - // @ts-expect-error this.typeNameIdOfOutput = this.buildTypeMapIndex("output", true); /** * Special type name IDs for searching by reference. * @type {number} */ - // @ts-expect-error this.typeNameIdOfReference = this.buildTypeMapIndex("reference"); /** @@ -1596,11 +1584,17 @@ class DocSearch { * This is effectively string interning, so that function matching can be * done more quickly. Two types with the same name but different item kinds * get the same ID. - * - * @param {string} name + * + * @template T extends string + * @overload + * @param {T} name * @param {boolean=} isAssocType - True if this is an assoc type - * - * @returns {number?} + * @returns {T extends "" ? null : number} + * + * @param {string} name + * @param {boolean=} isAssocType + * @returns {number | null} + * */ buildTypeMapIndex(name, isAssocType) { if (name === "" || name === null) { From 60c5855346576dea6666adb9e00479156242b495 Mon Sep 17 00:00:00 2001 From: binarycat Date: Tue, 4 Mar 2025 00:43:56 -0600 Subject: [PATCH 03/14] ParserQueryElement.typeFilter MAY be a string, OR number. ideally we would encode that it is a string before convertTypeFilterOnElem is called, and a number after, but i'm not sure that's possible without significant refactoring. --- src/librustdoc/html/static/js/rustdoc.d.ts | 2 +- src/librustdoc/html/static/js/search.js | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/librustdoc/html/static/js/rustdoc.d.ts b/src/librustdoc/html/static/js/rustdoc.d.ts index c7b7a46808f1b..bc4c9a12ac0a1 100644 --- a/src/librustdoc/html/static/js/rustdoc.d.ts +++ b/src/librustdoc/html/static/js/rustdoc.d.ts @@ -132,7 +132,7 @@ declare namespace rustdoc { generics: Array, bindings: Map>, bindingName: {name: string|null, generics: ParserQueryElement[]}|null, - typeFilter: string|null, + typeFilter: number|string|null, } /** diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js index bd0dab97f0184..45077f7920ba4 100644 --- a/src/librustdoc/html/static/js/search.js +++ b/src/librustdoc/html/static/js/search.js @@ -2319,15 +2319,13 @@ class DocSearch { * @param {rustdoc.ParserQueryElement} elem */ function convertTypeFilterOnElem(elem) { - if (elem.typeFilter !== null) { + if (typeof elem.typeFilter === 'string') { let typeFilter = elem.typeFilter; if (typeFilter === "const") { typeFilter = "constant"; } - // @ts-expect-error elem.typeFilter = itemTypeFromName(typeFilter); } else { - // @ts-expect-error elem.typeFilter = NO_TYPE_FILTER; } for (const elem2 of elem.generics) { From 7635f2bfc61b353b83c244cf758459486a2ea442 Mon Sep 17 00:00:00 2001 From: binarycat Date: Tue, 4 Mar 2025 11:03:55 -0600 Subject: [PATCH 04/14] fix whitespace --- src/librustdoc/html/static/js/search.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js index 45077f7920ba4..cc8c7a3e43a4a 100644 --- a/src/librustdoc/html/static/js/search.js +++ b/src/librustdoc/html/static/js/search.js @@ -1584,17 +1584,17 @@ class DocSearch { * This is effectively string interning, so that function matching can be * done more quickly. Two types with the same name but different item kinds * get the same ID. - * - * @template T extends string - * @overload + * + * @template T extends string + * @overload * @param {T} name * @param {boolean=} isAssocType - True if this is an assoc type * @returns {T extends "" ? null : number} - * - * @param {string} name + * + * @param {string} name * @param {boolean=} isAssocType * @returns {number | null} - * + * */ buildTypeMapIndex(name, isAssocType) { if (name === "" || name === null) { From 32ebe8ed04db275e68b4f1e08d7f6c8ddc806993 Mon Sep 17 00:00:00 2001 From: binarycat Date: Tue, 4 Mar 2025 13:37:56 -0600 Subject: [PATCH 05/14] don't use double quotes --- src/librustdoc/html/static/js/search.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js index cc8c7a3e43a4a..5daaddd50fb61 100644 --- a/src/librustdoc/html/static/js/search.js +++ b/src/librustdoc/html/static/js/search.js @@ -2319,7 +2319,7 @@ class DocSearch { * @param {rustdoc.ParserQueryElement} elem */ function convertTypeFilterOnElem(elem) { - if (typeof elem.typeFilter === 'string') { + if (typeof elem.typeFilter === "string") { let typeFilter = elem.typeFilter; if (typeFilter === "const") { typeFilter = "constant"; From d130e2545510a10373a147192d8c19cdd9bedc00 Mon Sep 17 00:00:00 2001 From: binarycat Date: Tue, 4 Mar 2025 13:54:56 -0600 Subject: [PATCH 06/14] search.js: local variable `extra` is an array, annotate it as such. --- src/librustdoc/html/static/js/search.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js index 5daaddd50fb61..b4f3bcde4d4d3 100644 --- a/src/librustdoc/html/static/js/search.js +++ b/src/librustdoc/html/static/js/search.js @@ -2398,9 +2398,9 @@ class DocSearch { continue; } if (!foundStopChar) { - let extra = ""; + /** @type String[] */ + let extra = []; if (isLastElemGeneric(query.elems, parserState)) { - // @ts-expect-error extra = [" after ", ">"]; } else if (prevIs(parserState, "\"")) { throw ["Cannot have more than one element if you use quotes"]; From 78b92f08f9d72fd44e8d1a641c23a25a75f7f25d Mon Sep 17 00:00:00 2001 From: binarycat Date: Tue, 4 Mar 2025 13:58:35 -0600 Subject: [PATCH 07/14] search.js: second argument of convertNameToId is optional --- src/librustdoc/html/static/js/search.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js index b4f3bcde4d4d3..57e776deb5c53 100644 --- a/src/librustdoc/html/static/js/search.js +++ b/src/librustdoc/html/static/js/search.js @@ -2538,7 +2538,7 @@ class DocSearch { * See `buildTypeMapIndex` for more information. * * @param {rustdoc.QueryElement} elem - * @param {boolean} isAssocType + * @param {boolean=} isAssocType */ const convertNameToId = (elem, isAssocType) => { const loweredName = elem.pathLast.toLowerCase(); @@ -2618,7 +2618,6 @@ class DocSearch { ]; } for (const elem2 of elem.generics) { - // @ts-expect-error convertNameToId(elem2); } elem.bindings = new Map(Array.from(elem.bindings.entries()) From 9581f1935bd7a8c66e17c6d65ee286f03ca2c60a Mon Sep 17 00:00:00 2001 From: binarycat Date: Tue, 4 Mar 2025 14:25:04 -0600 Subject: [PATCH 08/14] search.js: give pathSplitter a type signature --- src/librustdoc/html/static/js/search.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js index 57e776deb5c53..fb481638061db 100644 --- a/src/librustdoc/html/static/js/search.js +++ b/src/librustdoc/html/static/js/search.js @@ -2740,7 +2740,11 @@ class DocSearch { return [displayPath, href, `${exactPath}::${name}`]; }; - // @ts-expect-error + /** + * + * @param {string} path + * @returns {string} + */ function pathSplitter(path) { const tmp = "" + path.replace(/::/g, "::"); if (tmp.endsWith("")) { From 4f6772d2ac31cdf5ca4fb0b3087a0d884a1f2c5c Mon Sep 17 00:00:00 2001 From: binarycat Date: Tue, 4 Mar 2025 14:28:45 -0600 Subject: [PATCH 09/14] give local mgens a type --- src/librustdoc/html/static/js/search.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js index fb481638061db..335e35b211bf1 100644 --- a/src/librustdoc/html/static/js/search.js +++ b/src/librustdoc/html/static/js/search.js @@ -2834,7 +2834,7 @@ class DocSearch { } let fnInputs = null; let fnOutput = null; - // @ts-expect-error + /** @type {Map | null} */ let mgens = null; if (typeInfo !== "elems" && typeInfo !== "returned") { fnInputs = unifyFunctionTypes( @@ -3047,7 +3047,6 @@ class DocSearch { writeFn(nested, result); } return; - // @ts-expect-error } else if (mgens) { for (const [queryId, fnId] of mgens) { if (fnId === fnType.id) { From c05f6bf98d08cfb159051caaae850590758f6c15 Mon Sep 17 00:00:00 2001 From: binarycat Date: Tue, 4 Mar 2025 14:31:35 -0600 Subject: [PATCH 10/14] search.js: give local `where` a type --- src/librustdoc/html/static/js/search.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js index 335e35b211bf1..9d740cef3eb9b 100644 --- a/src/librustdoc/html/static/js/search.js +++ b/src/librustdoc/html/static/js/search.js @@ -3062,7 +3062,7 @@ class DocSearch { name: fnParamNames[-1 - fnType.id], highlighted: !!fnType.highlighted, }, result); - // @ts-expect-error + /** @type{string[]} */ const where = []; onEachBtwn( fnType.generics, @@ -3072,7 +3072,6 @@ class DocSearch { () => pushText({ name: " + ", highlighted: false }, where), ); if (where.length > 0) { - // @ts-expect-error whereClause.set(fnParamNames[-1 - fnType.id], where); } } else { From 374de12dad8e42e1595f1af5f8e43b8b2b71c61c Mon Sep 17 00:00:00 2001 From: binarycat Date: Tue, 4 Mar 2025 15:19:20 -0600 Subject: [PATCH 11/14] search.js: give buildIndex a proper return type some of the fields of rustdoc.Row were confusing null and undefined. --- src/librustdoc/html/static/js/rustdoc.d.ts | 3 ++- src/librustdoc/html/static/js/search.js | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/librustdoc/html/static/js/rustdoc.d.ts b/src/librustdoc/html/static/js/rustdoc.d.ts index bc4c9a12ac0a1..060d82056587d 100644 --- a/src/librustdoc/html/static/js/rustdoc.d.ts +++ b/src/librustdoc/html/static/js/rustdoc.d.ts @@ -182,10 +182,11 @@ declare namespace rustdoc { name: string, normalizedName: string, word: string, + paramNames: string[], parent: ({ty: number, name: string, path: string, exactPath: string}|null|undefined), path: string, ty: number, - type?: FunctionSearchType + type: FunctionSearchType | null, } /** diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js index 9d740cef3eb9b..ccaa8237ff893 100644 --- a/src/librustdoc/html/static/js/search.js +++ b/src/librustdoc/html/static/js/search.js @@ -1573,7 +1573,6 @@ class DocSearch { /** * @type {Array} */ - // @ts-expect-error this.searchIndex = this.buildIndex(rawSearchIndex); } @@ -1902,6 +1901,7 @@ class DocSearch { * Convert raw search index into in-memory search index. * * @param {Map} rawSearchIndex + * @returns {rustdoc.Row[]} */ buildIndex(rawSearchIndex) { /** @@ -2001,6 +2001,7 @@ class DocSearch { return cb; }; + /** @type {rustdoc.Row[]} */ const searchIndex = []; let currentIndex = 0; let id = 0; @@ -2225,6 +2226,7 @@ class DocSearch { // object defined above. const itemParentIdx = itemParentIdxDecoder.next(); normalizedName = word.indexOf("_") === -1 ? word : word.replace(/_/g, ""); + /** @type {rustdoc.Row} */ const row = { crate, ty: itemTypes.charCodeAt(i) - 65, // 65 = "A" From 5f390265409018a653ba6aef7ee7f2ce56afe972 Mon Sep 17 00:00:00 2001 From: binarycat Date: Tue, 4 Mar 2025 15:26:46 -0600 Subject: [PATCH 12/14] search.js: allow empty result arrays --- src/librustdoc/html/static/js/search.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js index ccaa8237ff893..8954cefa31639 100644 --- a/src/librustdoc/html/static/js/search.js +++ b/src/librustdoc/html/static/js/search.js @@ -2759,9 +2759,9 @@ class DocSearch { * Add extra data to result objects, and filter items that have been * marked for removal. * - * @param {[rustdoc.ResultObject]} results + * @param {rustdoc.ResultObject[]} results * @param {"sig"|"elems"|"returned"|null} typeInfo - * @returns {[rustdoc.ResultObject]} + * @returns {rustdoc.ResultObject[]} */ const transformResults = (results, typeInfo) => { const duplicates = new Set(); @@ -3175,7 +3175,7 @@ class DocSearch { * @param {rustdoc.Results} results * @param {"sig"|"elems"|"returned"|null} typeInfo * @param {string} preferredCrate - * @returns {Promise<[rustdoc.ResultObject]>} + * @returns {Promise} */ const sortResults = async(results, typeInfo, preferredCrate) => { const userQuery = parsedQuery.userQuery; @@ -3331,7 +3331,6 @@ class DocSearch { return 0; }); - // @ts-expect-error return transformResults(result_list, typeInfo); }; From a9a52ddc04d45dcf06622f360ad9e784adfedc65 Mon Sep 17 00:00:00 2001 From: binarycat Date: Tue, 4 Mar 2025 15:53:35 -0600 Subject: [PATCH 13/14] search.js: give RawSearchIndexCrate.a an index signature --- src/librustdoc/html/static/js/rustdoc.d.ts | 2 +- src/librustdoc/html/static/js/search.js | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/librustdoc/html/static/js/rustdoc.d.ts b/src/librustdoc/html/static/js/rustdoc.d.ts index 060d82056587d..1554c045a3271 100644 --- a/src/librustdoc/html/static/js/rustdoc.d.ts +++ b/src/librustdoc/html/static/js/rustdoc.d.ts @@ -397,7 +397,7 @@ declare namespace rustdoc { */ type RawSearchIndexCrate = { doc: string, - a: Object, + a: { [key: string]: number[] }, n: Array, t: string, D: string, diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js index 8954cefa31639..8deeff7f973cf 100644 --- a/src/librustdoc/html/static/js/search.js +++ b/src/librustdoc/html/static/js/search.js @@ -2269,16 +2269,14 @@ class DocSearch { continue; } - // @ts-expect-error + /** @type{number[]} */ let currentNameAliases; if (currentCrateAliases.has(alias_name)) { currentNameAliases = currentCrateAliases.get(alias_name); } else { currentNameAliases = []; - // @ts-expect-error currentCrateAliases.set(alias_name, currentNameAliases); } - // @ts-expect-error for (const local_alias of aliases[alias_name]) { currentNameAliases.push(local_alias + currentIndex); } From 892016766a70e929f9325f315d0a9fd953f54853 Mon Sep 17 00:00:00 2001 From: binarycat Date: Tue, 4 Mar 2025 15:54:48 -0600 Subject: [PATCH 14/14] search.js: remove incorrect outdated comment --- src/librustdoc/html/static/js/search.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js index 8deeff7f973cf..c275127997ab1 100644 --- a/src/librustdoc/html/static/js/search.js +++ b/src/librustdoc/html/static/js/search.js @@ -2102,8 +2102,6 @@ class DocSearch { // an array of [(Number) item type, // (String) name] const rawPaths = crateCorpus.p; - // an array of [(String) alias name - // [Number] index to items] const aliases = crateCorpus.a; // an array of [(Number) item index, // (String) comma-separated list of function generic param names]