From af4913fcf4a23ff6f4ddd68a6b0266629105bddb Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 9 Dec 2023 14:36:34 +0100 Subject: merge core_panic feature into panic_internals --- src/doc/unstable-book/src/library-features/core-panic.md | 5 ----- 1 file changed, 5 deletions(-) delete mode 100644 src/doc/unstable-book/src/library-features/core-panic.md (limited to 'src') diff --git a/src/doc/unstable-book/src/library-features/core-panic.md b/src/doc/unstable-book/src/library-features/core-panic.md deleted file mode 100644 index c197588404c..00000000000 --- a/src/doc/unstable-book/src/library-features/core-panic.md +++ /dev/null @@ -1,5 +0,0 @@ -# `core_panic` - -This feature is internal to the Rust compiler and is not intended for general use. - ------------------------- -- cgit 1.4.1-3-g733a5 From f6a045cc6b24dd033c207dd63d8adccdedf672d2 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Fri, 29 Sep 2023 12:52:30 -0700 Subject: rustdoc: search for tuples and unit by type with `()` --- src/doc/rustdoc/src/read-documentation/search.md | 67 ++++- src/librustdoc/html/render/search_index.rs | 3 + src/librustdoc/html/static/js/search.js | 100 +++++-- tests/rustdoc-js-std/parser-errors.js | 17 +- tests/rustdoc-js-std/parser-slice-array.js | 18 ++ tests/rustdoc-js-std/parser-tuple.js | 365 +++++++++++++++++++++++ tests/rustdoc-js-std/parser-weird-queries.js | 2 +- tests/rustdoc-js/tuple-unit.js | 80 +++++ tests/rustdoc-js/tuple-unit.rs | 18 ++ 9 files changed, 616 insertions(+), 54 deletions(-) create mode 100644 tests/rustdoc-js-std/parser-tuple.js create mode 100644 tests/rustdoc-js/tuple-unit.js create mode 100644 tests/rustdoc-js/tuple-unit.rs (limited to 'src') diff --git a/src/doc/rustdoc/src/read-documentation/search.md b/src/doc/rustdoc/src/read-documentation/search.md index 1f45bd6c6b8..d773794504e 100644 --- a/src/doc/rustdoc/src/read-documentation/search.md +++ b/src/doc/rustdoc/src/read-documentation/search.md @@ -150,12 +150,55 @@ will match these queries: But it *does not* match `Result` or `Result>`. -Function signature searches also support arrays and slices. The explicit name -`primitive:slice` and `primitive:array` can be used to match a slice -or array of bytes, while square brackets `[u8]` will match either one. Empty -square brackets, `[]`, will match any slice or array regardless of what -it contains, while a slice with a type parameter, like `[T]`, will only match -functions that actually operate on generic slices. +### Primitives with Special Syntax + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ShorthandExplicit 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
+ +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 +for `primitive:slice` or `primitive:array` using the explicit name syntax. +Empty square brackets, `[]`, will match any slice or array regardless of what +it contains, or an item type can be provided, such as `[u8]` or `[T]`, to +explicitly find functions that operate on byte slices or generic slices, +respectively. + +A single type expression wrapped in parens is the same as that type expression, +since parens act as the grouping operator. If they're empty, though, they will +match both `unit` and `tuple`, and if there's more than one type (or a trailing +or leading comma) it is the same as `primitive:tuple<...>`. ### Limitations and quirks of type-based search @@ -188,11 +231,10 @@ Most of these limitations should be addressed in future version of Rustdoc. that you don't want a type parameter, you can force it to match something else by giving it a different prefix like `struct:T`. - * It's impossible to search for references, pointers, or tuples. The + * It's impossible to search for references or pointers. The wrapped types can be searched for, so a function that takes `&File` can be found with `File`, but you'll get a parse error when typing an `&` - into the search field. Similarly, `Option<(T, U)>` can be matched with - `Option`, but `(` will give a parse error. + into the search field. * Searching for lifetimes is not supported. @@ -216,8 +258,9 @@ Item filters can be used in both name-based and type signature-based searches. ```text ident = *(ALPHA / DIGIT / "_") path = ident *(DOUBLE-COLON ident) [!] -slice = OPEN-SQUARE-BRACKET [ nonempty-arg-list ] CLOSE-SQUARE-BRACKET -arg = [type-filter *WS COLON *WS] (path [generics] / slice / [!]) +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 / [!]) type-sep = COMMA/WS *(COMMA/WS) nonempty-arg-list = *(type-sep) arg *(type-sep arg) *(type-sep) generic-arg-list = *(type-sep) arg [ EQUAL arg ] *(type-sep arg [ EQUAL arg ]) *(type-sep) @@ -263,6 +306,8 @@ OPEN-ANGLE-BRACKET = "<" CLOSE-ANGLE-BRACKET = ">" OPEN-SQUARE-BRACKET = "[" CLOSE-SQUARE-BRACKET = "]" +OPEN-PAREN = "(" +CLOSE-PAREN = ")" COLON = ":" DOUBLE-COLON = "::" QUOTE = %x22 diff --git a/src/librustdoc/html/render/search_index.rs b/src/librustdoc/html/render/search_index.rs index a1029320d2d..6c6a31bbb11 100644 --- a/src/librustdoc/html/render/search_index.rs +++ b/src/librustdoc/html/render/search_index.rs @@ -581,6 +581,9 @@ 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::Tuple(ref n) if n.is_empty() => { + Some(RenderTypeId::Primitive(clean::PrimitiveType::Unit)) + } clean::Tuple(_) => Some(RenderTypeId::Primitive(clean::PrimitiveType::Tuple)), clean::QPath(ref data) => { if data.self_type.is_self_type() diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js index e824a1fd4bd..b2263e9e3e1 100644 --- a/src/librustdoc/html/static/js/search.js +++ b/src/librustdoc/html/static/js/search.js @@ -260,6 +260,18 @@ function initSearch(rawSearchIndex) { * Special type name IDs for searching by both array and slice (`[]` syntax). */ let typeNameIdOfArrayOrSlice; + /** + * Special type name IDs for searching by tuple. + */ + let typeNameIdOfTuple; + /** + * Special type name IDs for searching by unit. + */ + let typeNameIdOfUnit; + /** + * Special type name IDs for searching by both tuple and unit (`()` syntax). + */ + let typeNameIdOfTupleOrUnit; /** * Add an item to the type Name->ID map, or, if one already exists, use it. @@ -295,11 +307,7 @@ function initSearch(rawSearchIndex) { } function isEndCharacter(c) { - return "=,>-]".indexOf(c) !== -1; - } - - function isErrorCharacter(c) { - return "()".indexOf(c) !== -1; + return "=,>-])".indexOf(c) !== -1; } function itemTypeFromName(typename) { @@ -585,8 +593,6 @@ function initSearch(rawSearchIndex) { throw ["Unexpected ", "!", ": it can only be at the end of an ident"]; } foundExclamation = parserState.pos; - } else if (isErrorCharacter(c)) { - throw ["Unexpected ", c]; } else if (isPathSeparator(c)) { if (c === ":") { if (!isPathStart(parserState)) { @@ -616,11 +622,14 @@ function initSearch(rawSearchIndex) { } } else if ( c === "[" || + c === "(" || isEndCharacter(c) || isSpecialStartCharacter(c) || isSeparatorCharacter(c) ) { break; + } else if (parserState.pos > 0) { + throw ["Unexpected ", c, " after ", parserState.userQuery[parserState.pos - 1]]; } else { throw ["Unexpected ", c]; } @@ -661,15 +670,24 @@ function initSearch(rawSearchIndex) { skipWhitespace(parserState); let start = parserState.pos; let end; - if (parserState.userQuery[parserState.pos] === "[") { + if ("[(".indexOf(parserState.userQuery[parserState.pos]) !== -1) { +let endChar = ")"; +let name = "()"; +let friendlyName = "tuple"; + +if (parserState.userQuery[parserState.pos] === "[") { + endChar = "]"; + name = "[]"; + friendlyName = "slice"; +} parserState.pos += 1; - getItemsBefore(query, parserState, generics, "]"); + 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", @@ -677,27 +695,31 @@ function initSearch(rawSearchIndex) { } parserState.typeFilter = null; parserState.isInBinding = null; - parserState.totalElems += 1; - if (isInGenerics) { - parserState.genericsElems += 1; - } for (const gen of generics) { if (gen.bindingName !== null) { - throw ["Type parameter ", "=", " cannot be within slice ", "[]"]; + throw ["Type parameter ", "=", ` cannot be within ${friendlyName} `, name]; } } - elems.push({ - name: "[]", - id: null, - fullPath: ["[]"], - pathWithoutLast: [], - pathLast: "[]", - normalizedPathLast: "[]", - generics, - typeFilter: "primitive", - bindingName: isInBinding, - bindings: new Map(), - }); + if (name === "()" && !foundSeparator && generics.length === 1 && typeFilter === null) { + elems.push(generics[0]); + } else { + 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, + }); + } } else { const isStringElem = parserState.userQuery[start] === "\""; // We handle the strings on their own mostly to make code easier to follow. @@ -770,9 +792,11 @@ function initSearch(rawSearchIndex) { * @param {Array} elems - This is where the new {QueryElement} will be added. * @param {string} endChar - This function will stop when it'll encounter this * character. + * @returns {{foundSeparator: bool}} */ 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. @@ -786,6 +810,8 @@ function initSearch(rawSearchIndex) { extra = "<"; } else if (endChar === "]") { extra = "["; + } else if (endChar === ")") { + extra = "("; } else if (endChar === "") { extra = "->"; } else { @@ -802,6 +828,7 @@ function initSearch(rawSearchIndex) { } else if (isSeparatorCharacter(c)) { parserState.pos += 1; foundStopChar = true; + foundSeparator = true; continue; } else if (c === ":" && isPathStart(parserState)) { throw ["Unexpected ", "::", ": paths cannot start with ", "::"]; @@ -879,6 +906,8 @@ function initSearch(rawSearchIndex) { parserState.typeFilter = oldTypeFilter; parserState.isInBinding = oldIsInBinding; + + return { foundSeparator }; } /** @@ -926,6 +955,8 @@ function initSearch(rawSearchIndex) { break; } throw ["Unexpected ", c, " (did you mean ", "->", "?)"]; + } else if (parserState.pos > 0) { + throw ["Unexpected ", c, " after ", parserState.userQuery[parserState.pos - 1]]; } throw ["Unexpected ", c]; } else if (c === ":" && !isPathStart(parserState)) { @@ -1599,6 +1630,11 @@ function initSearch(rawSearchIndex) { ) { // [] matches primitive:array or primitive:slice // if it matches, then we're fine, and this is an appropriate match candidate + } else if (queryElem.id === typeNameIdOfTupleOrUnit && + (fnType.id === typeNameIdOfTuple || fnType.id === typeNameIdOfUnit) + ) { + // () matches primitive:tuple or primitive:unit + // 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; } @@ -1792,7 +1828,7 @@ function initSearch(rawSearchIndex) { if (row.id > 0 && elem.id > 0 && elem.pathWithoutLast.length === 0 && typePassesFilter(elem.typeFilter, row.ty) && elem.generics.length === 0 && // special case - elem.id !== typeNameIdOfArrayOrSlice + elem.id !== typeNameIdOfArrayOrSlice && elem.id !== typeNameIdOfTupleOrUnit ) { return row.id === elem.id || checkIfInList( row.generics, @@ -2822,12 +2858,15 @@ ${item.displayPath}${name}\ */ 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) { input = typeNameIdOfArrayOrSlice; } + if (input === typeNameIdOfTuple || input === typeNameIdOfUnit) { + input = typeNameIdOfTupleOrUnit; + } // http://burtleburtle.net/bob/hash/integer.html // ~~ is toInt32. It's used before adding, so // the number stays in safe integer range. @@ -2922,7 +2961,10 @@ ${item.displayPath}${name}\ // 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. diff --git a/tests/rustdoc-js-std/parser-errors.js b/tests/rustdoc-js-std/parser-errors.js index f9f9c4f4de8..16d171260da 100644 --- a/tests/rustdoc-js-std/parser-errors.js +++ b/tests/rustdoc-js-std/parser-errors.js @@ -24,7 +24,7 @@ const PARSED = [ original: "-> *", returned: [], userQuery: "-> *", - error: "Unexpected `*`", + error: "Unexpected `*` after ` `", }, { query: 'a<"P">', @@ -107,15 +107,6 @@ const PARSED = [ userQuery: "a<::a>", error: "Unexpected `::`: paths cannot start with `::`", }, - { - query: "((a))", - elems: [], - foundElems: 0, - original: "((a))", - returned: [], - userQuery: "((a))", - error: "Unexpected `(`", - }, { query: "(p -> p", elems: [], @@ -123,7 +114,7 @@ const PARSED = [ original: "(p -> p", returned: [], userQuery: "(p -> p", - error: "Unexpected `(`", + error: "Unexpected `-` after `(`", }, { query: "::a::b", @@ -204,7 +195,7 @@ const PARSED = [ original: "a (b:", returned: [], userQuery: "a (b:", - error: "Unexpected `(`", + error: "Expected `,`, `:` or `->`, found `(`", }, { query: "_:", @@ -249,7 +240,7 @@ const PARSED = [ original: "ab'", returned: [], userQuery: "ab'", - error: "Unexpected `'`", + error: "Unexpected `'` after `b`", }, { query: "a->", diff --git a/tests/rustdoc-js-std/parser-slice-array.js b/tests/rustdoc-js-std/parser-slice-array.js index 239391bed42..1de52af94e6 100644 --- a/tests/rustdoc-js-std/parser-slice-array.js +++ b/tests/rustdoc-js-std/parser-slice-array.js @@ -266,6 +266,24 @@ const PARSED = [ userQuery: "]", error: "Unexpected `]`", }, + { + query: '[a', + elems: [], + foundElems: 0, + original: "[a", + returned: [], + userQuery: "[a", + error: "Unclosed `[`", + }, + { + query: 'a]', + elems: [], + foundElems: 0, + original: "a]", + returned: [], + userQuery: "a]", + error: "Unexpected `]` after `>`", + }, { query: 'primitive:[u8]', elems: [ diff --git a/tests/rustdoc-js-std/parser-tuple.js b/tests/rustdoc-js-std/parser-tuple.js new file mode 100644 index 00000000000..eb16289d3c0 --- /dev/null +++ b/tests/rustdoc-js-std/parser-tuple.js @@ -0,0 +1,365 @@ +const PARSED = [ + { + query: '(((D, ()))', + elems: [], + foundElems: 0, + original: '(((D, ()))', + returned: [], + userQuery: '(((d, ()))', + error: 'Unclosed `(`', + }, + { + query: '(((D, ())))', + elems: [ + { + name: "()", + fullPath: ["()"], + pathWithoutLast: [], + pathLast: "()", + generics: [ + { + name: "d", + fullPath: ["d"], + pathWithoutLast: [], + pathLast: "d", + generics: [], + typeFilter: -1, + }, + { + name: "()", + fullPath: ["()"], + pathWithoutLast: [], + pathLast: "()", + generics: [], + typeFilter: 1, + }, + ], + typeFilter: 1, + } + ], + foundElems: 1, + original: '(((D, ())))', + returned: [], + userQuery: '(((d, ())))', + error: null, + }, + { + query: '(),u8', + elems: [ + { + name: "()", + fullPath: ["()"], + pathWithoutLast: [], + pathLast: "()", + generics: [], + typeFilter: 1, + }, + { + name: "u8", + fullPath: ["u8"], + pathWithoutLast: [], + pathLast: "u8", + generics: [], + typeFilter: -1, + }, + ], + foundElems: 2, + original: "(),u8", + returned: [], + userQuery: "(),u8", + error: null, + }, + // Parens act as grouping operators when: + // - there's no commas directly nested within + // - there's at least two child types (zero means unit) + // - it's not tagged with a type filter + // Otherwise, they represent unit and/or tuple. To search for + // unit or tuple specifically, use `primitive:unit` or `primitive:tuple<...>`. + { + query: '(u8)', + elems: [ + { + name: "u8", + fullPath: ["u8"], + pathWithoutLast: [], + pathLast: "u8", + generics: [], + typeFilter: -1, + }, + ], + foundElems: 1, + original: "(u8)", + returned: [], + userQuery: "(u8)", + error: null, + }, + { + query: '(u8,)', + elems: [ + { + name: "()", + fullPath: ["()"], + pathWithoutLast: [], + pathLast: "()", + generics: [ + { + name: "u8", + fullPath: ["u8"], + pathWithoutLast: [], + pathLast: "u8", + generics: [], + typeFilter: -1, + }, + ], + typeFilter: 1, + }, + ], + foundElems: 1, + original: "(u8,)", + returned: [], + userQuery: "(u8,)", + error: null, + }, + { + query: '(,u8)', + elems: [ + { + name: "()", + fullPath: ["()"], + pathWithoutLast: [], + pathLast: "()", + generics: [ + { + name: "u8", + fullPath: ["u8"], + pathWithoutLast: [], + pathLast: "u8", + generics: [], + typeFilter: -1, + }, + ], + typeFilter: 1, + }, + ], + foundElems: 1, + original: "(,u8)", + returned: [], + userQuery: "(,u8)", + error: null, + }, + { + query: 'primitive:(u8)', + elems: [ + { + name: "()", + fullPath: ["()"], + pathWithoutLast: [], + pathLast: "()", + generics: [ + { + name: "u8", + fullPath: ["u8"], + pathWithoutLast: [], + pathLast: "u8", + generics: [], + typeFilter: -1, + }, + ], + typeFilter: 1, + }, + ], + foundElems: 1, + original: "primitive:(u8)", + returned: [], + userQuery: "primitive:(u8)", + error: null, + }, + { + query: '(primitive:u8)', + elems: [ + { + name: "u8", + fullPath: ["u8"], + pathWithoutLast: [], + pathLast: "u8", + generics: [], + typeFilter: 1, + }, + ], + foundElems: 1, + original: "(primitive:u8)", + returned: [], + userQuery: "(primitive:u8)", + error: null, + }, + { + query: '(u8,u8)', + elems: [ + { + name: "()", + fullPath: ["()"], + pathWithoutLast: [], + pathLast: "()", + generics: [ + { + name: "u8", + fullPath: ["u8"], + pathWithoutLast: [], + pathLast: "u8", + generics: [], + typeFilter: -1, + }, + { + name: "u8", + fullPath: ["u8"], + pathWithoutLast: [], + pathLast: "u8", + generics: [], + typeFilter: -1, + }, + ], + typeFilter: 1, + }, + ], + foundElems: 1, + original: "(u8,u8)", + returned: [], + userQuery: "(u8,u8)", + error: null, + }, + { + query: '(u8)', + elems: [ + { + name: "u8", + fullPath: ["u8"], + pathWithoutLast: [], + pathLast: "u8", + generics: [ + { + name: "u8", + fullPath: ["u8"], + pathWithoutLast: [], + pathLast: "u8", + generics: [], + typeFilter: -1, + }, + ], + typeFilter: -1, + }, + ], + foundElems: 1, + original: "(u8)", + returned: [], + userQuery: "(u8)", + error: null, + }, + { + query: '()', + elems: [ + { + name: "()", + fullPath: ["()"], + pathWithoutLast: [], + pathLast: "()", + generics: [], + typeFilter: 1, + }, + ], + foundElems: 1, + original: "()", + returned: [], + userQuery: "()", + error: null, + }, + { + query: '(>', + elems: [], + foundElems: 0, + original: "(>", + returned: [], + userQuery: "(>", + error: "Unexpected `>` after `(`", + }, + { + query: '(<', + elems: [], + foundElems: 0, + original: "(<", + returned: [], + userQuery: "(<", + error: "Found generics without a path", + }, + { + query: '(a>', + elems: [], + foundElems: 0, + original: "(a>", + returned: [], + userQuery: "(a>", + error: "Unexpected `>` after `(`", + }, + { + query: '(a<', + elems: [], + foundElems: 0, + original: "(a<", + returned: [], + userQuery: "(a<", + error: "Unclosed `<`", + }, + { + query: '(a', + elems: [], + foundElems: 0, + original: "(a", + returned: [], + userQuery: "(a", + error: "Unclosed `(`", + }, + { + query: '(', + elems: [], + foundElems: 0, + original: "(", + returned: [], + userQuery: "(", + error: "Unclosed `(`", + }, + { + query: ')', + elems: [], + foundElems: 0, + original: ")", + returned: [], + userQuery: ")", + error: "Unexpected `)`", + }, + { + query: '(a', + elems: [], + foundElems: 0, + original: "(a", + returned: [], + userQuery: "(a", + error: "Unclosed `(`", + }, + { + query: 'a)', + elems: [], + foundElems: 0, + original: "a)", + returned: [], + userQuery: "a)", + error: "Unexpected `)` after `>`", + }, + { + query: 'macro:(u8)', + elems: [], + foundElems: 0, + original: "macro:(u8)", + returned: [], + userQuery: "macro:(u8)", + error: "Invalid search type: primitive `()` and `macro` both specified", + }, +]; diff --git a/tests/rustdoc-js-std/parser-weird-queries.js b/tests/rustdoc-js-std/parser-weird-queries.js index ba68c9717c5..26b8c32d680 100644 --- a/tests/rustdoc-js-std/parser-weird-queries.js +++ b/tests/rustdoc-js-std/parser-weird-queries.js @@ -44,7 +44,7 @@ const PARSED = [ original: "a,b(c)", returned: [], userQuery: "a,b(c)", - error: "Unexpected `(`", + error: "Expected `,`, `:` or `->`, found `(`", }, { query: 'aaa,a', diff --git a/tests/rustdoc-js/tuple-unit.js b/tests/rustdoc-js/tuple-unit.js new file mode 100644 index 00000000000..d24a3da328c --- /dev/null +++ b/tests/rustdoc-js/tuple-unit.js @@ -0,0 +1,80 @@ +// exact-check + +const EXPECTED = [ + { + 'query': '()', + 'returned': [ + { 'path': 'tuple_unit', 'name': 'side_effect' }, + { 'path': 'tuple_unit', 'name': 'one' }, + { 'path': 'tuple_unit', 'name': 'two' }, + { 'path': 'tuple_unit', 'name': 'nest' }, + ], + 'in_args': [], + }, + { + 'query': 'primitive:unit', + 'returned': [ + { 'path': 'tuple_unit', 'name': 'side_effect' }, + ], + 'in_args': [], + }, + { + 'query': 'primitive:tuple', + 'returned': [ + { 'path': 'tuple_unit', 'name': 'one' }, + { 'path': 'tuple_unit', 'name': 'two' }, + { 'path': 'tuple_unit', 'name': 'nest' }, + ], + 'in_args': [], + }, + { + 'query': '(P)', + 'returned': [ + { 'path': 'tuple_unit', 'name': 'not_tuple' }, + { 'path': 'tuple_unit', 'name': 'one' }, + { 'path': 'tuple_unit', 'name': 'two' }, + ], + 'in_args': [], + }, + { + 'query': '(P,)', + 'returned': [ + { 'path': 'tuple_unit', 'name': 'one' }, + { 'path': 'tuple_unit', 'name': 'two' }, + ], + 'in_args': [], + }, + { + 'query': '(P, P)', + 'returned': [ + { 'path': 'tuple_unit', 'name': 'two' }, + ], + 'in_args': [], + }, + { + 'query': '(P, ())', + 'returned': [], + 'in_args': [], + }, + { + 'query': '(Q, ())', + 'returned': [ + { 'path': 'tuple_unit', 'name': 'nest' }, + ], + 'in_args': [], + }, + { + 'query': '(R)', + 'returned': [ + { 'path': 'tuple_unit', 'name': 'nest' }, + ], + 'in_args': [], + }, + { + 'query': '(u32)', + 'returned': [ + { 'path': 'tuple_unit', 'name': 'nest' }, + ], + 'in_args': [], + }, +]; diff --git a/tests/rustdoc-js/tuple-unit.rs b/tests/rustdoc-js/tuple-unit.rs new file mode 100644 index 00000000000..93f9a671cbc --- /dev/null +++ b/tests/rustdoc-js/tuple-unit.rs @@ -0,0 +1,18 @@ +pub struct P; +pub struct Q; +pub struct R(T); + +// Checks that tuple and unit both work +pub fn side_effect() { } + +// Check a non-tuple +pub fn not_tuple() -> P { loop {} } + +// Check a 1-tuple +pub fn one() -> (P,) { loop {} } + +// Check a 2-tuple +pub fn two() -> (P,P) { loop {} } + +// Check a nested tuple +pub fn nest() -> (Q, R<(u32,)>) { loop {} } -- cgit 1.4.1-3-g733a5 From e74339bd4b70ee93ca380c496e53177fd19193af Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Wed, 22 Nov 2023 18:20:31 -0700 Subject: Add a few more docs --- src/doc/rustdoc/src/read-documentation/search.md | 48 +++++++----------------- 1 file changed, 14 insertions(+), 34 deletions(-) (limited to 'src') diff --git a/src/doc/rustdoc/src/read-documentation/search.md b/src/doc/rustdoc/src/read-documentation/search.md index d773794504e..b5f4060f059 100644 --- a/src/doc/rustdoc/src/read-documentation/search.md +++ b/src/doc/rustdoc/src/read-documentation/search.md @@ -147,45 +147,20 @@ will match these queries: * `Read -> Result, Error>` * `Read -> Result` * `Read -> Result>` +* `Read -> u8` But it *does not* match `Result` or `Result>`. ### Primitives with Special Syntax - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ShorthandExplicit 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` and/or `primitive:array` | +| `()` | `primitive:unit` and/or `primitive:tuple` | +| `(T)` | `T` | +| `(T,)` | `primitive:tuple` | +| `!` | `primitive:never` | 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 @@ -200,6 +175,11 @@ since parens act as the grouping operator. If they're empty, though, they will match both `unit` and `tuple`, and if there's more than one type (or a trailing or leading comma) it is the same as `primitive:tuple<...>`. +However, since items can be left out of the query, `(T)` will still return +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`. + ### Limitations and quirks of type-based search Type-based search is still a buggy, experimental, work-in-progress feature. -- cgit 1.4.1-3-g733a5 From 96bd9cdcc4b70262c1d125794e7ab751f370d587 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Mon, 1 Jan 2024 09:41:39 +0300 Subject: pass allow-{dirty,staged} to clippy Signed-off-by: onur-ozkan --- src/bootstrap/src/core/build_steps/check.rs | 13 ++++++++++++- src/bootstrap/src/core/config/flags.rs | 4 ++++ src/etc/completions/x.py.fish | 2 ++ src/etc/completions/x.py.ps1 | 2 ++ src/etc/completions/x.py.sh | 2 +- src/etc/completions/x.py.zsh | 2 ++ 6 files changed, 23 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/bootstrap/src/core/build_steps/check.rs b/src/bootstrap/src/core/build_steps/check.rs index ecaaf91aec1..97a2494370c 100644 --- a/src/bootstrap/src/core/build_steps/check.rs +++ b/src/bootstrap/src/core/build_steps/check.rs @@ -28,7 +28,9 @@ fn args(builder: &Builder<'_>) -> Vec { arr.iter().copied().map(String::from) } - if let Subcommand::Clippy { fix, allow, deny, warn, forbid, .. } = &builder.config.cmd { + if let Subcommand::Clippy { fix, allow_dirty, allow_staged, allow, deny, warn, forbid } = + &builder.config.cmd + { // disable the most spammy clippy lints let ignored_lints = vec![ "many_single_char_names", // there are a lot in stdarch @@ -49,7 +51,16 @@ fn args(builder: &Builder<'_>) -> Vec { // As a workaround, avoid checking tests and benches when passed --fix. "--lib", "--bins", "--examples", ])); + + if *allow_dirty { + args.push("--allow-dirty".to_owned()); + } + + if *allow_staged { + args.push("--allow-staged".to_owned()); + } } + args.extend(strings(&["--", "--cap-lints", "warn"])); args.extend(ignored_lints.iter().map(|lint| format!("-Aclippy::{}", lint))); let mut clippy_lint_levels: Vec = Vec::new(); diff --git a/src/bootstrap/src/core/config/flags.rs b/src/bootstrap/src/core/config/flags.rs index 0b13726081b..8af454001a6 100644 --- a/src/bootstrap/src/core/config/flags.rs +++ b/src/bootstrap/src/core/config/flags.rs @@ -255,6 +255,10 @@ pub enum Subcommand { Clippy { #[arg(long)] fix: bool, + #[arg(long, requires = "fix")] + allow_dirty: bool, + #[arg(long, requires = "fix")] + allow_staged: bool, /// clippy lints to allow #[arg(global(true), short = 'A', action = clap::ArgAction::Append, value_name = "LINT")] allow: Vec, diff --git a/src/etc/completions/x.py.fish b/src/etc/completions/x.py.fish index 95bce9e31a4..9fc95fd09ba 100644 --- a/src/etc/completions/x.py.fish +++ b/src/etc/completions/x.py.fish @@ -143,6 +143,8 @@ complete -c x.py -n "__fish_seen_subcommand_from clippy" -l llvm-profile-use -d complete -c x.py -n "__fish_seen_subcommand_from clippy" -l reproducible-artifact -d 'Additional reproducible artifacts that should be added to the reproducible artifacts archive' -r complete -c x.py -n "__fish_seen_subcommand_from clippy" -l set -d 'override options in config.toml' -r -f complete -c x.py -n "__fish_seen_subcommand_from clippy" -l fix +complete -c x.py -n "__fish_seen_subcommand_from clippy" -l allow-dirty +complete -c x.py -n "__fish_seen_subcommand_from clippy" -l allow-staged complete -c x.py -n "__fish_seen_subcommand_from clippy" -s v -l verbose -d 'use verbose output (-vv for very verbose)' complete -c x.py -n "__fish_seen_subcommand_from clippy" -s i -l incremental -d 'use incremental compilation' complete -c x.py -n "__fish_seen_subcommand_from clippy" -l include-default-paths -d 'include default paths in addition to the provided ones' diff --git a/src/etc/completions/x.py.ps1 b/src/etc/completions/x.py.ps1 index dabc3b16e4d..6359b7ff086 100644 --- a/src/etc/completions/x.py.ps1 +++ b/src/etc/completions/x.py.ps1 @@ -188,6 +188,8 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock { [CompletionResult]::new('--reproducible-artifact', 'reproducible-artifact', [CompletionResultType]::ParameterName, 'Additional reproducible artifacts that should be added to the reproducible artifacts archive') [CompletionResult]::new('--set', 'set', [CompletionResultType]::ParameterName, 'override options in config.toml') [CompletionResult]::new('--fix', 'fix', [CompletionResultType]::ParameterName, 'fix') + [CompletionResult]::new('--allow-dirty', 'allow-dirty', [CompletionResultType]::ParameterName, 'allow-dirty') + [CompletionResult]::new('--allow-staged', 'allow-staged', [CompletionResultType]::ParameterName, 'allow-staged') [CompletionResult]::new('-v', 'v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') [CompletionResult]::new('--verbose', 'verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') [CompletionResult]::new('-i', 'i', [CompletionResultType]::ParameterName, 'use incremental compilation') diff --git a/src/etc/completions/x.py.sh b/src/etc/completions/x.py.sh index f739f46b88b..8ffd8f67df2 100644 --- a/src/etc/completions/x.py.sh +++ b/src/etc/completions/x.py.sh @@ -615,7 +615,7 @@ _x.py() { return 0 ;; x.py__clippy) - opts="-A -D -W -F -v -i -j -h --fix --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..." + opts="-A -D -W -F -v -i -j -h --fix --allow-dirty --allow-staged --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..." if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 diff --git a/src/etc/completions/x.py.zsh b/src/etc/completions/x.py.zsh index 639f0487f8b..ea7e4ba6758 100644 --- a/src/etc/completions/x.py.zsh +++ b/src/etc/completions/x.py.zsh @@ -182,6 +182,8 @@ _arguments "${_arguments_options[@]}" \ '*--reproducible-artifact=[Additional reproducible artifacts that should be added to the reproducible artifacts archive]:REPRODUCIBLE_ARTIFACT: ' \ '*--set=[override options in config.toml]:section.option=value:( )' \ '--fix[]' \ +'--allow-dirty[]' \ +'--allow-staged[]' \ '*-v[use verbose output (-vv for very verbose)]' \ '*--verbose[use verbose output (-vv for very verbose)]' \ '-i[use incremental compilation]' \ -- cgit 1.4.1-3-g733a5 From 205fb75cfa3339fcbac70e8da9c381060a8940cc Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Fri, 5 Jan 2024 17:11:25 +0300 Subject: rustc_span: Remove `fn fresh_expansion` In the past it did create a fresh expansion, but now, after surviving a number of refactorings, it does not. Now it's just a thin wrapper around `apply_mark`. --- compiler/rustc_span/src/hygiene.rs | 17 +---------------- src/librustdoc/passes/lint/check_code_block_syntax.rs | 4 ++-- 2 files changed, 3 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/compiler/rustc_span/src/hygiene.rs b/compiler/rustc_span/src/hygiene.rs index b717229b68d..fec05e8e0b3 100644 --- a/compiler/rustc_span/src/hygiene.rs +++ b/compiler/rustc_span/src/hygiene.rs @@ -850,21 +850,6 @@ impl fmt::Debug for SyntaxContext { } impl Span { - /// Creates a fresh expansion with given properties. - /// Expansions are normally created by macros, but in some cases expansions are created for - /// other compiler-generated code to set per-span properties like allowed unstable features. - /// The returned span belongs to the created expansion and has the new properties, - /// but its location is inherited from the current span. - pub fn fresh_expansion(self, expn_id: LocalExpnId) -> Span { - HygieneData::with(|data| { - self.with_ctxt(data.apply_mark( - self.ctxt(), - expn_id.to_expn_id(), - Transparency::Transparent, - )) - }) - } - /// Reuses the span but adds information like the kind of the desugaring and features that are /// allowed inside this span. pub fn mark_with_reason( @@ -879,7 +864,7 @@ impl Span { ..ExpnData::default(ExpnKind::Desugaring(reason), self, edition, None, None) }; let expn_id = LocalExpnId::fresh(expn_data, ctx); - self.fresh_expansion(expn_id) + self.apply_mark(expn_id.to_expn_id(), Transparency::Transparent) } } diff --git a/src/librustdoc/passes/lint/check_code_block_syntax.rs b/src/librustdoc/passes/lint/check_code_block_syntax.rs index 53c7f0f6e15..782938f1094 100644 --- a/src/librustdoc/passes/lint/check_code_block_syntax.rs +++ b/src/librustdoc/passes/lint/check_code_block_syntax.rs @@ -8,7 +8,7 @@ use rustc_errors::{ use rustc_parse::parse_stream_from_source_str; use rustc_resolve::rustdoc::source_span_for_markdown_range; use rustc_session::parse::ParseSess; -use rustc_span::hygiene::{AstPass, ExpnData, ExpnKind, LocalExpnId}; +use rustc_span::hygiene::{AstPass, ExpnData, ExpnKind, LocalExpnId, Transparency}; use rustc_span::source_map::{FilePathMapping, SourceMap}; use rustc_span::{FileName, InnerSpan, DUMMY_SP}; @@ -50,7 +50,7 @@ fn check_rust_syntax( let expn_data = ExpnData::default(ExpnKind::AstPass(AstPass::TestHarness), DUMMY_SP, edition, None, None); let expn_id = cx.tcx.with_stable_hashing_context(|hcx| LocalExpnId::fresh(expn_data, hcx)); - let span = DUMMY_SP.fresh_expansion(expn_id); + let span = DUMMY_SP.apply_mark(expn_id.to_expn_id(), Transparency::Transparent); let is_empty = rustc_driver::catch_fatal_errors(|| { parse_stream_from_source_str( -- cgit 1.4.1-3-g733a5