From 01d6ed525fdbb25d47ee3df58ca0ad6e23e4b867 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Thu, 24 May 2018 17:34:09 -0400 Subject: [PATCH 1/2] restore emplacement syntax (obsolete) --- src/librustc/hir/lowering.rs | 5 +++- src/librustc_passes/ast_validation.rs | 6 +++++ src/libsyntax/ast.rs | 3 +++ src/libsyntax/feature_gate.rs | 3 +++ src/libsyntax/fold.rs | 3 +++ src/libsyntax/parse/parser.rs | 13 ++++++++++ src/libsyntax/print/pprust.rs | 7 ++++++ src/libsyntax/util/parser.rs | 16 +++++++++---- src/libsyntax/visit.rs | 4 ++++ src/test/ui/obsolete-in-place/bad.bad.stderr | 18 ++++++++++++++ src/test/ui/obsolete-in-place/bad.rs | 25 ++++++++++++++++++++ 11 files changed, 97 insertions(+), 6 deletions(-) create mode 100644 src/test/ui/obsolete-in-place/bad.bad.stderr create mode 100644 src/test/ui/obsolete-in-place/bad.rs diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 02c2aa1c71ba0..12ceecc9e9991 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -2935,7 +2935,10 @@ impl<'a> LoweringContext<'a> { 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()) } diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs index 4f239a0868ebf..dd460b36d9f95 100644 --- a/src/librustc_passes/ast_validation.rs +++ b/src/librustc_passes/ast_validation.rs @@ -172,6 +172,12 @@ impl<'a> Visitor<'a> for AstValidator<'a> { 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 ") + .emit(); + } _ => {} } diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 6ae1729295f73..a17a4e63a7d09 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -1008,6 +1008,7 @@ impl Expr { 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, @@ -1066,6 +1067,8 @@ pub enum RangeLimits { pub enum ExprKind { /// A `box x` expression. Box(P), + /// First expr is the place; second expr is the value. + ObsoleteInPlace(P, P), /// An array (`[a, b, c, d]`) Array(Vec>), /// A function call diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 3a02646d0af5f..5b821b42983a5 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -1684,6 +1684,9 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { 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, diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 1e5c6a6866bd9..ecb4332379d3a 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -1194,6 +1194,9 @@ pub fn noop_fold_expr(Expr {id, node, span, attrs}: Expr, folder: &mu 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)) } diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 5a3e5586495cf..2c246d75b52aa 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -2839,6 +2839,17 @@ impl<'a> Parser<'a> { 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); @@ -3042,6 +3053,8 @@ impl<'a> Parser<'a> { } 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, diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 585d49d7076c4..7ce1594883308 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -2057,6 +2057,13 @@ impl<'a> State<'a> { 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)?; } diff --git a/src/libsyntax/util/parser.rs b/src/libsyntax/util/parser.rs index 524f9f127f57b..51b535275d649 100644 --- a/src/libsyntax/util/parser.rs +++ b/src/libsyntax/util/parser.rs @@ -56,6 +56,8 @@ pub enum AssocOp { GreaterEqual, /// `=` Assign, + /// `<-` + ObsoleteInPlace, /// `?=` where ? is one of the BinOpToken AssignOp(BinOpToken), /// `as` @@ -84,6 +86,7 @@ impl AssocOp { 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), @@ -153,6 +156,7 @@ impl AssocOp { LAnd => 6, LOr => 5, DotDot | DotDotEq => 4, + ObsoleteInPlace => 3, Assign | AssignOp(_) => 2, } } @@ -162,7 +166,7 @@ impl AssocOp { 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, @@ -174,8 +178,8 @@ impl AssocOp { 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 } } @@ -183,7 +187,7 @@ impl AssocOp { 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 @@ -211,7 +215,7 @@ impl AssocOp { 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 } } } @@ -238,6 +242,7 @@ pub enum ExprPrecedence { Binary(BinOpKind), + ObsoleteInPlace, Cast, Type, @@ -304,6 +309,7 @@ impl ExprPrecedence { // 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, diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index b6eb649daa24d..fdf8e52bbddd7 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -660,6 +660,10 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) { 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); } diff --git a/src/test/ui/obsolete-in-place/bad.bad.stderr b/src/test/ui/obsolete-in-place/bad.bad.stderr new file mode 100644 index 0000000000000..f870c09d6e52c --- /dev/null +++ b/src/test/ui/obsolete-in-place/bad.bad.stderr @@ -0,0 +1,18 @@ +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 + +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 + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/obsolete-in-place/bad.rs b/src/test/ui/obsolete-in-place/bad.rs new file mode 100644 index 0000000000000..21993e43331a6 --- /dev/null +++ b/src/test/ui/obsolete-in-place/bad.rs @@ -0,0 +1,25 @@ +// 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 or the MIT license +// , 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() { +} From 626818fc42cbcd50305daf79f83c3cfa24d6073f Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Fri, 25 May 2018 04:46:42 -0400 Subject: [PATCH 2/2] pacify the mercilous tidy --- src/librustc_passes/ast_validation.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs index dd460b36d9f95..abbd399a944a0 100644 --- a/src/librustc_passes/ast_validation.rs +++ b/src/librustc_passes/ast_validation.rs @@ -175,7 +175,8 @@ impl<'a> Visitor<'a> for AstValidator<'a> { ExprKind::ObsoleteInPlace(..) => { self.err_handler() .struct_span_err(expr.span, "emplacement syntax is obsolete (for now, anyway)") - .note("for more information, see ") + .note("for more information, see \ + ") .emit(); } _ => {}