1951: Lower the precedence of the `as` operator. r=matklad a=goffrie

Previously, the `as` operator was being parsed like a postfix expression, and
therefore being given the highest possible precedence. That caused it to bind
more tightly than prefix operators, which it should not. Instead, parse it
somewhat like a normal binary expression with some special-casing.

Fixes #1851.

Co-authored-by: Geoffry Song <goffrie@gmail.com>
This commit is contained in:
bors[bot] 2019-10-08 08:44:26 +00:00 committed by GitHub
commit d9338dfa98
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 160 additions and 1 deletions

View file

@ -250,6 +250,7 @@ fn current_op(p: &Parser) -> (u8, SyntaxKind) {
T![!] if p.at(T![!=]) => (5, T![!=]), T![!] if p.at(T![!=]) => (5, T![!=]),
T![-] if p.at(T![-=]) => (1, T![-=]), T![-] if p.at(T![-=]) => (1, T![-=]),
T![-] => (10, T![-]), T![-] => (10, T![-]),
T![as] => (12, T![as]),
_ => NOT_AN_OP _ => NOT_AN_OP
} }
@ -278,6 +279,14 @@ fn expr_bp(p: &mut Parser, r: Restrictions, bp: u8) -> (Option<CompletedMarker>,
if op_bp < bp { if op_bp < bp {
break; break;
} }
// test as_precedence
// fn foo() {
// let _ = &1 as *const i32;
// }
if p.at(T![as]) {
lhs = cast_expr(p, lhs);
continue;
}
let m = lhs.precede(p); let m = lhs.precede(p);
p.bump(op); p.bump(op);
@ -344,6 +353,7 @@ fn lhs(p: &mut Parser, r: Restrictions) -> Option<(CompletedMarker, BlockLike)>
)); ));
} }
}; };
// parse the interior of the unary expression
expr_bp(p, r, 255); expr_bp(p, r, 255);
Some((m.complete(p, kind), BlockLike::NotBlock)) Some((m.complete(p, kind), BlockLike::NotBlock))
} }
@ -378,7 +388,6 @@ fn postfix_expr(
} }
}, },
T![?] => try_expr(p, lhs), T![?] => try_expr(p, lhs),
T![as] => cast_expr(p, lhs),
_ => break, _ => break,
}; };
allow_calls = true; allow_calls = true;

View file

@ -0,0 +1,3 @@
fn foo() {
let _ = &1 as *const i32;
}

View file

@ -0,0 +1,43 @@
SOURCE_FILE@[0; 43)
FN_DEF@[0; 42)
FN_KW@[0; 2) "fn"
WHITESPACE@[2; 3) " "
NAME@[3; 6)
IDENT@[3; 6) "foo"
PARAM_LIST@[6; 8)
L_PAREN@[6; 7) "("
R_PAREN@[7; 8) ")"
WHITESPACE@[8; 9) " "
BLOCK_EXPR@[9; 42)
BLOCK@[9; 42)
L_CURLY@[9; 10) "{"
WHITESPACE@[10; 15) "\n "
LET_STMT@[15; 40)
LET_KW@[15; 18) "let"
WHITESPACE@[18; 19) " "
PLACEHOLDER_PAT@[19; 20)
UNDERSCORE@[19; 20) "_"
WHITESPACE@[20; 21) " "
EQ@[21; 22) "="
WHITESPACE@[22; 23) " "
CAST_EXPR@[23; 39)
REF_EXPR@[23; 25)
AMP@[23; 24) "&"
LITERAL@[24; 25)
INT_NUMBER@[24; 25) "1"
WHITESPACE@[25; 26) " "
AS_KW@[26; 28) "as"
WHITESPACE@[28; 29) " "
POINTER_TYPE@[29; 39)
STAR@[29; 30) "*"
CONST_KW@[30; 35) "const"
WHITESPACE@[35; 36) " "
PATH_TYPE@[36; 39)
PATH@[36; 39)
PATH_SEGMENT@[36; 39)
NAME_REF@[36; 39)
IDENT@[36; 39) "i32"
SEMI@[39; 40) ";"
WHITESPACE@[40; 41) "\n"
R_CURLY@[41; 42) "}"
WHITESPACE@[42; 43) "\n"

View file

@ -0,0 +1,7 @@
fn foo() {
1 + *&2 + 3;
*&1 as u64;
*x(1);
&x[1];
-1..2;
}

View file

@ -0,0 +1,97 @@
SOURCE_FILE@[0; 79)
FN_DEF@[0; 78)
FN_KW@[0; 2) "fn"
WHITESPACE@[2; 3) " "
NAME@[3; 6)
IDENT@[3; 6) "foo"
PARAM_LIST@[6; 8)
L_PAREN@[6; 7) "("
R_PAREN@[7; 8) ")"
WHITESPACE@[8; 9) " "
BLOCK_EXPR@[9; 78)
BLOCK@[9; 78)
L_CURLY@[9; 10) "{"
WHITESPACE@[10; 15) "\n "
EXPR_STMT@[15; 27)
BIN_EXPR@[15; 26)
BIN_EXPR@[15; 22)
LITERAL@[15; 16)
INT_NUMBER@[15; 16) "1"
WHITESPACE@[16; 17) " "
PLUS@[17; 18) "+"
WHITESPACE@[18; 19) " "
PREFIX_EXPR@[19; 22)
STAR@[19; 20) "*"
REF_EXPR@[20; 22)
AMP@[20; 21) "&"
LITERAL@[21; 22)
INT_NUMBER@[21; 22) "2"
WHITESPACE@[22; 23) " "
PLUS@[23; 24) "+"
WHITESPACE@[24; 25) " "
LITERAL@[25; 26)
INT_NUMBER@[25; 26) "3"
SEMI@[26; 27) ";"
WHITESPACE@[27; 32) "\n "
EXPR_STMT@[32; 43)
CAST_EXPR@[32; 42)
PREFIX_EXPR@[32; 35)
STAR@[32; 33) "*"
REF_EXPR@[33; 35)
AMP@[33; 34) "&"
LITERAL@[34; 35)
INT_NUMBER@[34; 35) "1"
WHITESPACE@[35; 36) " "
AS_KW@[36; 38) "as"
WHITESPACE@[38; 39) " "
PATH_TYPE@[39; 42)
PATH@[39; 42)
PATH_SEGMENT@[39; 42)
NAME_REF@[39; 42)
IDENT@[39; 42) "u64"
SEMI@[42; 43) ";"
WHITESPACE@[43; 48) "\n "
EXPR_STMT@[48; 54)
PREFIX_EXPR@[48; 53)
STAR@[48; 49) "*"
CALL_EXPR@[49; 53)
PATH_EXPR@[49; 50)
PATH@[49; 50)
PATH_SEGMENT@[49; 50)
NAME_REF@[49; 50)
IDENT@[49; 50) "x"
ARG_LIST@[50; 53)
L_PAREN@[50; 51) "("
LITERAL@[51; 52)
INT_NUMBER@[51; 52) "1"
R_PAREN@[52; 53) ")"
SEMI@[53; 54) ";"
WHITESPACE@[54; 59) "\n "
EXPR_STMT@[59; 65)
REF_EXPR@[59; 64)
AMP@[59; 60) "&"
INDEX_EXPR@[60; 64)
PATH_EXPR@[60; 61)
PATH@[60; 61)
PATH_SEGMENT@[60; 61)
NAME_REF@[60; 61)
IDENT@[60; 61) "x"
L_BRACK@[61; 62) "["
LITERAL@[62; 63)
INT_NUMBER@[62; 63) "1"
R_BRACK@[63; 64) "]"
SEMI@[64; 65) ";"
WHITESPACE@[65; 70) "\n "
EXPR_STMT@[70; 76)
RANGE_EXPR@[70; 75)
PREFIX_EXPR@[70; 72)
MINUS@[70; 71) "-"
LITERAL@[71; 72)
INT_NUMBER@[71; 72) "1"
DOTDOT@[72; 74) ".."
LITERAL@[74; 75)
INT_NUMBER@[74; 75) "2"
SEMI@[75; 76) ";"
WHITESPACE@[76; 77) "\n"
R_CURLY@[77; 78) "}"
WHITESPACE@[78; 79) "\n"