Skip to content

Do not discern between statements with and without semicolon after lowering to HIR #61753

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions src/librustc/cfg/construct.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
};
Expand Down
3 changes: 1 addition & 2 deletions src/librustc/hir/intravisit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
}
Expand Down
9 changes: 1 addition & 8 deletions src/librustc/hir/lowering.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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"),
}]
}
Expand Down
8 changes: 2 additions & 6 deletions src/librustc/hir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1205,20 +1205,16 @@ pub enum StmtKind {
/// An item binding.
Item(ItemId),

/// An expression without a trailing semi-colon (must have unit type).
/// An expression statement.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/// An expression statement.
/// An expression statement (may have any type).

Expr(P<Expr>),

/// An expression with a trailing semi-colon (may have any type).
Semi(P<Expr>),
}

impl StmtKind {
pub fn attrs(&self) -> &[Attribute] {
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,
}
}
}
Expand Down
38 changes: 1 addition & 37 deletions src/librustc/hir/print.rs
Original file line number Diff line number Diff line change
Expand Up @@ -992,23 +992,17 @@ 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))?
}
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)
}

Expand Down Expand Up @@ -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 {
Expand Down
3 changes: 1 addition & 2 deletions src/librustc/middle/expr_use_visitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/middle/liveness.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
}
Expand Down
3 changes: 1 addition & 2 deletions src/librustc/middle/region.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Expand Down
4 changes: 2 additions & 2 deletions src/librustc_lint/unused.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
};

Expand Down Expand Up @@ -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");
}
Expand Down
3 changes: 1 addition & 2 deletions src/librustc_mir/hair/cx/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
3 changes: 1 addition & 2 deletions src/librustc_passes/rvalue_promotion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down
8 changes: 2 additions & 6 deletions src/librustc_typeck/check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand All @@ -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());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(T-Lang: N.B. this removes the expectation that { expr } : () and so therefore:

{ core::default::Default::default() }
1;

may stop compiling (crater will find out).

We could add inference defaulting to () if that is desirable.

}
hir::StmtKind::Semi(ref expr) => {
self.check_expr(&expr);
}
}
Expand Down Expand Up @@ -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);
Expand Down
Original file line number Diff line number Diff line change
@@ -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
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unsafe { std::mem::uninitialized() } no longer needs to unify with (), so it cannot infer its type.

}

// Check that the tail statement in the body can be unit
Expand Down
9 changes: 9 additions & 0 deletions src/test/ui/for/for-loop-has-unit-body.stderr
Original file line number Diff line number Diff line change
@@ -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`.
4 changes: 3 additions & 1 deletion src/test/ui/mismatched_types/for-loop-has-unit-body.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
// compile-pass

fn main() {
for x in 0..3 {
x //~ ERROR mismatched types
x
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

x no longer needs to unify with (), so it's no longer an error.

}
}
12 changes: 0 additions & 12 deletions src/test/ui/mismatched_types/for-loop-has-unit-body.stderr

This file was deleted.

4 changes: 0 additions & 4 deletions src/test/ui/parser/expr-as-stmt.fixed
Original file line number Diff line number Diff line change
Expand Up @@ -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<u32>, b: Option<u32>) -> bool {
Expand Down
4 changes: 0 additions & 4 deletions src/test/ui/parser/expr-as-stmt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<u32>, b: Option<u32>) -> bool {
Expand Down
Loading