diff options
author | bors[bot] <bors[bot]@users.noreply.github.com> | 2018-12-17 19:43:51 +0000 |
---|---|---|
committer | bors[bot] <bors[bot]@users.noreply.github.com> | 2018-12-17 19:43:51 +0000 |
commit | 1875aa024f885f1d6119bff8aa828634b4941248 (patch) | |
tree | 273bdffe892f2eeef1850e2d3f7b1ca9ed228285 /crates/ra_syntax/src/grammar | |
parent | 8d42deeac354d1f8297d6c4d52b2707fb8d7a771 (diff) | |
parent | d0f1334226fc25a8c00ecccd64c0021e4aef9ca5 (diff) |
Merge #280
280: Fixed cast expression parsing in ra_syntax. r=matklad a=ruabmbua
Fixes #279
Related to https://github.com/rust-analyzer/rust-analyzer/pull/273
The cast expression expected any type via types::type_() function,
but the language spec does only allow TypeNoBounds (types without direct extra bounds
via `+`).
**Example:**
```rust
fn test() {
6i8 as i32 + 5;
}
```
This fails, because the types::type_() function which should parse the type after the
as keyword is greedy, and takes the plus sign after path types as extra type bounds.
My proposed fix is to replace the not implemented `type_no_plus()` just calls (`type_()`)
function, which is used at several places. The replacement is `type_with_bounds_cond(p: &mut Parser, allow_bounds: bool)`, which passes the condition to relevant sub-parsers.
This function is then called by `type_()` and the new public `type_no_bounds()`.
Co-authored-by: Roland Ruckerbauer <[email protected]>
Diffstat (limited to 'crates/ra_syntax/src/grammar')
-rw-r--r-- | crates/ra_syntax/src/grammar/expressions.rs | 6 | ||||
-rw-r--r-- | crates/ra_syntax/src/grammar/types.rs | 21 |
2 files changed, 18 insertions, 9 deletions
diff --git a/crates/ra_syntax/src/grammar/expressions.rs b/crates/ra_syntax/src/grammar/expressions.rs index 60c8602f9..a9449c7bf 100644 --- a/crates/ra_syntax/src/grammar/expressions.rs +++ b/crates/ra_syntax/src/grammar/expressions.rs | |||
@@ -368,12 +368,16 @@ fn try_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker { | |||
368 | // test cast_expr | 368 | // test cast_expr |
369 | // fn foo() { | 369 | // fn foo() { |
370 | // 82 as i32; | 370 | // 82 as i32; |
371 | // 81 as i8 + 1; | ||
372 | // 79 as i16 - 1; | ||
371 | // } | 373 | // } |
372 | fn cast_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker { | 374 | fn cast_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker { |
373 | assert!(p.at(AS_KW)); | 375 | assert!(p.at(AS_KW)); |
374 | let m = lhs.precede(p); | 376 | let m = lhs.precede(p); |
375 | p.bump(); | 377 | p.bump(); |
376 | types::type_(p); | 378 | // Use type_no_bounds(), because cast expressions are not |
379 | // allowed to have bounds. | ||
380 | types::type_no_bounds(p); | ||
377 | m.complete(p, CAST_EXPR) | 381 | m.complete(p, CAST_EXPR) |
378 | } | 382 | } |
379 | 383 | ||
diff --git a/crates/ra_syntax/src/grammar/types.rs b/crates/ra_syntax/src/grammar/types.rs index ed2718e73..811d399d4 100644 --- a/crates/ra_syntax/src/grammar/types.rs +++ b/crates/ra_syntax/src/grammar/types.rs | |||
@@ -11,6 +11,14 @@ pub(super) const TYPE_FIRST: TokenSet = token_set_union![ | |||
11 | const TYPE_RECOVERY_SET: TokenSet = token_set![R_PAREN, COMMA]; | 11 | const TYPE_RECOVERY_SET: TokenSet = token_set![R_PAREN, COMMA]; |
12 | 12 | ||
13 | pub(super) fn type_(p: &mut Parser) { | 13 | pub(super) fn type_(p: &mut Parser) { |
14 | type_with_bounds_cond(p, true); | ||
15 | } | ||
16 | |||
17 | pub(super) fn type_no_bounds(p: &mut Parser) { | ||
18 | type_with_bounds_cond(p, false); | ||
19 | } | ||
20 | |||
21 | fn type_with_bounds_cond(p: &mut Parser, allow_bounds: bool) { | ||
14 | match p.current() { | 22 | match p.current() { |
15 | L_PAREN => paren_or_tuple_type(p), | 23 | L_PAREN => paren_or_tuple_type(p), |
16 | EXCL => never_type(p), | 24 | EXCL => never_type(p), |
@@ -22,8 +30,9 @@ pub(super) fn type_(p: &mut Parser) { | |||
22 | FOR_KW => for_type(p), | 30 | FOR_KW => for_type(p), |
23 | IMPL_KW => impl_trait_type(p), | 31 | IMPL_KW => impl_trait_type(p), |
24 | DYN_KW => dyn_trait_type(p), | 32 | DYN_KW => dyn_trait_type(p), |
25 | L_ANGLE => path_type(p), | 33 | // Some path types are not allowed to have bounds (no plus) |
26 | _ if paths::is_path_start(p) => path_type(p), | 34 | L_ANGLE => path_type_(p, allow_bounds), |
35 | _ if paths::is_path_start(p) => path_type_(p, allow_bounds), | ||
27 | _ => { | 36 | _ => { |
28 | p.err_recover("expected type", TYPE_RECOVERY_SET); | 37 | p.err_recover("expected type", TYPE_RECOVERY_SET); |
29 | } | 38 | } |
@@ -35,10 +44,6 @@ pub(super) fn ascription(p: &mut Parser) { | |||
35 | type_(p) | 44 | type_(p) |
36 | } | 45 | } |
37 | 46 | ||
38 | fn type_no_plus(p: &mut Parser) { | ||
39 | type_(p); | ||
40 | } | ||
41 | |||
42 | fn paren_or_tuple_type(p: &mut Parser) { | 47 | fn paren_or_tuple_type(p: &mut Parser) { |
43 | assert!(p.at(L_PAREN)); | 48 | assert!(p.at(L_PAREN)); |
44 | let m = p.start(); | 49 | let m = p.start(); |
@@ -101,7 +106,7 @@ fn pointer_type(p: &mut Parser) { | |||
101 | } | 106 | } |
102 | }; | 107 | }; |
103 | 108 | ||
104 | type_no_plus(p); | 109 | type_no_bounds(p); |
105 | m.complete(p, POINTER_TYPE); | 110 | m.complete(p, POINTER_TYPE); |
106 | } | 111 | } |
107 | 112 | ||
@@ -147,7 +152,7 @@ fn reference_type(p: &mut Parser) { | |||
147 | p.bump(); | 152 | p.bump(); |
148 | p.eat(LIFETIME); | 153 | p.eat(LIFETIME); |
149 | p.eat(MUT_KW); | 154 | p.eat(MUT_KW); |
150 | type_no_plus(p); | 155 | type_no_bounds(p); |
151 | m.complete(p, REFERENCE_TYPE); | 156 | m.complete(p, REFERENCE_TYPE); |
152 | } | 157 | } |
153 | 158 | ||