@@ -95,7 +95,15 @@ use syntax::visit::{Visitor, FnKind};
95
95
RustcDecodable , Debug , Copy ) ]
96
96
pub enum CodeExtent {
97
97
Misc ( ast:: NodeId ) ,
98
- DestructionScope ( ast:: NodeId ) , // extent of destructors for temporaries of node-id
98
+
99
+ // extent of parameters passed to a function or closure (they
100
+ // outlive its body)
101
+ ParameterScope { fn_id : ast:: NodeId , body_id : ast:: NodeId } ,
102
+
103
+ // extent of destructors for temporaries of node-id
104
+ DestructionScope ( ast:: NodeId ) ,
105
+
106
+ // extent of code following a `let id = expr;` binding in a block
99
107
Remainder ( BlockRemainder )
100
108
}
101
109
@@ -153,15 +161,19 @@ impl CodeExtent {
153
161
pub fn node_id ( & self ) -> ast:: NodeId {
154
162
match * self {
155
163
CodeExtent :: Misc ( node_id) => node_id,
164
+
165
+ // These cases all return rough approximations to the
166
+ // precise extent denoted by `self`.
156
167
CodeExtent :: Remainder ( br) => br. block ,
157
168
CodeExtent :: DestructionScope ( node_id) => node_id,
169
+ CodeExtent :: ParameterScope { fn_id : _, body_id } => body_id,
158
170
}
159
171
}
160
172
161
173
/// Maps this scope to a potentially new one according to the
162
174
/// NodeId transformer `f_id`.
163
175
pub fn map_id < F > ( & self , f_id : F ) -> CodeExtent where
164
- F : FnOnce ( ast:: NodeId ) -> ast:: NodeId ,
176
+ F : Fn ( ast:: NodeId ) -> ast:: NodeId ,
165
177
{
166
178
match * self {
167
179
CodeExtent :: Misc ( node_id) => CodeExtent :: Misc ( f_id ( node_id) ) ,
@@ -170,6 +182,8 @@ impl CodeExtent {
170
182
block : f_id ( br. block ) , first_statement_index : br. first_statement_index } ) ,
171
183
CodeExtent :: DestructionScope ( node_id) =>
172
184
CodeExtent :: DestructionScope ( f_id ( node_id) ) ,
185
+ CodeExtent :: ParameterScope { fn_id, body_id } =>
186
+ CodeExtent :: ParameterScope { fn_id : f_id ( fn_id) , body_id : f_id ( body_id) } ,
173
187
}
174
188
}
175
189
@@ -180,6 +194,7 @@ impl CodeExtent {
180
194
match ast_map. find ( self . node_id ( ) ) {
181
195
Some ( ast_map:: NodeBlock ( ref blk) ) => {
182
196
match * self {
197
+ CodeExtent :: ParameterScope { .. } |
183
198
CodeExtent :: Misc ( _) |
184
199
CodeExtent :: DestructionScope ( _) => Some ( blk. span ) ,
185
200
@@ -277,6 +292,7 @@ enum InnermostDeclaringBlock {
277
292
Block ( ast:: NodeId ) ,
278
293
Statement ( DeclaringStatementContext ) ,
279
294
Match ( ast:: NodeId ) ,
295
+ FnDecl { fn_id : ast:: NodeId , body_id : ast:: NodeId } ,
280
296
}
281
297
282
298
impl InnermostDeclaringBlock {
@@ -285,6 +301,8 @@ impl InnermostDeclaringBlock {
285
301
InnermostDeclaringBlock :: None => {
286
302
return Option :: None ;
287
303
}
304
+ InnermostDeclaringBlock :: FnDecl { fn_id, body_id } =>
305
+ CodeExtent :: ParameterScope { fn_id : fn_id, body_id : body_id } ,
288
306
InnermostDeclaringBlock :: Block ( id) |
289
307
InnermostDeclaringBlock :: Match ( id) => CodeExtent :: from_node_id ( id) ,
290
308
InnermostDeclaringBlock :: Statement ( s) => s. to_code_extent ( ) ,
@@ -1198,25 +1216,34 @@ fn resolve_fn(visitor: &mut RegionResolutionVisitor,
1198
1216
body. id,
1199
1217
visitor. cx. parent) ;
1200
1218
1219
+ // This scope covers the function body, which includes the
1220
+ // bindings introduced by let statements as well as temporaries
1221
+ // created by the fn's tail expression (if any). It does *not*
1222
+ // include the fn parameters (see below).
1201
1223
let body_scope = CodeExtent :: from_node_id ( body. id ) ;
1202
1224
visitor. region_maps . mark_as_terminating_scope ( body_scope) ;
1203
1225
1204
1226
let dtor_scope = CodeExtent :: DestructionScope ( body. id ) ;
1205
1227
visitor. region_maps . record_encl_scope ( body_scope, dtor_scope) ;
1206
1228
1207
- record_superlifetime ( visitor, dtor_scope, body. span ) ;
1229
+ let fn_decl_scope = CodeExtent :: ParameterScope { fn_id : id, body_id : body. id } ;
1230
+ visitor. region_maps . record_encl_scope ( dtor_scope, fn_decl_scope) ;
1231
+
1232
+ record_superlifetime ( visitor, fn_decl_scope, body. span ) ;
1208
1233
1209
1234
if let Some ( root_id) = visitor. cx . root_id {
1210
1235
visitor. region_maps . record_fn_parent ( body. id , root_id) ;
1211
1236
}
1212
1237
1213
1238
let outer_cx = visitor. cx ;
1214
1239
1215
- // The arguments and `self` are parented to the body of the fn.
1240
+ // The arguments and `self` are parented to the fn.
1216
1241
visitor. cx = Context {
1217
1242
root_id : Some ( body. id ) ,
1218
- parent : InnermostEnclosingExpr :: Some ( body. id ) ,
1219
- var_parent : InnermostDeclaringBlock :: Block ( body. id )
1243
+ parent : InnermostEnclosingExpr :: None ,
1244
+ var_parent : InnermostDeclaringBlock :: FnDecl {
1245
+ fn_id : id, body_id : body. id
1246
+ } ,
1220
1247
} ;
1221
1248
visit:: walk_fn_decl ( visitor, decl) ;
1222
1249
0 commit comments