@@ -313,13 +313,7 @@ impl ExprCollector<'_> {
313313 let body = self . collect_labelled_block_opt ( label, e. loop_body ( ) ) ;
314314 self . alloc_expr ( Expr :: Loop { body, label } , syntax_ptr)
315315 }
316- ast:: Expr :: WhileExpr ( e) => {
317- let label = e. label ( ) . map ( |label| self . collect_label ( label) ) ;
318- let body = self . collect_labelled_block_opt ( label, e. loop_body ( ) ) ;
319- let condition = self . collect_expr_opt ( e. condition ( ) ) ;
320-
321- self . alloc_expr ( Expr :: While { condition, body, label } , syntax_ptr)
322- }
316+ ast:: Expr :: WhileExpr ( e) => self . collect_while_loop ( syntax_ptr, e) ,
323317 ast:: Expr :: ForExpr ( e) => self . collect_for_loop ( syntax_ptr, e) ,
324318 ast:: Expr :: CallExpr ( e) => {
325319 let is_rustc_box = {
@@ -731,6 +725,32 @@ impl ExprCollector<'_> {
731725 expr_id
732726 }
733727
728+ /// Desugar `ast::WhileExpr` from: `[opt_ident]: while <cond> <body>` into:
729+ /// ```ignore (pseudo-rust)
730+ /// [opt_ident]: loop {
731+ /// if <cond> {
732+ /// <body>
733+ /// }
734+ /// else {
735+ /// break;
736+ /// }
737+ /// }
738+ /// ```
739+ /// FIXME: Rustc wraps the condition in a construct equivalent to `{ let _t = <cond>; _t }`
740+ /// to preserve drop semantics. We should probably do the same in future.
741+ fn collect_while_loop ( & mut self , syntax_ptr : AstPtr < ast:: Expr > , e : ast:: WhileExpr ) -> ExprId {
742+ let label = e. label ( ) . map ( |label| self . collect_label ( label) ) ;
743+ let body = self . collect_labelled_block_opt ( label, e. loop_body ( ) ) ;
744+ let condition = self . collect_expr_opt ( e. condition ( ) ) ;
745+ let break_expr =
746+ self . alloc_expr ( Expr :: Break { expr : None , label : None } , syntax_ptr. clone ( ) ) ;
747+ let if_expr = self . alloc_expr (
748+ Expr :: If { condition, then_branch : body, else_branch : Some ( break_expr) } ,
749+ syntax_ptr. clone ( ) ,
750+ ) ;
751+ self . alloc_expr ( Expr :: Loop { body : if_expr, label } , syntax_ptr)
752+ }
753+
734754 /// Desugar `ast::ForExpr` from: `[opt_ident]: for <pat> in <head> <body>` into:
735755 /// ```ignore (pseudo-rust)
736756 /// match IntoIterator::into_iter(<head>) {
@@ -893,15 +913,14 @@ impl ExprCollector<'_> {
893913 self . alloc_expr ( Expr :: Match { expr, arms } , syntax_ptr)
894914 }
895915
896- fn collect_macro_call < F , T , U > (
916+ fn collect_macro_call < T , U > (
897917 & mut self ,
898918 mcall : ast:: MacroCall ,
899919 syntax_ptr : AstPtr < ast:: MacroCall > ,
900920 record_diagnostics : bool ,
901- collector : F ,
921+ collector : impl FnOnce ( & mut Self , Option < T > ) -> U ,
902922 ) -> U
903923 where
904- F : FnOnce ( & mut Self , Option < T > ) -> U ,
905924 T : ast:: AstNode ,
906925 {
907926 // File containing the macro call. Expansion errors will be attached here.
0 commit comments