Skip to content

Commit df7ab62

Browse files
committed
fix: Fix parsing of integer/keyword name refs in various places
1 parent f499faf commit df7ab62

33 files changed

+351
-133
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1733,7 +1733,7 @@ m!(C("0"));
17331733
macro_rules! m {
17341734
($k:expr) => { fn f() { K::$k; } }
17351735
}
1736-
/* parse error: expected identifier */
1736+
/* parse error: expected identifier, `self`, `super`, `crate`, or `Self` */
17371737
/* parse error: expected SEMICOLON */
17381738
/* parse error: expected SEMICOLON */
17391739
/* parse error: expected expression, item or let statement */

crates/parser/src/grammar.rs

Lines changed: 40 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -307,13 +307,49 @@ fn name(p: &mut Parser<'_>) {
307307
name_r(p, TokenSet::EMPTY);
308308
}
309309

310-
fn name_ref(p: &mut Parser<'_>) {
311-
if p.at(IDENT) {
310+
fn name_ref_or_self(p: &mut Parser<'_>) {
311+
if matches!(p.current(), T![ident] | T![self]) {
312312
let m = p.start();
313-
p.bump(IDENT);
313+
p.bump_any();
314+
m.complete(p, NAME_REF);
315+
} else {
316+
p.err_and_bump("expected identifier or `self`");
317+
}
318+
}
319+
320+
fn name_ref_or_upper_self(p: &mut Parser<'_>) {
321+
if matches!(p.current(), T![ident] | T![Self]) {
322+
let m = p.start();
323+
p.bump_any();
324+
m.complete(p, NAME_REF);
325+
} else {
326+
p.err_and_bump("expected identifier or `Self`");
327+
}
328+
}
329+
330+
const PATH_NAME_REF_KINDS: TokenSet =
331+
TokenSet::new(&[IDENT, T![self], T![super], T![crate], T![Self]]);
332+
333+
fn name_ref_mod_path(p: &mut Parser<'_>) {
334+
if p.at_ts(PATH_NAME_REF_KINDS) {
335+
let m = p.start();
336+
p.bump_any();
337+
m.complete(p, NAME_REF);
338+
} else {
339+
p.err_and_bump("expected identifier, `self`, `super`, `crate`, or `Self`");
340+
}
341+
}
342+
343+
const PATH_NAME_REF_OR_INDEX_KINDS: TokenSet =
344+
PATH_NAME_REF_KINDS.union(TokenSet::new(&[INT_NUMBER]));
345+
346+
fn name_ref_mod_path_or_index(p: &mut Parser<'_>) {
347+
if p.at_ts(PATH_NAME_REF_OR_INDEX_KINDS) {
348+
let m = p.start();
349+
p.bump_any();
314350
m.complete(p, NAME_REF);
315351
} else {
316-
p.err_and_bump("expected identifier");
352+
p.err_and_bump("expected integer, identifier, `self`, `super`, `crate`, or `Self`");
317353
}
318354
}
319355

crates/parser/src/grammar/expressions.rs

Lines changed: 38 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -449,7 +449,9 @@ fn postfix_dot_expr<const FLOAT_RECOVERY: bool>(
449449
let nth1 = if FLOAT_RECOVERY { 0 } else { 1 };
450450
let nth2 = if FLOAT_RECOVERY { 1 } else { 2 };
451451

452-
if p.nth(nth1) == IDENT && (p.nth(nth2) == T!['('] || p.nth_at(nth2, T![::])) {
452+
if PATH_NAME_REF_KINDS.contains(p.nth(nth1))
453+
&& (p.nth(nth2) == T!['('] || p.nth_at(nth2, T![::]))
454+
{
453455
return Ok(method_call_expr::<FLOAT_RECOVERY>(p, lhs));
454456
}
455457

@@ -510,21 +512,26 @@ fn index_expr(p: &mut Parser<'_>, lhs: CompletedMarker) -> CompletedMarker {
510512
// y.bar::<T>(1, 2,);
511513
// x.0.0.call();
512514
// x.0. call();
515+
// x.0()
513516
// }
514517
fn method_call_expr<const FLOAT_RECOVERY: bool>(
515518
p: &mut Parser<'_>,
516519
lhs: CompletedMarker,
517520
) -> CompletedMarker {
518521
if FLOAT_RECOVERY {
519-
assert!(p.nth(0) == IDENT && (p.nth(1) == T!['('] || p.nth_at(1, T![::])));
522+
assert!(p.at_ts(PATH_NAME_REF_KINDS) && (p.nth(1) == T!['('] || p.nth_at(1, T![::])));
520523
} else {
521-
assert!(p.at(T![.]) && p.nth(1) == IDENT && (p.nth(2) == T!['('] || p.nth_at(2, T![::])));
524+
assert!(
525+
p.at(T![.])
526+
&& PATH_NAME_REF_KINDS.contains(p.nth(1))
527+
&& (p.nth(2) == T!['('] || p.nth_at(2, T![::]))
528+
);
522529
}
523530
let m = lhs.precede(p);
524531
if !FLOAT_RECOVERY {
525532
p.bump(T![.]);
526533
}
527-
name_ref(p);
534+
name_ref_mod_path(p);
528535
generic_args::opt_generic_arg_list_expr(p);
529536
if p.at(T!['(']) {
530537
arg_list(p);
@@ -543,6 +550,8 @@ fn method_call_expr<const FLOAT_RECOVERY: bool>(
543550

544551
// test field_expr
545552
// fn foo() {
553+
// x.self;
554+
// x.Self;
546555
// x.foo;
547556
// x.0.bar;
548557
// x.0.1;
@@ -560,8 +569,8 @@ fn field_expr<const FLOAT_RECOVERY: bool>(
560569
if !FLOAT_RECOVERY {
561570
p.bump(T![.]);
562571
}
563-
if p.at(IDENT) || p.at(INT_NUMBER) {
564-
name_ref_or_index(p);
572+
if p.at_ts(PATH_NAME_REF_OR_INDEX_KINDS) {
573+
name_ref_mod_path_or_index(p);
565574
} else if p.at(FLOAT_NUMBER) {
566575
return match p.split_float(m) {
567576
(true, m) => {
@@ -679,34 +688,37 @@ pub(crate) fn record_expr_field_list(p: &mut Parser<'_>) {
679688
IDENT | INT_NUMBER if p.nth_at(1, T![::]) => {
680689
// test_err record_literal_missing_ellipsis_recovery
681690
// fn main() {
682-
// S { S::default() }
691+
// S { S::default() };
692+
// S { 0::default() };
683693
// }
684694
m.abandon(p);
685695
p.expect(T![..]);
686696
expr(p);
687697
}
698+
IDENT | INT_NUMBER if p.nth_at(1, T![..]) => {
699+
// test_err record_literal_before_ellipsis_recovery
700+
// fn main() {
701+
// S { field ..S::default() }
702+
// S { 0 ..S::default() }
703+
// }
704+
name_ref_or_index(p);
705+
p.error("expected `:`");
706+
m.complete(p, RECORD_EXPR_FIELD);
707+
}
688708
IDENT | INT_NUMBER => {
689-
if p.nth_at(1, T![..]) {
690-
// test_err record_literal_before_ellipsis_recovery
691-
// fn main() {
692-
// S { field ..S::default() }
693-
// }
709+
// test_err record_literal_field_eq_recovery
710+
// fn main() {
711+
// S { field = foo }
712+
// S { 0 = foo }
713+
// }
714+
if p.nth_at(1, T![:]) {
694715
name_ref_or_index(p);
695-
p.error("expected `:`");
696-
} else {
697-
// test_err record_literal_field_eq_recovery
698-
// fn main() {
699-
// S { field = foo }
700-
// }
701-
if p.nth_at(1, T![:]) {
702-
name_ref_or_index(p);
703-
p.bump(T![:]);
704-
} else if p.nth_at(1, T![=]) {
705-
name_ref_or_index(p);
706-
p.err_and_bump("expected `:`");
707-
}
708-
expr(p);
716+
p.bump(T![:]);
717+
} else if p.nth_at(1, T![=]) {
718+
name_ref_or_index(p);
719+
p.err_and_bump("expected `:`");
709720
}
721+
expr(p);
710722
m.complete(p, RECORD_EXPR_FIELD);
711723
}
712724
T![.] if p.at(T![..]) => {

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

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -259,13 +259,7 @@ fn builtin_expr(p: &mut Parser<'_>) -> Option<CompletedMarker> {
259259
type_(p);
260260
p.expect(T![,]);
261261
while !p.at(EOF) && !p.at(T![')']) {
262-
if p.at(IDENT) || p.at(INT_NUMBER) {
263-
name_ref_or_index(p);
264-
// } else if p.at(FLOAT_NUMBER) {
265-
// FIXME: needs float hack
266-
} else {
267-
p.err_and_bump("expected field name or number");
268-
}
262+
name_ref_mod_path_or_index(p);
269263
if !p.at(T![')']) {
270264
p.expect(T![.]);
271265
}
@@ -465,9 +459,9 @@ fn parse_clobber_abi(p: &mut Parser<'_>) {
465459

466460
fn parse_reg(p: &mut Parser<'_>) {
467461
p.expect(T!['(']);
468-
if p.at(T![ident]) {
462+
if p.at_ts(PATH_NAME_REF_KINDS) {
469463
let m = p.start();
470-
name_ref(p);
464+
name_ref_mod_path(p);
471465
m.complete(p, ASM_REG_SPEC);
472466
} else if p.at(T![string]) {
473467
let m = p.start();

crates/parser/src/grammar/generic_args.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,9 +59,9 @@ pub(crate) fn generic_arg(p: &mut Parser<'_>) -> bool {
5959

6060
// test macro_inside_generic_arg
6161
// type A = Foo<syn::Token![_]>;
62-
IDENT => {
62+
k if PATH_NAME_REF_KINDS.contains(k) => {
6363
let m = p.start();
64-
name_ref(p);
64+
name_ref_mod_path(p);
6565
paths::opt_path_type_args(p);
6666
match p.current() {
6767
T![=] => {

crates/parser/src/grammar/generic_params.rs

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,9 @@ fn type_bound(p: &mut Parser<'_>) -> bool {
145145
T![for] => types::for_type(p, false),
146146
// test precise_capturing
147147
// fn captures<'a: 'a, 'b: 'b, T>() -> impl Sized + use<'b, T, Self> {}
148+
149+
// test_err precise_capturing_invalid
150+
// type T = impl use<self, 1>;
148151
T![use] if p.nth_at(1, T![<]) => {
149152
p.bump_any();
150153
let m = p.start();
@@ -156,14 +159,10 @@ fn type_bound(p: &mut Parser<'_>) -> bool {
156159
|| "expected identifier or lifetime".into(),
157160
TokenSet::new(&[T![Self], IDENT, LIFETIME_IDENT]),
158161
|p| {
159-
if p.at(T![Self]) {
160-
let m = p.start();
161-
p.bump(T![Self]);
162-
m.complete(p, NAME_REF);
163-
} else if p.at(LIFETIME_IDENT) {
162+
if p.at(LIFETIME_IDENT) {
164163
lifetime(p);
165164
} else {
166-
name_ref(p);
165+
name_ref_or_upper_self(p);
167166
}
168167
true
169168
},

crates/parser/src/grammar/items.rs

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -254,22 +254,16 @@ fn opt_item_without_modifiers(p: &mut Parser<'_>, m: Marker) -> Result<(), Marke
254254

255255
// test extern_crate
256256
// extern crate foo;
257+
// extern crate self;
257258
fn extern_crate(p: &mut Parser<'_>, m: Marker) {
258259
p.bump(T![extern]);
259260
p.bump(T![crate]);
260261

261-
if p.at(T![self]) {
262-
// test extern_crate_self
263-
// extern crate self;
264-
let m = p.start();
265-
p.bump(T![self]);
266-
m.complete(p, NAME_REF);
267-
} else {
268-
name_ref(p);
269-
}
262+
name_ref_or_self(p);
270263

271264
// test extern_crate_rename
272265
// extern crate foo as bar;
266+
// extern crate self as bar;
273267
opt_rename(p);
274268
p.expect(T![;]);
275269
m.complete(p, EXTERN_CRATE);

crates/parser/src/grammar/paths.rs

Lines changed: 22 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -107,37 +107,32 @@ fn path_segment(p: &mut Parser<'_>, mode: Mode, first: bool) -> Option<Completed
107107
}
108108
} else {
109109
let mut empty = if first { !p.eat(T![::]) } else { true };
110-
match p.current() {
111-
IDENT => {
112-
name_ref(p);
113-
opt_path_args(p, mode);
114-
}
110+
if p.at_ts(PATH_NAME_REF_KINDS) {
115111
// test crate_path
116112
// use crate::foo;
117-
T![self] | T![super] | T![crate] | T![Self] => {
118-
let m = p.start();
119-
p.bump_any();
120-
m.complete(p, NAME_REF);
121-
}
122-
_ => {
123-
let recover_set = match mode {
124-
Mode::Use => items::ITEM_RECOVERY_SET,
125-
Mode::Attr => {
126-
items::ITEM_RECOVERY_SET.union(TokenSet::new(&[T![']'], T![=], T![#]]))
127-
}
128-
Mode::Vis => items::ITEM_RECOVERY_SET.union(TokenSet::new(&[T![')']])),
129-
Mode::Type => TYPE_PATH_SEGMENT_RECOVERY_SET,
130-
Mode::Expr => EXPR_PATH_SEGMENT_RECOVERY_SET,
131-
};
132-
empty &= p.err_recover("expected identifier", recover_set);
133-
if empty {
134-
// test_err empty_segment
135-
// use crate::;
136-
m.abandon(p);
137-
return None;
113+
name_ref_mod_path(p);
114+
opt_path_args(p, mode);
115+
} else {
116+
let recover_set = match mode {
117+
Mode::Use => items::ITEM_RECOVERY_SET,
118+
Mode::Attr => {
119+
items::ITEM_RECOVERY_SET.union(TokenSet::new(&[T![']'], T![=], T![#]]))
138120
}
121+
Mode::Vis => items::ITEM_RECOVERY_SET.union(TokenSet::new(&[T![')']])),
122+
Mode::Type => TYPE_PATH_SEGMENT_RECOVERY_SET,
123+
Mode::Expr => EXPR_PATH_SEGMENT_RECOVERY_SET,
124+
};
125+
empty &= p.err_recover(
126+
"expected identifier, `self`, `super`, `crate`, or `Self`",
127+
recover_set,
128+
);
129+
if empty {
130+
// test_err empty_segment
131+
// use crate::;
132+
m.abandon(p);
133+
return None;
139134
}
140-
};
135+
}
141136
}
142137
Some(m.complete(p, PATH_SEGMENT))
143138
}

crates/parser/test_data/generated/runner.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -210,10 +210,6 @@ mod ok {
210210
run_and_expect_no_errors("test_data/parser/inline/ok/extern_crate_rename.rs");
211211
}
212212
#[test]
213-
fn extern_crate_self() {
214-
run_and_expect_no_errors("test_data/parser/inline/ok/extern_crate_self.rs");
215-
}
216-
#[test]
217213
fn field_expr() { run_and_expect_no_errors("test_data/parser/inline/ok/field_expr.rs"); }
218214
#[test]
219215
fn fn_() { run_and_expect_no_errors("test_data/parser/inline/ok/fn_.rs"); }
@@ -774,6 +770,10 @@ mod err {
774770
run_and_expect_errors("test_data/parser/inline/err/pointer_type_no_mutability.rs");
775771
}
776772
#[test]
773+
fn precise_capturing_invalid() {
774+
run_and_expect_errors("test_data/parser/inline/err/precise_capturing_invalid.rs");
775+
}
776+
#[test]
777777
fn pub_expr() { run_and_expect_errors("test_data/parser/inline/err/pub_expr.rs"); }
778778
#[test]
779779
fn record_literal_before_ellipsis_recovery() {

crates/parser/test_data/parser/err/0004_use_path_bad_segment.rast

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,4 @@ SOURCE_FILE
1313
ERROR
1414
INT_NUMBER "92"
1515
SEMICOLON ";"
16-
error 9: expected identifier
16+
error 9: expected identifier, `self`, `super`, `crate`, or `Self`

0 commit comments

Comments
 (0)