Skip to content

Commit d03fe84

Browse files
committed
Auto merge of rust-lang#79328 - c410-f3r:hir-if, r=matthewjasper
Reintroduce hir::ExprKind::If Basically copied and paste rust-lang#59288/rust-lang/rust-clippy#4080 with some modifications. The vast majority of tests were fixed and now there are only a few remaining. Since I am still unable to figure out the missing pieces, any help with the following list is welcome. - [ ] **Unnecessary `typeck` exception**: [Cheated on this one to make CI green.](https://github.com/rust-lang/rust/pull/79328/files#diff-3faee9ba23fc54a12b7c43364ba81f8c5660045c7e1d7989a02a0cee1c5b2051) - [x] **Incorrect span**: [Span should reference `then` and `else` separately.](https://github.com/rust-lang/rust/pull/79328/files#diff-cf2c46e82222ee4b1037a68fff8a1af3c4f1de7a6b3fd798aacbf3c0475abe3d) - [x] **New note regarding `assert!`**: [Modified but not "wrong". Maybe can be a good thing?](https://github.com/rust-lang/rust/pull/79328/files#diff-9e0d7c89ed0224e2b62060c957177c27db43c30dfe3c2974cb6b5091cda9cfb5) - [x] **Inverted report location**: [Modified but not "wrong". Locations were inverted.](https://github.com/rust-lang/rust/pull/79328/files#diff-f637ce7c1f68d523a165aa9651765df05e36c4d7d279194b1a6b28b48a323691) - [x] **`src/test/ui/point-to-type-err-cause-on-impl-trait-return.rs` has weird errors**: [Not sure why this is happening.](https://github.com/rust-lang/rust/pull/79328/files#diff-c823c09660f5b112f95e97e8ff71f1797b6c7f37dbb3d16f8e98bbaea8072e95) - [x] **Missing diagnostic**: [???](https://github.com/rust-lang/rust/pull/79328/files#diff-6b8ab09360d725ba4513933827f9796b42ff9522b0690f80b76de067143af2fc)
2 parents 7bb1630 + b0ac0fb commit d03fe84

File tree

139 files changed

+3100
-3055
lines changed

Some content is hidden

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

139 files changed

+3100
-3055
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
@@ -1431,6 +1431,7 @@ impl Expr<'_> {
14311431
ExprKind::Lit(_) => ExprPrecedence::Lit,
14321432
ExprKind::Type(..) | ExprKind::Cast(..) => ExprPrecedence::Cast,
14331433
ExprKind::DropTemps(ref expr, ..) => expr.precedence(),
1434+
ExprKind::If(..) => ExprPrecedence::If,
14341435
ExprKind::Loop(..) => ExprPrecedence::Loop,
14351436
ExprKind::Match(..) => ExprPrecedence::Match,
14361437
ExprKind::Closure(..) => ExprPrecedence::Closure,
@@ -1492,6 +1493,7 @@ impl Expr<'_> {
14921493
| ExprKind::MethodCall(..)
14931494
| ExprKind::Struct(..)
14941495
| ExprKind::Tup(..)
1496+
| ExprKind::If(..)
14951497
| ExprKind::Match(..)
14961498
| ExprKind::Closure(..)
14971499
| ExprKind::Block(..)
@@ -1608,6 +1610,10 @@ pub enum ExprKind<'hir> {
16081610
/// This construct only exists to tweak the drop order in HIR lowering.
16091611
/// An example of that is the desugaring of `for` loops.
16101612
DropTemps(&'hir Expr<'hir>),
1613+
/// An `if` block, with an optional else block.
1614+
///
1615+
/// I.e., `if <expr> { <expr> } else { <expr> }`.
1616+
If(&'hir Expr<'hir>, &'hir Expr<'hir>, Option<&'hir Expr<'hir>>),
16111617
/// A conditionless loop (can be exited with `break`, `continue`, or `return`).
16121618
///
16131619
/// I.e., `'label: loop { <block> }`.
@@ -1761,8 +1767,6 @@ pub enum LocalSource {
17611767
pub enum MatchSource {
17621768
/// A `match _ { .. }`.
17631769
Normal,
1764-
/// An `if _ { .. }` (optionally with `else { .. }`).
1765-
IfDesugar { contains_else_clause: bool },
17661770
/// An `if let _ = _ { .. }` (optionally with `else { .. }`).
17671771
IfLetDesugar { contains_else_clause: bool },
17681772
/// An `if let _ = _ => { .. }` match guard.
@@ -1785,7 +1789,7 @@ impl MatchSource {
17851789
use MatchSource::*;
17861790
match self {
17871791
Normal => "match",
1788-
IfDesugar { .. } | IfLetDesugar { .. } | IfLetGuardDesugar => "if",
1792+
IfLetDesugar { .. } | IfLetGuardDesugar => "if",
17891793
WhileDesugar | WhileLetDesugar => "while",
17901794
ForLoopDesugar => "for",
17911795
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
@@ -1080,6 +1080,50 @@ impl<'a> State<'a> {
10801080
self.ann.post(self, AnnNode::Block(blk))
10811081
}
10821082

1083+
fn print_else(&mut self, els: Option<&hir::Expr<'_>>) {
1084+
match els {
1085+
Some(_else) => {
1086+
match _else.kind {
1087+
// "another else-if"
1088+
hir::ExprKind::If(ref i, ref then, ref e) => {
1089+
self.cbox(INDENT_UNIT - 1);
1090+
self.ibox(0);
1091+
self.s.word(" else if ");
1092+
self.print_expr_as_cond(&i);
1093+
self.s.space();
1094+
self.print_expr(&then);
1095+
self.print_else(e.as_ref().map(|e| &**e))
1096+
}
1097+
// "final else"
1098+
hir::ExprKind::Block(ref b, _) => {
1099+
self.cbox(INDENT_UNIT - 1);
1100+
self.ibox(0);
1101+
self.s.word(" else ");
1102+
self.print_block(&b)
1103+
}
1104+
// BLEAH, constraints would be great here
1105+
_ => {
1106+
panic!("print_if saw if with weird alternative");
1107+
}
1108+
}
1109+
}
1110+
_ => {}
1111+
}
1112+
}
1113+
1114+
pub fn print_if(
1115+
&mut self,
1116+
test: &hir::Expr<'_>,
1117+
blk: &hir::Expr<'_>,
1118+
elseopt: Option<&hir::Expr<'_>>,
1119+
) {
1120+
self.head("if");
1121+
self.print_expr_as_cond(test);
1122+
self.s.space();
1123+
self.print_expr(blk);
1124+
self.print_else(elseopt)
1125+
}
1126+
10831127
pub fn print_anon_const(&mut self, constant: &hir::AnonConst) {
10841128
self.ann.nested(self, Nested::Body(constant.body))
10851129
}
@@ -1349,6 +1393,9 @@ impl<'a> State<'a> {
13491393
// Print `}`:
13501394
self.bclose_maybe_open(expr.span, true);
13511395
}
1396+
hir::ExprKind::If(ref test, ref blk, ref elseopt) => {
1397+
self.print_if(&test, &blk, elseopt.as_ref().map(|e| &**e));
1398+
}
13521399
hir::ExprKind::Loop(ref blk, opt_label, _) => {
13531400
if let Some(label) = opt_label {
13541401
self.print_ident(label.ident);
@@ -2429,7 +2476,13 @@ impl<'a> State<'a> {
24292476
//
24302477
// Duplicated from `parse::classify`, but adapted for the HIR.
24312478
fn expr_requires_semi_to_be_stmt(e: &hir::Expr<'_>) -> bool {
2432-
!matches!(e.kind, hir::ExprKind::Match(..) | hir::ExprKind::Block(..) | hir::ExprKind::Loop(..))
2479+
!matches!(
2480+
e.kind,
2481+
hir::ExprKind::If(..)
2482+
| hir::ExprKind::Match(..)
2483+
| hir::ExprKind::Block(..)
2484+
| hir::ExprKind::Loop(..)
2485+
)
24332486
}
24342487

24352488
/// 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)