Skip to content

Commit e3021b4

Browse files
authored
Rollup merge of rust-lang#112571 - notriddle:notriddle/never-search, r=GuillaumeGomez
rustdoc-search: search never type with `!` This feature extends rustdoc to support the syntax that most users will naturally attempt to use to search for diverging functions. Part of rust-lang#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.
2 parents 269ea4b + db277f5 commit e3021b4

File tree

7 files changed

+200
-24
lines changed

7 files changed

+200
-24
lines changed

src/librustdoc/html/static/js/search.js

+43-5
Original file line numberDiff line numberDiff line change
@@ -386,6 +386,35 @@ function initSearch(rawSearchIndex) {
386386
if (query.literalSearch && parserState.totalElems - parserState.genericsElems > 0) {
387387
throw ["You cannot have more than one element if you use quotes"];
388388
}
389+
const typeFilter = parserState.typeFilter;
390+
parserState.typeFilter = null;
391+
if (name === "!") {
392+
if (typeFilter !== null && typeFilter !== "primitive") {
393+
throw [
394+
"Invalid search type: primitive never type ",
395+
"!",
396+
" and ",
397+
typeFilter,
398+
" both specified",
399+
];
400+
}
401+
if (generics.length !== 0) {
402+
throw [
403+
"Never type ",
404+
"!",
405+
" does not accept generic parameters",
406+
];
407+
}
408+
return {
409+
name: "never",
410+
id: -1,
411+
fullPath: ["never"],
412+
pathWithoutLast: [],
413+
pathLast: "never",
414+
generics: [],
415+
typeFilter: "primitive",
416+
};
417+
}
389418
const pathSegments = name.split("::");
390419
if (pathSegments.length > 1) {
391420
for (let i = 0, len = pathSegments.length; i < len; ++i) {
@@ -399,6 +428,13 @@ function initSearch(rawSearchIndex) {
399428
}
400429
throw ["Unexpected ", "::::"];
401430
}
431+
432+
if (pathSegment === "!") {
433+
pathSegments[i] = "never";
434+
if (i !== 0) {
435+
throw ["Never type ", "!", " is not associated item"];
436+
}
437+
}
402438
}
403439
}
404440
// In case we only have something like `<p>`, there is no name.
@@ -409,8 +445,6 @@ function initSearch(rawSearchIndex) {
409445
if (isInGenerics) {
410446
parserState.genericsElems += 1;
411447
}
412-
const typeFilter = parserState.typeFilter;
413-
parserState.typeFilter = null;
414448
return {
415449
name: name,
416450
id: -1,
@@ -459,10 +493,11 @@ function initSearch(rawSearchIndex) {
459493
break;
460494
}
461495
if (foundExclamation !== -1) {
462-
if (start <= (end - 2)) {
496+
if (foundExclamation !== start &&
497+
isIdentCharacter(parserState.userQuery[foundExclamation - 1])
498+
) {
463499
throw ["Cannot have associated items in macros"];
464500
} else {
465-
// if start == end - 1, we got the never type
466501
// while the never type has no associated macros, we still
467502
// can parse a path like that
468503
foundExclamation = -1;
@@ -478,7 +513,10 @@ function initSearch(rawSearchIndex) {
478513
end = parserState.pos;
479514
}
480515
// if start == end - 1, we got the never type
481-
if (foundExclamation !== -1 && start <= (end - 2)) {
516+
if (foundExclamation !== -1 &&
517+
foundExclamation !== start &&
518+
isIdentCharacter(parserState.userQuery[foundExclamation - 1])
519+
) {
482520
if (parserState.typeFilter === null) {
483521
parserState.typeFilter = "macro";
484522
} else if (parserState.typeFilter !== "macro") {

tests/rustdoc-js-std/never.js

+14-6
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,14 @@
1-
const EXPECTED = {
2-
'query': '!',
3-
'others': [
4-
{ 'path': 'std', 'name': 'never' },
5-
],
6-
};
1+
const EXPECTED = [
2+
{
3+
'query': '!',
4+
'others': [
5+
{ 'path': 'std', 'name': 'never' },
6+
],
7+
},
8+
{
9+
'query': '!::clone',
10+
'others': [
11+
{ 'path': 'std::never', 'name': 'clone' },
12+
],
13+
},
14+
];

tests/rustdoc-js-std/parser-errors.js

+9
Original file line numberDiff line numberDiff line change
@@ -359,6 +359,15 @@ const PARSED = [
359359
userQuery: "mod:a!",
360360
error: 'Invalid search type: macro `!` and `mod` both specified',
361361
},
362+
{
363+
query: "mod:!",
364+
elems: [],
365+
foundElems: 0,
366+
original: "mod:!",
367+
returned: [],
368+
userQuery: "mod:!",
369+
error: 'Invalid search type: primitive never type `!` and `mod` both specified',
370+
},
362371
{
363372
query: "a!::a",
364373
elems: [],

tests/rustdoc-js-std/parser-ident.js

+71-9
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,12 @@ const PARSED = [
88
pathLast: "r",
99
generics: [
1010
{
11-
name: "!",
12-
fullPath: ["!"],
11+
name: "never",
12+
fullPath: ["never"],
1313
pathWithoutLast: [],
14-
pathLast: "!",
14+
pathLast: "never",
1515
generics: [],
16+
typeFilter: 15,
1617
},
1718
],
1819
typeFilter: -1,
@@ -26,12 +27,12 @@ const PARSED = [
2627
{
2728
query: "!",
2829
elems: [{
29-
name: "!",
30-
fullPath: ["!"],
30+
name: "never",
31+
fullPath: ["never"],
3132
pathWithoutLast: [],
32-
pathLast: "!",
33+
pathLast: "never",
3334
generics: [],
34-
typeFilter: -1,
35+
typeFilter: 15,
3536
}],
3637
foundElems: 1,
3738
original: "!",
@@ -64,12 +65,21 @@ const PARSED = [
6465
userQuery: "a!::b",
6566
error: "Cannot have associated items in macros",
6667
},
68+
{
69+
query: "!<T>",
70+
elems: [],
71+
foundElems: 0,
72+
original: "!<T>",
73+
returned: [],
74+
userQuery: "!<t>",
75+
error: "Never type `!` does not accept generic parameters",
76+
},
6777
{
6878
query: "!::b",
6979
elems: [{
7080
name: "!::b",
71-
fullPath: ["!", "b"],
72-
pathWithoutLast: ["!"],
81+
fullPath: ["never", "b"],
82+
pathWithoutLast: ["never"],
7383
pathLast: "b",
7484
generics: [],
7585
typeFilter: -1,
@@ -80,6 +90,58 @@ const PARSED = [
8090
userQuery: "!::b",
8191
error: null,
8292
},
93+
{
94+
query: "b::!",
95+
elems: [],
96+
foundElems: 0,
97+
original: "b::!",
98+
returned: [],
99+
userQuery: "b::!",
100+
error: "Never type `!` is not associated item",
101+
},
102+
{
103+
query: "!::!",
104+
elems: [],
105+
foundElems: 0,
106+
original: "!::!",
107+
returned: [],
108+
userQuery: "!::!",
109+
error: "Never type `!` is not associated item",
110+
},
111+
{
112+
query: "b::!::c",
113+
elems: [],
114+
foundElems: 0,
115+
original: "b::!::c",
116+
returned: [],
117+
userQuery: "b::!::c",
118+
error: "Never type `!` is not associated item",
119+
},
120+
{
121+
query: "!::b<T>",
122+
elems: [{
123+
name: "!::b",
124+
fullPath: ["never", "b"],
125+
pathWithoutLast: ["never"],
126+
pathLast: "b",
127+
generics: [
128+
{
129+
name: "t",
130+
fullPath: ["t"],
131+
pathWithoutLast: [],
132+
pathLast: "t",
133+
generics: [],
134+
typeFilter: -1,
135+
}
136+
],
137+
typeFilter: -1,
138+
}],
139+
foundElems: 1,
140+
original: "!::b<T>",
141+
returned: [],
142+
userQuery: "!::b<t>",
143+
error: null,
144+
},
83145
{
84146
query: "a!::b!",
85147
elems: [],

tests/rustdoc-js-std/parser-returned.js

+4-4
Original file line numberDiff line numberDiff line change
@@ -84,12 +84,12 @@ const PARSED = [
8484
foundElems: 1,
8585
original: "-> !",
8686
returned: [{
87-
name: "!",
88-
fullPath: ["!"],
87+
name: "never",
88+
fullPath: ["never"],
8989
pathWithoutLast: [],
90-
pathLast: "!",
90+
pathLast: "never",
9191
generics: [],
92-
typeFilter: -1,
92+
typeFilter: 15,
9393
}],
9494
userQuery: "-> !",
9595
error: null,

tests/rustdoc-js/never-search.js

+46
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
// exact-check
2+
3+
const EXPECTED = [
4+
{
5+
'query': '-> !',
6+
'others': [
7+
{ 'path': 'never_search', 'name': 'loops' },
8+
],
9+
},
10+
{
11+
'query': '-> never',
12+
'others': [
13+
{ 'path': 'never_search', 'name': 'loops' },
14+
{ 'path': 'never_search', 'name': 'returns' },
15+
],
16+
},
17+
{
18+
'query': '!',
19+
'in_args': [
20+
{ 'path': 'never_search', 'name': 'impossible' },
21+
{ 'path': 'never_search', 'name': 'box_impossible' },
22+
],
23+
},
24+
{
25+
'query': 'never',
26+
'in_args': [
27+
{ 'path': 'never_search', 'name': 'impossible' },
28+
{ 'path': 'never_search', 'name': 'uninteresting' },
29+
{ 'path': 'never_search', 'name': 'box_impossible' },
30+
{ 'path': 'never_search', 'name': 'box_uninteresting' },
31+
],
32+
},
33+
{
34+
'query': 'box<!>',
35+
'in_args': [
36+
{ 'path': 'never_search', 'name': 'box_impossible' },
37+
],
38+
},
39+
{
40+
'query': 'box<never>',
41+
'in_args': [
42+
{ 'path': 'never_search', 'name': 'box_impossible' },
43+
{ 'path': 'never_search', 'name': 'box_uninteresting' },
44+
],
45+
},
46+
];

tests/rustdoc-js/never-search.rs

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#![feature(never_type)]
2+
3+
#[allow(nonstandard_style)]
4+
pub struct never;
5+
6+
pub fn loops() -> ! { loop {} }
7+
pub fn returns() -> never { never }
8+
9+
pub fn impossible(x: !) { match x {} }
10+
pub fn uninteresting(x: never) { match x { never => {} } }
11+
12+
pub fn box_impossible(x: Box<!>) { match *x {} }
13+
pub fn box_uninteresting(x: Box<never>) { match *x { never => {} } }

0 commit comments

Comments
 (0)