diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/doc/rustdoc/src/read-documentation/search.md | 54 | ||||
| -rw-r--r-- | src/librustdoc/html/render/search_index.rs | 40 | ||||
| -rw-r--r-- | src/librustdoc/html/static/js/search.js | 304 | ||||
| -rw-r--r-- | src/tools/miri/tests/pass/shims/time-with-isolation2.stdout | 2 |
4 files changed, 265 insertions, 135 deletions
diff --git a/src/doc/rustdoc/src/read-documentation/search.md b/src/doc/rustdoc/src/read-documentation/search.md index b5f4060f059..e2def14b357 100644 --- a/src/doc/rustdoc/src/read-documentation/search.md +++ b/src/doc/rustdoc/src/read-documentation/search.md @@ -63,11 +63,12 @@ Before describing the syntax in more detail, here's a few sample searches of the standard library and functions that are included in the results list: | Query | Results | -|-------|--------| +|-------|---------| | [`usize -> vec`][] | `slice::repeat` and `Vec::with_capacity` | | [`vec, vec -> bool`][] | `Vec::eq` | | [`option<T>, fnonce -> option<U>`][] | `Option::map` and `Option::and_then` | -| [`option<T>, fnonce -> option<T>`][] | `Option::filter` and `Option::inspect` | +| [`option<T>, (fnonce (T) -> bool) -> option<T>`][optionfilter] | `Option::filter` | +| [`option<T>, (T -> bool) -> option<T>`][optionfilter2] | `Option::filter` | | [`option -> default`][] | `Option::unwrap_or_default` | | [`stdout, [u8]`][stdoutu8] | `Stdout::write` | | [`any -> !`][] | `panic::panic_any` | @@ -77,7 +78,8 @@ the standard library and functions that are included in the results list: [`usize -> vec`]: ../../std/vec/struct.Vec.html?search=usize%20-%3E%20vec&filter-crate=std [`vec, vec -> bool`]: ../../std/vec/struct.Vec.html?search=vec,%20vec%20-%3E%20bool&filter-crate=std [`option<T>, fnonce -> option<U>`]: ../../std/vec/struct.Vec.html?search=option<T>%2C%20fnonce%20->%20option<U>&filter-crate=std -[`option<T>, fnonce -> option<T>`]: ../../std/vec/struct.Vec.html?search=option<T>%2C%20fnonce%20->%20option<T>&filter-crate=std +[optionfilter]: ../../std/vec/struct.Vec.html?search=option<T>%2C+(fnonce+(T)+->+bool)+->+option<T>&filter-crate=std +[optionfilter2]: ../../std/vec/struct.Vec.html?search=option<T>%2C+(T+->+bool)+->+option<T>&filter-crate=std [`option -> default`]: ../../std/vec/struct.Vec.html?search=option%20-%3E%20default&filter-crate=std [`any -> !`]: ../../std/vec/struct.Vec.html?search=any%20-%3E%20!&filter-crate=std [stdoutu8]: ../../std/vec/struct.Vec.html?search=stdout%2C%20[u8]&filter-crate=std @@ -151,16 +153,26 @@ will match these queries: But it *does not* match `Result<Vec, u8>` or `Result<u8<Vec>>`. +To search for a function that accepts a function as a parameter, +like `Iterator::all`, wrap the nested signature in parenthesis, +as in [`Iterator<T>, (T -> bool) -> bool`][iterator-all]. +You can also search for a specific closure trait, +such as `Iterator<T>, (FnMut(T) -> bool) -> bool`, +but you need to know which one you want. + +[iterator-all]: ../../std/vec/struct.Vec.html?search=Iterator<T>%2C+(T+->+bool)+->+bool&filter-crate=std + ### Primitives with Special Syntax -| Shorthand | Explicit names | -| --------- | ------------------------------------------------ | -| `[]` | `primitive:slice` and/or `primitive:array` | -| `[T]` | `primitive:slice<T>` and/or `primitive:array<T>` | -| `()` | `primitive:unit` and/or `primitive:tuple` | -| `(T)` | `T` | -| `(T,)` | `primitive:tuple<T>` | -| `!` | `primitive:never` | +| Shorthand | Explicit names | +| ---------------- | ------------------------------------------------- | +| `[]` | `primitive:slice` and/or `primitive:array` | +| `[T]` | `primitive:slice<T>` and/or `primitive:array<T>` | +| `()` | `primitive:unit` and/or `primitive:tuple` | +| `(T)` | `T` | +| `(T,)` | `primitive:tuple<T>` | +| `!` | `primitive:never` | +| `(T, U -> V, W)` | `fn(T, U) -> (V, W)`, `Fn`, `FnMut`, and `FnOnce` | When searching for `[]`, Rustdoc will return search results with either slices or arrays. If you know which one you want, you can force it to return results @@ -180,6 +192,10 @@ results for types that match tuples, even though it also matches the type on its own. That is, `(u32)` matches `(u32,)` for the exact same reason that it also matches `Result<u32, Error>`. +The `->` operator has lower precedence than comma. If it's not wrapped +in brackets, it delimits the return value for the function being searched for. +To search for functions that take functions as parameters, use parenthesis. + ### Limitations and quirks of type-based search Type-based search is still a buggy, experimental, work-in-progress feature. @@ -218,9 +234,6 @@ Most of these limitations should be addressed in future version of Rustdoc. * Searching for lifetimes is not supported. - * It's impossible to search for closures based on their parameters or - return values. - * It's impossible to search based on the length of an array. ## Item filtering @@ -237,19 +250,21 @@ Item filters can be used in both name-based and type signature-based searches. ```text ident = *(ALPHA / DIGIT / "_") -path = ident *(DOUBLE-COLON ident) [!] +path = ident *(DOUBLE-COLON ident) [BANG] slice-like = OPEN-SQUARE-BRACKET [ nonempty-arg-list ] CLOSE-SQUARE-BRACKET tuple-like = OPEN-PAREN [ nonempty-arg-list ] CLOSE-PAREN -arg = [type-filter *WS COLON *WS] (path [generics] / slice-like / tuple-like / [!]) +arg = [type-filter *WS COLON *WS] (path [generics] / slice-like / tuple-like) type-sep = COMMA/WS *(COMMA/WS) -nonempty-arg-list = *(type-sep) arg *(type-sep arg) *(type-sep) +nonempty-arg-list = *(type-sep) arg *(type-sep arg) *(type-sep) [ return-args ] generic-arg-list = *(type-sep) arg [ EQUAL arg ] *(type-sep arg [ EQUAL arg ]) *(type-sep) -generics = OPEN-ANGLE-BRACKET [ generic-arg-list ] *(type-sep) +normal-generics = OPEN-ANGLE-BRACKET [ generic-arg-list ] *(type-sep) CLOSE-ANGLE-BRACKET +fn-like-generics = OPEN-PAREN [ nonempty-arg-list ] CLOSE-PAREN [ RETURN-ARROW arg ] +generics = normal-generics / fn-like-generics return-args = RETURN-ARROW *(type-sep) nonempty-arg-list exact-search = [type-filter *WS COLON] [ RETURN-ARROW ] *WS QUOTE ident QUOTE [ generics ] -type-search = [ nonempty-arg-list ] [ return-args ] +type-search = [ nonempty-arg-list ] query = *WS (exact-search / type-search) *WS @@ -294,6 +309,7 @@ QUOTE = %x22 COMMA = "," RETURN-ARROW = "->" EQUAL = "=" +BANG = "!" ALPHA = %x41-5A / %x61-7A ; A-Z / a-z DIGIT = %x30-39 diff --git a/src/librustdoc/html/render/search_index.rs b/src/librustdoc/html/render/search_index.rs index cb059082f85..f153a908329 100644 --- a/src/librustdoc/html/render/search_index.rs +++ b/src/librustdoc/html/render/search_index.rs @@ -4,6 +4,7 @@ use std::collections::{BTreeMap, VecDeque}; use rustc_data_structures::fx::{FxHashMap, FxIndexMap}; use rustc_middle::ty::TyCtxt; use rustc_span::def_id::DefId; +use rustc_span::sym; use rustc_span::symbol::Symbol; use serde::ser::{Serialize, SerializeSeq, SerializeStruct, Serializer}; use thin_vec::ThinVec; @@ -566,6 +567,7 @@ fn get_index_type_id( // The type parameters are converted to generics in `simplify_fn_type` clean::Slice(_) => Some(RenderTypeId::Primitive(clean::PrimitiveType::Slice)), clean::Array(_, _) => Some(RenderTypeId::Primitive(clean::PrimitiveType::Array)), + clean::BareFunction(_) => Some(RenderTypeId::Primitive(clean::PrimitiveType::Fn)), clean::Tuple(ref n) if n.is_empty() => { Some(RenderTypeId::Primitive(clean::PrimitiveType::Unit)) } @@ -584,7 +586,7 @@ fn get_index_type_id( } } // Not supported yet - clean::BareFunction(_) | clean::Generic(_) | clean::ImplTrait(_) | clean::Infer => None, + clean::Generic(_) | clean::ImplTrait(_) | clean::Infer => None, } } @@ -785,6 +787,42 @@ fn simplify_fn_type<'tcx, 'a>( ); } res.push(get_index_type(arg, ty_generics, rgen)); + } else if let Type::BareFunction(ref bf) = *arg { + let mut ty_generics = Vec::new(); + for ty in bf.decl.inputs.values.iter().map(|arg| &arg.type_) { + simplify_fn_type( + self_, + generics, + ty, + tcx, + recurse + 1, + &mut ty_generics, + rgen, + is_return, + cache, + ); + } + // The search index, for simplicity's sake, represents fn pointers and closures + // the same way: as a tuple for the parameters, and an associated type for the + // return type. + let mut ty_output = Vec::new(); + simplify_fn_type( + self_, + generics, + &bf.decl.output, + tcx, + recurse + 1, + &mut ty_output, + rgen, + is_return, + cache, + ); + let ty_bindings = vec![(RenderTypeId::AssociatedType(sym::Output), ty_output)]; + res.push(RenderType { + id: get_index_type_id(&arg, rgen), + bindings: Some(ty_bindings), + generics: Some(ty_generics), + }); } else { // This is not a type parameter. So for example if we have `T, U: Option<T>`, and we're // looking at `Option`, we enter this "else" condition, otherwise if it's `T`, we don't. diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js index 7995a33f09f..73ac5608479 100644 --- a/src/librustdoc/html/static/js/search.js +++ b/src/librustdoc/html/static/js/search.js @@ -1,3 +1,4 @@ +// ignore-tidy-filelength /* global addClass, getNakedUrl, getSettingValue */ /* global onEachLazy, removeClass, searchState, browserSupportsHistoryApi, exports */ @@ -245,33 +246,49 @@ function initSearch(rawSearchIndex) { * * @type {Map<string, {id: integer, assocOnly: boolean}>} */ - let typeNameIdMap; + const typeNameIdMap = new Map(); const ALIASES = new Map(); /** * Special type name IDs for searching by array. */ - let typeNameIdOfArray; + const typeNameIdOfArray = buildTypeMapIndex("array"); /** * Special type name IDs for searching by slice. */ - let typeNameIdOfSlice; + const typeNameIdOfSlice = buildTypeMapIndex("slice"); /** * Special type name IDs for searching by both array and slice (`[]` syntax). */ - let typeNameIdOfArrayOrSlice; + const typeNameIdOfArrayOrSlice = buildTypeMapIndex("[]"); /** * Special type name IDs for searching by tuple. */ - let typeNameIdOfTuple; + const typeNameIdOfTuple = buildTypeMapIndex("tuple"); /** * Special type name IDs for searching by unit. */ - let typeNameIdOfUnit; + const typeNameIdOfUnit = buildTypeMapIndex("unit"); /** * Special type name IDs for searching by both tuple and unit (`()` syntax). */ - let typeNameIdOfTupleOrUnit; + const typeNameIdOfTupleOrUnit = buildTypeMapIndex("()"); + /** + * Special type name IDs for searching `fn`. + */ + const typeNameIdOfFn = buildTypeMapIndex("fn"); + /** + * Special type name IDs for searching `fnmut`. + */ + const typeNameIdOfFnMut = buildTypeMapIndex("fnmut"); + /** + * Special type name IDs for searching `fnonce`. + */ + const typeNameIdOfFnOnce = buildTypeMapIndex("fnonce"); + /** + * Special type name IDs for searching higher order functions (`->` syntax). + */ + const typeNameIdOfHof = buildTypeMapIndex("->"); /** * Add an item to the type Name->ID map, or, if one already exists, use it. @@ -464,6 +481,21 @@ function initSearch(rawSearchIndex) { } } + function makePrimitiveElement(name, extra) { + return Object.assign({ + name, + id: null, + fullPath: [name], + pathWithoutLast: [], + pathLast: name, + normalizedPathLast: name, + generics: [], + bindings: new Map(), + typeFilter: "primitive", + bindingName: null, + }, extra); + } + /** * @param {ParsedQuery} query * @param {ParserState} parserState @@ -501,18 +533,7 @@ function initSearch(rawSearchIndex) { } const bindingName = parserState.isInBinding; parserState.isInBinding = null; - return { - name: "never", - id: null, - fullPath: ["never"], - pathWithoutLast: [], - pathLast: "never", - normalizedPathLast: "never", - generics: [], - bindings: new Map(), - typeFilter: "primitive", - bindingName, - }; + return makePrimitiveElement("never", { bindingName }); } const quadcolon = /::\s*::/.exec(path); if (path.startsWith("::")) { @@ -558,7 +579,10 @@ function initSearch(rawSearchIndex) { // Syntactically, bindings are parsed as generics, // but the query engine treats them differently. if (gen.bindingName !== null) { - bindings.set(gen.bindingName.name, [gen, ...gen.bindingName.generics]); + if (gen.name !== null) { + gen.bindingName.generics.unshift(gen); + } + bindings.set(gen.bindingName.name, gen.bindingName.generics); return false; } return true; @@ -658,6 +682,38 @@ function initSearch(rawSearchIndex) { return end; } + function getFilteredNextElem(query, parserState, elems, isInGenerics) { + const start = parserState.pos; + if (parserState.userQuery[parserState.pos] === ":" && !isPathStart(parserState)) { + throw ["Expected type filter before ", ":"]; + } + getNextElem(query, parserState, elems, isInGenerics); + if (parserState.userQuery[parserState.pos] === ":" && !isPathStart(parserState)) { + if (parserState.typeFilter !== null) { + throw [ + "Unexpected ", + ":", + " (expected path after type filter ", + parserState.typeFilter + ":", + ")", + ]; + } + if (elems.length === 0) { + throw ["Expected type filter before ", ":"]; + } else if (query.literalSearch) { + throw ["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; + getNextElem(query, parserState, elems, isInGenerics); + } + } + /** * @param {ParsedQuery} query * @param {ParserState} parserState @@ -671,28 +727,19 @@ function initSearch(rawSearchIndex) { let start = parserState.pos; let end; if ("[(".indexOf(parserState.userQuery[parserState.pos]) !== -1) { -let endChar = ")"; -let name = "()"; -let friendlyName = "tuple"; - -if (parserState.userQuery[parserState.pos] === "[") { - endChar = "]"; - name = "[]"; - friendlyName = "slice"; -} + let endChar = ")"; + let name = "()"; + let friendlyName = "tuple"; + + if (parserState.userQuery[parserState.pos] === "[") { + endChar = "]"; + name = "[]"; + friendlyName = "slice"; + } parserState.pos += 1; const { foundSeparator } = getItemsBefore(query, parserState, generics, endChar); const typeFilter = parserState.typeFilter; - const isInBinding = parserState.isInBinding; - if (typeFilter !== null && typeFilter !== "primitive") { - throw [ - "Invalid search type: primitive ", - name, - " and ", - typeFilter, - " both specified", - ]; - } + const bindingName = parserState.isInBinding; parserState.typeFilter = null; parserState.isInBinding = null; for (const gen of generics) { @@ -702,23 +749,26 @@ if (parserState.userQuery[parserState.pos] === "[") { } if (name === "()" && !foundSeparator && generics.length === 1 && typeFilter === null) { elems.push(generics[0]); + } else if (name === "()" && generics.length === 1 && generics[0].name === "->") { + // `primitive:(a -> b)` parser to `primitive:"->"<output=b, (a,)>` + // not `primitive:"()"<"->"<output=b, (a,)>>` + generics[0].typeFilter = typeFilter; + elems.push(generics[0]); } else { + if (typeFilter !== null && typeFilter !== "primitive") { + throw [ + "Invalid search type: primitive ", + name, + " and ", + typeFilter, + " both specified", + ]; + } parserState.totalElems += 1; if (isInGenerics) { parserState.genericsElems += 1; } - elems.push({ - name: name, - id: null, - fullPath: [name], - pathWithoutLast: [], - pathLast: name, - normalizedPathLast: name, - generics, - bindings: new Map(), - typeFilter: "primitive", - bindingName: isInBinding, - }); + elems.push(makePrimitiveElement(name, { bindingName, generics })); } } else { const isStringElem = parserState.userQuery[start] === "\""; @@ -738,6 +788,32 @@ if (parserState.userQuery[parserState.pos] === "[") { } parserState.pos += 1; getItemsBefore(query, parserState, generics, ">"); + } else if (parserState.pos < parserState.length && + parserState.userQuery[parserState.pos] === "(" + ) { + if (start >= end) { + throw ["Found generics without a path"]; + } + if (parserState.isInBinding) { + throw ["Unexpected ", "(", " after ", "="]; + } + parserState.pos += 1; + const typeFilter = parserState.typeFilter; + parserState.typeFilter = null; + getItemsBefore(query, parserState, generics, ")"); + skipWhitespace(parserState); + if (isReturnArrow(parserState)) { + parserState.pos += 2; + skipWhitespace(parserState); + getFilteredNextElem(query, parserState, generics, isInGenerics); + generics[generics.length - 1].bindingName = makePrimitiveElement("output"); + } else { + generics.push(makePrimitiveElement(null, { + bindingName: makePrimitiveElement("output"), + typeFilter: null, + })); + } + parserState.typeFilter = typeFilter; } if (isStringElem) { skipWhitespace(parserState); @@ -797,7 +873,6 @@ if (parserState.userQuery[parserState.pos] === "[") { function getItemsBefore(query, parserState, elems, endChar) { let foundStopChar = true; let foundSeparator = false; - let start = parserState.pos; // If this is a generic, keep the outer item's type filter around. const oldTypeFilter = parserState.typeFilter; @@ -805,6 +880,19 @@ if (parserState.userQuery[parserState.pos] === "[") { const oldIsInBinding = parserState.isInBinding; parserState.isInBinding = null; + // ML-style Higher Order Function notation + // + // a way to search for any closure or fn pointer regardless of + // which closure trait is used + // + // Looks like this: + // + // `option<t>, (t -> u) -> option<u>` + // ^^^^^^ + // + // The Rust-style closure notation is implemented in getNextElem + let hofParameters = null; + let extra = ""; if (endChar === ">") { extra = "<"; @@ -825,6 +913,21 @@ if (parserState.userQuery[parserState.pos] === "[") { throw ["Unexpected ", endChar, " after ", "="]; } break; + } else if (endChar !== "" && isReturnArrow(parserState)) { + // ML-style HOF notation only works when delimited in something, + // otherwise a function arrow starts the return type of the top + if (parserState.isInBinding) { + throw ["Unexpected ", "->", " after ", "="]; + } + hofParameters = [...elems]; + elems.length = 0; + parserState.pos += 2; + foundStopChar = true; + foundSeparator = false; + continue; + } else if (c === " ") { + parserState.pos += 1; + continue; } else if (isSeparatorCharacter(c)) { parserState.pos += 1; foundStopChar = true; @@ -832,24 +935,6 @@ if (parserState.userQuery[parserState.pos] === "[") { continue; } else if (c === ":" && isPathStart(parserState)) { throw ["Unexpected ", "::", ": paths cannot start with ", "::"]; - } else if (c === ":") { - if (parserState.typeFilter !== null) { - throw ["Unexpected ", ":"]; - } - if (elems.length === 0) { - throw ["Expected type filter before ", ":"]; - } else if (query.literalSearch) { - throw ["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)) { throw ["Unexpected ", c, " after ", extra]; } @@ -884,8 +969,7 @@ if (parserState.userQuery[parserState.pos] === "[") { ]; } const posBefore = parserState.pos; - start = parserState.pos; - getNextElem(query, parserState, elems, endChar !== ""); + getFilteredNextElem(query, parserState, elems, endChar !== ""); if (endChar !== "" && parserState.pos >= parserState.length) { throw ["Unclosed ", extra]; } @@ -904,6 +988,27 @@ if (parserState.userQuery[parserState.pos] === "[") { // in any case. parserState.pos += 1; + if (hofParameters) { + // Commas in a HOF don't cause wrapping parens to become a tuple. + // If you want a one-tuple with a HOF in it, write `((a -> b),)`. + foundSeparator = false; + // HOFs can't have directly nested bindings. + if ([...elems, ...hofParameters].some(x => x.bindingName) || parserState.isInBinding) { + throw ["Unexpected ", "=", " within ", "->"]; + } + // HOFs are represented the same way closures are. + // The arguments are wrapped in a tuple, and the output + // is a binding, even though the compiler doesn't technically + // represent fn pointers that way. + const hofElem = makePrimitiveElement("->", { + generics: hofParameters, + bindings: new Map([["output", [...elems]]]), + typeFilter: null, + }); + elems.length = 0; + elems[0] = hofElem; + } + parserState.typeFilter = oldTypeFilter; parserState.isInBinding = oldIsInBinding; @@ -941,7 +1046,6 @@ if (parserState.userQuery[parserState.pos] === "[") { */ function parseInput(query, parserState) { let foundStopChar = true; - let start = parserState.pos; while (parserState.pos < parserState.length) { const c = parserState.userQuery[parserState.pos]; @@ -959,29 +1063,6 @@ if (parserState.userQuery[parserState.pos] === "[") { throw ["Unexpected ", c, " after ", parserState.userQuery[parserState.pos - 1]]; } throw ["Unexpected ", c]; - } else if (c === ":" && !isPathStart(parserState)) { - if (parserState.typeFilter !== null) { - throw [ - "Unexpected ", - ":", - " (expected path after type filter ", - parserState.typeFilter + ":", - ")", - ]; - } else if (query.elems.length === 0) { - throw ["Expected type filter before ", ":"]; - } else if (query.literalSearch) { - throw ["Cannot use quotes on type filter"]; - } - // The type filter doesn't count as an element since it's a modifier. - const typeFilterElem = query.elems.pop(); - checkExtraTypeFilterCharacters(start, parserState); - parserState.typeFilter = typeFilterElem.name; - parserState.pos += 1; - parserState.totalElems -= 1; - query.literalSearch = false; - foundStopChar = true; - continue; } else if (c === " ") { skipWhitespace(parserState); continue; @@ -1017,8 +1098,7 @@ if (parserState.userQuery[parserState.pos] === "[") { ]; } const before = query.elems.length; - start = parserState.pos; - getNextElem(query, parserState, query.elems, false); + getFilteredNextElem(query, parserState, query.elems, false); if (query.elems.length === before) { // Nothing was added, weird... Let's increase the position to not remain stuck. parserState.pos += 1; @@ -1258,11 +1338,6 @@ if (parserState.userQuery[parserState.pos] === "[") { * @returns {[ResultObject]} */ function sortResults(results, isType, preferredCrate) { - // if there are no results then return to default and fail - if (results.size === 0) { - return []; - } - const userQuery = parsedQuery.userQuery; const result_list = []; for (const result of results.values()) { @@ -1635,6 +1710,12 @@ if (parserState.userQuery[parserState.pos] === "[") { ) { // () matches primitive:tuple or primitive:unit // if it matches, then we're fine, and this is an appropriate match candidate + } else if (queryElem.id === typeNameIdOfHof && + (fnType.id === typeNameIdOfFn || fnType.id === typeNameIdOfFnMut || + fnType.id === typeNameIdOfFnOnce) + ) { + // -> matches fn, fnonce, and fnmut + // if it matches, then we're fine, and this is an appropriate match candidate } else if (fnType.id !== queryElem.id || queryElem.id === null) { return false; } @@ -1829,6 +1910,7 @@ if (parserState.userQuery[parserState.pos] === "[") { typePassesFilter(elem.typeFilter, row.ty) && elem.generics.length === 0 && // special case elem.id !== typeNameIdOfArrayOrSlice && elem.id !== typeNameIdOfTupleOrUnit + && elem.id !== typeNameIdOfHof ) { return row.id === elem.id || checkIfInList( row.generics, @@ -2991,7 +3073,7 @@ ${item.displayPath}<span class="${type}">${name}</span>\ */ function buildFunctionTypeFingerprint(type, output, fps) { let input = type.id; - // All forms of `[]`/`()` get collapsed down to one thing in the bloom filter. + // All forms of `[]`/`()`/`->` get collapsed down to one thing in the bloom filter. // Differentiating between arrays and slices, if the user asks for it, is // still done in the matching algorithm. if (input === typeNameIdOfArray || input === typeNameIdOfSlice) { @@ -3000,6 +3082,10 @@ ${item.displayPath}<span class="${type}">${name}</span>\ if (input === typeNameIdOfTuple || input === typeNameIdOfUnit) { input = typeNameIdOfTupleOrUnit; } + if (input === typeNameIdOfFn || input === typeNameIdOfFnMut || + input === typeNameIdOfFnOnce) { + input = typeNameIdOfHof; + } // http://burtleburtle.net/bob/hash/integer.html // ~~ is toInt32. It's used before adding, so // the number stays in safe integer range. @@ -3090,20 +3176,10 @@ ${item.displayPath}<span class="${type}">${name}</span>\ */ function buildIndex(rawSearchIndex) { searchIndex = []; - typeNameIdMap = new Map(); const charA = "A".charCodeAt(0); let currentIndex = 0; let id = 0; - // Initialize type map indexes for primitive list types - // that can be searched using `[]` syntax. - typeNameIdOfArray = buildTypeMapIndex("array"); - typeNameIdOfSlice = buildTypeMapIndex("slice"); - typeNameIdOfTuple = buildTypeMapIndex("tuple"); - typeNameIdOfUnit = buildTypeMapIndex("unit"); - typeNameIdOfArrayOrSlice = buildTypeMapIndex("[]"); - typeNameIdOfTupleOrUnit = buildTypeMapIndex("()"); - // Function type fingerprints are 128-bit bloom filters that are used to // estimate the distance between function and query. // This loop counts the number of items to allocate a fingerprint for. diff --git a/src/tools/miri/tests/pass/shims/time-with-isolation2.stdout b/src/tools/miri/tests/pass/shims/time-with-isolation2.stdout index c68b40b744b..dce51a7fdbe 100644 --- a/src/tools/miri/tests/pass/shims/time-with-isolation2.stdout +++ b/src/tools/miri/tests/pass/shims/time-with-isolation2.stdout @@ -1 +1 @@ -The loop took around 7s +The loop took around 12s |
