@@ -406,11 +406,14 @@ fn resolve_expr<'tcx>(visitor: &mut RegionResolutionVisitor<'tcx>, expr: &'tcx h
406406 match expr. kind {
407407 // Manually recurse over closures and inline consts, because they are the only
408408 // case of nested bodies that share the parent environment.
409- hir:: ExprKind :: Closure ( & hir:: Closure { body, .. } )
410- | hir:: ExprKind :: ConstBlock ( hir:: ConstBlock { body, .. } ) => {
409+ hir:: ExprKind :: Closure ( & hir:: Closure { body, .. } ) => {
411410 let body = visitor. tcx . hir ( ) . body ( body) ;
412411 visitor. visit_body ( body) ;
413412 }
413+ hir:: ExprKind :: ConstBlock ( expr) => visitor. enter_body ( expr. hir_id , |this| {
414+ this. cx . var_parent = None ;
415+ resolve_local ( this, None , Some ( expr) ) ;
416+ } ) ,
414417 hir:: ExprKind :: AssignOp ( _, left_expr, right_expr) => {
415418 debug ! (
416419 "resolve_expr - enabling pessimistic_yield, was previously {}" ,
@@ -781,25 +784,8 @@ impl<'tcx> RegionResolutionVisitor<'tcx> {
781784 }
782785 self . enter_scope ( Scope { id, data : ScopeData :: Node } ) ;
783786 }
784- }
785-
786- impl < ' tcx > Visitor < ' tcx > for RegionResolutionVisitor < ' tcx > {
787- fn visit_block ( & mut self , b : & ' tcx Block < ' tcx > ) {
788- resolve_block ( self , b) ;
789- }
790-
791- fn visit_body ( & mut self , body : & ' tcx hir:: Body < ' tcx > ) {
792- let body_id = body. id ( ) ;
793- let owner_id = self . tcx . hir ( ) . body_owner_def_id ( body_id) ;
794-
795- debug ! (
796- "visit_body(id={:?}, span={:?}, body.id={:?}, cx.parent={:?})" ,
797- owner_id,
798- self . tcx. sess. source_map( ) . span_to_diagnostic_string( body. value. span) ,
799- body_id,
800- self . cx. parent
801- ) ;
802787
788+ fn enter_body ( & mut self , hir_id : hir:: HirId , f : impl FnOnce ( & mut Self ) ) {
803789 // Save all state that is specific to the outer function
804790 // body. These will be restored once down below, once we've
805791 // visited the body.
@@ -811,50 +797,73 @@ impl<'tcx> Visitor<'tcx> for RegionResolutionVisitor<'tcx> {
811797 // control flow assumptions. This doesn't apply to nested
812798 // bodies within the `+=` statements. See #69307.
813799 let outer_pessimistic_yield = mem:: replace ( & mut self . pessimistic_yield , false ) ;
814- self . terminating_scopes . insert ( body. value . hir_id . local_id ) ;
815-
816- self . enter_scope ( Scope { id : body. value . hir_id . local_id , data : ScopeData :: CallSite } ) ;
817- self . enter_scope ( Scope { id : body. value . hir_id . local_id , data : ScopeData :: Arguments } ) ;
800+ self . terminating_scopes . insert ( hir_id. local_id ) ;
818801
819- // The arguments and `self` are parented to the fn.
820- self . cx . var_parent = self . cx . parent . take ( ) ;
821- for param in body. params {
822- self . visit_pat ( param. pat ) ;
823- }
802+ self . enter_scope ( Scope { id : hir_id. local_id , data : ScopeData :: CallSite } ) ;
803+ self . enter_scope ( Scope { id : hir_id. local_id , data : ScopeData :: Arguments } ) ;
824804
825- // The body of the every fn is a root scope.
826- self . cx . parent = self . cx . var_parent ;
827- if self . tcx . hir ( ) . body_owner_kind ( owner_id) . is_fn_or_closure ( ) {
828- self . visit_expr ( body. value )
829- } else {
830- // Only functions have an outer terminating (drop) scope, while
831- // temporaries in constant initializers may be 'static, but only
832- // according to rvalue lifetime semantics, using the same
833- // syntactical rules used for let initializers.
834- //
835- // e.g., in `let x = &f();`, the temporary holding the result from
836- // the `f()` call lives for the entirety of the surrounding block.
837- //
838- // Similarly, `const X: ... = &f();` would have the result of `f()`
839- // live for `'static`, implying (if Drop restrictions on constants
840- // ever get lifted) that the value *could* have a destructor, but
841- // it'd get leaked instead of the destructor running during the
842- // evaluation of `X` (if at all allowed by CTFE).
843- //
844- // However, `const Y: ... = g(&f());`, like `let y = g(&f());`,
845- // would *not* let the `f()` temporary escape into an outer scope
846- // (i.e., `'static`), which means that after `g` returns, it drops,
847- // and all the associated destruction scope rules apply.
848- self . cx . var_parent = None ;
849- resolve_local ( self , None , Some ( body. value ) ) ;
850- }
805+ f ( self ) ;
851806
852807 // Restore context we had at the start.
853808 self . expr_and_pat_count = outer_ec;
854809 self . cx = outer_cx;
855810 self . terminating_scopes = outer_ts;
856811 self . pessimistic_yield = outer_pessimistic_yield;
857812 }
813+ }
814+
815+ impl < ' tcx > Visitor < ' tcx > for RegionResolutionVisitor < ' tcx > {
816+ fn visit_block ( & mut self , b : & ' tcx Block < ' tcx > ) {
817+ resolve_block ( self , b) ;
818+ }
819+
820+ fn visit_body ( & mut self , body : & ' tcx hir:: Body < ' tcx > ) {
821+ let body_id = body. id ( ) ;
822+ let owner_id = self . tcx . hir ( ) . body_owner_def_id ( body_id) ;
823+
824+ debug ! (
825+ "visit_body(id={:?}, span={:?}, body.id={:?}, cx.parent={:?})" ,
826+ owner_id,
827+ self . tcx. sess. source_map( ) . span_to_diagnostic_string( body. value. span) ,
828+ body_id,
829+ self . cx. parent
830+ ) ;
831+
832+ self . enter_body ( body. value . hir_id , |this| {
833+ if this. tcx . hir ( ) . body_owner_kind ( owner_id) . is_fn_or_closure ( ) {
834+ // The arguments and `self` are parented to the fn.
835+ this. cx . var_parent = this. cx . parent . take ( ) ;
836+ for param in body. params {
837+ this. visit_pat ( param. pat ) ;
838+ }
839+
840+ // The body of the every fn is a root scope.
841+ this. cx . parent = this. cx . var_parent ;
842+ this. visit_expr ( body. value )
843+ } else {
844+ // Only functions have an outer terminating (drop) scope, while
845+ // temporaries in constant initializers may be 'static, but only
846+ // according to rvalue lifetime semantics, using the same
847+ // syntactical rules used for let initializers.
848+ //
849+ // e.g., in `let x = &f();`, the temporary holding the result from
850+ // the `f()` call lives for the entirety of the surrounding block.
851+ //
852+ // Similarly, `const X: ... = &f();` would have the result of `f()`
853+ // live for `'static`, implying (if Drop restrictions on constants
854+ // ever get lifted) that the value *could* have a destructor, but
855+ // it'd get leaked instead of the destructor running during the
856+ // evaluation of `X` (if at all allowed by CTFE).
857+ //
858+ // However, `const Y: ... = g(&f());`, like `let y = g(&f());`,
859+ // would *not* let the `f()` temporary escape into an outer scope
860+ // (i.e., `'static`), which means that after `g` returns, it drops,
861+ // and all the associated destruction scope rules apply.
862+ this. cx . var_parent = None ;
863+ resolve_local ( this, None , Some ( body. value ) ) ;
864+ }
865+ } )
866+ }
858867
859868 fn visit_arm ( & mut self , a : & ' tcx Arm < ' tcx > ) {
860869 resolve_arm ( self , a) ;
0 commit comments