about summary refs log tree commit diff
diff options
context:
space:
mode:
authorTadeo Kondrak <me@tadeo.ca>2023-08-01 19:04:36 -0600
committerTadeo Kondrak <me@tadeo.ca>2023-08-01 19:04:36 -0600
commit31bcba84f9281752b63254d9c7fdfb9c7792011f (patch)
tree8515f985d9ab37bd5c63d81c877feaf3d35dad01
parent151c750dac8d2a03a4a1f9c20d2fc29ad2042f02 (diff)
downloadrust-31bcba84f9281752b63254d9c7fdfb9c7792011f.tar.gz
rust-31bcba84f9281752b63254d9c7fdfb9c7792011f.zip
hir: Desugar `while` to `loop` and `break`
-rw-r--r--crates/hir-def/src/body/lower.rs11
-rw-r--r--crates/hir-ty/src/tests/macros.rs4
-rw-r--r--crates/hir-ty/src/tests/never_type.rs6
-rw-r--r--crates/hir-ty/src/tests/regression.rs2
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 152c02743f7..c8d1ca4fa70 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 <cond> { <body> }` to
+                // `loop { if <cond> { <body> } 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 b71c457f015..1e6e946a13f 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<isize>
             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<isize>
             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 59046c0435a..5d809b82392 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 375014d6c7f..6ea059065e9 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