Skip to content

Commit d5665e5

Browse files
authored
Merge pull request #19933 from Veykril/push-uyxorpyvnzsl
Better parser recovery for macro calls in type bound position
2 parents ba4b9f6 + 5d30017 commit d5665e5

File tree

6 files changed

+134
-10
lines changed

6 files changed

+134
-10
lines changed

crates/parser/src/grammar/generic_params.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,17 @@ fn type_bound(p: &mut Parser<'_>) -> bool {
201201
}
202202
if paths::is_use_path_start(p) {
203203
types::path_type_bounds(p, false);
204+
// test_err type_bounds_macro_call_recovery
205+
// fn foo<T: T![], T: T!, T: T!{}>() -> Box<T! + T!{}> {}
206+
if p.at(T![!]) {
207+
let m = p.start();
208+
p.bump(T![!]);
209+
p.error("unexpected `!` in type path, macro calls are not allowed here");
210+
if p.at_ts(TokenSet::new(&[T!['{'], T!['['], T!['(']])) {
211+
items::token_tree(p);
212+
}
213+
m.complete(p, ERROR);
214+
}
204215
} else {
205216
m.abandon(p);
206217
return false;

crates/parser/src/grammar/paths.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ fn path_segment(p: &mut Parser<'_>, mode: Mode, first: bool) -> Option<Completed
9898
types::type_(p);
9999
if p.eat(T![as]) {
100100
if is_use_path_start(p) {
101-
types::path_type(p);
101+
types::path_type_bounds(p, true);
102102
} else {
103103
p.error("expected a trait");
104104
}

crates/parser/src/grammar/types.rs

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -330,15 +330,6 @@ fn bare_dyn_trait_type(p: &mut Parser<'_>) {
330330
m.complete(p, DYN_TRAIT_TYPE);
331331
}
332332

333-
// test path_type
334-
// type A = Foo;
335-
// type B = ::Foo;
336-
// type C = self::Foo;
337-
// type D = super::Foo;
338-
pub(super) fn path_type(p: &mut Parser<'_>) {
339-
path_type_bounds(p, true);
340-
}
341-
342333
// test macro_call_type
343334
// type A = foo!();
344335
// type B = crate::foo!();
@@ -365,6 +356,11 @@ fn path_or_macro_type(p: &mut Parser<'_>, allow_bounds: bool) {
365356
}
366357
}
367358

359+
// test path_type
360+
// type A = Foo;
361+
// type B = ::Foo;
362+
// type C = self::Foo;
363+
// type D = super::Foo;
368364
pub(super) fn path_type_bounds(p: &mut Parser<'_>, allow_bounds: bool) {
369365
assert!(paths::is_path_start(p));
370366
let m = p.start();

crates/parser/test_data/generated/runner.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -876,6 +876,10 @@ mod err {
876876
run_and_expect_errors("test_data/parser/inline/err/tuple_pat_leading_comma.rs");
877877
}
878878
#[test]
879+
fn type_bounds_macro_call_recovery() {
880+
run_and_expect_errors("test_data/parser/inline/err/type_bounds_macro_call_recovery.rs");
881+
}
882+
#[test]
879883
fn type_in_array_recover() {
880884
run_and_expect_errors("test_data/parser/inline/err/type_in_array_recover.rs");
881885
}
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
SOURCE_FILE
2+
FN
3+
FN_KW "fn"
4+
WHITESPACE " "
5+
NAME
6+
IDENT "foo"
7+
GENERIC_PARAM_LIST
8+
L_ANGLE "<"
9+
TYPE_PARAM
10+
NAME
11+
IDENT "T"
12+
COLON ":"
13+
WHITESPACE " "
14+
TYPE_BOUND_LIST
15+
TYPE_BOUND
16+
PATH_TYPE
17+
PATH
18+
PATH_SEGMENT
19+
NAME_REF
20+
IDENT "T"
21+
ERROR
22+
BANG "!"
23+
TOKEN_TREE
24+
L_BRACK "["
25+
R_BRACK "]"
26+
COMMA ","
27+
WHITESPACE " "
28+
TYPE_PARAM
29+
NAME
30+
IDENT "T"
31+
COLON ":"
32+
WHITESPACE " "
33+
TYPE_BOUND_LIST
34+
TYPE_BOUND
35+
PATH_TYPE
36+
PATH
37+
PATH_SEGMENT
38+
NAME_REF
39+
IDENT "T"
40+
ERROR
41+
BANG "!"
42+
COMMA ","
43+
WHITESPACE " "
44+
TYPE_PARAM
45+
NAME
46+
IDENT "T"
47+
COLON ":"
48+
WHITESPACE " "
49+
TYPE_BOUND_LIST
50+
TYPE_BOUND
51+
PATH_TYPE
52+
PATH
53+
PATH_SEGMENT
54+
NAME_REF
55+
IDENT "T"
56+
ERROR
57+
BANG "!"
58+
TOKEN_TREE
59+
L_CURLY "{"
60+
R_CURLY "}"
61+
R_ANGLE ">"
62+
PARAM_LIST
63+
L_PAREN "("
64+
R_PAREN ")"
65+
WHITESPACE " "
66+
RET_TYPE
67+
THIN_ARROW "->"
68+
WHITESPACE " "
69+
PATH_TYPE
70+
PATH
71+
PATH_SEGMENT
72+
NAME_REF
73+
IDENT "Box"
74+
GENERIC_ARG_LIST
75+
L_ANGLE "<"
76+
TYPE_ARG
77+
DYN_TRAIT_TYPE
78+
TYPE_BOUND_LIST
79+
TYPE_BOUND
80+
MACRO_TYPE
81+
MACRO_CALL
82+
PATH
83+
PATH_SEGMENT
84+
NAME_REF
85+
IDENT "T"
86+
BANG "!"
87+
WHITESPACE " "
88+
PLUS "+"
89+
WHITESPACE " "
90+
TYPE_BOUND
91+
PATH_TYPE
92+
PATH
93+
PATH_SEGMENT
94+
NAME_REF
95+
IDENT "T"
96+
ERROR
97+
BANG "!"
98+
TOKEN_TREE
99+
L_CURLY "{"
100+
R_CURLY "}"
101+
R_ANGLE ">"
102+
WHITESPACE " "
103+
BLOCK_EXPR
104+
STMT_LIST
105+
L_CURLY "{"
106+
R_CURLY "}"
107+
WHITESPACE "\n"
108+
error 12: unexpected `!` in type path, macro calls are not allowed here
109+
error 21: unexpected `!` in type path, macro calls are not allowed here
110+
error 28: unexpected `!` in type path, macro calls are not allowed here
111+
error 43: expected `{`, `[`, `(`
112+
error 48: unexpected `!` in type path, macro calls are not allowed here
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
fn foo<T: T![], T: T!, T: T!{}>() -> Box<T! + T!{}> {}

0 commit comments

Comments
 (0)