From a5c52c72ae3c1d8b3896756541b115a1d5ea94b7 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Mon, 17 Dec 2018 04:57:32 +0300 Subject: [PATCH] AST/HIR: Introduce `ExprKind::Err` for better error recovery in the front-end --- src/librustc/cfg/construct.rs | 3 ++- src/librustc/hir/intravisit.rs | 1 + src/librustc/hir/lowering.rs | 2 ++ src/librustc/hir/mod.rs | 7 ++++++- src/librustc/hir/print.rs | 9 ++++++++- src/librustc/ich/impls_hir.rs | 3 ++- src/librustc/middle/expr_use_visitor.rs | 3 ++- src/librustc/middle/liveness.rs | 6 ++++-- src/librustc/middle/mem_categorization.rs | 2 +- src/librustc_mir/hair/cx/expr.rs | 1 + src/librustc_passes/rvalue_promotion.rs | 3 ++- src/librustc_typeck/check/mod.rs | 3 +++ src/libsyntax/ast.rs | 4 ++++ src/libsyntax/fold.rs | 1 + src/libsyntax/print/pprust.rs | 9 ++++++++- src/libsyntax/util/parser.rs | 4 +++- src/libsyntax/visit.rs | 1 + 17 files changed, 51 insertions(+), 11 deletions(-) diff --git a/src/librustc/cfg/construct.rs b/src/librustc/cfg/construct.rs index b6d3b6665be..978d20ea947 100644 --- a/src/librustc/cfg/construct.rs +++ b/src/librustc/cfg/construct.rs @@ -392,7 +392,8 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { hir::ExprKind::Closure(..) | hir::ExprKind::Lit(..) | - hir::ExprKind::Path(_) => { + hir::ExprKind::Path(_) | + hir::ExprKind::Err => { self.straightline(expr, pred, None::.iter()) } } diff --git a/src/librustc/hir/intravisit.rs b/src/librustc/hir/intravisit.rs index 17b001a5ce8..2f0a95445a8 100644 --- a/src/librustc/hir/intravisit.rs +++ b/src/librustc/hir/intravisit.rs @@ -1099,6 +1099,7 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) { ExprKind::Yield(ref subexpression) => { visitor.visit_expr(subexpression); } + ExprKind::Err => {} } } diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 039b525c864..59b9f83c242 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -4117,6 +4117,8 @@ impl<'a> LoweringContext<'a> { hir::ExprKind::Yield(P(expr)) } + ExprKind::Err => hir::ExprKind::Err, + // Desugar `ExprIfLet` // from: `if let = []` ExprKind::IfLet(ref pats, ref sub_expr, ref body, ref else_opt) => { diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 30817433823..601d310fc3a 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -1362,6 +1362,7 @@ impl Expr { ExprKind::Struct(..) => ExprPrecedence::Struct, ExprKind::Repeat(..) => ExprPrecedence::Repeat, ExprKind::Yield(..) => ExprPrecedence::Yield, + ExprKind::Err => ExprPrecedence::Err, } } @@ -1412,7 +1413,8 @@ impl Expr { ExprKind::AddrOf(..) | ExprKind::Binary(..) | ExprKind::Yield(..) | - ExprKind::Cast(..) => { + ExprKind::Cast(..) | + ExprKind::Err => { false } } @@ -1525,6 +1527,9 @@ pub enum ExprKind { /// A suspension point for generators. This is `yield ` in Rust. Yield(P), + + /// Placeholder for an expression that wasn't syntactically well formed in some way. + Err, } /// Optionally `Self`-qualified value/type path or associated extension. diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs index 9c869998d54..e19da011be1 100644 --- a/src/librustc/hir/print.rs +++ b/src/librustc/hir/print.rs @@ -430,7 +430,9 @@ impl<'a> State<'a> { self.s.word("_")?; } hir::TyKind::Err => { - self.s.word("?")?; + self.popen()?; + self.s.word("/*ERROR*/")?; + self.pclose()?; } } self.end() @@ -1540,6 +1542,11 @@ impl<'a> State<'a> { self.word_space("yield")?; self.print_expr_maybe_paren(&expr, parser::PREC_JUMP)?; } + hir::ExprKind::Err => { + self.popen()?; + self.s.word("/*ERROR*/")?; + self.pclose()?; + } } self.ann.post(self, AnnNode::Expr(expr))?; self.end() diff --git a/src/librustc/ich/impls_hir.rs b/src/librustc/ich/impls_hir.rs index f5d6827e89b..006f11d51e4 100644 --- a/src/librustc/ich/impls_hir.rs +++ b/src/librustc/ich/impls_hir.rs @@ -592,7 +592,8 @@ impl_stable_hash_for!(enum hir::ExprKind { InlineAsm(asm, inputs, outputs), Struct(path, fields, base), Repeat(val, times), - Yield(val) + Yield(val), + Err }); impl_stable_hash_for!(enum hir::LocalSource { diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index e6035d42f06..f9bcbb32229 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -479,7 +479,8 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { } hir::ExprKind::Continue(..) | - hir::ExprKind::Lit(..) => {} + hir::ExprKind::Lit(..) | + hir::ExprKind::Err => {} hir::ExprKind::Loop(ref blk, _, _) => { self.walk_block(&blk); diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index 4b75840263e..a78cf1a471b 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -515,6 +515,7 @@ fn visit_expr<'a, 'tcx>(ir: &mut IrMaps<'a, 'tcx>, expr: &'tcx Expr) { hir::ExprKind::Box(..) | hir::ExprKind::Yield(..) | hir::ExprKind::Type(..) | + hir::ExprKind::Err | hir::ExprKind::Path(hir::QPath::TypeRelative(..)) => { intravisit::walk_expr(ir, expr); } @@ -1254,7 +1255,8 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { self.propagate_through_exprs(inputs, succ) } - hir::ExprKind::Lit(..) | hir::ExprKind::Path(hir::QPath::TypeRelative(..)) => { + hir::ExprKind::Lit(..) | hir::ExprKind::Err | + hir::ExprKind::Path(hir::QPath::TypeRelative(..)) => { succ } @@ -1521,7 +1523,7 @@ fn check_expr<'a, 'tcx>(this: &mut Liveness<'a, 'tcx>, expr: &'tcx Expr) { hir::ExprKind::Block(..) | hir::ExprKind::AddrOf(..) | hir::ExprKind::Struct(..) | hir::ExprKind::Repeat(..) | hir::ExprKind::Closure(..) | hir::ExprKind::Path(_) | hir::ExprKind::Yield(..) | - hir::ExprKind::Box(..) | hir::ExprKind::Type(..) => { + hir::ExprKind::Box(..) | hir::ExprKind::Type(..) | hir::ExprKind::Err => { intravisit::walk_expr(this, expr); } } diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index f32d7c54afe..207382d5e1f 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -687,7 +687,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { hir::ExprKind::Block(..) | hir::ExprKind::Loop(..) | hir::ExprKind::Match(..) | hir::ExprKind::Lit(..) | hir::ExprKind::Break(..) | hir::ExprKind::Continue(..) | hir::ExprKind::Struct(..) | hir::ExprKind::Repeat(..) | - hir::ExprKind::InlineAsm(..) | hir::ExprKind::Box(..) => { + hir::ExprKind::InlineAsm(..) | hir::ExprKind::Box(..) | hir::ExprKind::Err => { Ok(self.cat_rvalue_node(expr.hir_id, expr.span, expr_ty)) } } diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs index 46d666cd81d..23cfd18ef5d 100644 --- a/src/librustc_mir/hair/cx/expr.rs +++ b/src/librustc_mir/hair/cx/expr.rs @@ -780,6 +780,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, hir::ExprKind::Tup(ref fields) => ExprKind::Tuple { fields: fields.to_ref() }, hir::ExprKind::Yield(ref v) => ExprKind::Yield { value: v.to_ref() }, + hir::ExprKind::Err => unreachable!(), }; Expr { diff --git a/src/librustc_passes/rvalue_promotion.rs b/src/librustc_passes/rvalue_promotion.rs index 2fa046a698a..f0b559f80a2 100644 --- a/src/librustc_passes/rvalue_promotion.rs +++ b/src/librustc_passes/rvalue_promotion.rs @@ -449,7 +449,8 @@ fn check_expr_kind<'a, 'tcx>( struct_result } - hir::ExprKind::Lit(_) => Promotable, + hir::ExprKind::Lit(_) | + hir::ExprKind::Err => Promotable, hir::ExprKind::AddrOf(_, ref expr) | hir::ExprKind::Repeat(ref expr, _) => { diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 15a9ba99fa7..0cfe06451a7 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -4513,6 +4513,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } tcx.mk_unit() } + hir::ExprKind::Err => { + tcx.types.err + } } } diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 7e228d8d7cf..f0e567f9cd6 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -1001,6 +1001,7 @@ impl Expr { ExprKind::Paren(..) => ExprPrecedence::Paren, ExprKind::Try(..) => ExprPrecedence::Try, ExprKind::Yield(..) => ExprPrecedence::Yield, + ExprKind::Err => ExprPrecedence::Err, } } } @@ -1160,6 +1161,9 @@ pub enum ExprKind { /// A `yield`, with an optional value to be yielded. Yield(Option>), + + /// Placeholder for an expression that wasn't syntactically well formed in some way. + Err, } /// The explicit `Self` type in a "qualified path". The actual diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 0abc74c2314..b8990264c5d 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -1367,6 +1367,7 @@ pub fn noop_fold_expr(Expr {id, node, span, attrs}: Expr, folder: &mu ExprKind::Yield(ex) => ExprKind::Yield(ex.map(|x| folder.fold_expr(x))), ExprKind::Try(ex) => ExprKind::Try(folder.fold_expr(ex)), ExprKind::TryBlock(body) => ExprKind::TryBlock(folder.fold_block(body)), + ExprKind::Err => ExprKind::Err, }, id: folder.new_id(id), span: folder.new_span(span), diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 931e91e9c79..2ad3d3a6d64 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -1093,7 +1093,9 @@ impl<'a> State<'a> { self.s.word("_")?; } ast::TyKind::Err => { - self.s.word("?")?; + self.popen()?; + self.s.word("/*ERROR*/")?; + self.pclose()?; } ast::TyKind::ImplicitSelf => { self.s.word("Self")?; @@ -2391,6 +2393,11 @@ impl<'a> State<'a> { self.s.space()?; self.print_block_with_attrs(blk, attrs)? } + ast::ExprKind::Err => { + self.popen()?; + self.s.word("/*ERROR*/")?; + self.pclose()? + } } self.ann.post(self, AnnNode::Expr(expr))?; self.end() diff --git a/src/libsyntax/util/parser.rs b/src/libsyntax/util/parser.rs index 52390fa5b1d..89d4e53b8d1 100644 --- a/src/libsyntax/util/parser.rs +++ b/src/libsyntax/util/parser.rs @@ -267,6 +267,7 @@ pub enum ExprPrecedence { TryBlock, Struct, Async, + Err, } impl ExprPrecedence { @@ -325,7 +326,8 @@ impl ExprPrecedence { ExprPrecedence::Block | ExprPrecedence::TryBlock | ExprPrecedence::Async | - ExprPrecedence::Struct => PREC_PAREN, + ExprPrecedence::Struct | + ExprPrecedence::Err => PREC_PAREN, } } } diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 43f8a13609e..156546bbba9 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -802,6 +802,7 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) { ExprKind::TryBlock(ref body) => { visitor.visit_block(body) } + ExprKind::Err => {} } visitor.visit_expr_post(expression)