Skip to content

Commit 80c3bd7

Browse files
committed
Break out some parsing cold functions
This recovers some instruction count regressions after changing most Pat parsing functions return a non-boxed Pat. It seems to be beneficial to break out a #[cold] parsing recovery function when the function includes more parsing, presumably because this requires more stack space and/or mem copies when LLVM optimizes the wrong path.
1 parent 7035846 commit 80c3bd7

File tree

2 files changed

+32
-20
lines changed

2 files changed

+32
-20
lines changed

compiler/rustc_parse/src/parser/diagnostics.rs

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1845,15 +1845,20 @@ impl<'a> Parser<'a> {
18451845
&mut self,
18461846
base: T,
18471847
) -> PResult<'a, T> {
1848-
if !self.may_recover() {
1849-
return Ok(base);
1848+
// Do not add `::` to expected tokens.
1849+
if self.may_recover() && self.token == token::PathSep {
1850+
return self.recover_from_bad_qpath(base);
18501851
}
1852+
Ok(base)
1853+
}
18511854

1852-
// Do not add `::` to expected tokens.
1853-
if self.token == token::PathSep {
1854-
if let Some(ty) = base.to_ty() {
1855-
return self.maybe_recover_from_bad_qpath_stage_2(ty.span, ty);
1856-
}
1855+
#[cold]
1856+
fn recover_from_bad_qpath<T: RecoverQPath>(
1857+
&mut self,
1858+
base: T,
1859+
) -> PResult<'a, T> {
1860+
if let Some(ty) = base.to_ty() {
1861+
return self.maybe_recover_from_bad_qpath_stage_2(ty.span, ty);
18571862
}
18581863
Ok(base)
18591864
}
@@ -2370,6 +2375,7 @@ impl<'a> Parser<'a> {
23702375
None
23712376
}
23722377

2378+
#[cold]
23732379
pub(super) fn recover_arg_parse(&mut self) -> PResult<'a, (Box<ast::Pat>, Box<ast::Ty>)> {
23742380
let pat = self.parse_pat_no_top_alt(Some(Expected::ArgumentName), None)?;
23752381
self.expect(exp!(Colon))?;
@@ -2750,7 +2756,8 @@ impl<'a> Parser<'a> {
27502756

27512757
/// Some special error handling for the "top-level" patterns in a match arm,
27522758
/// `for` loop, `let`, &c. (in contrast to subpatterns within such).
2753-
pub(crate) fn maybe_recover_colon_colon_in_pat_typo(
2759+
#[cold]
2760+
pub(crate) fn recover_colon_colon_in_pat_typo(
27542761
&mut self,
27552762
mut first_pat: Pat,
27562763
expected: Option<Expected>,
@@ -2935,7 +2942,15 @@ impl<'a> Parser<'a> {
29352942
if self.token != token::Comma {
29362943
return Ok(());
29372944
}
2945+
self.recover_unexpected_comma(lo, rt)
2946+
}
29382947

2948+
#[cold]
2949+
fn recover_unexpected_comma(
2950+
&mut self,
2951+
lo: Span,
2952+
rt: CommaRecoveryMode,
2953+
) -> PResult<'a, ()> {
29392954
// An unexpected comma after a top-level pattern is a clue that the
29402955
// user (perhaps more accustomed to some other language) forgot the
29412956
// parentheses in what should have been a tuple pattern; return a

compiler/rustc_parse/src/parser/pat.rs

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -199,8 +199,8 @@ impl<'a> Parser<'a> {
199199
// This complicated procedure is done purely for diagnostics UX.
200200

201201
// Check if the user wrote `foo:bar` instead of `foo::bar`.
202-
if ra == RecoverColon::Yes {
203-
first_pat = self.maybe_recover_colon_colon_in_pat_typo(first_pat, expected);
202+
if ra == RecoverColon::Yes && token::Colon == self.token.kind {
203+
first_pat = self.recover_colon_colon_in_pat_typo(first_pat, expected);
204204
}
205205

206206
if let Some(leading_vert_span) = leading_vert_span {
@@ -874,9 +874,12 @@ impl<'a> Parser<'a> {
874874
}
875875
};
876876

877-
let pat = self.mk_pat(lo.to(self.prev_token.span), pat);
878-
let pat = self.maybe_recover_from_bad_qpath(pat)?;
879-
let pat = self.recover_intersection_pat(pat)?;
877+
let mut pat = self.mk_pat(lo.to(self.prev_token.span), pat);
878+
879+
pat = self.maybe_recover_from_bad_qpath(pat)?;
880+
if self.eat_noexpect(&token::At) {
881+
pat = self.recover_intersection_pat(pat)?;
882+
}
880883

881884
if !allow_range_pat {
882885
self.ban_pat_range_if_ambiguous(&pat)
@@ -922,14 +925,8 @@ impl<'a> Parser<'a> {
922925
/// e.g. [F#][and] where they are called AND-patterns.
923926
///
924927
/// [and]: https://docs.microsoft.com/en-us/dotnet/fsharp/language-reference/pattern-matching
928+
#[cold]
925929
fn recover_intersection_pat(&mut self, lhs: Pat) -> PResult<'a, Pat> {
926-
if self.token != token::At {
927-
// Next token is not `@` so it's not going to be an intersection pattern.
928-
return Ok(lhs);
929-
}
930-
931-
// At this point we attempt to parse `@ $pat_rhs` and emit an error.
932-
self.bump(); // `@`
933930
let mut rhs = self.parse_pat_no_top_alt(None, None)?;
934931
let whole_span = lhs.span.to(rhs.span);
935932

0 commit comments

Comments
 (0)