Skip to content

Commit f85fc26

Browse files
committed
Reintroduce hir::ExprKind::If
1 parent c8915ee commit f85fc26

File tree

97 files changed

+1011
-752
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

97 files changed

+1011
-752
lines changed

compiler/rustc_ast_lowering/src/expr.rs

+31-25
Original file line numberDiff line numberDiff line change
@@ -87,9 +87,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
8787
ExprKind::Let(ref pat, ref scrutinee) => {
8888
self.lower_expr_let(e.span, pat, scrutinee)
8989
}
90-
ExprKind::If(ref cond, ref then, ref else_opt) => {
91-
self.lower_expr_if(e.span, cond, then, else_opt.as_deref())
92-
}
90+
ExprKind::If(ref cond, ref then, ref else_opt) => match cond.kind {
91+
ExprKind::Let(ref pat, ref scrutinee) => {
92+
self.lower_expr_if_let(e.span, pat, scrutinee, then, else_opt.as_deref())
93+
}
94+
_ => self.lower_expr_if(cond, then, else_opt.as_deref()),
95+
},
9396
ExprKind::While(ref cond, ref body, opt_label) => self
9497
.with_loop_scope(e.id, |this| {
9598
this.lower_expr_while_in_loop_scope(e.span, cond, body, opt_label)
@@ -337,10 +340,30 @@ impl<'hir> LoweringContext<'_, 'hir> {
337340

338341
fn lower_expr_if(
339342
&mut self,
340-
span: Span,
341343
cond: &Expr,
342344
then: &Block,
343345
else_opt: Option<&Expr>,
346+
) -> hir::ExprKind<'hir> {
347+
macro_rules! make_if {
348+
($opt:expr) => {{
349+
let then_expr = self.lower_block_expr(then);
350+
hir::ExprKind::If(self.lower_expr(cond), self.arena.alloc(then_expr), $opt)
351+
}};
352+
}
353+
if let Some(rslt) = else_opt {
354+
make_if!(Some(self.lower_expr(rslt)))
355+
} else {
356+
make_if!(None)
357+
}
358+
}
359+
360+
fn lower_expr_if_let(
361+
&mut self,
362+
span: Span,
363+
pat: &Pat,
364+
scrutinee: &Expr,
365+
then: &Block,
366+
else_opt: Option<&Expr>,
344367
) -> hir::ExprKind<'hir> {
345368
// FIXME(#53667): handle lowering of && and parens.
346369

@@ -353,30 +376,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
353376
let else_arm = self.arm(else_pat, else_expr);
354377

355378
// Handle then + scrutinee:
356-
let (then_pat, scrutinee, desugar) = match cond.kind {
357-
// `<pat> => <then>`:
358-
ExprKind::Let(ref pat, ref scrutinee) => {
359-
let scrutinee = self.lower_expr(scrutinee);
360-
let pat = self.lower_pat(pat);
361-
(pat, scrutinee, hir::MatchSource::IfLetDesugar { contains_else_clause })
362-
}
363-
// `true => <then>`:
364-
_ => {
365-
// Lower condition:
366-
let cond = self.lower_expr(cond);
367-
let span_block =
368-
self.mark_span_with_reason(DesugaringKind::CondTemporary, cond.span, None);
369-
// Wrap in a construct equivalent to `{ let _t = $cond; _t }`
370-
// to preserve drop semantics since `if cond { ... }` does not
371-
// let temporaries live outside of `cond`.
372-
let cond = self.expr_drop_temps(span_block, cond, ThinVec::new());
373-
let pat = self.pat_bool(span, true);
374-
(pat, cond, hir::MatchSource::IfDesugar { contains_else_clause })
375-
}
376-
};
379+
let scrutinee = self.lower_expr(scrutinee);
380+
let then_pat = self.lower_pat(pat);
381+
377382
let then_expr = self.lower_block_expr(then);
378383
let then_arm = self.arm(then_pat, self.arena.alloc(then_expr));
379384

385+
let desugar = hir::MatchSource::IfLetDesugar { contains_else_clause };
380386
hir::ExprKind::Match(scrutinee, arena_vec![self; then_arm, else_arm], desugar)
381387
}
382388

compiler/rustc_hir/src/hir.rs

+7-3
Original file line numberDiff line numberDiff line change
@@ -1398,6 +1398,7 @@ impl Expr<'_> {
13981398
ExprKind::Lit(_) => ExprPrecedence::Lit,
13991399
ExprKind::Type(..) | ExprKind::Cast(..) => ExprPrecedence::Cast,
14001400
ExprKind::DropTemps(ref expr, ..) => expr.precedence(),
1401+
ExprKind::If(..) => ExprPrecedence::If,
14011402
ExprKind::Loop(..) => ExprPrecedence::Loop,
14021403
ExprKind::Match(..) => ExprPrecedence::Match,
14031404
ExprKind::Closure(..) => ExprPrecedence::Closure,
@@ -1459,6 +1460,7 @@ impl Expr<'_> {
14591460
| ExprKind::MethodCall(..)
14601461
| ExprKind::Struct(..)
14611462
| ExprKind::Tup(..)
1463+
| ExprKind::If(..)
14621464
| ExprKind::Match(..)
14631465
| ExprKind::Closure(..)
14641466
| ExprKind::Block(..)
@@ -1575,6 +1577,10 @@ pub enum ExprKind<'hir> {
15751577
/// This construct only exists to tweak the drop order in HIR lowering.
15761578
/// An example of that is the desugaring of `for` loops.
15771579
DropTemps(&'hir Expr<'hir>),
1580+
/// An `if` block, with an optional else block.
1581+
///
1582+
/// I.e., `if <expr> { <expr> } else { <expr> }`.
1583+
If(&'hir Expr<'hir>, &'hir Expr<'hir>, Option<&'hir Expr<'hir>>),
15781584
/// A conditionless loop (can be exited with `break`, `continue`, or `return`).
15791585
///
15801586
/// I.e., `'label: loop { <block> }`.
@@ -1728,8 +1734,6 @@ pub enum LocalSource {
17281734
pub enum MatchSource {
17291735
/// A `match _ { .. }`.
17301736
Normal,
1731-
/// An `if _ { .. }` (optionally with `else { .. }`).
1732-
IfDesugar { contains_else_clause: bool },
17331737
/// An `if let _ = _ { .. }` (optionally with `else { .. }`).
17341738
IfLetDesugar { contains_else_clause: bool },
17351739
/// An `if let _ = _ => { .. }` match guard.
@@ -1752,7 +1756,7 @@ impl MatchSource {
17521756
use MatchSource::*;
17531757
match self {
17541758
Normal => "match",
1755-
IfDesugar { .. } | IfLetDesugar { .. } | IfLetGuardDesugar => "if",
1759+
IfLetDesugar { .. } | IfLetGuardDesugar => "if",
17561760
WhileDesugar | WhileLetDesugar => "while",
17571761
ForLoopDesugar => "for",
17581762
TryDesugar => "?",

compiler/rustc_hir/src/intravisit.rs

+5
Original file line numberDiff line numberDiff line change
@@ -1146,6 +1146,11 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>)
11461146
ExprKind::DropTemps(ref subexpression) => {
11471147
visitor.visit_expr(subexpression);
11481148
}
1149+
ExprKind::If(ref cond, ref then, ref else_opt) => {
1150+
visitor.visit_expr(cond);
1151+
visitor.visit_expr(then);
1152+
walk_list!(visitor, visit_expr, else_opt);
1153+
}
11491154
ExprKind::Loop(ref block, ref opt_label, _) => {
11501155
walk_list!(visitor, visit_label, opt_label);
11511156
visitor.visit_block(block);

compiler/rustc_hir_pretty/src/lib.rs

+54-1
Original file line numberDiff line numberDiff line change
@@ -1083,6 +1083,50 @@ impl<'a> State<'a> {
10831083
self.ann.post(self, AnnNode::Block(blk))
10841084
}
10851085

1086+
fn print_else(&mut self, els: Option<&hir::Expr<'_>>) {
1087+
match els {
1088+
Some(_else) => {
1089+
match _else.kind {
1090+
// "another else-if"
1091+
hir::ExprKind::If(ref i, ref then, ref e) => {
1092+
self.cbox(INDENT_UNIT - 1);
1093+
self.ibox(0);
1094+
self.s.word(" else if ");
1095+
self.print_expr_as_cond(&i);
1096+
self.s.space();
1097+
self.print_expr(&then);
1098+
self.print_else(e.as_ref().map(|e| &**e))
1099+
}
1100+
// "final else"
1101+
hir::ExprKind::Block(ref b, _) => {
1102+
self.cbox(INDENT_UNIT - 1);
1103+
self.ibox(0);
1104+
self.s.word(" else ");
1105+
self.print_block(&b)
1106+
}
1107+
// BLEAH, constraints would be great here
1108+
_ => {
1109+
panic!("print_if saw if with weird alternative");
1110+
}
1111+
}
1112+
}
1113+
_ => {}
1114+
}
1115+
}
1116+
1117+
pub fn print_if(
1118+
&mut self,
1119+
test: &hir::Expr<'_>,
1120+
blk: &hir::Expr<'_>,
1121+
elseopt: Option<&hir::Expr<'_>>,
1122+
) {
1123+
self.head("if");
1124+
self.print_expr_as_cond(test);
1125+
self.s.space();
1126+
self.print_expr(blk);
1127+
self.print_else(elseopt)
1128+
}
1129+
10861130
pub fn print_anon_const(&mut self, constant: &hir::AnonConst) {
10871131
self.ann.nested(self, Nested::Body(constant.body))
10881132
}
@@ -1352,6 +1396,9 @@ impl<'a> State<'a> {
13521396
// Print `}`:
13531397
self.bclose_maybe_open(expr.span, true);
13541398
}
1399+
hir::ExprKind::If(ref test, ref blk, ref elseopt) => {
1400+
self.print_if(&test, &blk, elseopt.as_ref().map(|e| &**e));
1401+
}
13551402
hir::ExprKind::Loop(ref blk, opt_label, _) => {
13561403
if let Some(label) = opt_label {
13571404
self.print_ident(label.ident);
@@ -2436,7 +2483,13 @@ impl<'a> State<'a> {
24362483
//
24372484
// Duplicated from `parse::classify`, but adapted for the HIR.
24382485
fn expr_requires_semi_to_be_stmt(e: &hir::Expr<'_>) -> bool {
2439-
!matches!(e.kind, hir::ExprKind::Match(..) | hir::ExprKind::Block(..) | hir::ExprKind::Loop(..))
2486+
!matches!(
2487+
e.kind,
2488+
hir::ExprKind::If(..)
2489+
| hir::ExprKind::Match(..)
2490+
| hir::ExprKind::Block(..)
2491+
| hir::ExprKind::Loop(..)
2492+
)
24402493
}
24412494

24422495
/// This statement requires a semicolon after it.

compiler/rustc_middle/src/hir/map/mod.rs

+7-5
Original file line numberDiff line numberDiff line change
@@ -658,20 +658,22 @@ impl<'hir> Map<'hir> {
658658
CRATE_HIR_ID
659659
}
660660

661-
/// When on a match arm tail expression or on a match arm, give back the enclosing `match`
662-
/// expression.
661+
/// When on an if expression, a match arm tail expression or a match arm, give back
662+
/// the enclosing `if` or `match` expression.
663663
///
664-
/// Used by error reporting when there's a type error in a match arm caused by the `match`
664+
/// Used by error reporting when there's a type error in an if or match arm caused by the
665665
/// expression needing to be unit.
666-
pub fn get_match_if_cause(&self, hir_id: HirId) -> Option<&'hir Expr<'hir>> {
666+
pub fn get_if_cause(&self, hir_id: HirId) -> Option<&'hir Expr<'hir>> {
667667
for (_, node) in self.parent_iter(hir_id) {
668668
match node {
669669
Node::Item(_)
670670
| Node::ForeignItem(_)
671671
| Node::TraitItem(_)
672672
| Node::ImplItem(_)
673673
| Node::Stmt(Stmt { kind: StmtKind::Local(_), .. }) => break,
674-
Node::Expr(expr @ Expr { kind: ExprKind::Match(..), .. }) => return Some(expr),
674+
Node::Expr(expr @ Expr { kind: ExprKind::If(..) | ExprKind::Match(..), .. }) => {
675+
return Some(expr);
676+
}
675677
_ => {}
676678
}
677679
}

compiler/rustc_mir_build/src/build/expr/as_place.rs

+1
Original file line numberDiff line numberDiff line change
@@ -531,6 +531,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
531531
| ExprKind::Borrow { .. }
532532
| ExprKind::AddressOf { .. }
533533
| ExprKind::Match { .. }
534+
| ExprKind::If { .. }
534535
| ExprKind::Loop { .. }
535536
| ExprKind::Block { .. }
536537
| ExprKind::Assign { .. }

compiler/rustc_mir_build/src/build/expr/as_rvalue.rs

+1
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
251251
| ExprKind::StaticRef { .. }
252252
| ExprKind::Block { .. }
253253
| ExprKind::Match { .. }
254+
| ExprKind::If { .. }
254255
| ExprKind::NeverToAny { .. }
255256
| ExprKind::Use { .. }
256257
| ExprKind::Borrow { .. }

compiler/rustc_mir_build/src/build/expr/category.rs

+1
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ impl Category {
4545

4646
ExprKind::LogicalOp { .. }
4747
| ExprKind::Match { .. }
48+
| ExprKind::If { .. }
4849
| ExprKind::NeverToAny { .. }
4950
| ExprKind::Use { .. }
5051
| ExprKind::Adt { .. }

compiler/rustc_mir_build/src/build/expr/into.rs

+34
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,40 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
6969
ExprKind::Match { scrutinee, arms } => {
7070
this.match_expr(destination, scope, expr_span, block, scrutinee, arms)
7171
}
72+
ExprKind::If { cond, then, else_opt } => {
73+
let place = unpack!(block = this.as_temp(block, Some(this.local_scope()), cond, Mutability::Mut));
74+
let operand = Operand::Move(Place::from(place));
75+
76+
let mut then_block = this.cfg.start_new_block();
77+
let mut else_block = this.cfg.start_new_block();
78+
let term = TerminatorKind::if_(this.hir.tcx(), operand, then_block, else_block);
79+
this.cfg.terminate(block, source_info, term);
80+
81+
unpack!(then_block = this.into(destination, scope, then_block, then));
82+
else_block = if let Some(else_opt) = else_opt {
83+
unpack!(this.into(destination, None, else_block, else_opt))
84+
} else {
85+
// Body of the `if` expression without an `else` clause must return `()`, thus
86+
// we implicitly generate a `else {}` if it is not specified.
87+
let correct_si = this.source_info(expr_span.shrink_to_hi());
88+
this.cfg.push_assign_unit(else_block, correct_si, destination, this.hir.tcx());
89+
else_block
90+
};
91+
92+
let join_block = this.cfg.start_new_block();
93+
this.cfg.terminate(
94+
then_block,
95+
source_info,
96+
TerminatorKind::Goto { target: join_block },
97+
);
98+
this.cfg.terminate(
99+
else_block,
100+
source_info,
101+
TerminatorKind::Goto { target: join_block },
102+
);
103+
104+
join_block.unit()
105+
},
72106
ExprKind::NeverToAny { source } => {
73107
let source = this.hir.mirror(source);
74108
let is_call = matches!(source.kind, ExprKind::Call { .. } | ExprKind::InlineAsm { .. });

compiler/rustc_mir_build/src/thir/cx/expr.rs

+5
Original file line numberDiff line numberDiff line change
@@ -537,6 +537,11 @@ fn make_mirror_unadjusted<'a, 'tcx>(
537537
},
538538
Err(err) => bug!("invalid loop id for continue: {}", err),
539539
},
540+
hir::ExprKind::If(cond, then, else_opt) => ExprKind::If {
541+
cond: cond.to_ref(),
542+
then: then.to_ref(),
543+
else_opt: else_opt.map(|el| el.to_ref()),
544+
},
540545
hir::ExprKind::Match(ref discr, ref arms, _) => ExprKind::Match {
541546
scrutinee: discr.to_ref(),
542547
arms: arms.iter().map(|a| convert_arm(cx, a)).collect(),

compiler/rustc_mir_build/src/thir/mod.rs

+5
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,11 @@ crate enum ExprKind<'tcx> {
139139
Box {
140140
value: ExprRef<'tcx>,
141141
},
142+
If {
143+
cond: ExprRef<'tcx>,
144+
then: ExprRef<'tcx>,
145+
else_opt: Option<ExprRef<'tcx>>,
146+
},
142147
Call {
143148
ty: Ty<'tcx>,
144149
fun: ExprRef<'tcx>,

compiler/rustc_mir_build/src/thir/pattern/check_match.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -403,7 +403,7 @@ fn report_arm_reachability<'p, 'tcx>(
403403
match is_useful {
404404
NotUseful => {
405405
match source {
406-
hir::MatchSource::IfDesugar { .. } | hir::MatchSource::WhileDesugar => bug!(),
406+
hir::MatchSource::WhileDesugar => bug!(),
407407

408408
hir::MatchSource::IfLetDesugar { .. } | hir::MatchSource::WhileLetDesugar => {
409409
// Check which arm we're on.

compiler/rustc_passes/src/check_const.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,7 @@ impl NonConstExpr {
4949

5050
// All other expressions are allowed.
5151
Self::Loop(Loop | While | WhileLet)
52-
| Self::Match(
53-
WhileDesugar | WhileLetDesugar | Normal | IfDesugar { .. } | IfLetDesugar { .. },
54-
) => &[],
52+
| Self::Match(WhileDesugar | WhileLetDesugar | Normal | IfLetDesugar { .. }) => &[],
5553
};
5654

5755
Some(gates)

compiler/rustc_passes/src/liveness.rs

+25-1
Original file line numberDiff line numberDiff line change
@@ -419,7 +419,7 @@ impl<'tcx> Visitor<'tcx> for IrMaps<'tcx> {
419419
}
420420

421421
// live nodes required for interesting control flow:
422-
hir::ExprKind::Match(..) | hir::ExprKind::Loop(..) => {
422+
hir::ExprKind::If(..) | hir::ExprKind::Match(..) | hir::ExprKind::Loop(..) => {
423423
self.add_live_node_for_node(expr.hir_id, ExprNode(expr.span));
424424
intravisit::walk_expr(self, expr);
425425
}
@@ -846,6 +846,29 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
846846
// at the label ident
847847
hir::ExprKind::Loop(ref blk, _, _) => self.propagate_through_loop(expr, &blk, succ),
848848

849+
hir::ExprKind::If(ref cond, ref then, ref else_opt) => {
850+
//
851+
// (cond)
852+
// |
853+
// v
854+
// (expr)
855+
// / \
856+
// | |
857+
// v v
858+
// (then)(els)
859+
// | |
860+
// v v
861+
// ( succ )
862+
//
863+
let else_ln =
864+
self.propagate_through_opt_expr(else_opt.as_ref().map(|e| &**e), succ);
865+
let then_ln = self.propagate_through_expr(&then, succ);
866+
let ln = self.live_node(expr.hir_id, expr.span);
867+
self.init_from_succ(ln, else_ln);
868+
self.merge_from_succ(ln, then_ln);
869+
self.propagate_through_expr(&cond, ln)
870+
}
871+
849872
hir::ExprKind::Match(ref e, arms, _) => {
850873
//
851874
// (e)
@@ -1336,6 +1359,7 @@ fn check_expr<'tcx>(this: &mut Liveness<'_, 'tcx>, expr: &'tcx Expr<'tcx>) {
13361359
| hir::ExprKind::Tup(..)
13371360
| hir::ExprKind::Binary(..)
13381361
| hir::ExprKind::Cast(..)
1362+
| hir::ExprKind::If(..)
13391363
| hir::ExprKind::DropTemps(..)
13401364
| hir::ExprKind::Unary(..)
13411365
| hir::ExprKind::Ret(..)

0 commit comments

Comments
 (0)