Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-def/src/body/lower.rs')
| -rw-r--r-- | crates/hir-def/src/body/lower.rs | 39 |
1 files changed, 29 insertions, 10 deletions
diff --git a/crates/hir-def/src/body/lower.rs b/crates/hir-def/src/body/lower.rs index 152c02743f..3853a6ab3a 100644 --- a/crates/hir-def/src/body/lower.rs +++ b/crates/hir-def/src/body/lower.rs @@ -313,13 +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) => { - 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) - } + 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 = { @@ -731,6 +725,32 @@ impl ExprCollector<'_> { expr_id } + /// Desugar `ast::WhileExpr` from: `[opt_ident]: while <cond> <body>` into: + /// ```ignore (pseudo-rust) + /// [opt_ident]: loop { + /// if <cond> { + /// <body> + /// } + /// else { + /// break; + /// } + /// } + /// ``` + /// FIXME: Rustc wraps the condition in a construct equivalent to `{ let _t = <cond>; _t }` + /// to preserve drop semantics. We should probably do the same in future. + fn collect_while_loop(&mut self, syntax_ptr: AstPtr<ast::Expr>, 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 <pat> in <head> <body>` into: /// ```ignore (pseudo-rust) /// match IntoIterator::into_iter(<head>) { @@ -893,15 +913,14 @@ impl ExprCollector<'_> { self.alloc_expr(Expr::Match { expr, arms }, syntax_ptr) } - fn collect_macro_call<F, T, U>( + fn collect_macro_call<T, U>( &mut self, mcall: ast::MacroCall, syntax_ptr: AstPtr<ast::MacroCall>, record_diagnostics: bool, - collector: F, + collector: impl FnOnce(&mut Self, Option<T>) -> U, ) -> U where - F: FnOnce(&mut Self, Option<T>) -> U, T: ast::AstNode, { // File containing the macro call. Expansion errors will be attached here. |