Skip to content

Commit 1875aa0

Browse files
bors[bot]ruabmbua
andcommitted
Merge #280
280: Fixed cast expression parsing in ra_syntax. r=matklad a=ruabmbua Fixes #279 Related to #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]>
2 parents 8d42dee + d0f1334 commit 1875aa0

File tree

4 files changed

+66
-15
lines changed

4 files changed

+66
-15
lines changed

crates/ra_syntax/src/grammar/expressions.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -368,12 +368,16 @@ fn try_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker {
368368
// test cast_expr
369369
// fn foo() {
370370
// 82 as i32;
371+
// 81 as i8 + 1;
372+
// 79 as i16 - 1;
371373
// }
372374
fn cast_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker {
373375
assert!(p.at(AS_KW));
374376
let m = lhs.precede(p);
375377
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);
377381
m.complete(p, CAST_EXPR)
378382
}
379383

crates/ra_syntax/src/grammar/types.rs

+13-8
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,14 @@ pub(super) const TYPE_FIRST: TokenSet = token_set_union![
1111
const TYPE_RECOVERY_SET: TokenSet = token_set![R_PAREN, COMMA];
1212

1313
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) {
1422
match p.current() {
1523
L_PAREN => paren_or_tuple_type(p),
1624
EXCL => never_type(p),
@@ -22,8 +30,9 @@ pub(super) fn type_(p: &mut Parser) {
2230
FOR_KW => for_type(p),
2331
IMPL_KW => impl_trait_type(p),
2432
DYN_KW => dyn_trait_type(p),
25-
L_ANGLE => path_type(p),
26-
_ if paths::is_path_start(p) => path_type(p),
33+
// Some path types are not allowed to have bounds (no plus)
34+
L_ANGLE => path_type_(p, allow_bounds),
35+
_ if paths::is_path_start(p) => path_type_(p, allow_bounds),
2736
_ => {
2837
p.err_recover("expected type", TYPE_RECOVERY_SET);
2938
}
@@ -35,10 +44,6 @@ pub(super) fn ascription(p: &mut Parser) {
3544
type_(p)
3645
}
3746

38-
fn type_no_plus(p: &mut Parser) {
39-
type_(p);
40-
}
41-
4247
fn paren_or_tuple_type(p: &mut Parser) {
4348
assert!(p.at(L_PAREN));
4449
let m = p.start();
@@ -101,7 +106,7 @@ fn pointer_type(p: &mut Parser) {
101106
}
102107
};
103108

104-
type_no_plus(p);
109+
type_no_bounds(p);
105110
m.complete(p, POINTER_TYPE);
106111
}
107112

@@ -147,7 +152,7 @@ fn reference_type(p: &mut Parser) {
147152
p.bump();
148153
p.eat(LIFETIME);
149154
p.eat(MUT_KW);
150-
type_no_plus(p);
155+
type_no_bounds(p);
151156
m.complete(p, REFERENCE_TYPE);
152157
}
153158

Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
fn foo() {
22
82 as i32;
3+
81 as i8 + 1;
4+
79 as i16 - 1;
35
}

crates/ra_syntax/tests/data/parser/inline/0079_cast_expr.txt

+46-6
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
SOURCE_FILE@[0; 28)
2-
FN_DEF@[0; 27)
1+
SOURCE_FILE@[0; 65)
2+
FN_DEF@[0; 64)
33
FN_KW@[0; 2)
44
WHITESPACE@[2; 3)
55
NAME@[3; 6)
@@ -8,7 +8,7 @@ SOURCE_FILE@[0; 28)
88
L_PAREN@[6; 7)
99
R_PAREN@[7; 8)
1010
WHITESPACE@[8; 9)
11-
BLOCK@[9; 27)
11+
BLOCK@[9; 64)
1212
L_CURLY@[9; 10)
1313
WHITESPACE@[10; 15)
1414
EXPR_STMT@[15; 25)
@@ -24,6 +24,46 @@ SOURCE_FILE@[0; 28)
2424
NAME_REF@[21; 24)
2525
IDENT@[21; 24) "i32"
2626
SEMI@[24; 25)
27-
WHITESPACE@[25; 26)
28-
R_CURLY@[26; 27)
29-
WHITESPACE@[27; 28)
27+
WHITESPACE@[25; 30)
28+
EXPR_STMT@[30; 43)
29+
BIN_EXPR@[30; 42)
30+
CAST_EXPR@[30; 38)
31+
LITERAL@[30; 32)
32+
INT_NUMBER@[30; 32) "81"
33+
WHITESPACE@[32; 33)
34+
AS_KW@[33; 35)
35+
WHITESPACE@[35; 36)
36+
PATH_TYPE@[36; 38)
37+
PATH@[36; 38)
38+
PATH_SEGMENT@[36; 38)
39+
NAME_REF@[36; 38)
40+
IDENT@[36; 38) "i8"
41+
WHITESPACE@[38; 39)
42+
PLUS@[39; 40)
43+
WHITESPACE@[40; 41)
44+
LITERAL@[41; 42)
45+
INT_NUMBER@[41; 42) "1"
46+
SEMI@[42; 43)
47+
WHITESPACE@[43; 48)
48+
EXPR_STMT@[48; 62)
49+
BIN_EXPR@[48; 61)
50+
CAST_EXPR@[48; 57)
51+
LITERAL@[48; 50)
52+
INT_NUMBER@[48; 50) "79"
53+
WHITESPACE@[50; 51)
54+
AS_KW@[51; 53)
55+
WHITESPACE@[53; 54)
56+
PATH_TYPE@[54; 57)
57+
PATH@[54; 57)
58+
PATH_SEGMENT@[54; 57)
59+
NAME_REF@[54; 57)
60+
IDENT@[54; 57) "i16"
61+
WHITESPACE@[57; 58)
62+
MINUS@[58; 59)
63+
WHITESPACE@[59; 60)
64+
LITERAL@[60; 61)
65+
INT_NUMBER@[60; 61) "1"
66+
SEMI@[61; 62)
67+
WHITESPACE@[62; 63)
68+
R_CURLY@[63; 64)
69+
WHITESPACE@[64; 65)

0 commit comments

Comments
 (0)