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