diff --git a/src/librustc/cfg/construct.rs b/src/librustc/cfg/construct.rs index 139c144fbcf4e..a12f6da3bd69b 100644 --- a/src/librustc/cfg/construct.rs +++ b/src/librustc/cfg/construct.rs @@ -106,8 +106,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { hir::StmtKind::Item(_) => { pred } - hir::StmtKind::Expr(ref expr) | - hir::StmtKind::Semi(ref expr) => { + hir::StmtKind::Expr(ref expr) => { self.expr(&expr, pred) } }; diff --git a/src/librustc/hir/intravisit.rs b/src/librustc/hir/intravisit.rs index f4f9d6261de48..219583a3cd96f 100644 --- a/src/librustc/hir/intravisit.rs +++ b/src/librustc/hir/intravisit.rs @@ -967,8 +967,7 @@ pub fn walk_stmt<'v, V: Visitor<'v>>(visitor: &mut V, statement: &'v Stmt) { match statement.node { StmtKind::Local(ref local) => visitor.visit_local(local), StmtKind::Item(item) => visitor.visit_nested_item(item), - StmtKind::Expr(ref expression) | - StmtKind::Semi(ref expression) => { + StmtKind::Expr(ref expression) => { visitor.visit_expr(expression) } } diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 5a548ce8d9ff4..cd49c2d7473df 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -5110,20 +5110,13 @@ impl<'a> LoweringContext<'a> { }) .collect(); } - StmtKind::Expr(ref e) => { + StmtKind::Expr(ref e) | StmtKind::Semi(ref e) => { hir::Stmt { hir_id: self.lower_node_id(s.id), node: hir::StmtKind::Expr(P(self.lower_expr(e))), span: s.span, } }, - StmtKind::Semi(ref e) => { - hir::Stmt { - hir_id: self.lower_node_id(s.id), - node: hir::StmtKind::Semi(P(self.lower_expr(e))), - span: s.span, - } - }, StmtKind::Mac(..) => panic!("Shouldn't exist here"), }] } diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 6ace4c4174b56..8270120c5f5a8 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -1205,11 +1205,8 @@ pub enum StmtKind { /// An item binding. Item(ItemId), - /// An expression without a trailing semi-colon (must have unit type). + /// An expression statement. Expr(P), - - /// An expression with a trailing semi-colon (may have any type). - Semi(P), } impl StmtKind { @@ -1217,8 +1214,7 @@ impl StmtKind { match *self { StmtKind::Local(ref l) => &l.attrs, StmtKind::Item(_) => &[], - StmtKind::Expr(ref e) | - StmtKind::Semi(ref e) => &e.attrs, + StmtKind::Expr(ref e) => &e.attrs, } } } diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs index 7b0a499fa5c66..8de0641b97975 100644 --- a/src/librustc/hir/print.rs +++ b/src/librustc/hir/print.rs @@ -992,6 +992,7 @@ impl<'a> State<'a> { match st.node { hir::StmtKind::Local(ref loc) => { self.print_local(loc.init.deref(), |this| this.print_local_decl(&loc))?; + self.s.word(";")?; } hir::StmtKind::Item(item) => { self.ann.nested(self, Nested::Item(item))? @@ -999,16 +1000,9 @@ impl<'a> State<'a> { hir::StmtKind::Expr(ref expr) => { self.space_if_not_bol()?; self.print_expr(&expr)?; - } - hir::StmtKind::Semi(ref expr) => { - self.space_if_not_bol()?; - self.print_expr(&expr)?; self.s.word(";")?; } } - if stmt_ends_with_semi(&st.node) { - self.s.word(";")?; - } self.maybe_print_trailing_comment(st.span, None) } @@ -2325,36 +2319,6 @@ impl<'a> State<'a> { } } -// Dup'ed from parse::classify, but adapted for the HIR. -/// Does this expression require a semicolon to be treated -/// as a statement? The negation of this: 'can this expression -/// be used as a statement without a semicolon' -- is used -/// as an early-bail-out in the parser so that, for instance, -/// if true {...} else {...} -/// |x| 5 -/// isn't parsed as (if true {...} else {...} | x) | 5 -fn expr_requires_semi_to_be_stmt(e: &hir::Expr) -> bool { - match e.node { - hir::ExprKind::Match(..) | - hir::ExprKind::Block(..) | - hir::ExprKind::While(..) | - hir::ExprKind::Loop(..) => false, - _ => true, - } -} - -/// this statement requires a semicolon after it. -/// note that in one case (stmt_semi), we've already -/// seen the semicolon, and thus don't need another. -fn stmt_ends_with_semi(stmt: &hir::StmtKind) -> bool { - match *stmt { - hir::StmtKind::Local(_) => true, - hir::StmtKind::Item(_) => false, - hir::StmtKind::Expr(ref e) => expr_requires_semi_to_be_stmt(&e), - hir::StmtKind::Semi(..) => false, - } -} - fn bin_op_to_assoc_op(op: hir::BinOpKind) -> AssocOp { use crate::hir::BinOpKind::*; match op { diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index 61770e6f48705..623ecba6c4d01 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -603,8 +603,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { // only the fn body we were given. } - hir::StmtKind::Expr(ref expr) | - hir::StmtKind::Semi(ref expr) => { + hir::StmtKind::Expr(ref expr) => { self.consume_expr(&expr); } } diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index 29c624575c3c2..b201148912a10 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -1004,7 +1004,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { self.define_bindings_in_pat(&local.pat, succ) } hir::StmtKind::Item(..) => succ, - hir::StmtKind::Expr(ref expr) | hir::StmtKind::Semi(ref expr) => { + hir::StmtKind::Expr(ref expr) => { self.propagate_through_expr(&expr, succ) } } diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs index 8b1eeeb7f51b7..c2c2454db76a6 100644 --- a/src/librustc/middle/region.rs +++ b/src/librustc/middle/region.rs @@ -804,8 +804,7 @@ fn resolve_block<'tcx>(visitor: &mut RegionResolutionVisitor<'tcx>, blk: &'tcx h ); visitor.cx.var_parent = visitor.cx.parent; } - hir::StmtKind::Expr(..) | - hir::StmtKind::Semi(..) => {} + hir::StmtKind::Expr(..) => {} } visitor.visit_stmt(statement) } diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs index d540b3f7e40a3..c3473c0d663a3 100644 --- a/src/librustc_lint/unused.rs +++ b/src/librustc_lint/unused.rs @@ -39,7 +39,7 @@ declare_lint_pass!(UnusedResults => [UNUSED_MUST_USE, UNUSED_RESULTS]); impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedResults { fn check_stmt(&mut self, cx: &LateContext<'_, '_>, s: &hir::Stmt) { let expr = match s.node { - hir::StmtKind::Semi(ref expr) => &**expr, + hir::StmtKind::Expr(ref expr) => &**expr, _ => return, }; @@ -227,7 +227,7 @@ declare_lint_pass!(PathStatements => [PATH_STATEMENTS]); impl<'a, 'tcx> LateLintPass<'a, 'tcx> for PathStatements { fn check_stmt(&mut self, cx: &LateContext<'_, '_>, s: &hir::Stmt) { - if let hir::StmtKind::Semi(ref expr) = s.node { + if let hir::StmtKind::Expr(ref expr) = s.node { if let hir::ExprKind::Path(_) = expr.node { cx.span_lint(PATH_STATEMENTS, s.span, "path statement with no effect"); } diff --git a/src/librustc_mir/hair/cx/block.rs b/src/librustc_mir/hair/cx/block.rs index 63239a36a1753..85601e9755933 100644 --- a/src/librustc_mir/hair/cx/block.rs +++ b/src/librustc_mir/hair/cx/block.rs @@ -51,8 +51,7 @@ fn mirror_stmts<'a, 'tcx>( let opt_dxn_ext = cx.region_scope_tree.opt_destruction_scope(hir_id.local_id); let stmt_span = StatementSpan(cx.tcx.hir().span_by_hir_id(hir_id)); match stmt.node { - hir::StmtKind::Expr(ref expr) | - hir::StmtKind::Semi(ref expr) => { + hir::StmtKind::Expr(ref expr) => { result.push(StmtRef::Mirror(Box::new(Stmt { kind: StmtKind::Expr { scope: region::Scope { diff --git a/src/librustc_passes/rvalue_promotion.rs b/src/librustc_passes/rvalue_promotion.rs index 7230b69468126..72c7c0643bbc8 100644 --- a/src/librustc_passes/rvalue_promotion.rs +++ b/src/librustc_passes/rvalue_promotion.rs @@ -227,8 +227,7 @@ impl<'a, 'tcx> CheckCrateVisitor<'a, 'tcx> { } // Item statements are allowed hir::StmtKind::Item(..) => Promotable, - hir::StmtKind::Expr(ref box_expr) | - hir::StmtKind::Semi(ref box_expr) => { + hir::StmtKind::Expr(ref box_expr) => { let _ = self.check_expr(box_expr); NotPromotable } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 22f17097fcbe3..87ebdada8d72c 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -4851,7 +4851,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Don't do all the complex logic below for `DeclItem`. match stmt.node { hir::StmtKind::Item(..) => return, - hir::StmtKind::Local(..) | hir::StmtKind::Expr(..) | hir::StmtKind::Semi(..) => {} + hir::StmtKind::Local(..) | hir::StmtKind::Expr(..) => {} } self.warn_if_unreachable(stmt.hir_id, stmt.span, "statement"); @@ -4869,10 +4869,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Ignore for now. hir::StmtKind::Item(_) => {} hir::StmtKind::Expr(ref expr) => { - // Check with expected type of `()`. - self.check_expr_has_type_or_error(&expr, self.tcx.mk_unit()); - } - hir::StmtKind::Semi(ref expr) => { self.check_expr(&expr); } } @@ -5289,7 +5285,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // taking the `;` off is enough to fix the error. let last_stmt = blk.stmts.last()?; let last_expr = match last_stmt.node { - hir::StmtKind::Semi(ref e) => e, + hir::StmtKind::Expr(ref e) => e, _ => return None, }; let last_expr_ty = self.node_ty(last_expr.hir_id); diff --git a/src/test/run-pass/for-loop-while/for-loop-has-unit-body.rs b/src/test/ui/for/for-loop-has-unit-body.rs similarity index 72% rename from src/test/run-pass/for-loop-while/for-loop-has-unit-body.rs rename to src/test/ui/for/for-loop-has-unit-body.rs index 009c59f2fa43d..70a849e1ef3ae 100644 --- a/src/test/run-pass/for-loop-while/for-loop-has-unit-body.rs +++ b/src/test/ui/for/for-loop-has-unit-body.rs @@ -1,8 +1,7 @@ -// run-pass fn main() { // Check that the tail statement in the body unifies with something for _ in 0..3 { - unsafe { std::mem::uninitialized() } + unsafe { std::mem::uninitialized() } //~ ERROR type annotations needed } // Check that the tail statement in the body can be unit diff --git a/src/test/ui/for/for-loop-has-unit-body.stderr b/src/test/ui/for/for-loop-has-unit-body.stderr new file mode 100644 index 0000000000000..6e033d88b5203 --- /dev/null +++ b/src/test/ui/for/for-loop-has-unit-body.stderr @@ -0,0 +1,9 @@ +error[E0282]: type annotations needed + --> $DIR/for-loop-has-unit-body.rs:4:18 + | +LL | unsafe { std::mem::uninitialized() } + | ^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type for `T` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/src/test/ui/mismatched_types/for-loop-has-unit-body.rs b/src/test/ui/mismatched_types/for-loop-has-unit-body.rs index a9433d7de6e17..21149213d4918 100644 --- a/src/test/ui/mismatched_types/for-loop-has-unit-body.rs +++ b/src/test/ui/mismatched_types/for-loop-has-unit-body.rs @@ -1,5 +1,7 @@ +// compile-pass + fn main() { for x in 0..3 { - x //~ ERROR mismatched types + x } } diff --git a/src/test/ui/mismatched_types/for-loop-has-unit-body.stderr b/src/test/ui/mismatched_types/for-loop-has-unit-body.stderr deleted file mode 100644 index 3c8ba8057c55a..0000000000000 --- a/src/test/ui/mismatched_types/for-loop-has-unit-body.stderr +++ /dev/null @@ -1,12 +0,0 @@ -error[E0308]: mismatched types - --> $DIR/for-loop-has-unit-body.rs:3:9 - | -LL | x - | ^ expected (), found integer - | - = note: expected type `()` - found type `{integer}` - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/parser/expr-as-stmt.fixed b/src/test/ui/parser/expr-as-stmt.fixed index 1ce6f9c25034f..226794cb296bc 100644 --- a/src/test/ui/parser/expr-as-stmt.fixed +++ b/src/test/ui/parser/expr-as-stmt.fixed @@ -5,24 +5,20 @@ fn foo() -> i32 { ({2}) + {2} //~ ERROR expected expression, found `+` - //~^ ERROR mismatched types } fn bar() -> i32 { ({2}) + 2 //~ ERROR expected expression, found `+` - //~^ ERROR mismatched types } fn zul() -> u32 { let foo = 3; ({ 42 }) + foo; //~ ERROR expected expression, found `+` - //~^ ERROR mismatched types 32 } fn baz() -> i32 { ({ 3 }) * 3 //~ ERROR type `{integer}` cannot be dereferenced - //~^ ERROR mismatched types } fn qux(a: Option, b: Option) -> bool { diff --git a/src/test/ui/parser/expr-as-stmt.rs b/src/test/ui/parser/expr-as-stmt.rs index b526c17488eaf..847ae7e27b3b7 100644 --- a/src/test/ui/parser/expr-as-stmt.rs +++ b/src/test/ui/parser/expr-as-stmt.rs @@ -5,24 +5,20 @@ fn foo() -> i32 { {2} + {2} //~ ERROR expected expression, found `+` - //~^ ERROR mismatched types } fn bar() -> i32 { {2} + 2 //~ ERROR expected expression, found `+` - //~^ ERROR mismatched types } fn zul() -> u32 { let foo = 3; { 42 } + foo; //~ ERROR expected expression, found `+` - //~^ ERROR mismatched types 32 } fn baz() -> i32 { { 3 } * 3 //~ ERROR type `{integer}` cannot be dereferenced - //~^ ERROR mismatched types } fn qux(a: Option, b: Option) -> bool { diff --git a/src/test/ui/parser/expr-as-stmt.stderr b/src/test/ui/parser/expr-as-stmt.stderr index a11209998a7d5..f66777f75a6bc 100644 --- a/src/test/ui/parser/expr-as-stmt.stderr +++ b/src/test/ui/parser/expr-as-stmt.stderr @@ -7,7 +7,7 @@ LL | {2} + {2} | help: parentheses are required to parse this as an expression: `({2})` error: expected expression, found `+` - --> $DIR/expr-as-stmt.rs:12:9 + --> $DIR/expr-as-stmt.rs:11:9 | LL | {2} + 2 | --- ^ expected expression @@ -15,7 +15,7 @@ LL | {2} + 2 | help: parentheses are required to parse this as an expression: `({2})` error: expected expression, found `+` - --> $DIR/expr-as-stmt.rs:18:12 + --> $DIR/expr-as-stmt.rs:16:12 | LL | { 42 } + foo; | ------ ^ expected expression @@ -23,7 +23,7 @@ LL | { 42 } + foo; | help: parentheses are required to parse this as an expression: `({ 42 })` error: expected expression, found `&&` - --> $DIR/expr-as-stmt.rs:30:5 + --> $DIR/expr-as-stmt.rs:26:5 | LL | if let Some(x) = a { true } else { false } | ------------------------------------------ help: parentheses are required to parse this as an expression: `(if let Some(x) = a { true } else { false })` @@ -31,7 +31,7 @@ LL | && | ^^ expected expression error: expected expression, found `>` - --> $DIR/expr-as-stmt.rs:37:7 + --> $DIR/expr-as-stmt.rs:33:7 | LL | } > 0 | ^ expected expression @@ -42,51 +42,14 @@ LL | _ => 1, LL | }) > 0 | -error[E0308]: mismatched types - --> $DIR/expr-as-stmt.rs:7:6 - | -LL | {2} + {2} - | ^ expected (), found integer - | - = note: expected type `()` - found type `{integer}` - -error[E0308]: mismatched types - --> $DIR/expr-as-stmt.rs:12:6 - | -LL | {2} + 2 - | ^ expected (), found integer - | - = note: expected type `()` - found type `{integer}` - -error[E0308]: mismatched types - --> $DIR/expr-as-stmt.rs:18:7 - | -LL | { 42 } + foo; - | ^^ expected (), found integer - | - = note: expected type `()` - found type `{integer}` - -error[E0308]: mismatched types - --> $DIR/expr-as-stmt.rs:24:7 - | -LL | { 3 } * 3 - | ^ expected (), found integer - | - = note: expected type `()` - found type `{integer}` - error[E0614]: type `{integer}` cannot be dereferenced - --> $DIR/expr-as-stmt.rs:24:11 + --> $DIR/expr-as-stmt.rs:21:11 | LL | { 3 } * 3 | ----- ^^^ | | | help: parentheses are required to parse this as an expression: `({ 3 })` -error: aborting due to 10 previous errors +error: aborting due to 6 previous errors -Some errors have detailed explanations: E0308, E0614. -For more information about an error, try `rustc --explain E0308`. +For more information about this error, try `rustc --explain E0614`. diff --git a/src/test/ui/resolve/token-error-correct-3.rs b/src/test/ui/resolve/token-error-correct-3.rs index 212b88ac8b05f..29ece8d898ed1 100644 --- a/src/test/ui/resolve/token-error-correct-3.rs +++ b/src/test/ui/resolve/token-error-correct-3.rs @@ -15,10 +15,10 @@ pub mod raw { callback(path.as_ref(); //~^ ERROR expected one of fs::create_dir_all(path.as_ref()).map(|()| true) - //~^ ERROR mismatched types } else { //~^ ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found `)` Ok(false); + //~^ ERROR if and else have incompatible types } panic!(); diff --git a/src/test/ui/resolve/token-error-correct-3.stderr b/src/test/ui/resolve/token-error-correct-3.stderr index 607573f27698b..1cd6fd2f93cde 100644 --- a/src/test/ui/resolve/token-error-correct-3.stderr +++ b/src/test/ui/resolve/token-error-correct-3.stderr @@ -7,11 +7,10 @@ LL | callback(path.as_ref(); | unclosed delimiter error: expected one of `.`, `;`, `?`, `}`, or an operator, found `)` - --> $DIR/token-error-correct-3.rs:19:9 + --> $DIR/token-error-correct-3.rs:18:9 | LL | fs::create_dir_all(path.as_ref()).map(|()| true) | - expected one of `.`, `;`, `?`, `}`, or an operator here -LL | LL | } else { | ^ unexpected token @@ -21,16 +20,27 @@ error[E0425]: cannot find function `is_directory` in this scope LL | if !is_directory(path.as_ref()) { | ^^^^^^^^^^^^ not found in this scope -error[E0308]: mismatched types - --> $DIR/token-error-correct-3.rs:17:13 +error[E0308]: if and else have incompatible types + --> $DIR/token-error-correct-3.rs:20:13 | -LL | fs::create_dir_all(path.as_ref()).map(|()| true) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- help: try adding a semicolon: `;` - | | - | expected (), found enum `std::result::Result` +LL | / if !is_directory(path.as_ref()) { +LL | | +LL | | callback(path.as_ref(); +LL | | +LL | | fs::create_dir_all(path.as_ref()).map(|()| true) + | | ------------------------------------------------ expected because of this +... | +LL | | Ok(false); + | | ^^^^^^^^^- + | | | | + | | | help: consider removing this semicolon + | | expected enum `std::result::Result`, found () +LL | | +LL | | } + | |_________- if and else have incompatible types | - = note: expected type `()` - found type `std::result::Result` + = note: expected type `std::result::Result` + found type `()` error: aborting due to 4 previous errors diff --git a/src/test/ui/struct-literal-variant-in-if.rs b/src/test/ui/struct-literal-variant-in-if.rs index 4ef8effaf1f5f..831f79dff2b23 100644 --- a/src/test/ui/struct-literal-variant-in-if.rs +++ b/src/test/ui/struct-literal-variant-in-if.rs @@ -9,7 +9,7 @@ fn test_E(x: E) { let field = true; if x == E::V { field } {} //~^ ERROR expected value, found struct variant `E::V` - //~| ERROR mismatched types + //~| ERROR if may be missing an else clause if x == E::I { field1: true, field2: 42 } {} //~^ ERROR struct literals are not allowed here if x == E::V { field: false } {} diff --git a/src/test/ui/struct-literal-variant-in-if.stderr b/src/test/ui/struct-literal-variant-in-if.stderr index f91b9d7dce60f..30485ac60ec4f 100644 --- a/src/test/ui/struct-literal-variant-in-if.stderr +++ b/src/test/ui/struct-literal-variant-in-if.stderr @@ -46,17 +46,19 @@ LL | if x == E::V { field } {} | | | help: surround the struct literal with parenthesis: `(E::V { field })` -error[E0308]: mismatched types - --> $DIR/struct-literal-variant-in-if.rs:10:20 +error[E0317]: if may be missing an else clause + --> $DIR/struct-literal-variant-in-if.rs:10:5 | -LL | fn test_E(x: E) { - | - help: try adding a return type: `-> bool` -LL | let field = true; LL | if x == E::V { field } {} - | ^^^^^ expected (), found bool + | ^^^^^^^^^^^^^^^-----^^ + | | | + | | found here + | expected (), found bool | = note: expected type `()` found type `bool` + = note: `if` expressions without `else` evaluate to `()` + = help: consider adding an `else` block that evaluates to the expected type error[E0308]: mismatched types --> $DIR/struct-literal-variant-in-if.rs:21:20 @@ -69,5 +71,5 @@ LL | let y: usize = (); error: aborting due to 7 previous errors -Some errors have detailed explanations: E0308, E0423. +Some errors have detailed explanations: E0308, E0317, E0423. For more information about an error, try `rustc --explain E0308`.