diff --git a/src/doc/rustdoc/src/how-to-read-rustdoc.md b/src/doc/rustdoc/src/how-to-read-rustdoc.md index 2957916d56c..56342f65d99 100644 --- a/src/doc/rustdoc/src/how-to-read-rustdoc.md +++ b/src/doc/rustdoc/src/how-to-read-rustdoc.md @@ -94,6 +94,17 @@ can be matched with the following queries: * `trait:Iterator -> primitive:usize` * `Iterator -> usize` +Generics and function parameters are order-agnostic, but sensitive to nesting +and number of matches. For example, a function with the signature +`fn read_all(&mut self: impl Read) -> Result, Error>` +will match these queries: + +* `Read -> Result, Error>` +* `Read -> Result` +* `Read -> Result>` + +But it *does not* match `Result` or `Result>`. + ### Changing displayed theme You can change the displayed theme by opening the settings menu (the gear diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js index 40cdc55bbc3..929dae81c8d 100644 --- a/src/librustdoc/html/static/js/search.js +++ b/src/librustdoc/html/static/js/search.js @@ -461,9 +461,7 @@ function initSearch(rawSearchIndex) { if (parserState.pos < parserState.length && parserState.userQuery[parserState.pos] === "<" ) { - if (isInGenerics) { - throw ["Unexpected ", "<", " after ", "<"]; - } else if (start >= end) { + if (start >= end) { throw ["Found generics without a path"]; } parserState.pos += 1; @@ -765,13 +763,10 @@ function initSearch(rawSearchIndex) { * ident = *(ALPHA / DIGIT / "_") * path = ident *(DOUBLE-COLON ident) [!] * 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 - * *(type-sep arg-without-generic) *(type-sep) - * generics = OPEN-ANGLE-BRACKET [ nonempty-arg-list-without-generics ] *(type-sep) - * CLOSE-ANGLE-BRACKET/EOF + * generics = OPEN-ANGLE-BRACKET [ nonempty-arg-list ] *(type-sep) + * CLOSE-ANGLE-BRACKET * return-args = RETURN-ARROW *(type-sep) nonempty-arg-list * * exact-search = [type-filter *WS COLON] [ RETURN-ARROW ] *WS QUOTE ident QUOTE [ generics ] @@ -1127,7 +1122,7 @@ function initSearch(rawSearchIndex) { currentEntryElems = []; elems.set(entry.name, currentEntryElems); } - currentEntryElems.push(entry.ty); + currentEntryElems.push(entry); } // We need to find the type that matches the most to remove it in order // to move forward. @@ -1136,8 +1131,12 @@ function initSearch(rawSearchIndex) { return false; } const matchElems = elems.get(generic.name); - const matchIdx = matchElems.findIndex(tmp_elem => - typePassesFilter(generic.typeFilter, tmp_elem)); + const matchIdx = matchElems.findIndex(tmp_elem => { + if (checkGenerics(tmp_elem, generic, 0, maxEditDistance) !== 0) { + return false; + } + return typePassesFilter(generic.typeFilter, tmp_elem.ty); + }); if (matchIdx === -1) { return false; } diff --git a/tests/rustdoc-js-std/parser-generics.js b/tests/rustdoc-js-std/parser-generics.js index c448d845acb..5a2266dbe36 100644 --- a/tests/rustdoc-js-std/parser-generics.js +++ b/tests/rustdoc-js-std/parser-generics.js @@ -1,4 +1,11 @@ -const QUERY = ['A, E>', 'p<> u8', '"p"']; +const QUERY = [ + 'A, E>', + 'p<> u8', + '"p"', + 'p>', + 'p, r>', + 'p>', +]; const PARSED = [ { @@ -7,7 +14,7 @@ const PARSED = [ original: 'A, E>', returned: [], userQuery: 'a, e>', - error: 'Unexpected `<` after `<`', + error: 'Unclosed `<`', }, { elems: [ @@ -59,4 +66,117 @@ const PARSED = [ userQuery: '"p"', error: null, }, + { + elems: [ + { + name: "p", + fullPath: ["p"], + pathWithoutLast: [], + pathLast: "p", + generics: [ + { + name: "u", + fullPath: ["u"], + pathWithoutLast: [], + pathLast: "u", + generics: [ + { + name: "x", + fullPath: ["x"], + pathWithoutLast: [], + pathLast: "x", + generics: [], + }, + ], + }, + ], + typeFilter: -1, + }, + ], + foundElems: 1, + original: 'p>', + returned: [], + userQuery: 'p>', + error: null, + }, + { + elems: [ + { + name: "p", + fullPath: ["p"], + pathWithoutLast: [], + pathLast: "p", + generics: [ + { + name: "u", + fullPath: ["u"], + pathWithoutLast: [], + pathLast: "u", + generics: [ + { + name: "x", + fullPath: ["x"], + pathWithoutLast: [], + pathLast: "x", + generics: [], + }, + ], + }, + { + name: "r", + fullPath: ["r"], + pathWithoutLast: [], + pathLast: "r", + generics: [], + }, + ], + typeFilter: -1, + }, + ], + foundElems: 1, + original: 'p, r>', + returned: [], + userQuery: 'p, r>', + error: null, + }, + { + elems: [ + { + name: "p", + fullPath: ["p"], + pathWithoutLast: [], + pathLast: "p", + generics: [ + { + name: "u", + fullPath: ["u"], + pathWithoutLast: [], + pathLast: "u", + generics: [ + { + name: "x", + fullPath: ["x"], + pathWithoutLast: [], + pathLast: "x", + generics: [], + }, + { + name: "r", + fullPath: ["r"], + pathWithoutLast: [], + pathLast: "r", + generics: [], + }, + ], + }, + ], + typeFilter: -1, + }, + ], + foundElems: 1, + original: 'p>', + returned: [], + userQuery: 'p>', + error: null, + }, ]; diff --git a/tests/rustdoc-js/generics-nested.js b/tests/rustdoc-js/generics-nested.js new file mode 100644 index 00000000000..8701f2d4986 --- /dev/null +++ b/tests/rustdoc-js/generics-nested.js @@ -0,0 +1,33 @@ +// exact-check + +const QUERY = [ + '-> Out>', + '-> Out>', + '-> Out', + '-> Out', +]; + +const EXPECTED = [ + { + // -> Out> + 'others': [ + { 'path': 'generics_nested', 'name': 'alef' }, + ], + }, + { + // -> Out> + 'others': [], + }, + { + // -> Out + 'others': [ + { 'path': 'generics_nested', 'name': 'bet' }, + ], + }, + { + // -> Out + 'others': [ + { 'path': 'generics_nested', 'name': 'bet' }, + ], + }, +]; diff --git a/tests/rustdoc-js/generics-nested.rs b/tests/rustdoc-js/generics-nested.rs new file mode 100644 index 00000000000..5140422e384 --- /dev/null +++ b/tests/rustdoc-js/generics-nested.rs @@ -0,0 +1,19 @@ +pub struct Out { + a: A, + b: B, +} + +pub struct First { + in_: In, +} + +pub struct Second; + +// Out> +pub fn alef() -> Out> { + loop {} +} + +pub fn bet() -> Out { + loop {} +}