diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2020-02-07 13:13:36 +0000 |
---|---|---|
committer | GitHub <[email protected]> | 2020-02-07 13:13:36 +0000 |
commit | 6d6a995e09c74a8b1075842fb3cd7232354389ae (patch) | |
tree | e445538d8619848896b69cfae6a80672b1faceb1 /crates/ra_parser | |
parent | 4d0d113c7d17483f3a6e0d09db7cc0cb5ed145c4 (diff) | |
parent | 90ff2be4e820601a1d16ba5716916f7424dfa10d (diff) |
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]>
Diffstat (limited to 'crates/ra_parser')
-rw-r--r-- | crates/ra_parser/src/grammar/expressions/atom.rs | 2 | ||||
-rw-r--r-- | crates/ra_parser/src/grammar/items.rs | 9 | ||||
-rw-r--r-- | crates/ra_parser/src/grammar/params.rs | 120 | ||||
-rw-r--r-- | crates/ra_parser/src/grammar/paths.rs | 4 | ||||
-rw-r--r-- | crates/ra_parser/src/grammar/types.rs | 2 |
5 files changed, 78 insertions, 59 deletions
diff --git a/crates/ra_parser/src/grammar/expressions/atom.rs b/crates/ra_parser/src/grammar/expressions/atom.rs index 2cc321473..f154077a8 100644 --- a/crates/ra_parser/src/grammar/expressions/atom.rs +++ b/crates/ra_parser/src/grammar/expressions/atom.rs | |||
@@ -229,7 +229,7 @@ fn lambda_expr(p: &mut Parser) -> CompletedMarker { | |||
229 | let m = p.start(); | 229 | let m = p.start(); |
230 | p.eat(T![async]); | 230 | p.eat(T![async]); |
231 | p.eat(T![move]); | 231 | p.eat(T![move]); |
232 | params::param_list_opt_types(p); | 232 | params::param_list_closure(p); |
233 | if opt_fn_ret_type(p) { | 233 | if opt_fn_ret_type(p) { |
234 | if !p.at(T!['{']) { | 234 | if !p.at(T!['{']) { |
235 | p.error("expected `{`"); | 235 | p.error("expected `{`"); |
diff --git a/crates/ra_parser/src/grammar/items.rs b/crates/ra_parser/src/grammar/items.rs index 6e23d9b72..7263c4d69 100644 --- a/crates/ra_parser/src/grammar/items.rs +++ b/crates/ra_parser/src/grammar/items.rs | |||
@@ -164,7 +164,7 @@ pub(super) fn maybe_item(p: &mut Parser, m: Marker, flavor: ItemFlavor) -> Resul | |||
164 | // async unsafe fn foo() {} | 164 | // async unsafe fn foo() {} |
165 | // unsafe const fn bar() {} | 165 | // unsafe const fn bar() {} |
166 | T![fn] => { | 166 | T![fn] => { |
167 | fn_def(p, flavor); | 167 | fn_def(p); |
168 | m.complete(p, FN_DEF); | 168 | m.complete(p, FN_DEF); |
169 | } | 169 | } |
170 | 170 | ||
@@ -301,7 +301,7 @@ pub(crate) fn extern_item_list(p: &mut Parser) { | |||
301 | m.complete(p, EXTERN_ITEM_LIST); | 301 | m.complete(p, EXTERN_ITEM_LIST); |
302 | } | 302 | } |
303 | 303 | ||
304 | fn fn_def(p: &mut Parser, flavor: ItemFlavor) { | 304 | fn fn_def(p: &mut Parser) { |
305 | assert!(p.at(T![fn])); | 305 | assert!(p.at(T![fn])); |
306 | p.bump(T![fn]); | 306 | p.bump(T![fn]); |
307 | 307 | ||
@@ -311,10 +311,7 @@ fn fn_def(p: &mut Parser, flavor: ItemFlavor) { | |||
311 | type_params::opt_type_param_list(p); | 311 | type_params::opt_type_param_list(p); |
312 | 312 | ||
313 | if p.at(T!['(']) { | 313 | if p.at(T!['(']) { |
314 | match flavor { | 314 | params::param_list_fn_def(p); |
315 | ItemFlavor::Mod => params::param_list(p), | ||
316 | ItemFlavor::Trait => params::param_list_opt_patterns(p), | ||
317 | } | ||
318 | } else { | 315 | } else { |
319 | p.error("expected function arguments"); | 316 | p.error("expected function arguments"); |
320 | } | 317 | } |
diff --git a/crates/ra_parser/src/grammar/params.rs b/crates/ra_parser/src/grammar/params.rs index c10b53316..94edc7f35 100644 --- a/crates/ra_parser/src/grammar/params.rs +++ b/crates/ra_parser/src/grammar/params.rs | |||
@@ -7,54 +7,60 @@ use super::*; | |||
7 | // fn b(x: i32) {} | 7 | // fn b(x: i32) {} |
8 | // fn c(x: i32, ) {} | 8 | // fn c(x: i32, ) {} |
9 | // fn d(x: i32, y: ()) {} | 9 | // fn d(x: i32, y: ()) {} |
10 | pub(super) fn param_list(p: &mut Parser) { | 10 | pub(super) fn param_list_fn_def(p: &mut Parser) { |
11 | list_(p, Flavor::Normal) | 11 | list_(p, Flavor::FnDef) |
12 | } | 12 | } |
13 | 13 | ||
14 | // test param_list_opt_patterns | 14 | // test param_list_opt_patterns |
15 | // fn foo<F: FnMut(&mut Foo<'a>)>(){} | 15 | // fn foo<F: FnMut(&mut Foo<'a>)>(){} |
16 | pub(super) fn param_list_opt_patterns(p: &mut Parser) { | 16 | pub(super) fn param_list_fn_trait(p: &mut Parser) { |
17 | list_(p, Flavor::OptionalPattern) | 17 | list_(p, Flavor::FnTrait) |
18 | } | 18 | } |
19 | 19 | ||
20 | pub(super) fn param_list_opt_types(p: &mut Parser) { | 20 | pub(super) fn param_list_fn_ptr(p: &mut Parser) { |
21 | list_(p, Flavor::OptionalType) | 21 | list_(p, Flavor::FnPointer) |
22 | } | 22 | } |
23 | 23 | ||
24 | #[derive(Clone, Copy, Eq, PartialEq)] | 24 | pub(super) fn param_list_closure(p: &mut Parser) { |
25 | enum Flavor { | 25 | list_(p, Flavor::Closure) |
26 | OptionalType, | ||
27 | OptionalPattern, | ||
28 | Normal, | ||
29 | } | 26 | } |
30 | 27 | ||
31 | impl Flavor { | 28 | #[derive(Debug, Clone, Copy)] |
32 | fn type_required(self) -> bool { | 29 | enum Flavor { |
33 | match self { | 30 | FnDef, // Includes trait fn params; omitted param idents are not supported |
34 | Flavor::OptionalType => false, | 31 | FnTrait, // Params for `Fn(...)`/`FnMut(...)`/`FnOnce(...)` annotations |
35 | _ => true, | 32 | FnPointer, |
36 | } | 33 | Closure, |
37 | } | ||
38 | } | 34 | } |
39 | 35 | ||
40 | fn list_(p: &mut Parser, flavor: Flavor) { | 36 | fn list_(p: &mut Parser, flavor: Flavor) { |
41 | let (bra, ket) = if flavor.type_required() { (T!['('], T![')']) } else { (T![|], T![|]) }; | 37 | use Flavor::*; |
42 | assert!(p.at(bra)); | 38 | |
39 | let (bra, ket) = match flavor { | ||
40 | Closure => (T![|], T![|]), | ||
41 | FnDef | FnTrait | FnPointer => (T!['('], T![')']), | ||
42 | }; | ||
43 | |||
43 | let m = p.start(); | 44 | let m = p.start(); |
44 | p.bump(bra); | 45 | p.bump(bra); |
45 | if flavor.type_required() { | 46 | |
47 | if let FnDef = flavor { | ||
46 | // test self_param_outer_attr | 48 | // test self_param_outer_attr |
47 | // fn f(#[must_use] self) {} | 49 | // fn f(#[must_use] self) {} |
48 | attributes::outer_attributes(p); | 50 | attributes::outer_attributes(p); |
49 | opt_self_param(p); | 51 | opt_self_param(p); |
50 | } | 52 | } |
53 | |||
51 | while !p.at(EOF) && !p.at(ket) { | 54 | while !p.at(EOF) && !p.at(ket) { |
52 | // test param_outer_arg | 55 | // test param_outer_arg |
53 | // fn f(#[attr1] pat: Type) {} | 56 | // fn f(#[attr1] pat: Type) {} |
54 | attributes::outer_attributes(p); | 57 | attributes::outer_attributes(p); |
55 | 58 | ||
56 | if flavor.type_required() && p.at(T![...]) { | 59 | // test param_list_vararg |
57 | break; | 60 | // extern "C" { fn printf(format: *const i8, ...) -> i32; } |
61 | match flavor { | ||
62 | FnDef | FnPointer if p.eat(T![...]) => break, | ||
63 | _ => (), | ||
58 | } | 64 | } |
59 | 65 | ||
60 | if !p.at_ts(VALUE_PARAMETER_FIRST) { | 66 | if !p.at_ts(VALUE_PARAMETER_FIRST) { |
@@ -66,11 +72,7 @@ fn list_(p: &mut Parser, flavor: Flavor) { | |||
66 | p.expect(T![,]); | 72 | p.expect(T![,]); |
67 | } | 73 | } |
68 | } | 74 | } |
69 | // test param_list_vararg | 75 | |
70 | // extern "C" { fn printf(format: *const i8, ...) -> i32; } | ||
71 | if flavor.type_required() { | ||
72 | p.eat(T![...]); | ||
73 | } | ||
74 | p.expect(ket); | 76 | p.expect(ket); |
75 | m.complete(p, PARAM_LIST); | 77 | m.complete(p, PARAM_LIST); |
76 | } | 78 | } |
@@ -80,36 +82,56 @@ const VALUE_PARAMETER_FIRST: TokenSet = patterns::PATTERN_FIRST.union(types::TYP | |||
80 | fn value_parameter(p: &mut Parser, flavor: Flavor) { | 82 | fn value_parameter(p: &mut Parser, flavor: Flavor) { |
81 | let m = p.start(); | 83 | let m = p.start(); |
82 | match flavor { | 84 | 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 => { | ||
84 | patterns::pattern(p); | 106 | patterns::pattern(p); |
85 | if p.at(T![:]) && !p.at(T![::]) || flavor.type_required() { | 107 | types::ascription(p); |
86 | types::ascription(p) | ||
87 | } | ||
88 | } | 108 | } |
89 | // test value_parameters_no_patterns | 109 | // test value_parameters_no_patterns |
90 | // type F = Box<Fn(a: i32, &b: &i32, &mut c: &i32, ())>; | 110 | // type F = Box<Fn(i32, &i32, &i32, ())>; |
91 | Flavor::OptionalPattern => { | 111 | Flavor::FnTrait => { |
92 | let la0 = p.current(); | 112 | types::type_(p); |
93 | let la1 = p.nth(1); | 113 | } |
94 | let la2 = p.nth(2); | 114 | // test fn_pointer_param_ident_path |
95 | let la3 = p.nth(3); | 115 | // type Foo = fn(Bar::Baz); |
96 | 116 | // type Qux = fn(baz: Bar::Baz); | |
97 | // test trait_fn_placeholder_parameter | 117 | Flavor::FnPointer => { |
98 | // trait Foo { | 118 | if p.at(IDENT) && p.nth(1) == T![:] && !p.nth_at(1, T![::]) { |
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 | { | ||
107 | patterns::pattern(p); | 119 | patterns::pattern(p); |
108 | types::ascription(p); | 120 | types::ascription(p); |
109 | } else { | 121 | } else { |
110 | types::type_(p); | 122 | types::type_(p); |
111 | } | 123 | } |
112 | } | 124 | } |
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 | } | ||
113 | } | 135 | } |
114 | m.complete(p, PARAM); | 136 | m.complete(p, PARAM); |
115 | } | 137 | } |
diff --git a/crates/ra_parser/src/grammar/paths.rs b/crates/ra_parser/src/grammar/paths.rs index ca8e075a1..f5bf3d7ce 100644 --- a/crates/ra_parser/src/grammar/paths.rs +++ b/crates/ra_parser/src/grammar/paths.rs | |||
@@ -97,9 +97,9 @@ fn opt_path_type_args(p: &mut Parser, mode: Mode) { | |||
97 | Mode::Use => return, | 97 | Mode::Use => return, |
98 | Mode::Type => { | 98 | Mode::Type => { |
99 | // test path_fn_trait_args | 99 | // test path_fn_trait_args |
100 | // type F = Box<Fn(x: i32) -> ()>; | 100 | // type F = Box<Fn(i32) -> ()>; |
101 | if p.at(T!['(']) { | 101 | if p.at(T!['(']) { |
102 | params::param_list_opt_patterns(p); | 102 | params::param_list_fn_trait(p); |
103 | opt_fn_ret_type(p); | 103 | opt_fn_ret_type(p); |
104 | } else { | 104 | } else { |
105 | type_args::opt_type_arg_list(p, false) | 105 | type_args::opt_type_arg_list(p, false) |
diff --git a/crates/ra_parser/src/grammar/types.rs b/crates/ra_parser/src/grammar/types.rs index 9b2e440fb..2c00bce80 100644 --- a/crates/ra_parser/src/grammar/types.rs +++ b/crates/ra_parser/src/grammar/types.rs | |||
@@ -183,7 +183,7 @@ fn fn_pointer_type(p: &mut Parser) { | |||
183 | return; | 183 | return; |
184 | } | 184 | } |
185 | if p.at(T!['(']) { | 185 | if p.at(T!['(']) { |
186 | params::param_list_opt_patterns(p); | 186 | params::param_list_fn_ptr(p); |
187 | } else { | 187 | } else { |
188 | p.error("expected parameters") | 188 | p.error("expected parameters") |
189 | } | 189 | } |