diff options
author | bors[bot] <bors[bot]@users.noreply.github.com> | 2019-03-31 10:11:48 +0100 |
---|---|---|
committer | bors[bot] <bors[bot]@users.noreply.github.com> | 2019-03-31 10:11:48 +0100 |
commit | c5ca49678f129045e59438df279829902034ec71 (patch) | |
tree | 3fd54185e0c064fbd6f718ac345064ce9c559efb /crates/ra_parser/src/grammar/types.rs | |
parent | 23dd53eb35ff50508d0c0fc5878a55754b12d381 (diff) | |
parent | 55dcdb7d094f473c73f87ecf997b24f8e35f2a5e (diff) |
Merge #1077
1077: Improve parsing of type bounds r=matklad a=vipentti
This adds new TYPE_BOUND_LIST and TYPE_BOUND syntax kinds. These are now used when parsing type bounds. In addition parsing paths inside a bound now does not recursively parse paths, rather they are treated as separate bounds, separated by +.
Basically now the generic params `struct S<T: 'a + ?Sized + (Copy)>;` in will be parsed as
```
TYPE_PARAM_LIST@[8; 33)
L_ANGLE@[8; 9)
TYPE_PARAM@[9; 32)
NAME@[9; 10)
IDENT@[9; 10) "T"
COLON@[10; 11)
WHITESPACE@[11; 12)
TYPE_BOUND_LIST@[12; 32)
TYPE_BOUND@[12; 14)
LIFETIME@[12; 14) "'a"
WHITESPACE@[14; 15)
PLUS@[15; 16)
WHITESPACE@[16; 17)
TYPE_BOUND@[17; 23)
QUESTION@[17; 18)
PATH_TYPE@[18; 23)
PATH@[18; 23)
PATH_SEGMENT@[18; 23)
NAME_REF@[18; 23)
IDENT@[18; 23) "Sized"
WHITESPACE@[23; 24)
PLUS@[24; 25)
WHITESPACE@[25; 26)
TYPE_BOUND@[26; 32)
L_PAREN@[26; 27)
PATH_TYPE@[27; 31)
PATH@[27; 31)
PATH_SEGMENT@[27; 31)
NAME_REF@[27; 31)
IDENT@[27; 31) "Copy"
R_PAREN@[31; 32)
R_ANGLE@[32; 33)
```
Previously it was parsed, with the paths nested:
```
TYPE_PARAM_LIST@[8; 33)
L_ANGLE@[8; 9)
TYPE_PARAM@[9; 32)
NAME@[9; 10)
IDENT@[9; 10) "T"
COLON@[10; 11)
WHITESPACE@[11; 12)
LIFETIME@[12; 14) "'a"
WHITESPACE@[14; 15)
PLUS@[15; 16)
WHITESPACE@[16; 17)
QUESTION@[17; 18)
PATH_TYPE@[18; 32)
PATH@[18; 23)
PATH_SEGMENT@[18; 23)
NAME_REF@[18; 23)
IDENT@[18; 23) "Sized"
WHITESPACE@[23; 24)
PLUS@[24; 25)
WHITESPACE@[25; 26)
L_PAREN@[26; 27)
PATH_TYPE@[27; 31)
PATH@[27; 31)
PATH_SEGMENT@[27; 31)
NAME_REF@[27; 31)
IDENT@[27; 31) "Copy"
R_PAREN@[31; 32)
R_ANGLE@[32; 33)
```
Looking for feedback.
Co-authored-by: Ville Penttinen <[email protected]>
Diffstat (limited to 'crates/ra_parser/src/grammar/types.rs')
-rw-r--r-- | crates/ra_parser/src/grammar/types.rs | 40 |
1 files changed, 33 insertions, 7 deletions
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 | ||
271 | pub(super) fn path_type_(p: &mut Parser, allow_bounds: bool) { | 271 | pub(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 | ||
287 | fn 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 | } |