@@ -434,7 +434,7 @@ pub struct ExprCollector<'db> {
434434 current_try_block_label : Option < LabelId > ,
435435
436436 label_ribs : Vec < LabelRib > ,
437- current_binding_owner : Option < ExprId > ,
437+ unowned_bindings : Vec < BindingId > ,
438438
439439 awaitable_context : Option < Awaitable > ,
440440}
@@ -536,7 +536,7 @@ impl<'db> ExprCollector<'db> {
536536 current_try_block_label : None ,
537537 is_lowering_coroutine : false ,
538538 label_ribs : Vec :: new ( ) ,
539- current_binding_owner : None ,
539+ unowned_bindings : Vec :: new ( ) ,
540540 awaitable_context : None ,
541541 current_block_legacy_macro_defs_count : FxHashMap :: default ( ) ,
542542 outer_impl_trait : false ,
@@ -1062,12 +1062,10 @@ impl<'db> ExprCollector<'db> {
10621062 Some ( ast:: BlockModifier :: Const ( _) ) => {
10631063 self . with_label_rib ( RibKind :: Constant , |this| {
10641064 this. with_awaitable_block ( Awaitable :: No ( "constant block" ) , |this| {
1065- let ( result_expr_id, prev_binding_owner) =
1066- this. initialize_binding_owner ( syntax_ptr) ;
1067- let inner_expr = this. collect_block ( e) ;
1068- this. store . exprs [ result_expr_id] = Expr :: Const ( inner_expr) ;
1069- this. current_binding_owner = prev_binding_owner;
1070- result_expr_id
1065+ this. with_binding_owner ( |this| {
1066+ let inner_expr = this. collect_block ( e) ;
1067+ this. alloc_expr ( Expr :: Const ( inner_expr) , syntax_ptr)
1068+ } )
10711069 } )
10721070 } )
10731071 }
@@ -1278,64 +1276,65 @@ impl<'db> ExprCollector<'db> {
12781276 }
12791277 }
12801278 ast:: Expr :: ClosureExpr ( e) => self . with_label_rib ( RibKind :: Closure , |this| {
1281- let ( result_expr_id , prev_binding_owner ) =
1282- this . initialize_binding_owner ( syntax_ptr ) ;
1283- let mut args = Vec :: new ( ) ;
1284- let mut arg_types = Vec :: new ( ) ;
1285- if let Some ( pl ) = e . param_list ( ) {
1286- let num_params = pl . params ( ) . count ( ) ;
1287- args . reserve_exact ( num_params) ;
1288- arg_types . reserve_exact ( num_params ) ;
1289- for param in pl . params ( ) {
1290- let pat = this . collect_pat_top ( param . pat ( ) ) ;
1291- let type_ref =
1292- param . ty ( ) . map ( |it| this . lower_type_ref_disallow_impl_trait ( it ) ) ;
1293- args . push ( pat ) ;
1294- arg_types . push ( type_ref ) ;
1279+ this . with_binding_owner ( |this| {
1280+ let mut args = Vec :: new ( ) ;
1281+ let mut arg_types = Vec :: new ( ) ;
1282+ if let Some ( pl ) = e . param_list ( ) {
1283+ let num_params = pl . params ( ) . count ( ) ;
1284+ args . reserve_exact ( num_params ) ;
1285+ arg_types . reserve_exact ( num_params) ;
1286+ for param in pl . params ( ) {
1287+ let pat = this . collect_pat_top ( param . pat ( ) ) ;
1288+ let type_ref =
1289+ param . ty ( ) . map ( |it| this . lower_type_ref_disallow_impl_trait ( it ) ) ;
1290+ args . push ( pat ) ;
1291+ arg_types . push ( type_ref ) ;
1292+ }
12951293 }
1296- }
1297- let ret_type = e
1298- . ret_type ( )
1299- . and_then ( |r| r. ty ( ) )
1300- . map ( |it| this. lower_type_ref_disallow_impl_trait ( it) ) ;
1294+ let ret_type = e
1295+ . ret_type ( )
1296+ . and_then ( |r| r. ty ( ) )
1297+ . map ( |it| this. lower_type_ref_disallow_impl_trait ( it) ) ;
13011298
1302- let prev_is_lowering_coroutine = mem:: take ( & mut this. is_lowering_coroutine ) ;
1303- let prev_try_block_label = this. current_try_block_label . take ( ) ;
1299+ let prev_is_lowering_coroutine = mem:: take ( & mut this. is_lowering_coroutine ) ;
1300+ let prev_try_block_label = this. current_try_block_label . take ( ) ;
13041301
1305- let awaitable = if e. async_token ( ) . is_some ( ) {
1306- Awaitable :: Yes
1307- } else {
1308- Awaitable :: No ( "non-async closure" )
1309- } ;
1310- let body =
1311- this . with_awaitable_block ( awaitable, |this| this. collect_expr_opt ( e. body ( ) ) ) ;
1302+ let awaitable = if e. async_token ( ) . is_some ( ) {
1303+ Awaitable :: Yes
1304+ } else {
1305+ Awaitable :: No ( "non-async closure" )
1306+ } ;
1307+ let body = this
1308+ . with_awaitable_block ( awaitable, |this| this. collect_expr_opt ( e. body ( ) ) ) ;
13121309
1313- let closure_kind = if this. is_lowering_coroutine {
1314- let movability = if e. static_token ( ) . is_some ( ) {
1315- Movability :: Static
1310+ let closure_kind = if this. is_lowering_coroutine {
1311+ let movability = if e. static_token ( ) . is_some ( ) {
1312+ Movability :: Static
1313+ } else {
1314+ Movability :: Movable
1315+ } ;
1316+ ClosureKind :: Coroutine ( movability)
1317+ } else if e. async_token ( ) . is_some ( ) {
1318+ ClosureKind :: Async
13161319 } else {
1317- Movability :: Movable
1320+ ClosureKind :: Closure
13181321 } ;
1319- ClosureKind :: Coroutine ( movability)
1320- } else if e. async_token ( ) . is_some ( ) {
1321- ClosureKind :: Async
1322- } else {
1323- ClosureKind :: Closure
1324- } ;
1325- let capture_by =
1326- if e. move_token ( ) . is_some ( ) { CaptureBy :: Value } else { CaptureBy :: Ref } ;
1327- this. is_lowering_coroutine = prev_is_lowering_coroutine;
1328- this. current_binding_owner = prev_binding_owner;
1329- this. current_try_block_label = prev_try_block_label;
1330- this. store . exprs [ result_expr_id] = Expr :: Closure {
1331- args : args. into ( ) ,
1332- arg_types : arg_types. into ( ) ,
1333- ret_type,
1334- body,
1335- closure_kind,
1336- capture_by,
1337- } ;
1338- result_expr_id
1322+ let capture_by =
1323+ if e. move_token ( ) . is_some ( ) { CaptureBy :: Value } else { CaptureBy :: Ref } ;
1324+ this. is_lowering_coroutine = prev_is_lowering_coroutine;
1325+ this. current_try_block_label = prev_try_block_label;
1326+ this. alloc_expr (
1327+ Expr :: Closure {
1328+ args : args. into ( ) ,
1329+ arg_types : arg_types. into ( ) ,
1330+ ret_type,
1331+ body,
1332+ closure_kind,
1333+ capture_by,
1334+ } ,
1335+ syntax_ptr,
1336+ )
1337+ } )
13391338 } ) ,
13401339 ast:: Expr :: BinExpr ( e) => {
13411340 let op = e. op_kind ( ) ;
@@ -1371,11 +1370,7 @@ impl<'db> ExprCollector<'db> {
13711370 let initializer = self . collect_expr_opt ( initializer) ;
13721371 let repeat = self . with_label_rib ( RibKind :: Constant , |this| {
13731372 if let Some ( repeat) = repeat {
1374- let syntax_ptr = AstPtr :: new ( & repeat) ;
1375- this. collect_as_a_binding_owner_bad (
1376- |this| this. collect_expr ( repeat) ,
1377- syntax_ptr,
1378- )
1373+ this. with_binding_owner ( |this| this. collect_expr ( repeat) )
13791374 } else {
13801375 this. missing_expr ( )
13811376 }
@@ -1632,31 +1627,13 @@ impl<'db> ExprCollector<'db> {
16321627 }
16331628 }
16341629
1635- fn initialize_binding_owner (
1636- & mut self ,
1637- syntax_ptr : AstPtr < ast:: Expr > ,
1638- ) -> ( ExprId , Option < ExprId > ) {
1639- let result_expr_id = self . alloc_expr ( Expr :: Missing , syntax_ptr) ;
1640- let prev_binding_owner = self . current_binding_owner . take ( ) ;
1641- self . current_binding_owner = Some ( result_expr_id) ;
1642-
1643- ( result_expr_id, prev_binding_owner)
1644- }
1645-
1646- /// FIXME: This function is bad. It will produce a dangling `Missing` expr which wastes memory. Currently
1647- /// it is used only for const blocks and repeat expressions, which are also hacky and ideally should have
1648- /// their own body. Don't add more usage for this function so that we can remove this function after
1649- /// separating those bodies.
1650- fn collect_as_a_binding_owner_bad (
1651- & mut self ,
1652- job : impl FnOnce ( & mut ExprCollector < ' _ > ) -> ExprId ,
1653- syntax_ptr : AstPtr < ast:: Expr > ,
1654- ) -> ExprId {
1655- let ( id, prev_owner) = self . initialize_binding_owner ( syntax_ptr) ;
1656- let tmp = job ( self ) ;
1657- self . store . exprs [ id] = mem:: replace ( & mut self . store . exprs [ tmp] , Expr :: Missing ) ;
1658- self . current_binding_owner = prev_owner;
1659- id
1630+ fn with_binding_owner ( & mut self , create_expr : impl FnOnce ( & mut Self ) -> ExprId ) -> ExprId {
1631+ let prev_unowned_bindings_len = self . unowned_bindings . len ( ) ;
1632+ let expr_id = create_expr ( self ) ;
1633+ for binding in self . unowned_bindings . drain ( prev_unowned_bindings_len..) {
1634+ self . store . binding_owners . insert ( binding, expr_id) ;
1635+ }
1636+ expr_id
16601637 }
16611638
16621639 /// Desugar `try { <stmts>; <expr> }` into `'<new_label>: { <stmts>; ::std::ops::Try::from_output(<expr>) }`,
@@ -2368,11 +2345,7 @@ impl<'db> ExprCollector<'db> {
23682345 ast:: Pat :: ConstBlockPat ( const_block_pat) => {
23692346 if let Some ( block) = const_block_pat. block_expr ( ) {
23702347 let expr_id = self . with_label_rib ( RibKind :: Constant , |this| {
2371- let syntax_ptr = AstPtr :: new ( & block. clone ( ) . into ( ) ) ;
2372- this. collect_as_a_binding_owner_bad (
2373- |this| this. collect_block ( block) ,
2374- syntax_ptr,
2375- )
2348+ this. with_binding_owner ( |this| this. collect_block ( block) )
23762349 } ) ;
23772350 Pat :: ConstBlock ( expr_id)
23782351 } else {
@@ -3376,9 +3349,7 @@ impl ExprCollector<'_> {
33763349 hygiene : HygieneId ,
33773350 ) -> BindingId {
33783351 let binding = self . store . bindings . alloc ( Binding { name, mode, problems : None , hygiene } ) ;
3379- if let Some ( owner) = self . current_binding_owner {
3380- self . store . binding_owners . insert ( binding, owner) ;
3381- }
3352+ self . unowned_bindings . push ( binding) ;
33823353 binding
33833354 }
33843355
0 commit comments