@@ -28,9 +28,9 @@ use crate::{
2828 data:: adt:: StructKind ,
2929 db:: DefDatabase ,
3030 hir:: {
31- dummy_expr_id, Array , Binding , BindingAnnotation , BindingId , ClosureKind , Expr , ExprId ,
32- Label , LabelId , Literal , MatchArm , Movability , Pat , PatId , RecordFieldPat , RecordLitField ,
33- Statement ,
31+ dummy_expr_id, Array , Binding , BindingAnnotation , BindingId , CaptureBy , ClosureKind , Expr ,
32+ ExprId , Label , LabelId , Literal , MatchArm , Movability , Pat , PatId , RecordFieldPat ,
33+ RecordLitField , Statement ,
3434 } ,
3535 item_scope:: BuiltinShadowMode ,
3636 lang_item:: LangItem ,
@@ -67,6 +67,7 @@ pub(super) fn lower(
6767 is_lowering_assignee_expr : false ,
6868 is_lowering_generator : false ,
6969 label_ribs : Vec :: new ( ) ,
70+ current_binding_owner : None ,
7071 }
7172 . collect ( params, body, is_async_fn)
7273}
@@ -92,6 +93,7 @@ struct ExprCollector<'a> {
9293
9394 // resolution
9495 label_ribs : Vec < LabelRib > ,
96+ current_binding_owner : Option < ExprId > ,
9597}
9698
9799#[ derive( Clone , Debug ) ]
@@ -261,11 +263,16 @@ impl ExprCollector<'_> {
261263 }
262264 Some ( ast:: BlockModifier :: Const ( _) ) => {
263265 self . with_label_rib ( RibKind :: Constant , |this| {
264- this. collect_block_ ( e, |id, statements, tail| Expr :: Const {
265- id,
266- statements,
267- tail,
268- } )
266+ this. collect_as_a_binding_owner_bad (
267+ |this| {
268+ this. collect_block_ ( e, |id, statements, tail| Expr :: Const {
269+ id,
270+ statements,
271+ tail,
272+ } )
273+ } ,
274+ syntax_ptr,
275+ )
269276 } )
270277 }
271278 None => self . collect_block ( e) ,
@@ -461,6 +468,8 @@ impl ExprCollector<'_> {
461468 }
462469 }
463470 ast:: Expr :: ClosureExpr ( e) => self . with_label_rib ( RibKind :: Closure , |this| {
471+ let ( result_expr_id, prev_binding_owner) =
472+ this. initialize_binding_owner ( syntax_ptr) ;
464473 let mut args = Vec :: new ( ) ;
465474 let mut arg_types = Vec :: new ( ) ;
466475 if let Some ( pl) = e. param_list ( ) {
@@ -494,17 +503,19 @@ impl ExprCollector<'_> {
494503 ClosureKind :: Closure
495504 } ;
496505 this. is_lowering_generator = prev_is_lowering_generator;
497-
498- this. alloc_expr (
499- Expr :: Closure {
500- args : args. into ( ) ,
501- arg_types : arg_types. into ( ) ,
502- ret_type,
503- body,
504- closure_kind,
505- } ,
506- syntax_ptr,
507- )
506+ let capture_by =
507+ if e. move_token ( ) . is_some ( ) { CaptureBy :: Value } else { CaptureBy :: Ref } ;
508+ this. is_lowering_generator = prev_is_lowering_generator;
509+ this. current_binding_owner = prev_binding_owner;
510+ this. body . exprs [ result_expr_id] = Expr :: Closure {
511+ args : args. into ( ) ,
512+ arg_types : arg_types. into ( ) ,
513+ ret_type,
514+ body,
515+ closure_kind,
516+ capture_by,
517+ } ;
518+ result_expr_id
508519 } ) ,
509520 ast:: Expr :: BinExpr ( e) => {
510521 let op = e. op_kind ( ) ;
@@ -545,7 +556,15 @@ impl ExprCollector<'_> {
545556 ArrayExprKind :: Repeat { initializer, repeat } => {
546557 let initializer = self . collect_expr_opt ( initializer) ;
547558 let repeat = self . with_label_rib ( RibKind :: Constant , |this| {
548- this. collect_expr_opt ( repeat)
559+ if let Some ( repeat) = repeat {
560+ let syntax_ptr = AstPtr :: new ( & repeat) ;
561+ this. collect_as_a_binding_owner_bad (
562+ |this| this. collect_expr ( repeat) ,
563+ syntax_ptr,
564+ )
565+ } else {
566+ this. missing_expr ( )
567+ }
549568 } ) ;
550569 self . alloc_expr (
551570 Expr :: Array ( Array :: Repeat { initializer, repeat } ) ,
@@ -592,6 +611,32 @@ impl ExprCollector<'_> {
592611 } )
593612 }
594613
614+ fn initialize_binding_owner (
615+ & mut self ,
616+ syntax_ptr : AstPtr < ast:: Expr > ,
617+ ) -> ( ExprId , Option < ExprId > ) {
618+ let result_expr_id = self . alloc_expr ( Expr :: Missing , syntax_ptr) ;
619+ let prev_binding_owner = self . current_binding_owner . take ( ) ;
620+ self . current_binding_owner = Some ( result_expr_id) ;
621+ ( result_expr_id, prev_binding_owner)
622+ }
623+
624+ /// FIXME: This function is bad. It will produce a dangling `Missing` expr which wastes memory. Currently
625+ /// it is used only for const blocks and repeat expressions, which are also hacky and ideally should have
626+ /// their own body. Don't add more usage for this function so that we can remove this function after
627+ /// separating those bodies.
628+ fn collect_as_a_binding_owner_bad (
629+ & mut self ,
630+ job : impl FnOnce ( & mut ExprCollector < ' _ > ) -> ExprId ,
631+ syntax_ptr : AstPtr < ast:: Expr > ,
632+ ) -> ExprId {
633+ let ( id, prev_owner) = self . initialize_binding_owner ( syntax_ptr) ;
634+ let tmp = job ( self ) ;
635+ self . body . exprs [ id] = mem:: replace ( & mut self . body . exprs [ tmp] , Expr :: Missing ) ;
636+ self . current_binding_owner = prev_owner;
637+ id
638+ }
639+
595640 /// Desugar `try { <stmts>; <expr> }` into `'<new_label>: { <stmts>; ::std::ops::Try::from_output(<expr>) }`,
596641 /// `try { <stmts>; }` into `'<new_label>: { <stmts>; ::std::ops::Try::from_output(()) }`
597642 /// and save the `<new_label>` to use it as a break target for desugaring of the `?` operator.
@@ -1112,8 +1157,13 @@ impl ExprCollector<'_> {
11121157 }
11131158 ast:: Pat :: ConstBlockPat ( const_block_pat) => {
11141159 if let Some ( block) = const_block_pat. block_expr ( ) {
1115- let expr_id =
1116- self . with_label_rib ( RibKind :: Constant , |this| this. collect_block ( block) ) ;
1160+ let expr_id = self . with_label_rib ( RibKind :: Constant , |this| {
1161+ let syntax_ptr = AstPtr :: new ( & block. clone ( ) . into ( ) ) ;
1162+ this. collect_as_a_binding_owner_bad (
1163+ |this| this. collect_block ( block) ,
1164+ syntax_ptr,
1165+ )
1166+ } ) ;
11171167 Pat :: ConstBlock ( expr_id)
11181168 } else {
11191169 Pat :: Missing
@@ -1272,7 +1322,12 @@ impl ExprCollector<'_> {
12721322 }
12731323
12741324 fn alloc_binding ( & mut self , name : Name , mode : BindingAnnotation ) -> BindingId {
1275- self . body . bindings . alloc ( Binding { name, mode, definitions : SmallVec :: new ( ) } )
1325+ self . body . bindings . alloc ( Binding {
1326+ name,
1327+ mode,
1328+ definitions : SmallVec :: new ( ) ,
1329+ owner : self . current_binding_owner ,
1330+ } )
12761331 }
12771332
12781333 fn alloc_pat ( & mut self , pat : Pat , ptr : PatPtr ) -> PatId {
0 commit comments