Skip to content

Commit 972c1c6

Browse files
committed
Fix restrictions when parsing rhs of equalities
1 parent 58c299f commit 972c1c6

File tree

3 files changed

+79
-8
lines changed

3 files changed

+79
-8
lines changed

src/libsyntax/parse/parser.rs

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2666,13 +2666,18 @@ impl<'a> Parser<'a> {
26662666
} else {
26672667
try!(self.parse_prefix_expr())
26682668
};
2669-
if self.expr_is_complete(&*lhs) && min_prec == 0 {
2669+
if self.expr_is_complete(&*lhs) {
26702670
// Semi-statement forms are odd. See https://github.com/rust-lang/rust/issues/29071
26712671
return Ok(lhs);
26722672
}
26732673
let cur_op_span = self.span;
26742674
self.expected_tokens.push(TokenType::Operator);
26752675
while let Some(op) = AssocOp::from_token(&self.token) {
2676+
let restrictions = if op.is_assign_like() {
2677+
self.restrictions & Restrictions::RESTRICTION_NO_STRUCT_LITERAL
2678+
} else {
2679+
self.restrictions
2680+
};
26762681
if op.precedence() < min_prec {
26772682
break;
26782683
}
@@ -2706,12 +2711,19 @@ impl<'a> Parser<'a> {
27062711
break
27072712
}
27082713

2714+
27092715
let rhs = try!(match op.fixity() {
2710-
Fixity::Right => self.parse_assoc_expr_with(op.precedence(), None),
2711-
Fixity::Left => self.parse_assoc_expr_with(op.precedence() + 1, None),
2716+
Fixity::Right => self.with_res(restrictions, |this|{
2717+
this.parse_assoc_expr_with(op.precedence(), None)
2718+
}),
2719+
Fixity::Left => self.with_res(restrictions, |this|{
2720+
this.parse_assoc_expr_with(op.precedence() + 1, None)
2721+
}),
27122722
// We currently have no non-associative operators that are not handled above by
27132723
// the special cases. The code is here only for future convenience.
2714-
Fixity::None => self.parse_assoc_expr_with(op.precedence() + 1, None),
2724+
Fixity::None => self.with_res(restrictions, |this|{
2725+
this.parse_assoc_expr_with(op.precedence() + 1, None)
2726+
}),
27152727
});
27162728

27172729
lhs = match op {
@@ -2974,13 +2986,22 @@ impl<'a> Parser<'a> {
29742986
self.parse_expr_res(Restrictions::empty())
29752987
}
29762988

2977-
/// Parse an expression, subject to the given restrictions
2978-
pub fn parse_expr_res(&mut self, r: Restrictions) -> PResult<P<Expr>> {
2989+
/// Evaluate the closure with restrictions in place.
2990+
///
2991+
/// After the closure is evaluated, restrictions are reset.
2992+
pub fn with_res<F>(&mut self, r: Restrictions, f: F) -> PResult<P<Expr>>
2993+
where F: FnOnce(&mut Self) -> PResult<P<Expr>> {
29792994
let old = self.restrictions;
29802995
self.restrictions = r;
2981-
let e = try!(self.parse_assoc_expr());
2996+
let r = f(self);
29822997
self.restrictions = old;
2983-
return Ok(e);
2998+
return r;
2999+
3000+
}
3001+
3002+
/// Parse an expression, subject to the given restrictions
3003+
pub fn parse_expr_res(&mut self, r: Restrictions) -> PResult<P<Expr>> {
3004+
self.with_res(r, |this| this.parse_assoc_expr())
29843005
}
29853006

29863007
/// Parse the RHS of a local variable declaration (e.g. '= 14;')

src/libsyntax/util/parser.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,16 @@ impl AssocOp {
172172
}
173173
}
174174

175+
pub fn is_assign_like(&self) -> bool {
176+
use self::AssocOp::*;
177+
match *self {
178+
Assign | AssignOp(_) | Inplace => true,
179+
Less | Greater | LessEqual | GreaterEqual | Equal | NotEqual | As | Multiply | Divide |
180+
Modulus | Add | Subtract | ShiftLeft | ShiftRight | BitAnd | BitXor | BitOr | LAnd |
181+
LOr | DotDot => false
182+
}
183+
}
184+
175185
pub fn to_ast_binop(&self) -> Option<ast::BinOp_> {
176186
use self::AssocOp::*;
177187
match *self {

src/test/run-pass/issue-29071-2.rs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
fn t1() -> u32 {
12+
let x;
13+
x = if true { [1, 2, 3] } else { [2, 3, 4] }[0];
14+
x
15+
}
16+
17+
fn t2() -> [u32; 1] {
18+
if true { [1, 2, 3]; } else { [2, 3, 4]; }
19+
[0]
20+
}
21+
22+
fn t3() -> u32 {
23+
let x;
24+
x = if true { i1 as F } else { i2 as F }();
25+
x
26+
}
27+
28+
fn t4() -> () {
29+
if true { i1 as F; } else { i2 as F; }
30+
()
31+
}
32+
33+
type F = fn() -> u32;
34+
fn i1() -> u32 { 1 }
35+
fn i2() -> u32 { 2 }
36+
37+
fn main() {
38+
assert_eq!(t1(), 1);
39+
assert_eq!(t3(), 1);
40+
}

0 commit comments

Comments
 (0)