aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_parser/src/grammar
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2020-02-07 13:13:36 +0000
committerGitHub <[email protected]>2020-02-07 13:13:36 +0000
commit6d6a995e09c74a8b1075842fb3cd7232354389ae (patch)
treee445538d8619848896b69cfae6a80672b1faceb1 /crates/ra_parser/src/grammar
parent4d0d113c7d17483f3a6e0d09db7cc0cb5ed145c4 (diff)
parent90ff2be4e820601a1d16ba5716916f7424dfa10d (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/src/grammar')
-rw-r--r--crates/ra_parser/src/grammar/expressions/atom.rs2
-rw-r--r--crates/ra_parser/src/grammar/items.rs9
-rw-r--r--crates/ra_parser/src/grammar/params.rs120
-rw-r--r--crates/ra_parser/src/grammar/paths.rs4
-rw-r--r--crates/ra_parser/src/grammar/types.rs2
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
304fn fn_def(p: &mut Parser, flavor: ItemFlavor) { 304fn 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: ()) {}
10pub(super) fn param_list(p: &mut Parser) { 10pub(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>)>(){}
16pub(super) fn param_list_opt_patterns(p: &mut Parser) { 16pub(super) fn param_list_fn_trait(p: &mut Parser) {
17 list_(p, Flavor::OptionalPattern) 17 list_(p, Flavor::FnTrait)
18} 18}
19 19
20pub(super) fn param_list_opt_types(p: &mut Parser) { 20pub(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)] 24pub(super) fn param_list_closure(p: &mut Parser) {
25enum Flavor { 25 list_(p, Flavor::Closure)
26 OptionalType,
27 OptionalPattern,
28 Normal,
29} 26}
30 27
31impl Flavor { 28#[derive(Debug, Clone, Copy)]
32 fn type_required(self) -> bool { 29enum 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
40fn list_(p: &mut Parser, flavor: Flavor) { 36fn 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
80fn value_parameter(p: &mut Parser, flavor: Flavor) { 82fn 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 }