From cc5664c5a22f0b8fcd268f5b5866bc91dacdda6a Mon Sep 17 00:00:00 2001 From: hkalbasi Date: Fri, 4 Aug 2023 16:35:13 +0330 Subject: [PATCH] Add rustc comment into while desugaring --- crates/hir-def/src/body/lower.rs | 41 +++++++++++++++++++++----------- 1 file changed, 27 insertions(+), 14 deletions(-) diff --git a/crates/hir-def/src/body/lower.rs b/crates/hir-def/src/body/lower.rs index c8d1ca4fa7..3df4357648 100644 --- a/crates/hir-def/src/body/lower.rs +++ b/crates/hir-def/src/body/lower.rs @@ -313,20 +313,7 @@ impl ExprCollector<'_> { let body = self.collect_labelled_block_opt(label, e.loop_body()); 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()); - 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::WhileExpr(e) => self.collect_while_loop(syntax_ptr, e), ast::Expr::ForExpr(e) => self.collect_for_loop(syntax_ptr, e), ast::Expr::CallExpr(e) => { let is_rustc_box = { @@ -738,6 +725,32 @@ impl ExprCollector<'_> { expr_id } + /// Desugar `ast::WhileExpr` from: `[opt_ident]: while ` into: + /// ```ignore (pseudo-rust) + /// [opt_ident]: loop { + /// if { + /// + /// } + /// else { + /// break; + /// } + /// } + /// ``` + /// FIXME: Rustc wraps the condition in a construct equivalent to `{ let _t = ; _t }` + /// to preserve drop semantics. We should probably do the same in future. + fn collect_while_loop(&mut self, syntax_ptr: AstPtr, e: ast::WhileExpr) -> ExprId { + 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()); + 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) + } + /// Desugar `ast::ForExpr` from: `[opt_ident]: for in ` into: /// ```ignore (pseudo-rust) /// match IntoIterator::into_iter() {