@@ -406,11 +406,14 @@ fn resolve_expr<'tcx>(visitor: &mut RegionResolutionVisitor<'tcx>, expr: &'tcx h
406
406
match expr. kind {
407
407
// Manually recurse over closures and inline consts, because they are the only
408
408
// 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, .. } ) => {
411
410
let body = visitor. tcx . hir ( ) . body ( body) ;
412
411
visitor. visit_body ( body) ;
413
412
}
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
+ } ) ,
414
417
hir:: ExprKind :: AssignOp ( _, left_expr, right_expr) => {
415
418
debug ! (
416
419
"resolve_expr - enabling pessimistic_yield, was previously {}" ,
@@ -781,25 +784,8 @@ impl<'tcx> RegionResolutionVisitor<'tcx> {
781
784
}
782
785
self . enter_scope ( Scope { id, data : ScopeData :: Node } ) ;
783
786
}
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
- ) ;
802
787
788
+ fn enter_body ( & mut self , hir_id : hir:: HirId , f : impl FnOnce ( & mut Self ) ) {
803
789
// Save all state that is specific to the outer function
804
790
// body. These will be restored once down below, once we've
805
791
// visited the body.
@@ -811,50 +797,73 @@ impl<'tcx> Visitor<'tcx> for RegionResolutionVisitor<'tcx> {
811
797
// control flow assumptions. This doesn't apply to nested
812
798
// bodies within the `+=` statements. See #69307.
813
799
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 ) ;
818
801
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 } ) ;
824
804
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 ) ;
851
806
852
807
// Restore context we had at the start.
853
808
self . expr_and_pat_count = outer_ec;
854
809
self . cx = outer_cx;
855
810
self . terminating_scopes = outer_ts;
856
811
self . pessimistic_yield = outer_pessimistic_yield;
857
812
}
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
+ }
858
867
859
868
fn visit_arm ( & mut self , a : & ' tcx Arm < ' tcx > ) {
860
869
resolve_arm ( self , a) ;
0 commit comments