Skip to content

Commit 06a3e92

Browse files
Fix parsing of self:: in fn param list
1 parent a6e4073 commit 06a3e92

6 files changed

Lines changed: 283 additions & 10 deletions

File tree

crates/parser/src/grammar/params.rs

Lines changed: 29 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,23 @@ fn variadic_param(p: &mut Parser<'_>) -> bool {
165165
// fn e(mut self) {}
166166
// }
167167
fn opt_self_param(p: &mut Parser<'_>, m: Marker) -> Result<(), Marker> {
168-
if p.at(T![self]) || p.at(T![mut]) && p.nth(1) == T![self] {
168+
let is_isolated_self = |p: &mut Parser<'_>, n| {
169+
// test non_isolated_self
170+
// fn f(self::S: S) {}
171+
// fn g(&self::S: &S) {}
172+
// fn h(&mut self::S: &mut S) {}
173+
174+
// test_err non_isolated_self_err
175+
// fn f(mut self::S: S) {}
176+
// fn g(&'l self::S: &S) {}
177+
// fn h(&'l mut self::S: &mut S) {}
178+
p.nth_at(n, T![self]) && !p.nth_at(n + 1, T![::])
179+
};
180+
let mut self_pos = 0;
181+
if p.at(T![mut]) {
182+
self_pos += 1;
183+
}
184+
if is_isolated_self(p, self_pos) {
169185
p.eat(T![mut]);
170186
self_as_name(p);
171187
// test arb_self_types
@@ -177,17 +193,20 @@ fn opt_self_param(p: &mut Parser<'_>, m: Marker) -> Result<(), Marker> {
177193
types::ascription(p);
178194
}
179195
} else {
180-
let la1 = p.nth(1);
181-
let la2 = p.nth(2);
182-
let la3 = p.nth(3);
183-
if !matches!(
184-
(p.current(), la1, la2, la3),
185-
(T![&], T![self], _, _)
186-
| (T![&], T![mut] | LIFETIME_IDENT, T![self], _)
187-
| (T![&], LIFETIME_IDENT, T![mut], T![self])
188-
) {
196+
if !p.at(T![&]) {
189197
return Err(m);
190198
}
199+
let mut self_pos = 1;
200+
if p.nth_at(self_pos, LIFETIME_IDENT) {
201+
self_pos += 1;
202+
}
203+
if p.nth_at(self_pos, T![mut]) {
204+
self_pos += 1;
205+
}
206+
if !is_isolated_self(p, self_pos) {
207+
return Err(m);
208+
}
209+
191210
p.bump(T![&]);
192211
if p.at(LIFETIME_IDENT) {
193212
lifetime(p);

crates/parser/test_data/generated/runner.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -492,6 +492,10 @@ mod ok {
492492
run_and_expect_no_errors("test_data/parser/inline/ok/nocontentexpr_after_item.rs");
493493
}
494494
#[test]
495+
fn non_isolated_self() {
496+
run_and_expect_no_errors("test_data/parser/inline/ok/non_isolated_self.rs");
497+
}
498+
#[test]
495499
fn not_null_pat() { run_and_expect_no_errors("test_data/parser/inline/ok/not_null_pat.rs"); }
496500
#[test]
497501
fn offset_of_parens() {
@@ -928,6 +932,10 @@ mod err {
928932
run_and_expect_errors("test_data/parser/inline/err/missing_static_type.rs");
929933
}
930934
#[test]
935+
fn non_isolated_self_err() {
936+
run_and_expect_errors("test_data/parser/inline/err/non_isolated_self_err.rs");
937+
}
938+
#[test]
931939
fn path_item_without_excl() {
932940
run_and_expect_errors("test_data/parser/inline/err/path_item_without_excl.rs");
933941
}
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
SOURCE_FILE
2+
FN
3+
FN_KW "fn"
4+
WHITESPACE " "
5+
NAME
6+
IDENT "f"
7+
PARAM_LIST
8+
L_PAREN "("
9+
PARAM
10+
IDENT_PAT
11+
MUT_KW "mut"
12+
WHITESPACE " "
13+
ERROR
14+
SELF_KW "self"
15+
COLON ":"
16+
ERROR
17+
COLON ":"
18+
PARAM
19+
IDENT_PAT
20+
NAME
21+
IDENT "S"
22+
COLON ":"
23+
WHITESPACE " "
24+
PATH_TYPE
25+
PATH
26+
PATH_SEGMENT
27+
NAME_REF
28+
IDENT "S"
29+
R_PAREN ")"
30+
WHITESPACE " "
31+
BLOCK_EXPR
32+
STMT_LIST
33+
L_CURLY "{"
34+
R_CURLY "}"
35+
WHITESPACE "\n"
36+
FN
37+
FN_KW "fn"
38+
WHITESPACE " "
39+
NAME
40+
IDENT "g"
41+
PARAM_LIST
42+
L_PAREN "("
43+
PARAM
44+
REF_PAT
45+
AMP "&"
46+
ERROR
47+
LIFETIME_IDENT "'l"
48+
WHITESPACE " "
49+
PARAM
50+
PATH_PAT
51+
PATH
52+
PATH
53+
PATH_SEGMENT
54+
NAME_REF
55+
SELF_KW "self"
56+
COLON2 "::"
57+
PATH_SEGMENT
58+
NAME_REF
59+
IDENT "S"
60+
COLON ":"
61+
WHITESPACE " "
62+
REF_TYPE
63+
AMP "&"
64+
PATH_TYPE
65+
PATH
66+
PATH_SEGMENT
67+
NAME_REF
68+
IDENT "S"
69+
R_PAREN ")"
70+
WHITESPACE " "
71+
BLOCK_EXPR
72+
STMT_LIST
73+
L_CURLY "{"
74+
R_CURLY "}"
75+
WHITESPACE "\n"
76+
FN
77+
FN_KW "fn"
78+
WHITESPACE " "
79+
NAME
80+
IDENT "h"
81+
PARAM_LIST
82+
L_PAREN "("
83+
PARAM
84+
REF_PAT
85+
AMP "&"
86+
ERROR
87+
LIFETIME_IDENT "'l"
88+
WHITESPACE " "
89+
PARAM
90+
IDENT_PAT
91+
MUT_KW "mut"
92+
WHITESPACE " "
93+
ERROR
94+
SELF_KW "self"
95+
COLON ":"
96+
ERROR
97+
COLON ":"
98+
PARAM
99+
IDENT_PAT
100+
NAME
101+
IDENT "S"
102+
COLON ":"
103+
WHITESPACE " "
104+
REF_TYPE
105+
AMP "&"
106+
MUT_KW "mut"
107+
WHITESPACE " "
108+
PATH_TYPE
109+
PATH
110+
PATH_SEGMENT
111+
NAME_REF
112+
IDENT "S"
113+
R_PAREN ")"
114+
WHITESPACE " "
115+
BLOCK_EXPR
116+
STMT_LIST
117+
L_CURLY "{"
118+
R_CURLY "}"
119+
WHITESPACE "\n"
120+
error 9: expected a name
121+
error 14: expected type
122+
error 15: expected `,`
123+
error 30: expected pattern
124+
error 32: missing type for function parameter
125+
error 32: expected `,`
126+
error 55: expected pattern
127+
error 57: missing type for function parameter
128+
error 57: expected `,`
129+
error 62: expected a name
130+
error 67: expected type
131+
error 68: expected `,`
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
fn f(mut self::S: S) {}
2+
fn g(&'l self::S: &S) {}
3+
fn h(&'l mut self::S: &mut S) {}
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
SOURCE_FILE
2+
FN
3+
FN_KW "fn"
4+
WHITESPACE " "
5+
NAME
6+
IDENT "f"
7+
PARAM_LIST
8+
L_PAREN "("
9+
PARAM
10+
PATH_PAT
11+
PATH
12+
PATH
13+
PATH_SEGMENT
14+
NAME_REF
15+
SELF_KW "self"
16+
COLON2 "::"
17+
PATH_SEGMENT
18+
NAME_REF
19+
IDENT "S"
20+
COLON ":"
21+
WHITESPACE " "
22+
PATH_TYPE
23+
PATH
24+
PATH_SEGMENT
25+
NAME_REF
26+
IDENT "S"
27+
R_PAREN ")"
28+
WHITESPACE " "
29+
BLOCK_EXPR
30+
STMT_LIST
31+
L_CURLY "{"
32+
R_CURLY "}"
33+
WHITESPACE "\n"
34+
FN
35+
FN_KW "fn"
36+
WHITESPACE " "
37+
NAME
38+
IDENT "g"
39+
PARAM_LIST
40+
L_PAREN "("
41+
PARAM
42+
REF_PAT
43+
AMP "&"
44+
PATH_PAT
45+
PATH
46+
PATH
47+
PATH_SEGMENT
48+
NAME_REF
49+
SELF_KW "self"
50+
COLON2 "::"
51+
PATH_SEGMENT
52+
NAME_REF
53+
IDENT "S"
54+
COLON ":"
55+
WHITESPACE " "
56+
REF_TYPE
57+
AMP "&"
58+
PATH_TYPE
59+
PATH
60+
PATH_SEGMENT
61+
NAME_REF
62+
IDENT "S"
63+
R_PAREN ")"
64+
WHITESPACE " "
65+
BLOCK_EXPR
66+
STMT_LIST
67+
L_CURLY "{"
68+
R_CURLY "}"
69+
WHITESPACE "\n"
70+
FN
71+
FN_KW "fn"
72+
WHITESPACE " "
73+
NAME
74+
IDENT "h"
75+
PARAM_LIST
76+
L_PAREN "("
77+
PARAM
78+
REF_PAT
79+
AMP "&"
80+
MUT_KW "mut"
81+
WHITESPACE " "
82+
PATH_PAT
83+
PATH
84+
PATH
85+
PATH_SEGMENT
86+
NAME_REF
87+
SELF_KW "self"
88+
COLON2 "::"
89+
PATH_SEGMENT
90+
NAME_REF
91+
IDENT "S"
92+
COLON ":"
93+
WHITESPACE " "
94+
REF_TYPE
95+
AMP "&"
96+
MUT_KW "mut"
97+
WHITESPACE " "
98+
PATH_TYPE
99+
PATH
100+
PATH_SEGMENT
101+
NAME_REF
102+
IDENT "S"
103+
R_PAREN ")"
104+
WHITESPACE " "
105+
BLOCK_EXPR
106+
STMT_LIST
107+
L_CURLY "{"
108+
R_CURLY "}"
109+
WHITESPACE "\n"
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
fn f(self::S: S) {}
2+
fn g(&self::S: &S) {}
3+
fn h(&mut self::S: &mut S) {}

0 commit comments

Comments
 (0)