Skip to content

Commit 3ee6710

Browse files
committed
Auto merge of rust-lang#119384 - matthiaskrgr:rollup-hhz9ws0, r=matthiaskrgr
Rollup of 5 pull requests Successful merges: - rust-lang#119331 (rustdoc-search: count path edits with separate edit limit) - rust-lang#119359 (Simplify Parser::ident_or_error) - rust-lang#119376 (Add regression test for rust-lang#106630) - rust-lang#119379 (Update `parse_seq` doc) - rust-lang#119380 (Don't suggest writing a bodyless arm if the pattern can never be a never pattern) r? `@ghost` `@rustbot` modify labels: rollup
2 parents f4d794e + e8831b6 commit 3ee6710

24 files changed

+249
-92
lines changed

compiler/rustc_parse/src/parser/expr.rs

+7-1
Original file line numberDiff line numberDiff line change
@@ -2937,7 +2937,13 @@ impl<'a> Parser<'a> {
29372937
let is_almost_fat_arrow = TokenKind::FatArrow
29382938
.similar_tokens()
29392939
.is_some_and(|similar_tokens| similar_tokens.contains(&this.token.kind));
2940-
let mut result = if !is_fat_arrow && !is_almost_fat_arrow {
2940+
2941+
// this avoids the compiler saying that a `,` or `}` was expected even though
2942+
// the pattern isn't a never pattern (and thus an arm body is required)
2943+
let armless = (!is_fat_arrow && !is_almost_fat_arrow && pat.could_be_never_pattern())
2944+
|| matches!(this.token.kind, token::Comma | token::CloseDelim(Delimiter::Brace));
2945+
2946+
let mut result = if armless {
29412947
// A pattern without a body, allowed for never patterns.
29422948
arm_body = None;
29432949
this.expect_one_of(&[token::Comma], &[token::CloseDelim(Delimiter::Brace)]).map(

compiler/rustc_parse/src/parser/mod.rs

+32-22
Original file line numberDiff line numberDiff line change
@@ -320,9 +320,15 @@ impl TokenType {
320320
}
321321
}
322322

323+
/// Used by [`Parser::expect_any_with_type`].
323324
#[derive(Copy, Clone, Debug)]
324325
enum TokenExpectType {
326+
/// Unencountered tokens are inserted into [`Parser::expected_tokens`].
327+
/// See [`Parser::check`].
325328
Expect,
329+
330+
/// Unencountered tokens are not inserted into [`Parser::expected_tokens`].
331+
/// See [`Parser::check_noexpect`].
326332
NoExpect,
327333
}
328334

@@ -504,18 +510,10 @@ impl<'a> Parser<'a> {
504510
}
505511

506512
fn ident_or_err(&mut self, recover: bool) -> PResult<'a, (Ident, /* is_raw */ bool)> {
507-
let result = self.token.ident().ok_or_else(|| self.expected_ident_found(recover));
508-
509-
let (ident, is_raw) = match result {
510-
Ok(ident) => ident,
511-
Err(err) => match err {
512-
// we recovered!
513-
Ok(ident) => ident,
514-
Err(err) => return Err(err),
515-
},
516-
};
517-
518-
Ok((ident, is_raw))
513+
match self.token.ident() {
514+
Some(ident) => Ok(ident),
515+
None => self.expected_ident_found(recover),
516+
}
519517
}
520518

521519
/// Checks if the next token is `tok`, and returns `true` if so.
@@ -766,13 +764,17 @@ impl<'a> Parser<'a> {
766764
}
767765
}
768766

767+
/// Checks if the next token is contained within `kets`, and returns `true` if so.
769768
fn expect_any_with_type(&mut self, kets: &[&TokenKind], expect: TokenExpectType) -> bool {
770769
kets.iter().any(|k| match expect {
771770
TokenExpectType::Expect => self.check(k),
772-
TokenExpectType::NoExpect => self.token == **k,
771+
TokenExpectType::NoExpect => self.check_noexpect(k),
773772
})
774773
}
775774

775+
/// Parses a sequence until the specified delimiters. The function
776+
/// `f` must consume tokens until reaching the next separator or
777+
/// closing bracket.
776778
fn parse_seq_to_before_tokens<T>(
777779
&mut self,
778780
kets: &[&TokenKind],
@@ -791,13 +793,15 @@ impl<'a> Parser<'a> {
791793
}
792794
if let Some(t) = &sep.sep {
793795
if first {
796+
// no separator for the first element
794797
first = false;
795798
} else {
799+
// check for separator
796800
match self.expect(t) {
797-
Ok(false) => {
801+
Ok(false) /* not recovered */ => {
798802
self.current_closure.take();
799803
}
800-
Ok(true) => {
804+
Ok(true) /* recovered */ => {
801805
self.current_closure.take();
802806
recovered = true;
803807
break;
@@ -965,19 +969,19 @@ impl<'a> Parser<'a> {
965969
Ok(())
966970
}
967971

968-
/// Parses a sequence, not including the closing delimiter. The function
972+
/// Parses a sequence, not including the delimiters. The function
969973
/// `f` must consume tokens until reaching the next separator or
970974
/// closing bracket.
971975
fn parse_seq_to_before_end<T>(
972976
&mut self,
973977
ket: &TokenKind,
974978
sep: SeqSep,
975979
f: impl FnMut(&mut Parser<'a>) -> PResult<'a, T>,
976-
) -> PResult<'a, (ThinVec<T>, bool, bool)> {
980+
) -> PResult<'a, (ThinVec<T>, bool /* trailing */, bool /* recovered */)> {
977981
self.parse_seq_to_before_tokens(&[ket], sep, TokenExpectType::Expect, f)
978982
}
979983

980-
/// Parses a sequence, including the closing delimiter. The function
984+
/// Parses a sequence, including only the closing delimiter. The function
981985
/// `f` must consume tokens until reaching the next separator or
982986
/// closing bracket.
983987
fn parse_seq_to_end<T>(
@@ -993,7 +997,7 @@ impl<'a> Parser<'a> {
993997
Ok((val, trailing))
994998
}
995999

996-
/// Parses a sequence, including the closing delimiter. The function
1000+
/// Parses a sequence, including both delimiters. The function
9971001
/// `f` must consume tokens until reaching the next separator or
9981002
/// closing bracket.
9991003
fn parse_unspanned_seq<T>(
@@ -1002,16 +1006,19 @@ impl<'a> Parser<'a> {
10021006
ket: &TokenKind,
10031007
sep: SeqSep,
10041008
f: impl FnMut(&mut Parser<'a>) -> PResult<'a, T>,
1005-
) -> PResult<'a, (ThinVec<T>, bool)> {
1009+
) -> PResult<'a, (ThinVec<T>, bool /* trailing */)> {
10061010
self.expect(bra)?;
10071011
self.parse_seq_to_end(ket, sep, f)
10081012
}
10091013

1014+
/// Parses a comma-separated sequence, including both delimiters.
1015+
/// The function `f` must consume tokens until reaching the next separator or
1016+
/// closing bracket.
10101017
fn parse_delim_comma_seq<T>(
10111018
&mut self,
10121019
delim: Delimiter,
10131020
f: impl FnMut(&mut Parser<'a>) -> PResult<'a, T>,
1014-
) -> PResult<'a, (ThinVec<T>, bool)> {
1021+
) -> PResult<'a, (ThinVec<T>, bool /* trailing */)> {
10151022
self.parse_unspanned_seq(
10161023
&token::OpenDelim(delim),
10171024
&token::CloseDelim(delim),
@@ -1020,10 +1027,13 @@ impl<'a> Parser<'a> {
10201027
)
10211028
}
10221029

1030+
/// Parses a comma-separated sequence delimited by parentheses (e.g. `(x, y)`).
1031+
/// The function `f` must consume tokens until reaching the next separator or
1032+
/// closing bracket.
10231033
fn parse_paren_comma_seq<T>(
10241034
&mut self,
10251035
f: impl FnMut(&mut Parser<'a>) -> PResult<'a, T>,
1026-
) -> PResult<'a, (ThinVec<T>, bool)> {
1036+
) -> PResult<'a, (ThinVec<T>, bool /* trailing */)> {
10271037
self.parse_delim_comma_seq(Delimiter::Parenthesis, f)
10281038
}
10291039

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

+30-17
Original file line numberDiff line numberDiff line change
@@ -1805,11 +1805,20 @@ function initSearch(rawSearchIndex) {
18051805
return unifyFunctionTypes([row], [elem], whereClause, mgens);
18061806
}
18071807

1808-
function checkPath(contains, ty, maxEditDistance) {
1808+
/**
1809+
* Compute an "edit distance" that ignores missing path elements.
1810+
* @param {string[]} contains search query path
1811+
* @param {Row} ty indexed item
1812+
* @returns {null|number} edit distance
1813+
*/
1814+
function checkPath(contains, ty) {
18091815
if (contains.length === 0) {
18101816
return 0;
18111817
}
1812-
let ret_dist = maxEditDistance + 1;
1818+
const maxPathEditDistance = Math.floor(
1819+
contains.reduce((acc, next) => acc + next.length, 0) / 3
1820+
);
1821+
let ret_dist = maxPathEditDistance + 1;
18131822
const path = ty.path.split("::");
18141823

18151824
if (ty.parent && ty.parent.name) {
@@ -1821,15 +1830,23 @@ function initSearch(rawSearchIndex) {
18211830
pathiter: for (let i = length - clength; i >= 0; i -= 1) {
18221831
let dist_total = 0;
18231832
for (let x = 0; x < clength; ++x) {
1824-
const dist = editDistance(path[i + x], contains[x], maxEditDistance);
1825-
if (dist > maxEditDistance) {
1826-
continue pathiter;
1833+
const [p, c] = [path[i + x], contains[x]];
1834+
if (Math.floor((p.length - c.length) / 3) <= maxPathEditDistance &&
1835+
p.indexOf(c) !== -1
1836+
) {
1837+
// discount distance on substring match
1838+
dist_total += Math.floor((p.length - c.length) / 3);
1839+
} else {
1840+
const dist = editDistance(p, c, maxPathEditDistance);
1841+
if (dist > maxPathEditDistance) {
1842+
continue pathiter;
1843+
}
1844+
dist_total += dist;
18271845
}
1828-
dist_total += dist;
18291846
}
18301847
ret_dist = Math.min(ret_dist, Math.round(dist_total / clength));
18311848
}
1832-
return ret_dist;
1849+
return ret_dist > maxPathEditDistance ? null : ret_dist;
18331850
}
18341851

18351852
function typePassesFilter(filter, type) {
@@ -2030,8 +2047,8 @@ function initSearch(rawSearchIndex) {
20302047
}
20312048

20322049
if (elem.fullPath.length > 1) {
2033-
path_dist = checkPath(elem.pathWithoutLast, row, maxEditDistance);
2034-
if (path_dist > maxEditDistance) {
2050+
path_dist = checkPath(elem.pathWithoutLast, row);
2051+
if (path_dist === null) {
20352052
return;
20362053
}
20372054
}
@@ -2045,7 +2062,7 @@ function initSearch(rawSearchIndex) {
20452062

20462063
const dist = editDistance(row.normalizedName, elem.normalizedPathLast, maxEditDistance);
20472064

2048-
if (index === -1 && dist + path_dist > maxEditDistance) {
2065+
if (index === -1 && dist > maxEditDistance) {
20492066
return;
20502067
}
20512068

@@ -2100,13 +2117,9 @@ function initSearch(rawSearchIndex) {
21002117
}
21012118

21022119
function innerRunQuery() {
2103-
let queryLen = 0;
2104-
for (const elem of parsedQuery.elems) {
2105-
queryLen += elem.name.length;
2106-
}
2107-
for (const elem of parsedQuery.returned) {
2108-
queryLen += elem.name.length;
2109-
}
2120+
const queryLen =
2121+
parsedQuery.elems.reduce((acc, next) => acc + next.pathLast.length, 0) +
2122+
parsedQuery.returned.reduce((acc, next) => acc + next.pathLast.length, 0);
21102123
const maxEditDistance = Math.floor(queryLen / 3);
21112124

21122125
/**

tests/rustdoc-js-std/asrawfd.js

-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ const EXPECTED = {
77
// Validate that type alias methods get the correct path.
88
{ 'path': 'std::os::fd::AsRawFd', 'name': 'as_raw_fd' },
99
{ 'path': 'std::os::fd::AsRawFd', 'name': 'as_raw_fd' },
10-
{ 'path': 'std::os::linux::process::PidFd', 'name': 'as_raw_fd' },
1110
{ 'path': 'std::os::fd::RawFd', 'name': 'as_raw_fd' },
1211
],
1312
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
// exact-check
2+
const FILTER_CRATE = "std";
3+
const EXPECTED = [
4+
{
5+
query: 'vec::intoiterator',
6+
others: [
7+
// trait std::iter::IntoIterator is not the first result
8+
{ 'path': 'std::vec', 'name': 'IntoIter' },
9+
{ 'path': 'std::vec::Vec', 'name': 'into_iter' },
10+
{ 'path': 'std::vec::Drain', 'name': 'into_iter' },
11+
{ 'path': 'std::vec::IntoIter', 'name': 'into_iter' },
12+
{ 'path': 'std::vec::ExtractIf', 'name': 'into_iter' },
13+
{ 'path': 'std::vec::Splice', 'name': 'into_iter' },
14+
{ 'path': 'std::collections::VecDeque', 'name': 'into_iter' },
15+
],
16+
},
17+
{
18+
query: 'vec::iter',
19+
others: [
20+
// std::net::ToSocketAttrs::iter should not show up here
21+
{ 'path': 'std::vec', 'name': 'IntoIter' },
22+
{ 'path': 'std::vec::Vec', 'name': 'from_iter' },
23+
{ 'path': 'std::vec::Vec', 'name': 'into_iter' },
24+
{ 'path': 'std::vec::Drain', 'name': 'into_iter' },
25+
{ 'path': 'std::vec::IntoIter', 'name': 'into_iter' },
26+
{ 'path': 'std::vec::ExtractIf', 'name': 'into_iter' },
27+
{ 'path': 'std::vec::Splice', 'name': 'into_iter' },
28+
{ 'path': 'std::collections::VecDeque', 'name': 'iter' },
29+
{ 'path': 'std::collections::VecDeque', 'name': 'iter_mut' },
30+
{ 'path': 'std::collections::VecDeque', 'name': 'from_iter' },
31+
{ 'path': 'std::collections::VecDeque', 'name': 'into_iter' },
32+
],
33+
},
34+
{
35+
query: 'slice::itermut',
36+
others: [
37+
// std::collections::btree_map::itermut should not show up here
38+
{ 'path': 'std::slice', 'name': 'IterMut' },
39+
{ 'path': 'std::slice', 'name': 'iter_mut' },
40+
],
41+
},
42+
];

tests/rustdoc-js-std/path-ordering.js

+20-11
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,20 @@
1-
const EXPECTED = {
2-
query: 'hashset::insert',
3-
others: [
4-
// ensure hashset::insert comes first
5-
{ 'path': 'std::collections::hash_set::HashSet', 'name': 'insert' },
6-
{ 'path': 'std::collections::hash_set::HashSet', 'name': 'get_or_insert' },
7-
{ 'path': 'std::collections::hash_set::HashSet', 'name': 'get_or_insert_with' },
8-
{ 'path': 'std::collections::hash_set::HashSet', 'name': 'get_or_insert_owned' },
9-
{ 'path': 'std::collections::hash_map::HashMap', 'name': 'insert' },
10-
],
11-
};
1+
const EXPECTED = [
2+
{
3+
query: 'hashset::insert',
4+
others: [
5+
// ensure hashset::insert comes first
6+
{ 'path': 'std::collections::hash_set::HashSet', 'name': 'insert' },
7+
{ 'path': 'std::collections::hash_set::HashSet', 'name': 'get_or_insert' },
8+
{ 'path': 'std::collections::hash_set::HashSet', 'name': 'get_or_insert_with' },
9+
{ 'path': 'std::collections::hash_set::HashSet', 'name': 'get_or_insert_owned' },
10+
],
11+
},
12+
{
13+
query: 'hash::insert',
14+
others: [
15+
// ensure hashset/hashmap::insert come first
16+
{ 'path': 'std::collections::hash_map::HashMap', 'name': 'insert' },
17+
{ 'path': 'std::collections::hash_set::HashSet', 'name': 'insert' },
18+
],
19+
},
20+
];

tests/rustdoc-js/exact-match.js

-1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,5 @@ const EXPECTED = {
33
'others': [
44
{ 'path': 'exact_match::Si', 'name': 'pc' },
55
{ 'path': 'exact_match::Psi', 'name': 'pc' },
6-
{ 'path': 'exact_match::Si', 'name': 'pa' },
76
],
87
};

tests/rustdoc-js/module-substring.js

+15-7
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,15 @@
1-
const EXPECTED = {
2-
'query': 'ig::pc',
3-
'others': [
4-
{ 'path': 'module_substring::Sig', 'name': 'pc' },
5-
{ 'path': 'module_substring::Si', 'name': 'pc' },
6-
],
7-
};
1+
const EXPECTED = [
2+
{
3+
'query': 'ig::pc',
4+
'others': [
5+
{ 'path': 'module_substring::Sig', 'name': 'pc' },
6+
],
7+
},
8+
{
9+
'query': 'si::pc',
10+
'others': [
11+
{ 'path': 'module_substring::Si', 'name': 'pc' },
12+
{ 'path': 'module_substring::Sig', 'name': 'pc' },
13+
],
14+
},
15+
];
+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// exact-check
2+
3+
const EXPECTED = [
4+
{
5+
'query': 'xxxxxxxxxxx::hocuspocusprestidigitation',
6+
// do not match abracadabra::hocuspocusprestidigitation
7+
'others': [],
8+
},
9+
{
10+
// exact match
11+
'query': 'abracadabra::hocuspocusprestidigitation',
12+
'others': [
13+
{ 'path': 'abracadabra', 'name': 'HocusPocusPrestidigitation' },
14+
],
15+
},
16+
{
17+
// swap br/rb; that's edit distance 2, where maxPathEditDistance = 3 (11 / 3)
18+
'query': 'arbacadarba::hocuspocusprestidigitation',
19+
'others': [
20+
{ 'path': 'abracadabra', 'name': 'HocusPocusPrestidigitation' },
21+
],
22+
},
23+
{
24+
// truncate 5 chars, where maxEditDistance = 7 (21 / 3)
25+
'query': 'abracadarba::hocusprestidigitation',
26+
'others': [
27+
{ 'path': 'abracadabra', 'name': 'HocusPocusPrestidigitation' },
28+
],
29+
},
30+
{
31+
// truncate 9 chars, where maxEditDistance = 5 (17 / 3)
32+
'query': 'abracadarba::hprestidigitation',
33+
'others': [],
34+
},
35+
];

0 commit comments

Comments
 (0)