Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit e37ec72

Browse files
committed
Auto merge of rust-lang#15373 - tadeokondrak:desugar-while-to-loop, r=HKalbasi
internal: Desugar while to loop and break I was reading through rust-analyzer's code and was wondering why this wasn't desugared into a loop.
2 parents d398ad3 + 92a97c2 commit e37ec72

File tree

11 files changed

+21
-75
lines changed

11 files changed

+21
-75
lines changed

crates/hir-def/src/body/lower.rs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -314,11 +314,18 @@ impl ExprCollector<'_> {
314314
self.alloc_expr(Expr::Loop { body, label }, syntax_ptr)
315315
}
316316
ast::Expr::WhileExpr(e) => {
317+
// Desugar `while <cond> { <body> }` to
318+
// `loop { if <cond> { <body> } else { break } }`
317319
let label = e.label().map(|label| self.collect_label(label));
318320
let body = self.collect_labelled_block_opt(label, e.loop_body());
319321
let condition = self.collect_expr_opt(e.condition());
320-
321-
self.alloc_expr(Expr::While { condition, body, label }, syntax_ptr)
322+
let break_expr =
323+
self.alloc_expr(Expr::Break { expr: None, label: None }, syntax_ptr.clone());
324+
let if_expr = self.alloc_expr(
325+
Expr::If { condition, then_branch: body, else_branch: Some(break_expr) },
326+
syntax_ptr.clone(),
327+
);
328+
self.alloc_expr(Expr::Loop { body: if_expr, label }, syntax_ptr)
322329
}
323330
ast::Expr::ForExpr(e) => self.collect_for_loop(syntax_ptr, e),
324331
ast::Expr::CallExpr(e) => {

crates/hir-def/src/body/pretty.rs

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -178,14 +178,6 @@ impl Printer<'_> {
178178
w!(self, "loop ");
179179
self.print_expr(*body);
180180
}
181-
Expr::While { condition, body, label } => {
182-
if let Some(lbl) = label {
183-
w!(self, "{}: ", self.body[*lbl].name.display(self.db));
184-
}
185-
w!(self, "while ");
186-
self.print_expr(*condition);
187-
self.print_expr(*body);
188-
}
189181
Expr::Call { callee, args, is_assignee_expr: _ } => {
190182
self.print_expr(*callee);
191183
w!(self, "(");

crates/hir-def/src/body/scope.rs

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -228,11 +228,6 @@ fn compute_expr_scopes(expr: ExprId, body: &Body, scopes: &mut ExprScopes, scope
228228
scopes.set_scope(expr, scope);
229229
compute_block_scopes(statements, *tail, body, scopes, &mut scope);
230230
}
231-
Expr::While { condition, body: body_expr, label } => {
232-
let mut scope = scopes.new_labeled_scope(*scope, make_label(label));
233-
compute_expr_scopes(*condition, body, scopes, &mut scope);
234-
compute_expr_scopes(*body_expr, body, scopes, &mut scope);
235-
}
236231
Expr::Loop { body: body_expr, label } => {
237232
let mut scope = scopes.new_labeled_scope(*scope, make_label(label));
238233
compute_expr_scopes(*body_expr, body, scopes, &mut scope);

crates/hir-def/src/hir.rs

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -191,11 +191,6 @@ pub enum Expr {
191191
body: ExprId,
192192
label: Option<LabelId>,
193193
},
194-
While {
195-
condition: ExprId,
196-
body: ExprId,
197-
label: Option<LabelId>,
198-
},
199194
Call {
200195
callee: ExprId,
201196
args: Box<[ExprId]>,
@@ -379,10 +374,6 @@ impl Expr {
379374
}
380375
}
381376
Expr::Loop { body, .. } => f(*body),
382-
Expr::While { condition, body, .. } => {
383-
f(*condition);
384-
f(*body);
385-
}
386377
Expr::Call { callee, args, .. } => {
387378
f(*callee);
388379
args.iter().copied().for_each(f);

crates/hir-ty/src/infer/closure.rs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -488,10 +488,6 @@ impl InferenceContext<'_> {
488488
self.consume_expr(*tail);
489489
}
490490
}
491-
Expr::While { condition, body, label: _ } => {
492-
self.consume_expr(*condition);
493-
self.consume_expr(*body);
494-
}
495491
Expr::Call { callee, args, is_assignee_expr: _ } => {
496492
self.consume_expr(*callee);
497493
self.consume_exprs(args.iter().copied());

crates/hir-ty/src/infer/expr.rs

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -198,19 +198,6 @@ impl InferenceContext<'_> {
198198
None => self.result.standard_types.never.clone(),
199199
}
200200
}
201-
&Expr::While { condition, body, label } => {
202-
self.with_breakable_ctx(BreakableKind::Loop, None, label, |this| {
203-
this.infer_expr(
204-
condition,
205-
&Expectation::HasType(this.result.standard_types.bool_.clone()),
206-
);
207-
this.infer_expr(body, &Expectation::HasType(TyBuilder::unit()));
208-
});
209-
210-
// the body may not run, so it diverging doesn't mean we diverge
211-
self.diverges = Diverges::Maybe;
212-
TyBuilder::unit()
213-
}
214201
Expr::Closure { body, args, ret_type, arg_types, closure_kind, capture_by: _ } => {
215202
assert_eq!(args.len(), arg_types.len());
216203

crates/hir-ty/src/infer/mutability.rs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -69,10 +69,6 @@ impl InferenceContext<'_> {
6969
self.infer_mut_expr(*tail, Mutability::Not);
7070
}
7171
}
72-
&Expr::While { condition: c, body, label: _ } => {
73-
self.infer_mut_expr(c, Mutability::Not);
74-
self.infer_mut_expr(body, Mutability::Not);
75-
}
7672
Expr::MethodCall { receiver: it, method_name: _, args, generic_args: _ }
7773
| Expr::Call { callee: it, args, is_assignee_expr: _ } => {
7874
self.infer_mut_not_expr_iter(args.iter().copied().chain(Some(*it)));

crates/hir-ty/src/mir/lower.rs

Lines changed: 0 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -582,36 +582,6 @@ impl<'ctx> MirLowerCtx<'ctx> {
582582
Ok(())
583583
})
584584
}
585-
Expr::While { condition, body, label } => {
586-
self.lower_loop(current, place, *label, expr_id.into(), |this, begin| {
587-
let scope = this.push_drop_scope();
588-
let Some((discr, to_switch)) =
589-
this.lower_expr_to_some_operand(*condition, begin)?
590-
else {
591-
return Ok(());
592-
};
593-
let fail_cond = this.new_basic_block();
594-
let after_cond = this.new_basic_block();
595-
this.set_terminator(
596-
to_switch,
597-
TerminatorKind::SwitchInt {
598-
discr,
599-
targets: SwitchTargets::static_if(1, after_cond, fail_cond),
600-
},
601-
expr_id.into(),
602-
);
603-
let fail_cond = this.drop_until_scope(this.drop_scopes.len() - 1, fail_cond);
604-
let end = this.current_loop_end()?;
605-
this.set_goto(fail_cond, end, expr_id.into());
606-
if let Some((_, block)) = this.lower_expr_as_place(after_cond, *body, true)? {
607-
let block = scope.pop_and_drop(this, block);
608-
this.set_goto(block, begin, expr_id.into());
609-
} else {
610-
scope.pop_assume_dropped(this);
611-
}
612-
Ok(())
613-
})
614-
}
615585
Expr::Call { callee, args, .. } => {
616586
if let Some((func_id, generic_args)) = self.infer.method_resolution(expr_id) {
617587
let ty = chalk_ir::TyKind::FnDef(

crates/hir-ty/src/tests/macros.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,8 @@ fn expr_macro_def_expanded_in_various_places() {
209209
104..105 '_': IntoIterator::Item<isize>
210210
117..119 '{}': ()
211211
124..134 '|| spam!()': impl Fn() -> isize
212+
140..156 'while ...!() {}': !
213+
140..156 'while ...!() {}': ()
212214
140..156 'while ...!() {}': ()
213215
154..156 '{}': ()
214216
161..174 'break spam!()': !
@@ -300,6 +302,8 @@ fn expr_macro_rules_expanded_in_various_places() {
300302
118..119 '_': IntoIterator::Item<isize>
301303
131..133 '{}': ()
302304
138..148 '|| spam!()': impl Fn() -> isize
305+
154..170 'while ...!() {}': !
306+
154..170 'while ...!() {}': ()
303307
154..170 'while ...!() {}': ()
304308
168..170 '{}': ()
305309
175..188 'break spam!()': !

crates/hir-ty/src/tests/never_type.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -412,17 +412,23 @@ fn diverging_expression_3_break() {
412412
355..654 '{ ...; }; }': ()
413413
398..399 'x': u32
414414
407..433 '{ whil...; }; }': u32
415+
409..430 'while ...eak; }': !
416+
409..430 'while ...eak; }': ()
415417
409..430 'while ...eak; }': ()
416418
415..419 'true': bool
417419
420..430 '{ break; }': ()
418420
422..427 'break': !
419421
537..538 'x': u32
420422
546..564 '{ whil... {}; }': u32
423+
548..561 'while true {}': !
424+
548..561 'while true {}': ()
421425
548..561 'while true {}': ()
422426
554..558 'true': bool
423427
559..561 '{}': ()
424428
615..616 'x': u32
425429
624..651 '{ whil...; }; }': u32
430+
626..648 'while ...urn; }': !
431+
626..648 'while ...urn; }': ()
426432
626..648 'while ...urn; }': ()
427433
632..636 'true': bool
428434
637..648 '{ return; }': ()

crates/hir-ty/src/tests/regression.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1267,6 +1267,8 @@ fn test() {
12671267
"#,
12681268
expect![[r#"
12691269
10..59 '{ ... } }': ()
1270+
16..57 'while ... }': !
1271+
16..57 'while ... }': ()
12701272
16..57 'while ... }': ()
12711273
22..30 '{ true }': bool
12721274
24..28 'true': bool

0 commit comments

Comments
 (0)