From 31bcba84f9281752b63254d9c7fdfb9c7792011f Mon Sep 17 00:00:00 2001 From: Tadeo Kondrak Date: Tue, 1 Aug 2023 19:04:36 -0600 Subject: [PATCH] hir: Desugar `while` to `loop` and `break` --- crates/hir-def/src/body/lower.rs | 11 +++++++++-- crates/hir-ty/src/tests/macros.rs | 4 ++++ crates/hir-ty/src/tests/never_type.rs | 6 ++++++ crates/hir-ty/src/tests/regression.rs | 2 ++ 4 files changed, 21 insertions(+), 2 deletions(-) diff --git a/crates/hir-def/src/body/lower.rs b/crates/hir-def/src/body/lower.rs index 152c02743f..c8d1ca4fa7 100644 --- a/crates/hir-def/src/body/lower.rs +++ b/crates/hir-def/src/body/lower.rs @@ -314,11 +314,18 @@ impl ExprCollector<'_> { self.alloc_expr(Expr::Loop { body, label }, syntax_ptr) } ast::Expr::WhileExpr(e) => { + // Desugar `while { }` to + // `loop { if { } else { break } }` let label = e.label().map(|label| self.collect_label(label)); let body = self.collect_labelled_block_opt(label, e.loop_body()); let condition = self.collect_expr_opt(e.condition()); - - self.alloc_expr(Expr::While { condition, body, label }, syntax_ptr) + let break_expr = + self.alloc_expr(Expr::Break { expr: None, label: None }, syntax_ptr.clone()); + let if_expr = self.alloc_expr( + Expr::If { condition, then_branch: body, else_branch: Some(break_expr) }, + syntax_ptr.clone(), + ); + self.alloc_expr(Expr::Loop { body: if_expr, label }, syntax_ptr) } ast::Expr::ForExpr(e) => self.collect_for_loop(syntax_ptr, e), ast::Expr::CallExpr(e) => { diff --git a/crates/hir-ty/src/tests/macros.rs b/crates/hir-ty/src/tests/macros.rs index b71c457f01..1e6e946a13 100644 --- a/crates/hir-ty/src/tests/macros.rs +++ b/crates/hir-ty/src/tests/macros.rs @@ -209,6 +209,8 @@ fn expr_macro_def_expanded_in_various_places() { 104..105 '_': IntoIterator::Item 117..119 '{}': () 124..134 '|| spam!()': impl Fn() -> isize + 140..156 'while ...!() {}': ! + 140..156 'while ...!() {}': () 140..156 'while ...!() {}': () 154..156 '{}': () 161..174 'break spam!()': ! @@ -300,6 +302,8 @@ fn expr_macro_rules_expanded_in_various_places() { 118..119 '_': IntoIterator::Item 131..133 '{}': () 138..148 '|| spam!()': impl Fn() -> isize + 154..170 'while ...!() {}': ! + 154..170 'while ...!() {}': () 154..170 'while ...!() {}': () 168..170 '{}': () 175..188 'break spam!()': ! diff --git a/crates/hir-ty/src/tests/never_type.rs b/crates/hir-ty/src/tests/never_type.rs index 59046c0435..5d809b8239 100644 --- a/crates/hir-ty/src/tests/never_type.rs +++ b/crates/hir-ty/src/tests/never_type.rs @@ -412,17 +412,23 @@ fn diverging_expression_3_break() { 355..654 '{ ...; }; }': () 398..399 'x': u32 407..433 '{ whil...; }; }': u32 + 409..430 'while ...eak; }': ! + 409..430 'while ...eak; }': () 409..430 'while ...eak; }': () 415..419 'true': bool 420..430 '{ break; }': () 422..427 'break': ! 537..538 'x': u32 546..564 '{ whil... {}; }': u32 + 548..561 'while true {}': ! + 548..561 'while true {}': () 548..561 'while true {}': () 554..558 'true': bool 559..561 '{}': () 615..616 'x': u32 624..651 '{ whil...; }; }': u32 + 626..648 'while ...urn; }': ! + 626..648 'while ...urn; }': () 626..648 'while ...urn; }': () 632..636 'true': bool 637..648 '{ return; }': () diff --git a/crates/hir-ty/src/tests/regression.rs b/crates/hir-ty/src/tests/regression.rs index 375014d6c7..6ea059065e 100644 --- a/crates/hir-ty/src/tests/regression.rs +++ b/crates/hir-ty/src/tests/regression.rs @@ -1267,6 +1267,8 @@ fn test() { "#, expect![[r#" 10..59 '{ ... } }': () + 16..57 'while ... }': ! + 16..57 'while ... }': () 16..57 'while ... }': () 22..30 '{ true }': bool 24..28 'true': bool