@@ -28,9 +28,9 @@ use crate::{
28
28
data:: adt:: StructKind ,
29
29
db:: DefDatabase ,
30
30
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 ,
34
34
} ,
35
35
item_scope:: BuiltinShadowMode ,
36
36
lang_item:: LangItem ,
@@ -67,6 +67,7 @@ pub(super) fn lower(
67
67
is_lowering_assignee_expr : false ,
68
68
is_lowering_generator : false ,
69
69
label_ribs : Vec :: new ( ) ,
70
+ current_binding_owner : None ,
70
71
}
71
72
. collect ( params, body, is_async_fn)
72
73
}
@@ -92,6 +93,7 @@ struct ExprCollector<'a> {
92
93
93
94
// resolution
94
95
label_ribs : Vec < LabelRib > ,
96
+ current_binding_owner : Option < ExprId > ,
95
97
}
96
98
97
99
#[ derive( Clone , Debug ) ]
@@ -261,11 +263,16 @@ impl ExprCollector<'_> {
261
263
}
262
264
Some ( ast:: BlockModifier :: Const ( _) ) => {
263
265
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
+ )
269
276
} )
270
277
}
271
278
None => self . collect_block ( e) ,
@@ -461,6 +468,8 @@ impl ExprCollector<'_> {
461
468
}
462
469
}
463
470
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) ;
464
473
let mut args = Vec :: new ( ) ;
465
474
let mut arg_types = Vec :: new ( ) ;
466
475
if let Some ( pl) = e. param_list ( ) {
@@ -494,17 +503,19 @@ impl ExprCollector<'_> {
494
503
ClosureKind :: Closure
495
504
} ;
496
505
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
508
519
} ) ,
509
520
ast:: Expr :: BinExpr ( e) => {
510
521
let op = e. op_kind ( ) ;
@@ -545,7 +556,15 @@ impl ExprCollector<'_> {
545
556
ArrayExprKind :: Repeat { initializer, repeat } => {
546
557
let initializer = self . collect_expr_opt ( initializer) ;
547
558
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
+ }
549
568
} ) ;
550
569
self . alloc_expr (
551
570
Expr :: Array ( Array :: Repeat { initializer, repeat } ) ,
@@ -592,6 +611,32 @@ impl ExprCollector<'_> {
592
611
} )
593
612
}
594
613
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
+
595
640
/// Desugar `try { <stmts>; <expr> }` into `'<new_label>: { <stmts>; ::std::ops::Try::from_output(<expr>) }`,
596
641
/// `try { <stmts>; }` into `'<new_label>: { <stmts>; ::std::ops::Try::from_output(()) }`
597
642
/// and save the `<new_label>` to use it as a break target for desugaring of the `?` operator.
@@ -1112,8 +1157,13 @@ impl ExprCollector<'_> {
1112
1157
}
1113
1158
ast:: Pat :: ConstBlockPat ( const_block_pat) => {
1114
1159
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
+ } ) ;
1117
1167
Pat :: ConstBlock ( expr_id)
1118
1168
} else {
1119
1169
Pat :: Missing
@@ -1272,7 +1322,12 @@ impl ExprCollector<'_> {
1272
1322
}
1273
1323
1274
1324
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
+ } )
1276
1331
}
1277
1332
1278
1333
fn alloc_pat ( & mut self , pat : Pat , ptr : PatPtr ) -> PatId {
0 commit comments