fn lower_expr(&mut self, e: &Expr) -> hir::Expr {
let kind = match e.node {
ExprKind::Box(ref inner) => hir::ExprBox(P(self.lower_expr(inner))),
-
+ ExprKind::ObsoleteInPlace(..) => {
+ self.sess.abort_if_errors();
+ span_bug!(e.span, "encountered ObsoleteInPlace expr during lowering");
+ }
ExprKind::Array(ref exprs) => {
hir::ExprArray(exprs.iter().map(|x| self.lower_expr(x)).collect())
}
ExprKind::InlineAsm(..) if !self.session.target.target.options.allow_asm => {
span_err!(self.session, expr.span, E0472, "asm! is unsupported on this target");
}
+ ExprKind::ObsoleteInPlace(..) => {
+ self.err_handler()
+ .struct_span_err(expr.span, "emplacement syntax is obsolete (for now, anyway)")
+ .note("for more information, see <https://github.com/rust-lang/rust/issues/27779#issuecomment-378416911>")
+ .emit();
+ }
_ => {}
}
pub fn precedence(&self) -> ExprPrecedence {
match self.node {
ExprKind::Box(_) => ExprPrecedence::Box,
+ ExprKind::ObsoleteInPlace(..) => ExprPrecedence::ObsoleteInPlace,
ExprKind::Array(_) => ExprPrecedence::Array,
ExprKind::Call(..) => ExprPrecedence::Call,
ExprKind::MethodCall(..) => ExprPrecedence::MethodCall,
pub enum ExprKind {
/// A `box x` expression.
Box(P<Expr>),
+ /// First expr is the place; second expr is the value.
+ ObsoleteInPlace(P<Expr>, P<Expr>),
/// An array (`[a, b, c, d]`)
Array(Vec<P<Expr>>),
/// A function call
gate_feature_post!(&self, type_ascription, e.span,
"type ascription is experimental");
}
+ ast::ExprKind::ObsoleteInPlace(..) => {
+ // these get a hard error in ast-validation
+ }
ast::ExprKind::Yield(..) => {
gate_feature_post!(&self, generators,
e.span,
ExprKind::Box(e) => {
ExprKind::Box(folder.fold_expr(e))
}
+ ExprKind::ObsoleteInPlace(a, b) => {
+ ExprKind::ObsoleteInPlace(folder.fold_expr(a), folder.fold_expr(b))
+ }
ExprKind::Array(exprs) => {
ExprKind::Array(folder.fold_exprs(exprs))
}
let (span, e) = self.interpolated_or_expr_span(e)?;
(lo.to(span), ExprKind::AddrOf(m, e))
}
+ token::Ident(..) if self.token.is_keyword(keywords::In) => {
+ self.bump();
+ let place = self.parse_expr_res(
+ Restrictions::NO_STRUCT_LITERAL,
+ None,
+ )?;
+ let blk = self.parse_block()?;
+ let span = blk.span;
+ let blk_expr = self.mk_expr(span, ExprKind::Block(blk, None), ThinVec::new());
+ (lo.to(span), ExprKind::ObsoleteInPlace(place, blk_expr))
+ }
token::Ident(..) if self.token.is_keyword(keywords::Box) => {
self.bump();
let e = self.parse_prefix_expr(None);
}
AssocOp::Assign =>
self.mk_expr(span, ExprKind::Assign(lhs, rhs), ThinVec::new()),
+ AssocOp::ObsoleteInPlace =>
+ self.mk_expr(span, ExprKind::ObsoleteInPlace(lhs, rhs), ThinVec::new()),
AssocOp::AssignOp(k) => {
let aop = match k {
token::Plus => BinOpKind::Add,
self.word_space("box")?;
self.print_expr_maybe_paren(expr, parser::PREC_PREFIX)?;
}
+ ast::ExprKind::ObsoleteInPlace(ref place, ref expr) => {
+ let prec = AssocOp::ObsoleteInPlace.precedence() as i8;
+ self.print_expr_maybe_paren(place, prec + 1)?;
+ self.s.space()?;
+ self.word_space("<-")?;
+ self.print_expr_maybe_paren(expr, prec)?;
+ }
ast::ExprKind::Array(ref exprs) => {
self.print_expr_vec(&exprs[..], attrs)?;
}
GreaterEqual,
/// `=`
Assign,
+ /// `<-`
+ ObsoleteInPlace,
/// `?=` where ? is one of the BinOpToken
AssignOp(BinOpToken),
/// `as`
use self::AssocOp::*;
match *t {
Token::BinOpEq(k) => Some(AssignOp(k)),
+ Token::LArrow => Some(ObsoleteInPlace),
Token::Eq => Some(Assign),
Token::BinOp(BinOpToken::Star) => Some(Multiply),
Token::BinOp(BinOpToken::Slash) => Some(Divide),
LAnd => 6,
LOr => 5,
DotDot | DotDotEq => 4,
+ ObsoleteInPlace => 3,
Assign | AssignOp(_) => 2,
}
}
use self::AssocOp::*;
// NOTE: it is a bug to have an operators that has same precedence but different fixities!
match *self {
- Assign | AssignOp(_) => Fixity::Right,
+ ObsoleteInPlace | Assign | AssignOp(_) => Fixity::Right,
As | Multiply | Divide | Modulus | Add | Subtract | ShiftLeft | ShiftRight | BitAnd |
BitXor | BitOr | Less | Greater | LessEqual | GreaterEqual | Equal | NotEqual |
LAnd | LOr | Colon => Fixity::Left,
use self::AssocOp::*;
match *self {
Less | Greater | LessEqual | GreaterEqual | Equal | NotEqual => true,
- Assign | AssignOp(_) | As | Multiply | Divide | Modulus | Add | Subtract |
- ShiftLeft | ShiftRight | BitAnd | BitXor | BitOr | LAnd | LOr |
+ ObsoleteInPlace | Assign | AssignOp(_) | As | Multiply | Divide | Modulus | Add |
+ Subtract | ShiftLeft | ShiftRight | BitAnd | BitXor | BitOr | LAnd | LOr |
DotDot | DotDotEq | Colon => false
}
}
pub fn is_assign_like(&self) -> bool {
use self::AssocOp::*;
match *self {
- Assign | AssignOp(_) => true,
+ Assign | AssignOp(_) | ObsoleteInPlace => true,
Less | Greater | LessEqual | GreaterEqual | Equal | NotEqual | As | Multiply | Divide |
Modulus | Add | Subtract | ShiftLeft | ShiftRight | BitAnd | BitXor | BitOr | LAnd |
LOr | DotDot | DotDotEq | Colon => false
BitOr => Some(BinOpKind::BitOr),
LAnd => Some(BinOpKind::And),
LOr => Some(BinOpKind::Or),
- Assign | AssignOp(_) | As | DotDot | DotDotEq | Colon => None
+ ObsoleteInPlace | Assign | AssignOp(_) | As | DotDot | DotDotEq | Colon => None
}
}
}
Binary(BinOpKind),
+ ObsoleteInPlace,
Cast,
Type,
// Binop-like expr kinds, handled by `AssocOp`.
ExprPrecedence::Binary(op) => AssocOp::from_ast_binop(op).precedence() as i8,
+ ExprPrecedence::ObsoleteInPlace => AssocOp::ObsoleteInPlace.precedence() as i8,
ExprPrecedence::Cast => AssocOp::As.precedence() as i8,
ExprPrecedence::Type => AssocOp::Colon.precedence() as i8,
ExprKind::Box(ref subexpression) => {
visitor.visit_expr(subexpression)
}
+ ExprKind::ObsoleteInPlace(ref place, ref subexpression) => {
+ visitor.visit_expr(place);
+ visitor.visit_expr(subexpression)
+ }
ExprKind::Array(ref subexpressions) => {
walk_list!(visitor, visit_expr, subexpressions);
}
--- /dev/null
+error: emplacement syntax is obsolete (for now, anyway)
+ --> $DIR/bad.rs:19:5
+ |
+LL | x <- y; //[bad]~ ERROR emplacement syntax is obsolete
+ | ^^^^^^
+ |
+ = note: for more information, see <https://github.com/rust-lang/rust/issues/27779#issuecomment-378416911>
+
+error: emplacement syntax is obsolete (for now, anyway)
+ --> $DIR/bad.rs:20:5
+ |
+LL | in(foo) { bar }; //[bad]~ ERROR emplacement syntax is obsolete
+ | ^^^^^^^^^^^^^^^
+ |
+ = note: for more information, see <https://github.com/rust-lang/rust/issues/27779#issuecomment-378416911>
+
+error: aborting due to 2 previous errors
+
--- /dev/null
+// 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.
+
+// Check that `<-` and `in` syntax gets a hard error.
+
+// revisions: good bad
+//[good] run-pass
+
+#[cfg(bad)]
+fn main() {
+ let (x, y, foo, bar);
+ x <- y; //[bad]~ ERROR emplacement syntax is obsolete
+ in(foo) { bar }; //[bad]~ ERROR emplacement syntax is obsolete
+}
+
+#[cfg(good)]
+fn main() {
+}