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