mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-24 15:54:15 +00:00
Fix restrictions when parsing rhs of equalities
This commit is contained in:
parent
58c299f81d
commit
972c1c6a5f
@ -2666,13 +2666,18 @@ impl<'a> Parser<'a> {
|
||||
} else {
|
||||
try!(self.parse_prefix_expr())
|
||||
};
|
||||
if self.expr_is_complete(&*lhs) && min_prec == 0 {
|
||||
if self.expr_is_complete(&*lhs) {
|
||||
// Semi-statement forms are odd. See https://github.com/rust-lang/rust/issues/29071
|
||||
return Ok(lhs);
|
||||
}
|
||||
let cur_op_span = self.span;
|
||||
self.expected_tokens.push(TokenType::Operator);
|
||||
while let Some(op) = AssocOp::from_token(&self.token) {
|
||||
let restrictions = if op.is_assign_like() {
|
||||
self.restrictions & Restrictions::RESTRICTION_NO_STRUCT_LITERAL
|
||||
} else {
|
||||
self.restrictions
|
||||
};
|
||||
if op.precedence() < min_prec {
|
||||
break;
|
||||
}
|
||||
@ -2706,12 +2711,19 @@ impl<'a> Parser<'a> {
|
||||
break
|
||||
}
|
||||
|
||||
|
||||
let rhs = try!(match op.fixity() {
|
||||
Fixity::Right => self.parse_assoc_expr_with(op.precedence(), None),
|
||||
Fixity::Left => self.parse_assoc_expr_with(op.precedence() + 1, None),
|
||||
Fixity::Right => self.with_res(restrictions, |this|{
|
||||
this.parse_assoc_expr_with(op.precedence(), None)
|
||||
}),
|
||||
Fixity::Left => self.with_res(restrictions, |this|{
|
||||
this.parse_assoc_expr_with(op.precedence() + 1, None)
|
||||
}),
|
||||
// We currently have no non-associative operators that are not handled above by
|
||||
// the special cases. The code is here only for future convenience.
|
||||
Fixity::None => self.parse_assoc_expr_with(op.precedence() + 1, None),
|
||||
Fixity::None => self.with_res(restrictions, |this|{
|
||||
this.parse_assoc_expr_with(op.precedence() + 1, None)
|
||||
}),
|
||||
});
|
||||
|
||||
lhs = match op {
|
||||
@ -2974,13 +2986,22 @@ impl<'a> Parser<'a> {
|
||||
self.parse_expr_res(Restrictions::empty())
|
||||
}
|
||||
|
||||
/// Parse an expression, subject to the given restrictions
|
||||
pub fn parse_expr_res(&mut self, r: Restrictions) -> PResult<P<Expr>> {
|
||||
/// Evaluate the closure with restrictions in place.
|
||||
///
|
||||
/// After the closure is evaluated, restrictions are reset.
|
||||
pub fn with_res<F>(&mut self, r: Restrictions, f: F) -> PResult<P<Expr>>
|
||||
where F: FnOnce(&mut Self) -> PResult<P<Expr>> {
|
||||
let old = self.restrictions;
|
||||
self.restrictions = r;
|
||||
let e = try!(self.parse_assoc_expr());
|
||||
let r = f(self);
|
||||
self.restrictions = old;
|
||||
return Ok(e);
|
||||
return r;
|
||||
|
||||
}
|
||||
|
||||
/// Parse an expression, subject to the given restrictions
|
||||
pub fn parse_expr_res(&mut self, r: Restrictions) -> PResult<P<Expr>> {
|
||||
self.with_res(r, |this| this.parse_assoc_expr())
|
||||
}
|
||||
|
||||
/// Parse the RHS of a local variable declaration (e.g. '= 14;')
|
||||
|
@ -172,6 +172,16 @@ impl AssocOp {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_assign_like(&self) -> bool {
|
||||
use self::AssocOp::*;
|
||||
match *self {
|
||||
Assign | AssignOp(_) | Inplace => true,
|
||||
Less | Greater | LessEqual | GreaterEqual | Equal | NotEqual | As | Multiply | Divide |
|
||||
Modulus | Add | Subtract | ShiftLeft | ShiftRight | BitAnd | BitXor | BitOr | LAnd |
|
||||
LOr | DotDot => false
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_ast_binop(&self) -> Option<ast::BinOp_> {
|
||||
use self::AssocOp::*;
|
||||
match *self {
|
||||
|
40
src/test/run-pass/issue-29071-2.rs
Normal file
40
src/test/run-pass/issue-29071-2.rs
Normal file
@ -0,0 +1,40 @@
|
||||
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
fn t1() -> u32 {
|
||||
let x;
|
||||
x = if true { [1, 2, 3] } else { [2, 3, 4] }[0];
|
||||
x
|
||||
}
|
||||
|
||||
fn t2() -> [u32; 1] {
|
||||
if true { [1, 2, 3]; } else { [2, 3, 4]; }
|
||||
[0]
|
||||
}
|
||||
|
||||
fn t3() -> u32 {
|
||||
let x;
|
||||
x = if true { i1 as F } else { i2 as F }();
|
||||
x
|
||||
}
|
||||
|
||||
fn t4() -> () {
|
||||
if true { i1 as F; } else { i2 as F; }
|
||||
()
|
||||
}
|
||||
|
||||
type F = fn() -> u32;
|
||||
fn i1() -> u32 { 1 }
|
||||
fn i2() -> u32 { 2 }
|
||||
|
||||
fn main() {
|
||||
assert_eq!(t1(), 1);
|
||||
assert_eq!(t3(), 1);
|
||||
}
|
Loading…
Reference in New Issue
Block a user