Skip to content

Commit acc7e65

Browse files
committed
Auto merge of #59288 - Centril:hir-if-to-match, r=oli-obk
[let_chains, 1/6] Remove hir::ExprKind::If Per #53667 (comment). r? @oli-obk
2 parents d595b11 + f9cc5a6 commit acc7e65

40 files changed

+725
-675
lines changed

src/librustc/cfg/construct.rs

-41
Original file line numberDiff line numberDiff line change
@@ -166,47 +166,6 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
166166
self.add_ast_node(expr.hir_id.local_id, &[blk_exit])
167167
}
168168

169-
hir::ExprKind::If(ref cond, ref then, None) => {
170-
//
171-
// [pred]
172-
// |
173-
// v 1
174-
// [cond]
175-
// |
176-
// / \
177-
// / \
178-
// v 2 *
179-
// [then] |
180-
// | |
181-
// v 3 v 4
182-
// [..expr..]
183-
//
184-
let cond_exit = self.expr(&cond, pred); // 1
185-
let then_exit = self.expr(&then, cond_exit); // 2
186-
self.add_ast_node(expr.hir_id.local_id, &[cond_exit, then_exit]) // 3,4
187-
}
188-
189-
hir::ExprKind::If(ref cond, ref then, Some(ref otherwise)) => {
190-
//
191-
// [pred]
192-
// |
193-
// v 1
194-
// [cond]
195-
// |
196-
// / \
197-
// / \
198-
// v 2 v 3
199-
// [then][otherwise]
200-
// | |
201-
// v 4 v 5
202-
// [..expr..]
203-
//
204-
let cond_exit = self.expr(&cond, pred); // 1
205-
let then_exit = self.expr(&then, cond_exit); // 2
206-
let else_exit = self.expr(&otherwise, cond_exit); // 3
207-
self.add_ast_node(expr.hir_id.local_id, &[then_exit, else_exit]) // 4, 5
208-
}
209-
210169
hir::ExprKind::While(ref cond, ref body, _) => {
211170
//
212171
// [pred]

src/librustc/hir/intravisit.rs

-5
Original file line numberDiff line numberDiff line change
@@ -1032,11 +1032,6 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) {
10321032
ExprKind::DropTemps(ref subexpression) => {
10331033
visitor.visit_expr(subexpression);
10341034
}
1035-
ExprKind::If(ref head_expression, ref if_block, ref optional_else) => {
1036-
visitor.visit_expr(head_expression);
1037-
visitor.visit_expr(if_block);
1038-
walk_list!(visitor, visit_expr, optional_else);
1039-
}
10401035
ExprKind::While(ref subexpression, ref block, ref opt_label) => {
10411036
walk_list!(visitor, visit_label, opt_label);
10421037
visitor.visit_expr(subexpression);

src/librustc/hir/lowering.rs

+65-59
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ use syntax::ext::hygiene::Mark;
6262
use syntax::print::pprust;
6363
use syntax::ptr::P;
6464
use syntax::source_map::{respan, CompilerDesugaringKind, Spanned};
65+
use syntax::source_map::CompilerDesugaringKind::IfTemporary;
6566
use syntax::std_inject;
6667
use syntax::symbol::{keywords, Symbol};
6768
use syntax::tokenstream::{TokenStream, TokenTree};
@@ -4115,31 +4116,46 @@ impl<'a> LoweringContext<'a> {
41154116
}
41164117
// More complicated than you might expect because the else branch
41174118
// might be `if let`.
4118-
ExprKind::If(ref cond, ref blk, ref else_opt) => {
4119-
let else_opt = else_opt.as_ref().map(|els| {
4120-
match els.node {
4119+
ExprKind::If(ref cond, ref then, ref else_opt) => {
4120+
// `true => then`:
4121+
let then_pat = self.pat_bool(e.span, true);
4122+
let then_blk = self.lower_block(then, false);
4123+
let then_expr = self.expr_block(then_blk, ThinVec::new());
4124+
let then_arm = self.arm(hir_vec![then_pat], P(then_expr));
4125+
4126+
// `_ => else_block` where `else_block` is `{}` if there's `None`:
4127+
let else_pat = self.pat_wild(e.span);
4128+
let else_expr = match else_opt {
4129+
None => self.expr_block_empty(e.span),
4130+
Some(els) => match els.node {
41214131
ExprKind::IfLet(..) => {
41224132
// Wrap the `if let` expr in a block.
4123-
let span = els.span;
4124-
let els = P(self.lower_expr(els));
4125-
let blk = P(hir::Block {
4126-
stmts: hir_vec![],
4127-
expr: Some(els),
4128-
hir_id: self.next_id(),
4129-
rules: hir::DefaultBlock,
4130-
span,
4131-
targeted_by_break: false,
4132-
});
4133-
P(self.expr_block(blk, ThinVec::new()))
4133+
let els = self.lower_expr(els);
4134+
let blk = self.block_all(els.span, hir_vec![], Some(P(els)));
4135+
self.expr_block(P(blk), ThinVec::new())
41344136
}
4135-
_ => P(self.lower_expr(els)),
4137+
_ => self.lower_expr(els),
41364138
}
4137-
});
4138-
4139-
let then_blk = self.lower_block(blk, false);
4140-
let then_expr = self.expr_block(then_blk, ThinVec::new());
4139+
};
4140+
let else_arm = self.arm(hir_vec![else_pat], P(else_expr));
4141+
4142+
// Lower condition:
4143+
let span_block = self
4144+
.sess
4145+
.source_map()
4146+
.mark_span_with_reason(IfTemporary, cond.span, None);
4147+
let cond = self.lower_expr(cond);
4148+
// Wrap in a construct equivalent to `{ let _t = $cond; _t }` to preserve drop
4149+
// semantics since `if cond { ... }` don't let temporaries live outside of `cond`.
4150+
let cond = self.expr_drop_temps(span_block, P(cond), ThinVec::new());
41414151

4142-
hir::ExprKind::If(P(self.lower_expr(cond)), P(then_expr), else_opt)
4152+
hir::ExprKind::Match(
4153+
P(cond),
4154+
vec![then_arm, else_arm].into(),
4155+
hir::MatchSource::IfDesugar {
4156+
contains_else_clause: else_opt.is_some()
4157+
},
4158+
)
41434159
}
41444160
ExprKind::While(ref cond, ref body, opt_label) => self.with_loop_scope(e.id, |this| {
41454161
hir::ExprKind::While(
@@ -4486,16 +4502,16 @@ impl<'a> LoweringContext<'a> {
44864502
arms.push(self.arm(pats, body_expr));
44874503
}
44884504

4489-
// _ => [<else_opt>|()]
4505+
// _ => [<else_opt>|{}]
44904506
{
44914507
let wildcard_arm: Option<&Expr> = else_opt.as_ref().map(|p| &**p);
44924508
let wildcard_pattern = self.pat_wild(e.span);
44934509
let body = if let Some(else_expr) = wildcard_arm {
4494-
P(self.lower_expr(else_expr))
4510+
self.lower_expr(else_expr)
44954511
} else {
4496-
P(self.expr_tuple(e.span, hir_vec![]))
4512+
self.expr_block_empty(e.span)
44974513
};
4498-
arms.push(self.arm(hir_vec![wildcard_pattern], body));
4514+
arms.push(self.arm(hir_vec![wildcard_pattern], P(body)));
44994515
}
45004516

45014517
let contains_else_clause = else_opt.is_some();
@@ -4658,11 +4674,7 @@ impl<'a> LoweringContext<'a> {
46584674
ThinVec::new(),
46594675
))
46604676
};
4661-
let match_stmt = hir::Stmt {
4662-
hir_id: self.next_id(),
4663-
node: hir::StmtKind::Expr(match_expr),
4664-
span: head_sp,
4665-
};
4677+
let match_stmt = self.stmt(head_sp, hir::StmtKind::Expr(match_expr));
46664678

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

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

46864698
let body_block = self.with_loop_scope(e.id, |this| this.lower_block(body, false));
46874699
let body_expr = P(self.expr_block(body_block, ThinVec::new()));
4688-
let body_stmt = hir::Stmt {
4689-
hir_id: self.next_id(),
4690-
node: hir::StmtKind::Expr(body_expr),
4691-
span: body.span,
4692-
};
4700+
let body_stmt = self.stmt(body.span, hir::StmtKind::Expr(body_expr));
46934701

46944702
let loop_block = P(self.block_all(
46954703
e.span,
@@ -4869,12 +4877,7 @@ impl<'a> LoweringContext<'a> {
48694877
.into_iter()
48704878
.map(|item_id| {
48714879
let item_id = hir::ItemId { id: self.lower_node_id(item_id) };
4872-
4873-
hir::Stmt {
4874-
hir_id: self.next_id(),
4875-
node: hir::StmtKind::Item(item_id),
4876-
span: s.span,
4877-
}
4880+
self.stmt(s.span, hir::StmtKind::Item(item_id))
48784881
})
48794882
.collect();
48804883
ids.push({
@@ -5174,28 +5177,32 @@ impl<'a> LoweringContext<'a> {
51745177
}
51755178
}
51765179

5180+
fn stmt(&mut self, span: Span, node: hir::StmtKind) -> hir::Stmt {
5181+
hir::Stmt { span, node, hir_id: self.next_id() }
5182+
}
5183+
51775184
fn stmt_let_pat(
51785185
&mut self,
5179-
sp: Span,
5180-
ex: Option<P<hir::Expr>>,
5186+
span: Span,
5187+
init: Option<P<hir::Expr>>,
51815188
pat: P<hir::Pat>,
51825189
source: hir::LocalSource,
51835190
) -> hir::Stmt {
51845191
let local = hir::Local {
51855192
pat,
51865193
ty: None,
5187-
init: ex,
5194+
init,
51885195
hir_id: self.next_id(),
5189-
span: sp,
5190-
attrs: ThinVec::new(),
5196+
span,
51915197
source,
5198+
attrs: ThinVec::new()
51925199
};
5200+
self.stmt(span, hir::StmtKind::Local(P(local)))
5201+
}
51935202

5194-
hir::Stmt {
5195-
hir_id: self.next_id(),
5196-
node: hir::StmtKind::Local(P(local)),
5197-
span: sp
5198-
}
5203+
fn expr_block_empty(&mut self, span: Span) -> hir::Expr {
5204+
let blk = self.block_all(span, hir_vec![], None);
5205+
self.expr_block(P(blk), ThinVec::new())
51995206
}
52005207

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

5245+
/// Constructs a `true` or `false` literal pattern.
5246+
fn pat_bool(&mut self, span: Span, val: bool) -> P<hir::Pat> {
5247+
let lit = Spanned { span, node: LitKind::Bool(val) };
5248+
let expr = self.expr(span, hir::ExprKind::Lit(lit), ThinVec::new());
5249+
self.pat(span, hir::PatKind::Lit(P(expr)))
5250+
}
5251+
52385252
fn pat_ok(&mut self, span: Span, pat: P<hir::Pat>) -> P<hir::Pat> {
52395253
self.pat_std_enum(span, &["result", "Result", "Ok"], hir_vec![pat])
52405254
}
@@ -5622,15 +5636,7 @@ impl<'a> LoweringContext<'a> {
56225636
&["task", "Poll", "Pending"],
56235637
hir_vec![],
56245638
);
5625-
let empty_block = P(hir::Block {
5626-
stmts: hir_vec![],
5627-
expr: None,
5628-
hir_id: self.next_id(),
5629-
rules: hir::DefaultBlock,
5630-
span,
5631-
targeted_by_break: false,
5632-
});
5633-
let empty_block = P(self.expr_block(empty_block, ThinVec::new()));
5639+
let empty_block = P(self.expr_block_empty(span));
56345640
self.arm(hir_vec![pending_pat], empty_block)
56355641
};
56365642

src/librustc/hir/mod.rs

+4-6
Original file line numberDiff line numberDiff line change
@@ -1368,7 +1368,6 @@ impl Expr {
13681368
ExprKind::Lit(_) => ExprPrecedence::Lit,
13691369
ExprKind::Type(..) | ExprKind::Cast(..) => ExprPrecedence::Cast,
13701370
ExprKind::DropTemps(ref expr, ..) => expr.precedence(),
1371-
ExprKind::If(..) => ExprPrecedence::If,
13721371
ExprKind::While(..) => ExprPrecedence::While,
13731372
ExprKind::Loop(..) => ExprPrecedence::Loop,
13741373
ExprKind::Match(..) => ExprPrecedence::Match,
@@ -1421,7 +1420,6 @@ impl Expr {
14211420
ExprKind::MethodCall(..) |
14221421
ExprKind::Struct(..) |
14231422
ExprKind::Tup(..) |
1424-
ExprKind::If(..) |
14251423
ExprKind::Match(..) |
14261424
ExprKind::Closure(..) |
14271425
ExprKind::Block(..) |
@@ -1498,10 +1496,6 @@ pub enum ExprKind {
14981496
/// This construct only exists to tweak the drop order in HIR lowering.
14991497
/// An example of that is the desugaring of `for` loops.
15001498
DropTemps(P<Expr>),
1501-
/// An `if` block, with an optional else block.
1502-
///
1503-
/// I.e., `if <expr> { <expr> } else { <expr> }`.
1504-
If(P<Expr>, P<Expr>, Option<P<Expr>>),
15051499
/// A while loop, with an optional label
15061500
///
15071501
/// I.e., `'label: while expr { <block> }`.
@@ -1615,6 +1609,10 @@ pub enum LocalSource {
16151609
pub enum MatchSource {
16161610
/// A `match _ { .. }`.
16171611
Normal,
1612+
/// An `if _ { .. }` (optionally with `else { .. }`).
1613+
IfDesugar {
1614+
contains_else_clause: bool,
1615+
},
16181616
/// An `if let _ = _ { .. }` (optionally with `else { .. }`).
16191617
IfLetDesugar {
16201618
contains_else_clause: bool,

src/librustc/hir/print.rs

-63
Original file line numberDiff line numberDiff line change
@@ -1093,65 +1093,6 @@ impl<'a> State<'a> {
10931093
self.ann.post(self, AnnNode::Block(blk))
10941094
}
10951095

1096-
fn print_else(&mut self, els: Option<&hir::Expr>) -> io::Result<()> {
1097-
match els {
1098-
Some(_else) => {
1099-
match _else.node {
1100-
// "another else-if"
1101-
hir::ExprKind::If(ref i, ref then, ref e) => {
1102-
self.cbox(indent_unit - 1)?;
1103-
self.ibox(0)?;
1104-
self.s.word(" else if ")?;
1105-
self.print_expr_as_cond(&i)?;
1106-
self.s.space()?;
1107-
self.print_expr(&then)?;
1108-
self.print_else(e.as_ref().map(|e| &**e))
1109-
}
1110-
// "final else"
1111-
hir::ExprKind::Block(ref b, _) => {
1112-
self.cbox(indent_unit - 1)?;
1113-
self.ibox(0)?;
1114-
self.s.word(" else ")?;
1115-
self.print_block(&b)
1116-
}
1117-
// BLEAH, constraints would be great here
1118-
_ => {
1119-
panic!("print_if saw if with weird alternative");
1120-
}
1121-
}
1122-
}
1123-
_ => Ok(()),
1124-
}
1125-
}
1126-
1127-
pub fn print_if(&mut self,
1128-
test: &hir::Expr,
1129-
blk: &hir::Expr,
1130-
elseopt: Option<&hir::Expr>)
1131-
-> io::Result<()> {
1132-
self.head("if")?;
1133-
self.print_expr_as_cond(test)?;
1134-
self.s.space()?;
1135-
self.print_expr(blk)?;
1136-
self.print_else(elseopt)
1137-
}
1138-
1139-
pub fn print_if_let(&mut self,
1140-
pat: &hir::Pat,
1141-
expr: &hir::Expr,
1142-
blk: &hir::Block,
1143-
elseopt: Option<&hir::Expr>)
1144-
-> io::Result<()> {
1145-
self.head("if let")?;
1146-
self.print_pat(pat)?;
1147-
self.s.space()?;
1148-
self.word_space("=")?;
1149-
self.print_expr_as_cond(expr)?;
1150-
self.s.space()?;
1151-
self.print_block(blk)?;
1152-
self.print_else(elseopt)
1153-
}
1154-
11551096
pub fn print_anon_const(&mut self, constant: &hir::AnonConst) -> io::Result<()> {
11561097
self.ann.nested(self, Nested::Body(constant.body))
11571098
}
@@ -1406,9 +1347,6 @@ impl<'a> State<'a> {
14061347
// Print `}`:
14071348
self.bclose_maybe_open(expr.span, indent_unit, true)?;
14081349
}
1409-
hir::ExprKind::If(ref test, ref blk, ref elseopt) => {
1410-
self.print_if(&test, &blk, elseopt.as_ref().map(|e| &**e))?;
1411-
}
14121350
hir::ExprKind::While(ref test, ref blk, opt_label) => {
14131351
if let Some(label) = opt_label {
14141352
self.print_ident(label.ident)?;
@@ -2414,7 +2352,6 @@ impl<'a> State<'a> {
24142352
/// isn't parsed as (if true {...} else {...} | x) | 5
24152353
fn expr_requires_semi_to_be_stmt(e: &hir::Expr) -> bool {
24162354
match e.node {
2417-
hir::ExprKind::If(..) |
24182355
hir::ExprKind::Match(..) |
24192356
hir::ExprKind::Block(..) |
24202357
hir::ExprKind::While(..) |

src/librustc/ich/impls_syntax.rs

+1
Original file line numberDiff line numberDiff line change
@@ -395,6 +395,7 @@ impl_stable_hash_for!(enum ::syntax_pos::hygiene::ExpnFormat {
395395
});
396396

397397
impl_stable_hash_for!(enum ::syntax_pos::hygiene::CompilerDesugaringKind {
398+
IfTemporary,
398399
Async,
399400
Await,
400401
QuestionMark,

0 commit comments

Comments
 (0)