Skip to content

Commit 778e08d

Browse files
authored
Merge pull request #20180 from ChayimFriedman2/parser-stuck
fix: Always bump in the parser in `err_and_bump()`
2 parents 5bae4f5 + 87cddda commit 778e08d

File tree

4 files changed

+50
-8
lines changed

4 files changed

+50
-8
lines changed

crates/hir-def/src/macro_expansion_tests/mod.rs

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,21 +20,24 @@ use base_db::RootQueryDb;
2020
use expect_test::Expect;
2121
use hir_expand::{
2222
AstId, InFile, MacroCallId, MacroCallKind, MacroKind,
23+
builtin::quote::quote,
2324
db::ExpandDatabase,
2425
proc_macro::{ProcMacro, ProcMacroExpander, ProcMacroExpansionError, ProcMacroKind},
2526
span_map::SpanMapRef,
2627
};
27-
use intern::Symbol;
28+
use intern::{Symbol, sym};
2829
use itertools::Itertools;
29-
use span::{Edition, Span};
30+
use span::{Edition, ROOT_ERASED_FILE_AST_ID, Span, SpanAnchor, SyntaxContext};
3031
use stdx::{format_to, format_to_acc};
3132
use syntax::{
3233
AstNode, AstPtr,
3334
SyntaxKind::{COMMENT, EOF, IDENT, LIFETIME_IDENT},
3435
SyntaxNode, T,
3536
ast::{self, edit::IndentLevel},
3637
};
38+
use syntax_bridge::token_tree_to_syntax_node;
3739
use test_fixture::WithFixture;
40+
use tt::{TextRange, TextSize};
3841

3942
use crate::{
4043
AdtId, Lookup, ModuleDefId,
@@ -386,3 +389,38 @@ impl ProcMacroExpander for IdentityWhenValidProcMacroExpander {
386389
other.type_id() == TypeId::of::<Self>()
387390
}
388391
}
392+
393+
#[test]
394+
fn regression_20171() {
395+
// This really isn't the appropriate place to put this test, but it's convenient with access to `quote!`.
396+
let span = Span {
397+
range: TextRange::empty(TextSize::new(0)),
398+
anchor: SpanAnchor {
399+
file_id: span::EditionedFileId::current_edition(span::FileId::from_raw(0)),
400+
ast_id: ROOT_ERASED_FILE_AST_ID,
401+
},
402+
ctx: SyntaxContext::root(Edition::CURRENT),
403+
};
404+
let close_brace = tt::Punct { char: '}', spacing: tt::Spacing::Alone, span };
405+
let dotdot1 = tt::Punct { char: '.', spacing: tt::Spacing::Joint, span };
406+
let dotdot2 = tt::Punct { char: '.', spacing: tt::Spacing::Alone, span };
407+
let dollar_crate = sym::dollar_crate;
408+
let tt = quote! {
409+
span => {
410+
if !((matches!(
411+
drive_parser(&mut parser, data, false),
412+
Err(TarParserError::CorruptField {
413+
field: CorruptFieldContext::PaxKvLength,
414+
error: GeneralParseError::ParseInt(ParseIntError { #dotdot1 #dotdot2 })
415+
})
416+
#close_brace ))) {
417+
#dollar_crate::panic::panic_2021!();
418+
}}
419+
};
420+
token_tree_to_syntax_node(
421+
&tt,
422+
syntax_bridge::TopEntryPoint::MacroStmts,
423+
&mut |_| Edition::CURRENT,
424+
Edition::CURRENT,
425+
);
426+
}

crates/hir-expand/src/builtin/quote.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ macro_rules! quote {
129129
}
130130
}
131131
}
132-
pub(super) use quote;
132+
pub use quote;
133133

134134
pub trait ToTokenTree {
135135
fn to_tokens(self, span: Span, builder: &mut TopSubtreeBuilder);

crates/parser/src/grammar/expressions/atom.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -411,18 +411,19 @@ fn parse_asm_expr(p: &mut Parser<'_>, m: Marker) -> Option<CompletedMarker> {
411411
dir_spec.abandon(p);
412412
op.abandon(p);
413413
op_n.abandon(p);
414-
p.err_and_bump("expected asm operand");
415414

416-
// improves error recovery and handles err_and_bump recovering from `{` which gets
417-
// the parser stuck here
415+
// improves error recovery
418416
if p.at(T!['{']) {
417+
p.error("expected asm operand");
419418
// test_err bad_asm_expr
420419
// fn foo() {
421420
// builtin#asm(
422421
// label crashy = { return; }
423422
// );
424423
// }
425424
expr(p);
425+
} else {
426+
p.err_and_bump("expected asm operand");
426427
}
427428

428429
if p.at(T!['}']) {

crates/parser/src/parser.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ pub(crate) struct Parser<'t> {
2929
edition: Edition,
3030
}
3131

32-
const PARSER_STEP_LIMIT: usize = 15_000_000;
32+
const PARSER_STEP_LIMIT: usize = if cfg!(debug_assertions) { 150_000 } else { 15_000_000 };
3333

3434
impl<'t> Parser<'t> {
3535
pub(super) fn new(inp: &'t Input, edition: Edition) -> Parser<'t> {
@@ -254,7 +254,10 @@ impl<'t> Parser<'t> {
254254

255255
/// Create an error node and consume the next token.
256256
pub(crate) fn err_and_bump(&mut self, message: &str) {
257-
self.err_recover(message, TokenSet::EMPTY);
257+
let m = self.start();
258+
self.error(message);
259+
self.bump_any();
260+
m.complete(self, ERROR);
258261
}
259262

260263
/// Create an error node and consume the next token unless it is in the recovery set.

0 commit comments

Comments
 (0)