about summary refs log tree commit diff
path: root/tests/rustdoc-js
AgeCommit message (Collapse)AuthorLines
2023-12-15rustdoc-search: remove parallel searchWords arrayMichael Howell-7/+17
This might have made sense if the algorithm could use `searchWords` to skip having to look at `searchIndex`, but since it always does a substring check on both the stock word and the normalizedName, it doesn't seem to help performance anyway.
2023-12-13rustdoc-search: use set ops for ranking and filteringMichael Howell-15/+117
This commit adds ranking and quick filtering to type-based search, improving performance and having it order results based on their type signatures. Motivation ---------- If I write a query like `str -> String`, a lot of functions come up. That's to be expected, but `String::from_str` should come up on top, and it doesn't right now. This is because the sorting algorithm is based on the functions name, and doesn't consider the type signature at all. `slice::join` even comes up above it! To fix this, the sorting should take into account the function's signature, and the closer match should come up on top. Guide-level description ----------------------- When searching by type signature, types with a "closer" match will show up above types that match less precisely. Reference-level explanation --------------------------- Functions signature search works in three major phases: * A compact "fingerprint," based on the [bloom filter] technique, is used to check for matches and to estimate the distance. It sometimes has false positive matches, but it also operates on 128 bit contiguous memory and requires no backtracking, so it performs a lot better than real unification. The fingerprint represents the set of items in the type signature, but it does not represent nesting, and it ignores when the same item appears more than once. The result is rejected if any query bits are absent in the function, or if the distance is higher than the current maximum and 200 results have already been found. * The second step performs unification. This is where nesting and true bag semantics are taken into account, and it has no false positives. It uses a recursive, backtracking algorithm. The result is rejected if any query elements are absent in the function. [bloom filter]: https://en.wikipedia.org/wiki/Bloom_filter Drawbacks --------- This makes the code bigger. More than that, this design is a subtle trade-off. It makes the cases I've tested against measurably faster, but it's not clear how well this extends to other crates with potentially more functions and fewer types. The more complex things get, the more important it is to gather a good set of data to test with (this is arguably more important than the actual benchmarking ifrastructure right now). Rationale and alternatives -------------------------- Throwing a bloom filter in front makes it faster. More than that, it tries to take a tactic where the system can not only check for potential matches, but also gets an accurate distance function without needing to do unification. That way it can skip unification even on items that have the needed elems, as long as they have more items than the currently found maximum. If I didn't want to be able to cheaply do set operations on the fingerprint, a [cuckoo filter] is supposed to have better performance. But the nice bit-banging set intersection doesn't work AFAIK. I also looked into [minhashing], but since it's actually an unbiased estimate of the similarity coefficient, I'm not sure how it could be used to skip unification (I wouldn't know if the estimate was too low or too high). This function actually uses the number of distinct items as its "distance function." This should give the same results that it would have gotten from a Jaccard Distance $1-\frac{|F\cap{}Q|}{|F\cup{}Q|}$, while being cheaper to compute. This is because: * The function $F$ must be a superset of the query $Q$, so their union is just $F$ and the intersection is $Q$ and it can be reduced to $1-\frac{|Q|}{|F|}. * There are no magic thresholds. These values are only being used to compare against each other while sorting (and, if 200 results are found, to compare with the maximum match). This means we only care if one value is bigger than the other, not what it's actual value is, and since $Q$ is the same for everything, it can be safely left out, reducing the formula to $1-\frac{1}{|F|} = \frac{|F|}{|F|}-\frac{1}{|F|} = |F|-1$. And, since the values are only being compared with each other, $|F|$ is fine. Prior art --------- This is significantly different from how Hoogle does it. It doesn't account for order, and it has no special account for nesting, though `Box<t>` is still two items, while `t` is only one. This should give the same results that it would have gotten from a Jaccard Distance $1-\frac{|A\cap{}B|}{|A\cup{}B|}$, while being cheaper to compute. Unresolved questions -------------------- `[]` and `()`, the slice/array and tuple/union operators, are ignored while building the signature for the query. This is because they match more than one thing, making them ambiguous. Unfortunately, this also makes them a performance cliff. Is this likely to be a problem? Right now, the system just stashes the type distance into the same field that levenshtein distance normally goes in. This means exact query matches show up on top (for example, if you have a function like `fn nothing(a: Nothing, b: i32)`, then searching for `nothing` will show it on top even if there's another function with `fn bar(x: Nothing)` that's technically a closer match in type signature. Future possibilities -------------------- It should be possible to adopt more sorting criteria to act as a tie breaker, which could be determined during unification. [cuckoo filter]: https://en.wikipedia.org/wiki/Cuckoo_filter [minhashing]: https://en.wikipedia.org/wiki/MinHash
2023-12-10rustdoc-search: fix fast path unboxing bindingsMichael Howell-0/+11
2023-12-10rustdoc-search: do not treat associated type names as typesMichael Howell-0/+84
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.
2023-11-24rustdoc-search: avoid infinite where clause unboxMichael Howell-0/+44
Fixes #118242
2023-11-19rustdoc-search: add support for associated typesMichael Howell-0/+349
2023-11-17rustdoc-search: fix accidental shared, mutable mapMichael Howell-0/+35
2023-10-11Add regression test for #115480Guillaume Gomez-0/+32
2023-10-10Rollup merge of #109422 - notriddle:notriddle/impl-disambiguate-search, ↵Guillaume Gomez-0/+50
r=GuillaumeGomez rustdoc-search: add impl disambiguator to duplicate assoc items Preview (to see the difference, click the link and pay attention to the specific function that comes up): | Before | After | |--|--| | [`simd<i64>, simd<i64> -> simd<i64>`](https://doc.rust-lang.org/nightly/std/?search=simd%3Ci64%3E%2C%20simd%3Ci64%3E%20-%3E%20simd%3Ci64%3E) | [`simd<i64>, simd<i64> -> simd<i64>`](https://notriddle.com/rustdoc-demo-html-3/impl-disambiguate-search/std/index.html?search=simd%3Ci64%3E%2C%20simd%3Ci64%3E%20-%3E%20simd%3Ci64%3E) | | [`cow, vec -> bool`](https://doc.rust-lang.org/nightly/std/?search=cow%2C%20vec%20-%3E%20bool) | [`cow, vec -> bool`](https://notriddle.com/rustdoc-demo-html-3/impl-disambiguate-search/std/index.html?search=cow%2C%20vec%20-%3E%20bool) Helps with #90929 This changes the search results, specifically, when there's more than one impl with an associated item with the same name. For example, the search queries `simd<i8> -> simd<i8>` and `simd<i64> -> simd<i64>` don't link to the same function, but most of the functions have the same names. This change should probably be FCP-ed, especially since it adds a new anchor link format for `main.js` to handle, so that URLs like `struct.Vec.html#impl-AsMut<[T]>-for-Vec<T,+A>/method.as_mut` redirect to `struct.Vec.html#method.as_mut-2`. It's a strange design, but there are a few reasons for it: * I'd like to avoid making the HTML bigger. Obviously, fixing this bug is going to add at least a little more data to the search index, but adding more HTML penalises viewers for the benefit of searchers. * Breaking `struct.Vec.html#method.len` would also be a disappointment. On the other hand: * The path-style anchors might be less prone to link rot than the numbered anchors. It's definitely less likely to have URLs that appear to "work", but silently point at the wrong thing. * This commit arranges the path-style anchor to redirect to the numbered anchor. Nothing stops rustdoc from doing the opposite, making path-style anchors the default and redirecting the "legacy" numbered ones. ### The bug On the "Before" links, this example search calls for `i64`: ![image](https://github.com/rust-lang/rust/assets/1593513/9431d89d-41dc-4f68-bbb1-3e2704a973d2) But if I click any of the results, I get `f64` instead. ![image](https://github.com/rust-lang/rust/assets/1593513/6d89c692-1847-421a-84d9-22e359d9cf82) The PR fixes this problem by adding enough information to the search result `href` to disambiguate methods with different types but the same name. More detailed description of the problem at: https://github.com/rust-lang/rust/pull/109422#issuecomment-1491089293 > When a struct/enum/union has multiple impls with different type parameters, it can have multiple methods that have the same name, but which are on different impls. Besides Simd, [Any](https://doc.rust-lang.org/nightly/std/any/trait.Any.html?search=any%3A%3Adowncast) also demonstrates this pattern. It has three methods named `downcast`, on three different impls. > > When that happens, it presents a challenge in linking to the method. Normally we link like `#method.foo`. When there are multiple `foo`, we number them like `#method.foo`, `#method.foo-1`, `#method.foo-2`, etc. > > It also presents a challenge for our search code. Currently we store all the variants in the index, but don’t have any way to generate unambiguous URLs in the results page, or to distinguish them in the SERP. > > To fix this, we need three things: > > 1. A fragment format that fully specifies the impl type parameters when needed to disambiguate (`#impl-SimdOrd-for-Simd<i64,+LANES>/method.simd_max`) > 2. A search index that stores methods with enough information to disambiguate the impl they were on. > 3. A search results interface that can display multiple methods on the same type with the same name, when appropriate OR a disambiguation landing section on item pages? > > For reviewers: it can be hard to see the new fragment format in action since it immediately gets rewritten to the numbered form.
2023-10-05rustdoc-search: fix bug with multi-item impl traitMichael Howell-5/+20
2023-09-21rustdoc-search: add impl disambiguator to duplicate assoc itemsMichael Howell-0/+50
Helps with #90929 This changes the search results, specifically, when there's more than one impl with an associated item with the same name. For example, the search queries `simd<i8> -> simd<i8>` and `simd<i64> -> simd<i64>` don't link to the same function, but most of the functions have the same names. This change should probably be FCP-ed, especially since it adds a new anchor link format for `main.js` to handle, so that URLs like `struct.Vec.html#impl-AsMut<[T]>-for-Vec<T,+A>/method.as_mut` redirect to `struct.Vec.html#method.as_mut-2`. It's a strange design, but there are a few reasons for it: * I'd like to avoid making the HTML bigger. Obviously, fixing this bug is going to add at least a little more data to the search index, but adding more HTML penalises viewers for the benefit of searchers. * Breaking `struct.Vec.html#method.len` would also be a disappointment. On the other hand: * The path-style anchors might be less prone to link rot than the numbered anchors. It's definitely less likely to have URLs that appear to "work", but silently point at the wrong thing. * This commit arranges the path-style anchor to redirect to the numbered anchor. Nothing stops rustdoc from doing the opposite, making path-style anchors the default and redirecting the "legacy" numbered ones.
2023-09-09rustdoc-search: fix bugs when unboxing and reordering combineMichael Howell-0/+75
2023-09-03rustdoc: fix test case for generics that look like namesMichael Howell-2/+6
2023-09-03rustdoc-search: add support for type parametersMichael Howell-0/+102
When writing a type-driven search query in rustdoc, specifically one with more than one query element, non-existent types become generic parameters instead of auto-correcting (which is currently only done for single-element queries) or giving no result. You can also force a generic type parameter by writing `generic:T` (and can force it to not use a generic type parameter with something like `struct:T` or whatever, though if this happens it means the thing you're looking for doesn't exist and will give you no results). There is no syntax provided for specifying type constraints for generic type parameters. When you have a generic type parameter in a search query, it will only match up with generic type parameters in the actual function, not concrete types that match, not concrete types that implement a trait. It also strictly matches based on when they're the same or different, so `option<T>, option<U> -> option<U>` matches `Option::and`, but not `Option::or`. Similarly, `option<T>, option<T> -> option<T>`` matches `Option::or`, but not `Option::and`.
2023-09-02Correctly handle paths from foreign itemsGuillaume Gomez-0/+19
2023-09-01Add tests for type-based searchGuillaume Gomez-0/+41
2023-06-15Auto merge of #112233 - notriddle:notriddle/search-unify, r=GuillaumeGomezbors-0/+181
rustdoc-search: clean up type unification and "unboxing" This PR redesigns parameter matching, return matching, and generics matching to use a single function that compares two lists of types. It also makes the algorithms more consistent, so the "unboxing" behavior where `Vec<i32>` is considered a match for `i32` works inside generics, and not just at the top level.
2023-06-12rustdoc-search: search never type with `!`Michael Howell-0/+59
This feature extends rustdoc to support the syntax that most users will naturally attempt to use to search for diverging functions. Part of #60485 It's already possible to do this search with `primitive:never`, but that's not what the Rust language itself uses, so nobody will try it if they aren't told or helped along.
2023-06-11rustdoc-search: fix order-independence bugMichael Howell-0/+108
2023-06-11rustdoc-search: build args, return, and generics on one unifierMichael Howell-0/+73
This enhances generics with the "unboxing" behavior where A<T> matches T. It makes this unboxing transitive over generics.
2023-06-10rustdoc: add note about slice/array searches to help popupMichael Howell-1/+1
2023-06-10rustdoc: search for slices and arrays by type with `[]`Michael Howell-0/+21
Part of #60485
2023-06-09Update rustdoc-js* formatGuillaume Gomez-216/+104
2023-05-06Rollup merge of #110780 - notriddle:notriddle/slice-index, r=GuillaumeGomezYuki Okushi-0/+81
rustdoc-search: add slices and arrays to index This indexes them as primitives with generics, so `slice<u32>` is how you search for `[u32]`, and `array<u32>` for `[u32; 1]`. A future commit will desugar the square bracket syntax to search both arrays and slices at once.
2023-04-24rustdoc-search: add slices and arrays to indexMichael Howell-0/+81
This indexes them as primitives with generics, so `slice<u32>` is how you search for `[u32]`, and `array<u32>` for `[u32; 1]`. A future commit will desugar the square bracket syntax to search both arrays and slices at once.
2023-04-17rustdoc: restructure type search engine to pick-and-use IDsMichael Howell-0/+27
This change makes it so, instead of mixing string distance with type unification, function signature search works by mapping names to IDs at the start, reporting to the user any cases where it had to make corrections, and then matches with IDs when going through the items. This only changes function searches. Name searches are left alone, and corrections are only done when there's a single item in the search query.
2023-04-14rustdoc-search: add support for nested genericsMichael Howell-0/+52
2023-03-20rustdoc: add support for type filters in arguments and genericsMichael Howell-0/+39
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).
2023-03-19rustdoc: implement bag semantics for function parameter searchMichael Howell-0/+24
This tweak to the function signature search engine makes things so that, if a type is repeated in the search query, it'll only match if the function actually includes it that many times.
2023-03-07rustdoc: fix type search when more than one `where` clause appliesMichael Howell-1/+15
2023-03-07rustdoc: fix type search index for `fn<T>() -> &T where T: Trait`Michael Howell-1/+12
2023-03-04rustdoc: function signature search with traits in `where` clauseMichael Howell-0/+35
2023-02-16rustdoc: search by macro when query ends with `!`Michael Howell-0/+20
Related to #96399
2023-01-21rustdoc: update test cases to match with stricter match criteriaMichael Howell-1/+0
2023-01-21rustdoc: compute maximum Levenshtein distance based on the queryMichael Howell-2/+0
The heuristic is pretty close to the name resolver. Fixes #103357
2023-01-14rustdoc: update search test casesMichael Howell-2/+1
2023-01-11Move /src/test to /testsAlbert Larsan-0/+1300