Skip to content

Commit

Permalink
Auto merge of #59288 - Centril:hir-if-to-match, r=oli-obk
Browse files Browse the repository at this point in the history
[let_chains, 1/6] Remove hir::ExprKind::If

Per rust-lang/rust#53667 (comment).

r? @oli-obk
  • Loading branch information
bors committed May 10, 2019
2 parents d595b11 + f9cc5a6 commit acc7e65
Show file tree
Hide file tree
Showing 40 changed files with 725 additions and 675 deletions.
41 changes: 0 additions & 41 deletions src/librustc/cfg/construct.rs
Original file line number Diff line number Diff line change
Expand Up @@ -166,47 +166,6 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
self.add_ast_node(expr.hir_id.local_id, &[blk_exit])
}

hir::ExprKind::If(ref cond, ref then, None) => {
//
// [pred]
// |
// v 1
// [cond]
// |
// / \
// / \
// v 2 *
// [then] |
// | |
// v 3 v 4
// [..expr..]
//
let cond_exit = self.expr(&cond, pred); // 1
let then_exit = self.expr(&then, cond_exit); // 2
self.add_ast_node(expr.hir_id.local_id, &[cond_exit, then_exit]) // 3,4
}

hir::ExprKind::If(ref cond, ref then, Some(ref otherwise)) => {
//
// [pred]
// |
// v 1
// [cond]
// |
// / \
// / \
// v 2 v 3
// [then][otherwise]
// | |
// v 4 v 5
// [..expr..]
//
let cond_exit = self.expr(&cond, pred); // 1
let then_exit = self.expr(&then, cond_exit); // 2
let else_exit = self.expr(&otherwise, cond_exit); // 3
self.add_ast_node(expr.hir_id.local_id, &[then_exit, else_exit]) // 4, 5
}

hir::ExprKind::While(ref cond, ref body, _) => {
//
// [pred]
Expand Down
5 changes: 0 additions & 5 deletions src/librustc/hir/intravisit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1032,11 +1032,6 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) {
ExprKind::DropTemps(ref subexpression) => {
visitor.visit_expr(subexpression);
}
ExprKind::If(ref head_expression, ref if_block, ref optional_else) => {
visitor.visit_expr(head_expression);
visitor.visit_expr(if_block);
walk_list!(visitor, visit_expr, optional_else);
}
ExprKind::While(ref subexpression, ref block, ref opt_label) => {
walk_list!(visitor, visit_label, opt_label);
visitor.visit_expr(subexpression);
Expand Down
124 changes: 65 additions & 59 deletions src/librustc/hir/lowering.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ use syntax::ext::hygiene::Mark;
use syntax::print::pprust;
use syntax::ptr::P;
use syntax::source_map::{respan, CompilerDesugaringKind, Spanned};
use syntax::source_map::CompilerDesugaringKind::IfTemporary;
use syntax::std_inject;
use syntax::symbol::{keywords, Symbol};
use syntax::tokenstream::{TokenStream, TokenTree};
Expand Down Expand Up @@ -4115,31 +4116,46 @@ impl<'a> LoweringContext<'a> {
}
// More complicated than you might expect because the else branch
// might be `if let`.
ExprKind::If(ref cond, ref blk, ref else_opt) => {
let else_opt = else_opt.as_ref().map(|els| {
match els.node {
ExprKind::If(ref cond, ref then, ref else_opt) => {
// `true => then`:
let then_pat = self.pat_bool(e.span, true);
let then_blk = self.lower_block(then, false);
let then_expr = self.expr_block(then_blk, ThinVec::new());
let then_arm = self.arm(hir_vec![then_pat], P(then_expr));

// `_ => else_block` where `else_block` is `{}` if there's `None`:
let else_pat = self.pat_wild(e.span);
let else_expr = match else_opt {
None => self.expr_block_empty(e.span),
Some(els) => match els.node {
ExprKind::IfLet(..) => {
// Wrap the `if let` expr in a block.
let span = els.span;
let els = P(self.lower_expr(els));
let blk = P(hir::Block {
stmts: hir_vec![],
expr: Some(els),
hir_id: self.next_id(),
rules: hir::DefaultBlock,
span,
targeted_by_break: false,
});
P(self.expr_block(blk, ThinVec::new()))
let els = self.lower_expr(els);
let blk = self.block_all(els.span, hir_vec![], Some(P(els)));
self.expr_block(P(blk), ThinVec::new())
}
_ => P(self.lower_expr(els)),
_ => self.lower_expr(els),
}
});

let then_blk = self.lower_block(blk, false);
let then_expr = self.expr_block(then_blk, ThinVec::new());
};
let else_arm = self.arm(hir_vec![else_pat], P(else_expr));

// Lower condition:
let span_block = self
.sess
.source_map()
.mark_span_with_reason(IfTemporary, cond.span, None);
let cond = self.lower_expr(cond);
// Wrap in a construct equivalent to `{ let _t = $cond; _t }` to preserve drop
// semantics since `if cond { ... }` don't let temporaries live outside of `cond`.
let cond = self.expr_drop_temps(span_block, P(cond), ThinVec::new());

hir::ExprKind::If(P(self.lower_expr(cond)), P(then_expr), else_opt)
hir::ExprKind::Match(
P(cond),
vec![then_arm, else_arm].into(),
hir::MatchSource::IfDesugar {
contains_else_clause: else_opt.is_some()
},
)
}
ExprKind::While(ref cond, ref body, opt_label) => self.with_loop_scope(e.id, |this| {
hir::ExprKind::While(
Expand Down Expand Up @@ -4486,16 +4502,16 @@ impl<'a> LoweringContext<'a> {
arms.push(self.arm(pats, body_expr));
}

// _ => [<else_opt>|()]
// _ => [<else_opt>|{}]
{
let wildcard_arm: Option<&Expr> = else_opt.as_ref().map(|p| &**p);
let wildcard_pattern = self.pat_wild(e.span);
let body = if let Some(else_expr) = wildcard_arm {
P(self.lower_expr(else_expr))
self.lower_expr(else_expr)
} else {
P(self.expr_tuple(e.span, hir_vec![]))
self.expr_block_empty(e.span)
};
arms.push(self.arm(hir_vec![wildcard_pattern], body));
arms.push(self.arm(hir_vec![wildcard_pattern], P(body)));
}

let contains_else_clause = else_opt.is_some();
Expand Down Expand Up @@ -4658,11 +4674,7 @@ impl<'a> LoweringContext<'a> {
ThinVec::new(),
))
};
let match_stmt = hir::Stmt {
hir_id: self.next_id(),
node: hir::StmtKind::Expr(match_expr),
span: head_sp,
};
let match_stmt = self.stmt(head_sp, hir::StmtKind::Expr(match_expr));

let next_expr = P(self.expr_ident(head_sp, next_ident, next_pat_hid));

Expand All @@ -4685,11 +4697,7 @@ impl<'a> LoweringContext<'a> {

let body_block = self.with_loop_scope(e.id, |this| this.lower_block(body, false));
let body_expr = P(self.expr_block(body_block, ThinVec::new()));
let body_stmt = hir::Stmt {
hir_id: self.next_id(),
node: hir::StmtKind::Expr(body_expr),
span: body.span,
};
let body_stmt = self.stmt(body.span, hir::StmtKind::Expr(body_expr));

let loop_block = P(self.block_all(
e.span,
Expand Down Expand Up @@ -4869,12 +4877,7 @@ impl<'a> LoweringContext<'a> {
.into_iter()
.map(|item_id| {
let item_id = hir::ItemId { id: self.lower_node_id(item_id) };

hir::Stmt {
hir_id: self.next_id(),
node: hir::StmtKind::Item(item_id),
span: s.span,
}
self.stmt(s.span, hir::StmtKind::Item(item_id))
})
.collect();
ids.push({
Expand Down Expand Up @@ -5174,28 +5177,32 @@ impl<'a> LoweringContext<'a> {
}
}

fn stmt(&mut self, span: Span, node: hir::StmtKind) -> hir::Stmt {
hir::Stmt { span, node, hir_id: self.next_id() }
}

fn stmt_let_pat(
&mut self,
sp: Span,
ex: Option<P<hir::Expr>>,
span: Span,
init: Option<P<hir::Expr>>,
pat: P<hir::Pat>,
source: hir::LocalSource,
) -> hir::Stmt {
let local = hir::Local {
pat,
ty: None,
init: ex,
init,
hir_id: self.next_id(),
span: sp,
attrs: ThinVec::new(),
span,
source,
attrs: ThinVec::new()
};
self.stmt(span, hir::StmtKind::Local(P(local)))
}

hir::Stmt {
hir_id: self.next_id(),
node: hir::StmtKind::Local(P(local)),
span: sp
}
fn expr_block_empty(&mut self, span: Span) -> hir::Expr {
let blk = self.block_all(span, hir_vec![], None);
self.expr_block(P(blk), ThinVec::new())
}

fn block_expr(&mut self, expr: P<hir::Expr>) -> hir::Block {
Expand Down Expand Up @@ -5235,6 +5242,13 @@ impl<'a> LoweringContext<'a> {
)
}

/// Constructs a `true` or `false` literal pattern.
fn pat_bool(&mut self, span: Span, val: bool) -> P<hir::Pat> {
let lit = Spanned { span, node: LitKind::Bool(val) };
let expr = self.expr(span, hir::ExprKind::Lit(lit), ThinVec::new());
self.pat(span, hir::PatKind::Lit(P(expr)))
}

fn pat_ok(&mut self, span: Span, pat: P<hir::Pat>) -> P<hir::Pat> {
self.pat_std_enum(span, &["result", "Result", "Ok"], hir_vec![pat])
}
Expand Down Expand Up @@ -5622,15 +5636,7 @@ impl<'a> LoweringContext<'a> {
&["task", "Poll", "Pending"],
hir_vec![],
);
let empty_block = P(hir::Block {
stmts: hir_vec![],
expr: None,
hir_id: self.next_id(),
rules: hir::DefaultBlock,
span,
targeted_by_break: false,
});
let empty_block = P(self.expr_block(empty_block, ThinVec::new()));
let empty_block = P(self.expr_block_empty(span));
self.arm(hir_vec![pending_pat], empty_block)
};

Expand Down
10 changes: 4 additions & 6 deletions src/librustc/hir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1368,7 +1368,6 @@ impl Expr {
ExprKind::Lit(_) => ExprPrecedence::Lit,
ExprKind::Type(..) | ExprKind::Cast(..) => ExprPrecedence::Cast,
ExprKind::DropTemps(ref expr, ..) => expr.precedence(),
ExprKind::If(..) => ExprPrecedence::If,
ExprKind::While(..) => ExprPrecedence::While,
ExprKind::Loop(..) => ExprPrecedence::Loop,
ExprKind::Match(..) => ExprPrecedence::Match,
Expand Down Expand Up @@ -1421,7 +1420,6 @@ impl Expr {
ExprKind::MethodCall(..) |
ExprKind::Struct(..) |
ExprKind::Tup(..) |
ExprKind::If(..) |
ExprKind::Match(..) |
ExprKind::Closure(..) |
ExprKind::Block(..) |
Expand Down Expand Up @@ -1498,10 +1496,6 @@ pub enum ExprKind {
/// This construct only exists to tweak the drop order in HIR lowering.
/// An example of that is the desugaring of `for` loops.
DropTemps(P<Expr>),
/// An `if` block, with an optional else block.
///
/// I.e., `if <expr> { <expr> } else { <expr> }`.
If(P<Expr>, P<Expr>, Option<P<Expr>>),
/// A while loop, with an optional label
///
/// I.e., `'label: while expr { <block> }`.
Expand Down Expand Up @@ -1615,6 +1609,10 @@ pub enum LocalSource {
pub enum MatchSource {
/// A `match _ { .. }`.
Normal,
/// An `if _ { .. }` (optionally with `else { .. }`).
IfDesugar {
contains_else_clause: bool,
},
/// An `if let _ = _ { .. }` (optionally with `else { .. }`).
IfLetDesugar {
contains_else_clause: bool,
Expand Down
63 changes: 0 additions & 63 deletions src/librustc/hir/print.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1093,65 +1093,6 @@ impl<'a> State<'a> {
self.ann.post(self, AnnNode::Block(blk))
}

fn print_else(&mut self, els: Option<&hir::Expr>) -> io::Result<()> {
match els {
Some(_else) => {
match _else.node {
// "another else-if"
hir::ExprKind::If(ref i, ref then, ref e) => {
self.cbox(indent_unit - 1)?;
self.ibox(0)?;
self.s.word(" else if ")?;
self.print_expr_as_cond(&i)?;
self.s.space()?;
self.print_expr(&then)?;
self.print_else(e.as_ref().map(|e| &**e))
}
// "final else"
hir::ExprKind::Block(ref b, _) => {
self.cbox(indent_unit - 1)?;
self.ibox(0)?;
self.s.word(" else ")?;
self.print_block(&b)
}
// BLEAH, constraints would be great here
_ => {
panic!("print_if saw if with weird alternative");
}
}
}
_ => Ok(()),
}
}

pub fn print_if(&mut self,
test: &hir::Expr,
blk: &hir::Expr,
elseopt: Option<&hir::Expr>)
-> io::Result<()> {
self.head("if")?;
self.print_expr_as_cond(test)?;
self.s.space()?;
self.print_expr(blk)?;
self.print_else(elseopt)
}

pub fn print_if_let(&mut self,
pat: &hir::Pat,
expr: &hir::Expr,
blk: &hir::Block,
elseopt: Option<&hir::Expr>)
-> io::Result<()> {
self.head("if let")?;
self.print_pat(pat)?;
self.s.space()?;
self.word_space("=")?;
self.print_expr_as_cond(expr)?;
self.s.space()?;
self.print_block(blk)?;
self.print_else(elseopt)
}

pub fn print_anon_const(&mut self, constant: &hir::AnonConst) -> io::Result<()> {
self.ann.nested(self, Nested::Body(constant.body))
}
Expand Down Expand Up @@ -1406,9 +1347,6 @@ impl<'a> State<'a> {
// Print `}`:
self.bclose_maybe_open(expr.span, indent_unit, true)?;
}
hir::ExprKind::If(ref test, ref blk, ref elseopt) => {
self.print_if(&test, &blk, elseopt.as_ref().map(|e| &**e))?;
}
hir::ExprKind::While(ref test, ref blk, opt_label) => {
if let Some(label) = opt_label {
self.print_ident(label.ident)?;
Expand Down Expand Up @@ -2414,7 +2352,6 @@ impl<'a> State<'a> {
/// 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::If(..) |
hir::ExprKind::Match(..) |
hir::ExprKind::Block(..) |
hir::ExprKind::While(..) |
Expand Down
1 change: 1 addition & 0 deletions src/librustc/ich/impls_syntax.rs
Original file line number Diff line number Diff line change
Expand Up @@ -395,6 +395,7 @@ impl_stable_hash_for!(enum ::syntax_pos::hygiene::ExpnFormat {
});

impl_stable_hash_for!(enum ::syntax_pos::hygiene::CompilerDesugaringKind {
IfTemporary,
Async,
Await,
QuestionMark,
Expand Down
Loading

0 comments on commit acc7e65

Please sign in to comment.