aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_parser/src/grammar
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_parser/src/grammar')
-rw-r--r--crates/ra_parser/src/grammar/expressions.rs1
-rw-r--r--crates/ra_parser/src/grammar/expressions/atom.rs16
-rw-r--r--crates/ra_parser/src/grammar/items.rs2
-rw-r--r--crates/ra_parser/src/grammar/items/traits.rs1
-rw-r--r--crates/ra_parser/src/grammar/type_args.rs1
-rw-r--r--crates/ra_parser/src/grammar/type_params.rs45
-rw-r--r--crates/ra_parser/src/grammar/types.rs40
7 files changed, 81 insertions, 25 deletions
diff --git a/crates/ra_parser/src/grammar/expressions.rs b/crates/ra_parser/src/grammar/expressions.rs
index 73e1acd5a..bf5d6544d 100644
--- a/crates/ra_parser/src/grammar/expressions.rs
+++ b/crates/ra_parser/src/grammar/expressions.rs
@@ -410,6 +410,7 @@ fn try_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker {
410// 82 as i32; 410// 82 as i32;
411// 81 as i8 + 1; 411// 81 as i8 + 1;
412// 79 as i16 - 1; 412// 79 as i16 - 1;
413// 0x36 as u8 <= 0x37;
413// } 414// }
414fn cast_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker { 415fn cast_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker {
415 assert!(p.at(AS_KW)); 416 assert!(p.at(AS_KW));
diff --git a/crates/ra_parser/src/grammar/expressions/atom.rs b/crates/ra_parser/src/grammar/expressions/atom.rs
index a23977bfb..d0feed616 100644
--- a/crates/ra_parser/src/grammar/expressions/atom.rs
+++ b/crates/ra_parser/src/grammar/expressions/atom.rs
@@ -68,6 +68,7 @@ pub(super) fn atom_expr(p: &mut Parser, r: Restrictions) -> Option<(CompletedMar
68 L_BRACK => array_expr(p), 68 L_BRACK => array_expr(p),
69 PIPE => lambda_expr(p), 69 PIPE => lambda_expr(p),
70 MOVE_KW if la == PIPE => lambda_expr(p), 70 MOVE_KW if la == PIPE => lambda_expr(p),
71 ASYNC_KW if la == PIPE || (la == MOVE_KW && p.nth(2) == PIPE) => lambda_expr(p),
71 IF_KW => if_expr(p), 72 IF_KW => if_expr(p),
72 73
73 LOOP_KW => loop_expr(p, None), 74 LOOP_KW => loop_expr(p, None),
@@ -92,10 +93,10 @@ pub(super) fn atom_expr(p: &mut Parser, r: Restrictions) -> Option<(CompletedMar
92 } 93 }
93 } 94 }
94 } 95 }
95 96 ASYNC_KW if la == L_CURLY || (la == MOVE_KW && p.nth(2) == L_CURLY) => {
96 ASYNC_KW if la == L_CURLY => {
97 let m = p.start(); 97 let m = p.start();
98 p.bump(); 98 p.bump();
99 p.eat(MOVE_KW);
99 block_expr(p, Some(m)) 100 block_expr(p, Some(m))
100 } 101 }
101 MATCH_KW => match_expr(p), 102 MATCH_KW => match_expr(p),
@@ -190,10 +191,19 @@ fn array_expr(p: &mut Parser) -> CompletedMarker {
190// || -> i32 { 92 }; 191// || -> i32 { 92 };
191// |x| x; 192// |x| x;
192// move |x: i32,| x; 193// move |x: i32,| x;
194// async || {};
195// move || {};
196// async move || {};
193// } 197// }
194fn lambda_expr(p: &mut Parser) -> CompletedMarker { 198fn lambda_expr(p: &mut Parser) -> CompletedMarker {
195 assert!(p.at(PIPE) || (p.at(MOVE_KW) && p.nth(1) == PIPE)); 199 assert!(
200 p.at(PIPE)
201 || (p.at(MOVE_KW) && p.nth(1) == PIPE)
202 || (p.at(ASYNC_KW) && p.nth(1) == PIPE)
203 || (p.at(ASYNC_KW) && p.nth(1) == MOVE_KW && p.nth(2) == PIPE)
204 );
196 let m = p.start(); 205 let m = p.start();
206 p.eat(ASYNC_KW);
197 p.eat(MOVE_KW); 207 p.eat(MOVE_KW);
198 params::param_list_opt_types(p); 208 params::param_list_opt_types(p);
199 if opt_fn_ret_type(p) { 209 if opt_fn_ret_type(p) {
diff --git a/crates/ra_parser/src/grammar/items.rs b/crates/ra_parser/src/grammar/items.rs
index c24e6d1e0..c4b8ef3c7 100644
--- a/crates/ra_parser/src/grammar/items.rs
+++ b/crates/ra_parser/src/grammar/items.rs
@@ -82,7 +82,7 @@ pub(super) fn maybe_item(p: &mut Parser, m: Marker, flavor: ItemFlavor) -> Resul
82 // test_err async_without_semicolon 82 // test_err async_without_semicolon
83 // fn foo() { let _ = async {} } 83 // fn foo() { let _ = async {} }
84 has_mods |= p.eat(CONST_KW); 84 has_mods |= p.eat(CONST_KW);
85 if p.at(ASYNC_KW) && p.nth(1) != L_CURLY { 85 if p.at(ASYNC_KW) && p.nth(1) != L_CURLY && p.nth(1) != MOVE_KW && p.nth(1) != PIPE {
86 p.eat(ASYNC_KW); 86 p.eat(ASYNC_KW);
87 has_mods = true; 87 has_mods = true;
88 } 88 }
diff --git a/crates/ra_parser/src/grammar/items/traits.rs b/crates/ra_parser/src/grammar/items/traits.rs
index f49615f6b..d03a6be0d 100644
--- a/crates/ra_parser/src/grammar/items/traits.rs
+++ b/crates/ra_parser/src/grammar/items/traits.rs
@@ -2,6 +2,7 @@ use super::*;
2 2
3// test trait_item 3// test trait_item
4// trait T<U>: Hash + Clone where U: Copy {} 4// trait T<U>: Hash + Clone where U: Copy {}
5// trait X<U: Debug + Display>: Hash + Clone where U: Copy {}
5pub(super) fn trait_def(p: &mut Parser) { 6pub(super) fn trait_def(p: &mut Parser) {
6 assert!(p.at(TRAIT_KW)); 7 assert!(p.at(TRAIT_KW));
7 p.bump(); 8 p.bump();
diff --git a/crates/ra_parser/src/grammar/type_args.rs b/crates/ra_parser/src/grammar/type_args.rs
index f889419c5..684976b99 100644
--- a/crates/ra_parser/src/grammar/type_args.rs
+++ b/crates/ra_parser/src/grammar/type_args.rs
@@ -8,6 +8,7 @@ pub(super) fn opt_type_arg_list(p: &mut Parser, colon_colon_required: bool) {
8 p.bump(); 8 p.bump();
9 p.bump(); 9 p.bump();
10 } 10 }
11 (false, L_ANGLE, EQ) => return,
11 (false, L_ANGLE, _) => { 12 (false, L_ANGLE, _) => {
12 m = p.start(); 13 m = p.start();
13 p.bump(); 14 p.bump();
diff --git a/crates/ra_parser/src/grammar/type_params.rs b/crates/ra_parser/src/grammar/type_params.rs
index 40f998682..07d9b0792 100644
--- a/crates/ra_parser/src/grammar/type_params.rs
+++ b/crates/ra_parser/src/grammar/type_params.rs
@@ -79,23 +79,40 @@ fn lifetime_bounds(p: &mut Parser) {
79 } 79 }
80} 80}
81 81
82pub(super) fn bounds_without_colon(p: &mut Parser) { 82pub(super) fn bounds_without_colon_m(p: &mut Parser, marker: Marker) -> CompletedMarker {
83 loop { 83 while type_bound(p) {
84 let has_paren = p.eat(L_PAREN);
85 p.eat(QUESTION);
86 match p.current() {
87 LIFETIME => p.bump(),
88 FOR_KW => types::for_type(p),
89 _ if paths::is_path_start(p) => types::path_type(p),
90 _ => break,
91 }
92 if has_paren {
93 p.expect(R_PAREN);
94 }
95 if !p.eat(PLUS) { 84 if !p.eat(PLUS) {
96 break; 85 break;
97 } 86 }
98 } 87 }
88
89 marker.complete(p, TYPE_BOUND_LIST)
90}
91
92pub(super) fn bounds_without_colon(p: &mut Parser) {
93 let m = p.start();
94 bounds_without_colon_m(p, m);
95}
96
97fn type_bound(p: &mut Parser) -> bool {
98 let m = p.start();
99 let has_paren = p.eat(L_PAREN);
100 p.eat(QUESTION);
101 match p.current() {
102 LIFETIME => p.bump(),
103 FOR_KW => types::for_type(p),
104 _ if paths::is_path_start(p) => types::path_type_(p, false),
105 _ => {
106 m.abandon(p);
107 return false;
108 }
109 }
110 if has_paren {
111 p.expect(R_PAREN);
112 }
113 m.complete(p, TYPE_BOUND);
114
115 true
99} 116}
100 117
101// test where_clause 118// test where_clause
@@ -148,7 +165,7 @@ fn where_predicate(p: &mut Parser) {
148 LIFETIME => { 165 LIFETIME => {
149 p.bump(); 166 p.bump();
150 if p.at(COLON) { 167 if p.at(COLON) {
151 lifetime_bounds(p); 168 bounds(p);
152 } else { 169 } else {
153 p.error("expected colon"); 170 p.error("expected colon");
154 } 171 }
diff --git a/crates/ra_parser/src/grammar/types.rs b/crates/ra_parser/src/grammar/types.rs
index fdd4f2c52..a46da9b44 100644
--- a/crates/ra_parser/src/grammar/types.rs
+++ b/crates/ra_parser/src/grammar/types.rs
@@ -261,21 +261,47 @@ fn path_or_macro_type_(p: &mut Parser, allow_bounds: bool) {
261 PATH_TYPE 261 PATH_TYPE
262 }; 262 };
263 263
264 if allow_bounds && p.eat(PLUS) { 264 let path = m.complete(p, kind);
265 type_params::bounds_without_colon(p);
266 }
267 265
268 m.complete(p, kind); 266 if allow_bounds {
267 opt_path_type_bounds_as_dyn_trait_type(p, path);
268 }
269} 269}
270 270
271pub(super) fn path_type_(p: &mut Parser, allow_bounds: bool) { 271pub(super) fn path_type_(p: &mut Parser, allow_bounds: bool) {
272 assert!(paths::is_path_start(p) || p.at(L_ANGLE)); 272 assert!(paths::is_path_start(p) || p.at(L_ANGLE));
273 let m = p.start(); 273 let m = p.start();
274 paths::type_path(p); 274 paths::type_path(p);
275
275 // test path_type_with_bounds 276 // test path_type_with_bounds
276 // fn foo() -> Box<T + 'f> {} 277 // fn foo() -> Box<T + 'f> {}
277 if allow_bounds && p.eat(PLUS) { 278 // fn foo() -> Box<dyn T + 'f> {}
278 type_params::bounds_without_colon(p); 279 let path = m.complete(p, PATH_TYPE);
280 if allow_bounds {
281 opt_path_type_bounds_as_dyn_trait_type(p, path);
279 } 282 }
280 m.complete(p, PATH_TYPE); 283}
284
285/// This turns a parsed PATH_TYPE optionally into a DYN_TRAIT_TYPE
286/// with a TYPE_BOUND_LIST
287fn opt_path_type_bounds_as_dyn_trait_type(p: &mut Parser, path_type_marker: CompletedMarker) {
288 if !p.at(PLUS) {
289 return;
290 }
291
292 // First create a TYPE_BOUND from the completed PATH_TYPE
293 let m = path_type_marker.precede(p).complete(p, TYPE_BOUND);
294
295 // Next setup a marker for the TYPE_BOUND_LIST
296 let m = m.precede(p);
297
298 // This gets consumed here so it gets properly set
299 // in the TYPE_BOUND_LIST
300 p.eat(PLUS);
301
302 // Parse rest of the bounds into the TYPE_BOUND_LIST
303 let m = type_params::bounds_without_colon_m(p, m);
304
305 // Finally precede everything with DYN_TRAIT_TYPE
306 m.precede(p).complete(p, DYN_TRAIT_TYPE);
281} 307}