aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
authorVille Penttinen <[email protected]>2019-03-31 08:35:55 +0100
committerVille Penttinen <[email protected]>2019-03-31 08:38:36 +0100
commit98cff6ecec1b0af2cb9cead544526a0dbf2760f5 (patch)
tree511188639f3fca256f1b4a319973fd20108e1680 /crates
parente3f9d6555beec6fb4bebf6aef3e983149f7aee3a (diff)
Change parsing bounds in path_types
Now bounds inside a path are parsed as DYN_TRAIT_TYPE, previously they would be parsed as `PATH_TYPE` followed by `TYPE_BOUND_LIST`. Basically this means `Box<T + 'f>` is now parsed almost the same as `Box<dyn T + 'f>` with the exception of not having the `dyn` keyword.
Diffstat (limited to 'crates')
-rw-r--r--crates/ra_parser/src/grammar/type_params.rs11
-rw-r--r--crates/ra_parser/src/grammar/types.rs40
2 files changed, 40 insertions, 11 deletions
diff --git a/crates/ra_parser/src/grammar/type_params.rs b/crates/ra_parser/src/grammar/type_params.rs
index 01175c0a3..42763fc87 100644
--- a/crates/ra_parser/src/grammar/type_params.rs
+++ b/crates/ra_parser/src/grammar/type_params.rs
@@ -79,16 +79,19 @@ 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 let m = p.start();
84
85 while type_bound(p) { 83 while type_bound(p) {
86 if !p.eat(PLUS) { 84 if !p.eat(PLUS) {
87 break; 85 break;
88 } 86 }
89 } 87 }
90 88
91 m.complete(p, TYPE_BOUND_LIST); 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);
92} 95}
93 96
94fn type_bound(p: &mut Parser) -> bool { 97fn type_bound(p: &mut Parser) -> bool {
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}