@@ -24,14 +24,16 @@ use std::mem;
24
24
use std:: rc:: Rc ;
25
25
use serialize;
26
26
use syntax:: codemap;
27
- use syntax:: ast:: { self , NodeId } ;
27
+ use syntax:: ast;
28
28
use syntax_pos:: Span ;
29
29
use ty:: TyCtxt ;
30
30
use ty:: maps:: Providers ;
31
31
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 ;
35
37
36
38
pub type CodeExtent < ' tcx > = & ' tcx CodeExtentData ;
37
39
@@ -811,7 +813,17 @@ fn resolve_expr<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>, expr:
811
813
}
812
814
}
813
815
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
+
815
827
visitor. cx = prev_cx;
816
828
}
817
829
@@ -1041,74 +1053,6 @@ fn resolve_local<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>,
1041
1053
}
1042
1054
}
1043
1055
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
-
1112
1056
impl < ' a , ' tcx > RegionResolutionVisitor < ' a , ' tcx > {
1113
1057
pub fn intern_code_extent ( & mut self ,
1114
1058
data : CodeExtentData ,
@@ -1152,29 +1096,57 @@ impl<'a, 'tcx> RegionResolutionVisitor<'a, 'tcx> {
1152
1096
1153
1097
impl < ' a , ' tcx > Visitor < ' tcx > for RegionResolutionVisitor < ' a , ' tcx > {
1154
1098
fn nested_visit_map < ' this > ( & ' this mut self ) -> NestedVisitorMap < ' this , ' tcx > {
1155
- NestedVisitorMap :: OnlyBodies ( & self . map )
1099
+ NestedVisitorMap :: None
1156
1100
}
1157
1101
1158
1102
fn visit_block ( & mut self , b : & ' tcx Block ) {
1159
1103
resolve_block ( self , b) ;
1160
1104
}
1161
1105
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 ) ;
1165
1109
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) ;
1169
1115
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 ( ) ) ;
1173
1118
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;
1177
1148
}
1149
+
1178
1150
fn visit_arm ( & mut self , a : & ' tcx Arm ) {
1179
1151
resolve_arm ( self , a) ;
1180
1152
}
@@ -1192,21 +1164,18 @@ impl<'a, 'tcx> Visitor<'tcx> for RegionResolutionVisitor<'a, 'tcx> {
1192
1164
}
1193
1165
}
1194
1166
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 )
1196
1168
-> Rc < RegionMaps < ' tcx > >
1197
1169
{
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 {
1200
1172
return tcx. region_maps ( closure_base_def_id) ;
1201
1173
}
1202
1174
1203
1175
let mut maps = RegionMaps :: new ( ) ;
1204
1176
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) {
1210
1179
let mut visitor = RegionResolutionVisitor {
1211
1180
tcx : tcx,
1212
1181
region_maps : & mut maps,
@@ -1218,7 +1187,8 @@ fn region_maps<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, fn_id: DefId)
1218
1187
} ,
1219
1188
terminating_scopes : NodeSet ( ) ,
1220
1189
} ;
1221
- visitor. visit_hir_map_node ( node) ;
1190
+
1191
+ visitor. visit_body ( tcx. hir . body ( body) ) ;
1222
1192
}
1223
1193
1224
1194
Rc :: new ( maps)
0 commit comments