@@ -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 krate : base_db:: Crate ,
@@ -538,7 +538,7 @@ impl<'db> ExprCollector<'db> {
538538 current_try_block_label : None ,
539539 is_lowering_coroutine : false ,
540540 label_ribs : Vec :: new ( ) ,
541- current_binding_owner : None ,
541+ unowned_bindings : Vec :: new ( ) ,
542542 awaitable_context : None ,
543543 current_block_legacy_macro_defs_count : FxHashMap :: default ( ) ,
544544 outer_impl_trait : false ,
@@ -1065,12 +1065,10 @@ impl<'db> ExprCollector<'db> {
10651065 Some ( ast:: BlockModifier :: Const ( _) ) => {
10661066 self . with_label_rib ( RibKind :: Constant , |this| {
10671067 this. with_awaitable_block ( Awaitable :: No ( "constant block" ) , |this| {
1068- let ( result_expr_id, prev_binding_owner) =
1069- this. initialize_binding_owner ( syntax_ptr) ;
1070- let inner_expr = this. collect_block ( e) ;
1071- this. store . exprs [ result_expr_id] = Expr :: Const ( inner_expr) ;
1072- this. current_binding_owner = prev_binding_owner;
1073- result_expr_id
1068+ this. with_binding_owner ( |this| {
1069+ let inner_expr = this. collect_block ( e) ;
1070+ this. alloc_expr ( Expr :: Const ( inner_expr) , syntax_ptr)
1071+ } )
10741072 } )
10751073 } )
10761074 }
@@ -1281,64 +1279,65 @@ impl<'db> ExprCollector<'db> {
12811279 }
12821280 }
12831281 ast:: Expr :: ClosureExpr ( e) => self . with_label_rib ( RibKind :: Closure , |this| {
1284- let ( result_expr_id , prev_binding_owner ) =
1285- this . initialize_binding_owner ( syntax_ptr ) ;
1286- let mut args = Vec :: new ( ) ;
1287- let mut arg_types = Vec :: new ( ) ;
1288- if let Some ( pl ) = e . param_list ( ) {
1289- let num_params = pl . params ( ) . count ( ) ;
1290- args . reserve_exact ( num_params) ;
1291- arg_types . reserve_exact ( num_params ) ;
1292- for param in pl . params ( ) {
1293- let pat = this . collect_pat_top ( param . pat ( ) ) ;
1294- let type_ref =
1295- param . ty ( ) . map ( |it| this . lower_type_ref_disallow_impl_trait ( it ) ) ;
1296- args . push ( pat ) ;
1297- arg_types . push ( type_ref ) ;
1282+ this . with_binding_owner ( |this| {
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 ) ;
1295+ }
12981296 }
1299- }
1300- let ret_type = e
1301- . ret_type ( )
1302- . and_then ( |r| r. ty ( ) )
1303- . map ( |it| this. lower_type_ref_disallow_impl_trait ( it) ) ;
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) ) ;
13041301
1305- let prev_is_lowering_coroutine = mem:: take ( & mut this. is_lowering_coroutine ) ;
1306- let prev_try_block_label = this. current_try_block_label . take ( ) ;
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 ( ) ;
13071304
1308- let awaitable = if e. async_token ( ) . is_some ( ) {
1309- Awaitable :: Yes
1310- } else {
1311- Awaitable :: No ( "non-async closure" )
1312- } ;
1313- let body =
1314- this . with_awaitable_block ( awaitable, |this| this. collect_expr_opt ( e. body ( ) ) ) ;
1305+ let awaitable = if e. async_token ( ) . is_some ( ) {
1306+ Awaitable :: Yes
1307+ } else {
1308+ Awaitable :: No ( "non-async closure" )
1309+ } ;
1310+ let body = this
1311+ . with_awaitable_block ( awaitable, |this| this. collect_expr_opt ( e. body ( ) ) ) ;
13151312
1316- let closure_kind = if this. is_lowering_coroutine {
1317- let movability = if e. static_token ( ) . is_some ( ) {
1318- Movability :: Static
1313+ let closure_kind = if this. is_lowering_coroutine {
1314+ let movability = if e. static_token ( ) . is_some ( ) {
1315+ Movability :: Static
1316+ } else {
1317+ Movability :: Movable
1318+ } ;
1319+ ClosureKind :: Coroutine ( movability)
1320+ } else if e. async_token ( ) . is_some ( ) {
1321+ ClosureKind :: Async
13191322 } else {
1320- Movability :: Movable
1323+ ClosureKind :: Closure
13211324 } ;
1322- ClosureKind :: Coroutine ( movability)
1323- } else if e. async_token ( ) . is_some ( ) {
1324- ClosureKind :: Async
1325- } else {
1326- ClosureKind :: Closure
1327- } ;
1328- let capture_by =
1329- if e. move_token ( ) . is_some ( ) { CaptureBy :: Value } else { CaptureBy :: Ref } ;
1330- this. is_lowering_coroutine = prev_is_lowering_coroutine;
1331- this. current_binding_owner = prev_binding_owner;
1332- this. current_try_block_label = prev_try_block_label;
1333- this. store . exprs [ result_expr_id] = Expr :: Closure {
1334- args : args. into ( ) ,
1335- arg_types : arg_types. into ( ) ,
1336- ret_type,
1337- body,
1338- closure_kind,
1339- capture_by,
1340- } ;
1341- result_expr_id
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_try_block_label = prev_try_block_label;
1329+ this. alloc_expr (
1330+ 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+ syntax_ptr,
1339+ )
1340+ } )
13421341 } ) ,
13431342 ast:: Expr :: BinExpr ( e) => {
13441343 let op = e. op_kind ( ) ;
@@ -1374,11 +1373,7 @@ impl<'db> ExprCollector<'db> {
13741373 let initializer = self . collect_expr_opt ( initializer) ;
13751374 let repeat = self . with_label_rib ( RibKind :: Constant , |this| {
13761375 if let Some ( repeat) = repeat {
1377- let syntax_ptr = AstPtr :: new ( & repeat) ;
1378- this. collect_as_a_binding_owner_bad (
1379- |this| this. collect_expr ( repeat) ,
1380- syntax_ptr,
1381- )
1376+ this. with_binding_owner ( |this| this. collect_expr ( repeat) )
13821377 } else {
13831378 this. missing_expr ( )
13841379 }
@@ -1635,31 +1630,13 @@ impl<'db> ExprCollector<'db> {
16351630 }
16361631 }
16371632
1638- fn initialize_binding_owner (
1639- & mut self ,
1640- syntax_ptr : AstPtr < ast:: Expr > ,
1641- ) -> ( ExprId , Option < ExprId > ) {
1642- let result_expr_id = self . alloc_expr ( Expr :: Missing , syntax_ptr) ;
1643- let prev_binding_owner = self . current_binding_owner . take ( ) ;
1644- self . current_binding_owner = Some ( result_expr_id) ;
1645-
1646- ( result_expr_id, prev_binding_owner)
1647- }
1648-
1649- /// FIXME: This function is bad. It will produce a dangling `Missing` expr which wastes memory. Currently
1650- /// it is used only for const blocks and repeat expressions, which are also hacky and ideally should have
1651- /// their own body. Don't add more usage for this function so that we can remove this function after
1652- /// separating those bodies.
1653- fn collect_as_a_binding_owner_bad (
1654- & mut self ,
1655- job : impl FnOnce ( & mut ExprCollector < ' _ > ) -> ExprId ,
1656- syntax_ptr : AstPtr < ast:: Expr > ,
1657- ) -> ExprId {
1658- let ( id, prev_owner) = self . initialize_binding_owner ( syntax_ptr) ;
1659- let tmp = job ( self ) ;
1660- self . store . exprs [ id] = mem:: replace ( & mut self . store . exprs [ tmp] , Expr :: Missing ) ;
1661- self . current_binding_owner = prev_owner;
1662- id
1633+ fn with_binding_owner ( & mut self , create_expr : impl FnOnce ( & mut Self ) -> ExprId ) -> ExprId {
1634+ let prev_unowned_bindings_len = self . unowned_bindings . len ( ) ;
1635+ let expr_id = create_expr ( self ) ;
1636+ for binding in self . unowned_bindings . drain ( prev_unowned_bindings_len..) {
1637+ self . store . binding_owners . insert ( binding, expr_id) ;
1638+ }
1639+ expr_id
16631640 }
16641641
16651642 /// Desugar `try { <stmts>; <expr> }` into `'<new_label>: { <stmts>; ::std::ops::Try::from_output(<expr>) }`,
@@ -2371,11 +2348,7 @@ impl<'db> ExprCollector<'db> {
23712348 ast:: Pat :: ConstBlockPat ( const_block_pat) => {
23722349 if let Some ( block) = const_block_pat. block_expr ( ) {
23732350 let expr_id = self . with_label_rib ( RibKind :: Constant , |this| {
2374- let syntax_ptr = AstPtr :: new ( & block. clone ( ) . into ( ) ) ;
2375- this. collect_as_a_binding_owner_bad (
2376- |this| this. collect_block ( block) ,
2377- syntax_ptr,
2378- )
2351+ this. with_binding_owner ( |this| this. collect_block ( block) )
23792352 } ) ;
23802353 Pat :: ConstBlock ( expr_id)
23812354 } else {
@@ -3379,9 +3352,7 @@ impl ExprCollector<'_> {
33793352 hygiene : HygieneId ,
33803353 ) -> BindingId {
33813354 let binding = self . store . bindings . alloc ( Binding { name, mode, problems : None , hygiene } ) ;
3382- if let Some ( owner) = self . current_binding_owner {
3383- self . store . binding_owners . insert ( binding, owner) ;
3384- }
3355+ self . unowned_bindings . push ( binding) ;
33853356 binding
33863357 }
33873358
0 commit comments