@@ -24,14 +24,16 @@ use std::mem;
2424use std:: rc:: Rc ;
2525use serialize;
2626use syntax:: codemap;
27- use syntax:: ast:: { self , NodeId } ;
27+ use syntax:: ast;
2828use syntax_pos:: Span ;
2929use ty:: TyCtxt ;
3030use ty:: maps:: Providers ;
3131
32- use hir; use hir:: def_id:: DefId ;
33- use hir:: intravisit:: { self , Visitor , FnKind , NestedVisitorMap } ;
34- use hir:: { Block , Item , FnDecl , Arm , Pat , PatKind , Stmt , Expr , Local } ;
32+ use hir;
33+ use hir:: def_id:: DefId ;
34+ use hir:: intravisit:: { self , Visitor , NestedVisitorMap } ;
35+ use hir:: { Block , Arm , Pat , PatKind , Stmt , Expr , Local } ;
36+ use mir:: transform:: MirSource ;
3537
3638pub type CodeExtent < ' tcx > = & ' tcx CodeExtentData ;
3739
@@ -811,7 +813,17 @@ fn resolve_expr<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>, expr:
811813 }
812814 }
813815
814- intravisit:: walk_expr ( visitor, expr) ;
816+ match expr. node {
817+ // Manually recurse over closures, because they are the only
818+ // case of nested bodies that share the parent environment.
819+ hir:: ExprClosure ( .., body, _) => {
820+ let body = visitor. tcx . hir . body ( body) ;
821+ visitor. visit_body ( body) ;
822+ }
823+
824+ _ => intravisit:: walk_expr ( visitor, expr)
825+ }
826+
815827 visitor. cx = prev_cx;
816828}
817829
@@ -1041,74 +1053,6 @@ fn resolve_local<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>,
10411053 }
10421054}
10431055
1044- fn resolve_item_like < ' a , ' tcx , F > ( visitor : & mut RegionResolutionVisitor < ' a , ' tcx > , walk : F )
1045- where F : FnOnce ( & mut RegionResolutionVisitor < ' a , ' tcx > )
1046- {
1047- // Items create a new outer block scope as far as we're concerned.
1048- let prev_cx = visitor. cx ;
1049- let prev_ts = mem:: replace ( & mut visitor. terminating_scopes , NodeSet ( ) ) ;
1050- visitor. cx = Context {
1051- root_id : None ,
1052- var_parent : None ,
1053- parent : None ,
1054- } ;
1055- walk ( visitor) ;
1056- visitor. cx = prev_cx;
1057- visitor. terminating_scopes = prev_ts;
1058- }
1059-
1060- fn resolve_fn < ' a , ' tcx > ( visitor : & mut RegionResolutionVisitor < ' a , ' tcx > ,
1061- kind : FnKind < ' tcx > ,
1062- decl : & ' tcx hir:: FnDecl ,
1063- body_id : hir:: BodyId ,
1064- sp : Span ,
1065- id : ast:: NodeId ) {
1066- visitor. cx . parent = Some ( visitor. new_code_extent (
1067- CodeExtentData :: CallSiteScope { fn_id : id, body_id : body_id. node_id } ) ) ;
1068-
1069- debug ! ( "region::resolve_fn(id={:?}, \
1070- span={:?}, \
1071- body.id={:?}, \
1072- cx.parent={:?})",
1073- id,
1074- visitor. tcx. sess. codemap( ) . span_to_string( sp) ,
1075- body_id,
1076- visitor. cx. parent) ;
1077-
1078- let fn_decl_scope = visitor. new_code_extent (
1079- CodeExtentData :: ParameterScope { fn_id : id, body_id : body_id. node_id } ) ;
1080-
1081- if let Some ( root_id) = visitor. cx . root_id {
1082- visitor. region_maps . record_fn_parent ( body_id. node_id , root_id) ;
1083- }
1084-
1085- let outer_cx = visitor. cx ;
1086- let outer_ts = mem:: replace ( & mut visitor. terminating_scopes , NodeSet ( ) ) ;
1087- visitor. terminating_scopes . insert ( body_id. node_id ) ;
1088-
1089- // The arguments and `self` are parented to the fn.
1090- visitor. cx = Context {
1091- root_id : Some ( body_id. node_id ) ,
1092- parent : None ,
1093- var_parent : Some ( fn_decl_scope) ,
1094- } ;
1095-
1096- intravisit:: walk_fn_decl ( visitor, decl) ;
1097- intravisit:: walk_fn_kind ( visitor, kind) ;
1098-
1099- // The body of the every fn is a root scope.
1100- visitor. cx = Context {
1101- root_id : Some ( body_id. node_id ) ,
1102- parent : Some ( fn_decl_scope) ,
1103- var_parent : Some ( fn_decl_scope) ,
1104- } ;
1105- visitor. visit_nested_body ( body_id) ;
1106-
1107- // Restore context we had at the start.
1108- visitor. cx = outer_cx;
1109- visitor. terminating_scopes = outer_ts;
1110- }
1111-
11121056impl < ' a , ' tcx > RegionResolutionVisitor < ' a , ' tcx > {
11131057 pub fn intern_code_extent ( & mut self ,
11141058 data : CodeExtentData ,
@@ -1152,29 +1096,57 @@ impl<'a, 'tcx> RegionResolutionVisitor<'a, 'tcx> {
11521096
11531097impl < ' a , ' tcx > Visitor < ' tcx > for RegionResolutionVisitor < ' a , ' tcx > {
11541098 fn nested_visit_map < ' this > ( & ' this mut self ) -> NestedVisitorMap < ' this , ' tcx > {
1155- NestedVisitorMap :: OnlyBodies ( & self . map )
1099+ NestedVisitorMap :: None
11561100 }
11571101
11581102 fn visit_block ( & mut self , b : & ' tcx Block ) {
11591103 resolve_block ( self , b) ;
11601104 }
11611105
1162- fn visit_item ( & mut self , i : & ' tcx Item ) {
1163- resolve_item_like ( self , |this| intravisit :: walk_item ( this , i ) ) ;
1164- }
1106+ fn visit_body ( & mut self , body : & ' tcx hir :: Body ) {
1107+ let body_id = body . id ( ) ;
1108+ let owner_id = self . map . body_owner ( body_id ) ;
11651109
1166- fn visit_impl_item ( & mut self , ii : & ' tcx hir:: ImplItem ) {
1167- resolve_item_like ( self , |this| intravisit:: walk_impl_item ( this, ii) ) ;
1168- }
1110+ debug ! ( "visit_body(id={:?}, span={:?}, body.id={:?}, cx.parent={:?})" ,
1111+ owner_id,
1112+ self . tcx. sess. codemap( ) . span_to_string( body. value. span) ,
1113+ body_id,
1114+ self . cx. parent) ;
11691115
1170- fn visit_trait_item ( & mut self , ti : & ' tcx hir:: TraitItem ) {
1171- resolve_item_like ( self , |this| intravisit:: walk_trait_item ( this, ti) ) ;
1172- }
1116+ let outer_cx = self . cx ;
1117+ let outer_ts = mem:: replace ( & mut self . terminating_scopes , NodeSet ( ) ) ;
11731118
1174- fn visit_fn ( & mut self , fk : FnKind < ' tcx > , fd : & ' tcx FnDecl ,
1175- b : hir:: BodyId , s : Span , n : NodeId ) {
1176- resolve_fn ( self , fk, fd, b, s, n) ;
1119+ // Only functions have an outer terminating (drop) scope,
1120+ // while temporaries in constant initializers are 'static.
1121+ if let MirSource :: Fn ( _) = MirSource :: from_node ( self . tcx , owner_id) {
1122+ self . terminating_scopes . insert ( body_id. node_id ) ;
1123+ }
1124+
1125+ if let Some ( root_id) = self . cx . root_id {
1126+ self . region_maps . record_fn_parent ( body_id. node_id , root_id) ;
1127+ }
1128+ self . cx . root_id = Some ( body_id. node_id ) ;
1129+
1130+ self . cx . parent = Some ( self . new_code_extent (
1131+ CodeExtentData :: CallSiteScope { fn_id : owner_id, body_id : body_id. node_id } ) ) ;
1132+ self . cx . parent = Some ( self . new_code_extent (
1133+ CodeExtentData :: ParameterScope { fn_id : owner_id, body_id : body_id. node_id } ) ) ;
1134+
1135+ // The arguments and `self` are parented to the fn.
1136+ self . cx . var_parent = self . cx . parent . take ( ) ;
1137+ for argument in & body. arguments {
1138+ self . visit_pat ( & argument. pat ) ;
1139+ }
1140+
1141+ // The body of the every fn is a root scope.
1142+ self . cx . parent = self . cx . var_parent ;
1143+ self . visit_expr ( & body. value ) ;
1144+
1145+ // Restore context we had at the start.
1146+ self . cx = outer_cx;
1147+ self . terminating_scopes = outer_ts;
11771148 }
1149+
11781150 fn visit_arm ( & mut self , a : & ' tcx Arm ) {
11791151 resolve_arm ( self , a) ;
11801152 }
@@ -1192,21 +1164,18 @@ impl<'a, 'tcx> Visitor<'tcx> for RegionResolutionVisitor<'a, 'tcx> {
11921164 }
11931165}
11941166
1195- fn region_maps < ' a , ' tcx > ( tcx : TyCtxt < ' a , ' tcx , ' tcx > , fn_id : DefId )
1167+ fn region_maps < ' a , ' tcx > ( tcx : TyCtxt < ' a , ' tcx , ' tcx > , def_id : DefId )
11961168 -> Rc < RegionMaps < ' tcx > >
11971169{
1198- let closure_base_def_id = tcx. closure_base_def_id ( fn_id ) ;
1199- if closure_base_def_id != fn_id {
1170+ let closure_base_def_id = tcx. closure_base_def_id ( def_id ) ;
1171+ if closure_base_def_id != def_id {
12001172 return tcx. region_maps ( closure_base_def_id) ;
12011173 }
12021174
12031175 let mut maps = RegionMaps :: new ( ) ;
12041176
1205- let fn_node_id = tcx. hir . as_local_node_id ( fn_id)
1206- . expect ( "fn DefId should be for LOCAL_CRATE" ) ;
1207- let node = tcx. hir . get ( fn_node_id) ;
1208-
1209- {
1177+ let id = tcx. hir . as_local_node_id ( def_id) . unwrap ( ) ;
1178+ if let Some ( body) = tcx. hir . maybe_body_owned_by ( id) {
12101179 let mut visitor = RegionResolutionVisitor {
12111180 tcx : tcx,
12121181 region_maps : & mut maps,
@@ -1218,7 +1187,8 @@ fn region_maps<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, fn_id: DefId)
12181187 } ,
12191188 terminating_scopes : NodeSet ( ) ,
12201189 } ;
1221- visitor. visit_hir_map_node ( node) ;
1190+
1191+ visitor. visit_body ( tcx. hir . body ( body) ) ;
12221192 }
12231193
12241194 Rc :: new ( maps)
0 commit comments