Skip to content

Commit 44eeaea

Browse files
committed
Auto merge of #15415 - Veykril:eager-parser-input, r=Veykril
fix: Fix float parser hack creating empty NameRef tokens Fixes #15403
2 parents d9e9ca2 + cba39f8 commit 44eeaea

File tree

4 files changed

+46
-7
lines changed

4 files changed

+46
-7
lines changed

crates/hir-def/src/macro_expansion_tests/mbe/regression.rs

+27
Original file line numberDiff line numberDiff line change
@@ -909,3 +909,30 @@ macro_rules! with_std {
909909
"##]],
910910
)
911911
}
912+
913+
#[test]
914+
fn eager_regression_15403() {
915+
check(
916+
r#"
917+
#[rustc_builtin_macro]
918+
#[macro_export]
919+
macro_rules! format_args {}
920+
921+
fn main() {
922+
format_args /* +errors */ !("{}", line.1.);
923+
}
924+
925+
"#,
926+
expect![[r##"
927+
#[rustc_builtin_macro]
928+
#[macro_export]
929+
macro_rules! format_args {}
930+
931+
fn main() {
932+
/* error: expected field name or number *//* parse error: expected field name or number */
933+
::core::fmt::Arguments::new_v1(&["", ], &[::core::fmt::ArgumentV1::new(&(line.1.), ::core::fmt::Display::fmt), ]);
934+
}
935+
936+
"##]],
937+
);
938+
}

crates/mbe/src/syntax_bridge.rs

+1
Original file line numberDiff line numberDiff line change
@@ -961,6 +961,7 @@ impl TtTreeSink<'_> {
961961
if has_pseudo_dot {
962962
assert!(right.is_empty(), "{left}.{right}");
963963
} else {
964+
assert!(!right.is_empty(), "{left}.{right}");
964965
self.inner.start_node(SyntaxKind::NAME_REF);
965966
self.inner.token(SyntaxKind::INT_NUMBER, right);
966967
self.inner.finish_node();

crates/parser/src/shortcuts.rs

+9-4
Original file line numberDiff line numberDiff line change
@@ -46,12 +46,16 @@ impl LexedStr<'_> {
4646
// Tag the token as joint if it is float with a fractional part
4747
// we use this jointness to inform the parser about what token split
4848
// event to emit when we encounter a float literal in a field access
49-
if kind == SyntaxKind::FLOAT_NUMBER && !self.text(i).ends_with('.') {
50-
res.was_joint();
49+
if kind == SyntaxKind::FLOAT_NUMBER {
50+
if !self.text(i).ends_with('.') {
51+
res.was_joint();
52+
} else {
53+
was_joint = false;
54+
}
55+
} else {
56+
was_joint = true;
5157
}
5258
}
53-
54-
was_joint = true;
5559
}
5660
}
5761
res
@@ -204,6 +208,7 @@ impl Builder<'_, '_> {
204208
assert!(right.is_empty(), "{left}.{right}");
205209
self.state = State::Normal;
206210
} else {
211+
assert!(!right.is_empty(), "{left}.{right}");
207212
(self.sink)(StrStep::Enter { kind: SyntaxKind::NAME_REF });
208213
(self.sink)(StrStep::Token { kind: SyntaxKind::INT_NUMBER, text: right });
209214
(self.sink)(StrStep::Exit);

crates/syntax/src/lib.rs

+9-3
Original file line numberDiff line numberDiff line change
@@ -195,11 +195,16 @@ impl ast::TokenTree {
195195
// Tag the token as joint if it is float with a fractional part
196196
// we use this jointness to inform the parser about what token split
197197
// event to emit when we encounter a float literal in a field access
198-
if kind == SyntaxKind::FLOAT_NUMBER && !t.text().ends_with('.') {
199-
parser_input.was_joint();
198+
if kind == SyntaxKind::FLOAT_NUMBER {
199+
if !t.text().ends_with('.') {
200+
parser_input.was_joint();
201+
} else {
202+
was_joint = false;
203+
}
204+
} else {
205+
was_joint = true;
200206
}
201207
}
202-
was_joint = true;
203208
}
204209
}
205210

@@ -250,6 +255,7 @@ impl ast::TokenTree {
250255
if has_pseudo_dot {
251256
assert!(right.is_empty(), "{left}.{right}");
252257
} else {
258+
assert!(!right.is_empty(), "{left}.{right}");
253259
builder.start_node(SyntaxKind::NAME_REF);
254260
builder.token(SyntaxKind::INT_NUMBER, right);
255261
builder.finish_node();

0 commit comments

Comments
 (0)