Skip to content

Commit 6d6a995

Browse files
bors[bot]tobz1000
andauthored
Merge #3040
3040: Rework value parameter parsing r=matklad a=tobz1000 Fixes #2847. - `Fn__(...)` parameters with idents/patterns no longer parse - Trait function parameters with arbitrary patterns parse - Trait function parameters without idents/patterns no longer parse - `fn(...)` parameters no longer parse with patterns other than a single ident __Question__: The pre-existing test `param_list_opt_patterns` has been kept as-is, although the name no longer makes sense (it's testing `Fn__(...)` params, which aren't allowed patterns any more). What would be best to do about this? Co-authored-by: Toby Dimmick <[email protected]>
2 parents 4d0d113 + 90ff2be commit 6d6a995

19 files changed

+686
-259
lines changed

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,7 @@ fn lambda_expr(p: &mut Parser) -> CompletedMarker {
229229
let m = p.start();
230230
p.eat(T![async]);
231231
p.eat(T![move]);
232-
params::param_list_opt_types(p);
232+
params::param_list_closure(p);
233233
if opt_fn_ret_type(p) {
234234
if !p.at(T!['{']) {
235235
p.error("expected `{`");

crates/ra_parser/src/grammar/items.rs

+3-6
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ pub(super) fn maybe_item(p: &mut Parser, m: Marker, flavor: ItemFlavor) -> Resul
164164
// async unsafe fn foo() {}
165165
// unsafe const fn bar() {}
166166
T![fn] => {
167-
fn_def(p, flavor);
167+
fn_def(p);
168168
m.complete(p, FN_DEF);
169169
}
170170

@@ -301,7 +301,7 @@ pub(crate) fn extern_item_list(p: &mut Parser) {
301301
m.complete(p, EXTERN_ITEM_LIST);
302302
}
303303

304-
fn fn_def(p: &mut Parser, flavor: ItemFlavor) {
304+
fn fn_def(p: &mut Parser) {
305305
assert!(p.at(T![fn]));
306306
p.bump(T![fn]);
307307

@@ -311,10 +311,7 @@ fn fn_def(p: &mut Parser, flavor: ItemFlavor) {
311311
type_params::opt_type_param_list(p);
312312

313313
if p.at(T!['(']) {
314-
match flavor {
315-
ItemFlavor::Mod => params::param_list(p),
316-
ItemFlavor::Trait => params::param_list_opt_patterns(p),
317-
}
314+
params::param_list_fn_def(p);
318315
} else {
319316
p.error("expected function arguments");
320317
}

crates/ra_parser/src/grammar/params.rs

+71-49
Original file line numberDiff line numberDiff line change
@@ -7,54 +7,60 @@ use super::*;
77
// fn b(x: i32) {}
88
// fn c(x: i32, ) {}
99
// fn d(x: i32, y: ()) {}
10-
pub(super) fn param_list(p: &mut Parser) {
11-
list_(p, Flavor::Normal)
10+
pub(super) fn param_list_fn_def(p: &mut Parser) {
11+
list_(p, Flavor::FnDef)
1212
}
1313

1414
// test param_list_opt_patterns
1515
// fn foo<F: FnMut(&mut Foo<'a>)>(){}
16-
pub(super) fn param_list_opt_patterns(p: &mut Parser) {
17-
list_(p, Flavor::OptionalPattern)
16+
pub(super) fn param_list_fn_trait(p: &mut Parser) {
17+
list_(p, Flavor::FnTrait)
1818
}
1919

20-
pub(super) fn param_list_opt_types(p: &mut Parser) {
21-
list_(p, Flavor::OptionalType)
20+
pub(super) fn param_list_fn_ptr(p: &mut Parser) {
21+
list_(p, Flavor::FnPointer)
2222
}
2323

24-
#[derive(Clone, Copy, Eq, PartialEq)]
25-
enum Flavor {
26-
OptionalType,
27-
OptionalPattern,
28-
Normal,
24+
pub(super) fn param_list_closure(p: &mut Parser) {
25+
list_(p, Flavor::Closure)
2926
}
3027

31-
impl Flavor {
32-
fn type_required(self) -> bool {
33-
match self {
34-
Flavor::OptionalType => false,
35-
_ => true,
36-
}
37-
}
28+
#[derive(Debug, Clone, Copy)]
29+
enum Flavor {
30+
FnDef, // Includes trait fn params; omitted param idents are not supported
31+
FnTrait, // Params for `Fn(...)`/`FnMut(...)`/`FnOnce(...)` annotations
32+
FnPointer,
33+
Closure,
3834
}
3935

4036
fn list_(p: &mut Parser, flavor: Flavor) {
41-
let (bra, ket) = if flavor.type_required() { (T!['('], T![')']) } else { (T![|], T![|]) };
42-
assert!(p.at(bra));
37+
use Flavor::*;
38+
39+
let (bra, ket) = match flavor {
40+
Closure => (T![|], T![|]),
41+
FnDef | FnTrait | FnPointer => (T!['('], T![')']),
42+
};
43+
4344
let m = p.start();
4445
p.bump(bra);
45-
if flavor.type_required() {
46+
47+
if let FnDef = flavor {
4648
// test self_param_outer_attr
4749
// fn f(#[must_use] self) {}
4850
attributes::outer_attributes(p);
4951
opt_self_param(p);
5052
}
53+
5154
while !p.at(EOF) && !p.at(ket) {
5255
// test param_outer_arg
5356
// fn f(#[attr1] pat: Type) {}
5457
attributes::outer_attributes(p);
5558

56-
if flavor.type_required() && p.at(T![...]) {
57-
break;
59+
// test param_list_vararg
60+
// extern "C" { fn printf(format: *const i8, ...) -> i32; }
61+
match flavor {
62+
FnDef | FnPointer if p.eat(T![...]) => break,
63+
_ => (),
5864
}
5965

6066
if !p.at_ts(VALUE_PARAMETER_FIRST) {
@@ -66,11 +72,7 @@ fn list_(p: &mut Parser, flavor: Flavor) {
6672
p.expect(T![,]);
6773
}
6874
}
69-
// test param_list_vararg
70-
// extern "C" { fn printf(format: *const i8, ...) -> i32; }
71-
if flavor.type_required() {
72-
p.eat(T![...]);
73-
}
75+
7476
p.expect(ket);
7577
m.complete(p, PARAM_LIST);
7678
}
@@ -80,36 +82,56 @@ const VALUE_PARAMETER_FIRST: TokenSet = patterns::PATTERN_FIRST.union(types::TYP
8082
fn value_parameter(p: &mut Parser, flavor: Flavor) {
8183
let m = p.start();
8284
match flavor {
83-
Flavor::OptionalType | Flavor::Normal => {
85+
// test trait_fn_placeholder_parameter
86+
// trait Foo {
87+
// fn bar(_: u64, mut x: i32);
88+
// }
89+
90+
// test trait_fn_patterns
91+
// trait T {
92+
// fn f1((a, b): (usize, usize)) {}
93+
// fn f2(S { a, b }: S) {}
94+
// fn f3(NewType(a): NewType) {}
95+
// fn f4(&&a: &&usize) {}
96+
// }
97+
98+
// test fn_patterns
99+
// impl U {
100+
// fn f1((a, b): (usize, usize)) {}
101+
// fn f2(S { a, b }: S) {}
102+
// fn f3(NewType(a): NewType) {}
103+
// fn f4(&&a: &&usize) {}
104+
// }
105+
Flavor::FnDef => {
84106
patterns::pattern(p);
85-
if p.at(T![:]) && !p.at(T![::]) || flavor.type_required() {
86-
types::ascription(p)
87-
}
107+
types::ascription(p);
88108
}
89109
// test value_parameters_no_patterns
90-
// type F = Box<Fn(a: i32, &b: &i32, &mut c: &i32, ())>;
91-
Flavor::OptionalPattern => {
92-
let la0 = p.current();
93-
let la1 = p.nth(1);
94-
let la2 = p.nth(2);
95-
let la3 = p.nth(3);
96-
97-
// test trait_fn_placeholder_parameter
98-
// trait Foo {
99-
// fn bar(_: u64, mut x: i32);
100-
// }
101-
if (la0 == IDENT || la0 == T![_]) && la1 == T![:] && !p.nth_at(1, T![::])
102-
|| la0 == T![mut] && la1 == IDENT && la2 == T![:]
103-
|| la0 == T![&]
104-
&& (la1 == IDENT && la2 == T![:] && !p.nth_at(2, T![::])
105-
|| la1 == T![mut] && la2 == IDENT && la3 == T![:] && !p.nth_at(3, T![::]))
106-
{
110+
// type F = Box<Fn(i32, &i32, &i32, ())>;
111+
Flavor::FnTrait => {
112+
types::type_(p);
113+
}
114+
// test fn_pointer_param_ident_path
115+
// type Foo = fn(Bar::Baz);
116+
// type Qux = fn(baz: Bar::Baz);
117+
Flavor::FnPointer => {
118+
if p.at(IDENT) && p.nth(1) == T![:] && !p.nth_at(1, T![::]) {
107119
patterns::pattern(p);
108120
types::ascription(p);
109121
} else {
110122
types::type_(p);
111123
}
112124
}
125+
// test closure_params
126+
// fn main() {
127+
// let foo = |bar, baz: Baz, qux: Qux::Quux| ();
128+
// }
129+
Flavor::Closure => {
130+
patterns::pattern(p);
131+
if p.at(T![:]) && !p.at(T![::]) {
132+
types::ascription(p);
133+
}
134+
}
113135
}
114136
m.complete(p, PARAM);
115137
}

crates/ra_parser/src/grammar/paths.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -97,9 +97,9 @@ fn opt_path_type_args(p: &mut Parser, mode: Mode) {
9797
Mode::Use => return,
9898
Mode::Type => {
9999
// test path_fn_trait_args
100-
// type F = Box<Fn(x: i32) -> ()>;
100+
// type F = Box<Fn(i32) -> ()>;
101101
if p.at(T!['(']) {
102-
params::param_list_opt_patterns(p);
102+
params::param_list_fn_trait(p);
103103
opt_fn_ret_type(p);
104104
} else {
105105
type_args::opt_type_arg_list(p, false)

crates/ra_parser/src/grammar/types.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,7 @@ fn fn_pointer_type(p: &mut Parser) {
183183
return;
184184
}
185185
if p.at(T!['(']) {
186-
params::param_list_opt_patterns(p);
186+
params::param_list_fn_ptr(p);
187187
} else {
188188
p.error("expected parameters")
189189
}
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
type F = Box<Fn(a: i32, &b: &i32, &mut c: &i32, ())>;
1+
type F = Box<Fn(i32, &i32, &i32, ())>;
Original file line numberDiff line numberDiff line change
@@ -1,81 +1,60 @@
1-
SOURCE_FILE@[0; 54)
2-
TYPE_ALIAS_DEF@[0; 53)
1+
SOURCE_FILE@[0; 39)
2+
TYPE_ALIAS_DEF@[0; 38)
33
TYPE_KW@[0; 4) "type"
44
WHITESPACE@[4; 5) " "
55
NAME@[5; 6)
66
IDENT@[5; 6) "F"
77
WHITESPACE@[6; 7) " "
88
EQ@[7; 8) "="
99
WHITESPACE@[8; 9) " "
10-
PATH_TYPE@[9; 52)
11-
PATH@[9; 52)
12-
PATH_SEGMENT@[9; 52)
10+
PATH_TYPE@[9; 37)
11+
PATH@[9; 37)
12+
PATH_SEGMENT@[9; 37)
1313
NAME_REF@[9; 12)
1414
IDENT@[9; 12) "Box"
15-
TYPE_ARG_LIST@[12; 52)
15+
TYPE_ARG_LIST@[12; 37)
1616
L_ANGLE@[12; 13) "<"
17-
TYPE_ARG@[13; 51)
18-
PATH_TYPE@[13; 51)
19-
PATH@[13; 51)
20-
PATH_SEGMENT@[13; 51)
17+
TYPE_ARG@[13; 36)
18+
PATH_TYPE@[13; 36)
19+
PATH@[13; 36)
20+
PATH_SEGMENT@[13; 36)
2121
NAME_REF@[13; 15)
2222
IDENT@[13; 15) "Fn"
23-
PARAM_LIST@[15; 51)
23+
PARAM_LIST@[15; 36)
2424
L_PAREN@[15; 16) "("
25-
PARAM@[16; 22)
26-
BIND_PAT@[16; 17)
27-
NAME@[16; 17)
28-
IDENT@[16; 17) "a"
29-
COLON@[17; 18) ":"
30-
WHITESPACE@[18; 19) " "
31-
PATH_TYPE@[19; 22)
32-
PATH@[19; 22)
33-
PATH_SEGMENT@[19; 22)
34-
NAME_REF@[19; 22)
35-
IDENT@[19; 22) "i32"
36-
COMMA@[22; 23) ","
37-
WHITESPACE@[23; 24) " "
38-
PARAM@[24; 32)
39-
REF_PAT@[24; 26)
40-
AMP@[24; 25) "&"
41-
BIND_PAT@[25; 26)
42-
NAME@[25; 26)
43-
IDENT@[25; 26) "b"
44-
COLON@[26; 27) ":"
45-
WHITESPACE@[27; 28) " "
46-
REFERENCE_TYPE@[28; 32)
47-
AMP@[28; 29) "&"
48-
PATH_TYPE@[29; 32)
49-
PATH@[29; 32)
50-
PATH_SEGMENT@[29; 32)
51-
NAME_REF@[29; 32)
52-
IDENT@[29; 32) "i32"
53-
COMMA@[32; 33) ","
54-
WHITESPACE@[33; 34) " "
55-
PARAM@[34; 46)
56-
REF_PAT@[34; 40)
57-
AMP@[34; 35) "&"
58-
MUT_KW@[35; 38) "mut"
59-
WHITESPACE@[38; 39) " "
60-
BIND_PAT@[39; 40)
61-
NAME@[39; 40)
62-
IDENT@[39; 40) "c"
63-
COLON@[40; 41) ":"
64-
WHITESPACE@[41; 42) " "
65-
REFERENCE_TYPE@[42; 46)
66-
AMP@[42; 43) "&"
67-
PATH_TYPE@[43; 46)
68-
PATH@[43; 46)
69-
PATH_SEGMENT@[43; 46)
70-
NAME_REF@[43; 46)
71-
IDENT@[43; 46) "i32"
72-
COMMA@[46; 47) ","
73-
WHITESPACE@[47; 48) " "
74-
PARAM@[48; 50)
75-
TUPLE_TYPE@[48; 50)
76-
L_PAREN@[48; 49) "("
77-
R_PAREN@[49; 50) ")"
78-
R_PAREN@[50; 51) ")"
79-
R_ANGLE@[51; 52) ">"
80-
SEMI@[52; 53) ";"
81-
WHITESPACE@[53; 54) "\n"
25+
PARAM@[16; 19)
26+
PATH_TYPE@[16; 19)
27+
PATH@[16; 19)
28+
PATH_SEGMENT@[16; 19)
29+
NAME_REF@[16; 19)
30+
IDENT@[16; 19) "i32"
31+
COMMA@[19; 20) ","
32+
WHITESPACE@[20; 21) " "
33+
PARAM@[21; 25)
34+
REFERENCE_TYPE@[21; 25)
35+
AMP@[21; 22) "&"
36+
PATH_TYPE@[22; 25)
37+
PATH@[22; 25)
38+
PATH_SEGMENT@[22; 25)
39+
NAME_REF@[22; 25)
40+
IDENT@[22; 25) "i32"
41+
COMMA@[25; 26) ","
42+
WHITESPACE@[26; 27) " "
43+
PARAM@[27; 31)
44+
REFERENCE_TYPE@[27; 31)
45+
AMP@[27; 28) "&"
46+
PATH_TYPE@[28; 31)
47+
PATH@[28; 31)
48+
PATH_SEGMENT@[28; 31)
49+
NAME_REF@[28; 31)
50+
IDENT@[28; 31) "i32"
51+
COMMA@[31; 32) ","
52+
WHITESPACE@[32; 33) " "
53+
PARAM@[33; 35)
54+
TUPLE_TYPE@[33; 35)
55+
L_PAREN@[33; 34) "("
56+
R_PAREN@[34; 35) ")"
57+
R_PAREN@[35; 36) ")"
58+
R_ANGLE@[36; 37) ">"
59+
SEMI@[37; 38) ";"
60+
WHITESPACE@[38; 39) "\n"
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
type F = Box<Fn(x: i32) -> ()>;
1+
type F = Box<Fn(i32) -> ()>;

0 commit comments

Comments
 (0)