From ebd5ce1828dd2dfdef35786e1374c7ca30f1b0c9 Mon Sep 17 00:00:00 2001 From: binarycat Date: Thu, 9 Jan 2025 14:16:05 -0600 Subject: [PATCH] for purely return-type based searches, deprioritize clone-like functions A clone-like function in a function that takes as an argument the type that it returns. However, functions that return a type variable are not counted as clone-line. Because we're not unifying the whole function at once, a function like `U -> T` would otherwise be counted as "clone-like" because the generics will just unify with anything when done seperatly. Co-authored-by: Michael Howell --- src/librustdoc/html/static/js/search.js | 46 +++++++++++++++++++++++ tests/rustdoc-js-std/return-based-sort.js | 30 +++++++++++++++ 2 files changed, 76 insertions(+) create mode 100644 tests/rustdoc-js-std/return-based-sort.js diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js index 5fd5eb1447843..0a0550ab82f9b 100644 --- a/src/librustdoc/html/static/js/search.js +++ b/src/librustdoc/html/static/js/search.js @@ -2717,9 +2717,26 @@ class DocSearch { const normalizedUserQuery = parsedQuery.userQuery.toLowerCase(); const isMixedCase = normalizedUserQuery !== userQuery; const result_list = []; + const isReturnTypeQuery = parsedQuery.elems.length === 0 || + typeInfo === "returned"; for (const result of results.values()) { result.item = this.searchIndex[result.id]; result.word = this.searchIndex[result.id].word; + if (isReturnTypeQuery) { + // we are doing a return-type based search, + // deprioritize "clone-like" results, + // ie. functions that also take the queried type as an argument. + const hasType = result.item && result.item.type; + if (!hasType) { + continue; + } + const inputs = result.item.type.inputs; + const where_clause = result.item.type.where_clause; + if (containsTypeFromQuery(inputs, where_clause)) { + result.path_dist *= 100; + result.dist *= 100; + } + } result_list.push(result); } @@ -3540,6 +3557,35 @@ class DocSearch { return false; } + /** + * This function checks if the given list contains any + * (non-generic) types mentioned in the query. + * + * @param {Array} list - A list of function types. + * @param {[FunctionType]} where_clause - Trait bounds for generic items. + */ + function containsTypeFromQuery(list, where_clause) { + if (!list) return false; + for (const ty of parsedQuery.returned) { + // negative type ids are generics + if (ty.id < 0) { + continue; + } + if (checkIfInList(list, ty, where_clause, null, 0)) { + return true; + } + } + for (const ty of parsedQuery.elems) { + if (ty.id < 0) { + continue; + } + if (checkIfInList(list, ty, where_clause, null, 0)) { + return true; + } + } + return false; + } + /** * This function checks if the object (`row`) matches the given type (`elem`) and its * generics (if any). diff --git a/tests/rustdoc-js-std/return-based-sort.js b/tests/rustdoc-js-std/return-based-sort.js new file mode 100644 index 0000000000000..30baf1cd36e58 --- /dev/null +++ b/tests/rustdoc-js-std/return-based-sort.js @@ -0,0 +1,30 @@ +// test that `clone`-like functions are sorted lower when +// a search is based soley on return type + +const FILTER_CRATE = "core"; + +const EXPECTED = [ + { + 'query': '-> AllocError', + 'others': [ + { 'path': 'core::alloc::Allocator', 'name': 'allocate' }, + { 'path': 'core::alloc::AllocError', 'name': 'clone' }, + ], + }, + { + 'query': 'AllocError', + 'returned': [ + { 'path': 'core::alloc::Allocator', 'name': 'allocate' }, + { 'path': 'core::alloc::AllocError', 'name': 'clone' }, + ], + }, + { + 'query': '-> &str', + 'others': [ + // type_name_of_val should not be consider clone-like + { 'path': 'core::any', 'name': 'type_name_of_val' }, + // this returns `Option<&str>`, and thus should be sorted lower + { 'path': 'core::str::Split', 'name': 'next' }, + ], + }, +]