@@ -162,17 +162,7 @@ pub struct inherited {
162
162
adjustments : HashMap < ast:: node_id , @ty:: AutoAdjustment >
163
163
}
164
164
165
- pub enum FnKind {
166
- // This is a for-closure. The ty::t is the return type of the
167
- // enclosing function.
168
- ForLoop ( ty:: t ) ,
169
-
170
- // A do-closure.
171
- DoBlock ,
172
-
173
- // A normal closure or fn item.
174
- Vanilla
175
- }
165
+ pub enum FnKind { ForLoop , DoBlock , Vanilla }
176
166
177
167
pub struct FnCtxt {
178
168
// var_bindings, locals and next_var_id are shared
@@ -260,14 +250,8 @@ pub fn check_bare_fn(ccx: @mut CrateCtxt,
260
250
let fty = ty:: node_id_to_type ( ccx. tcx , id) ;
261
251
match ty:: get ( fty) . sty {
262
252
ty:: ty_bare_fn( ref fn_ty) => {
263
- let fcx =
264
- check_fn ( ccx, self_info, fn_ty. purity ,
265
- & fn_ty. sig , decl, body, Vanilla ,
266
- @Nil , blank_inherited ( ccx) ) ; ;
267
-
268
- vtable:: resolve_in_block ( fcx, body) ;
269
- regionck:: regionck_fn ( fcx, body) ;
270
- writeback:: resolve_type_vars_in_fn ( fcx, decl, body, self_info) ;
253
+ check_fn ( ccx, self_info, fn_ty. purity , None ,
254
+ & fn_ty. sig , decl, body, Vanilla , None )
271
255
}
272
256
_ => ccx. tcx . sess . impossible_case ( body. span ,
273
257
"check_bare_fn: function type expected" )
@@ -277,34 +261,26 @@ pub fn check_bare_fn(ccx: @mut CrateCtxt,
277
261
pub fn check_fn ( ccx : @mut CrateCtxt ,
278
262
+self_info : Option < SelfInfo > ,
279
263
purity : ast:: purity ,
264
+ sigil : Option < ast:: Sigil > ,
280
265
fn_sig : & ty:: FnSig ,
281
266
decl : & ast:: fn_decl ,
282
267
body : & ast:: blk ,
283
268
fn_kind : FnKind ,
284
- inherited_isr : isr_alist ,
285
- inherited : @inherited ) -> @mut FnCtxt
286
- {
287
- /*!
288
- *
289
- * Helper used by check_bare_fn and check_expr_fn. Does the
290
- * grungy work of checking a function body and returns the
291
- * function context used for that purpose, since in the case of a
292
- * fn item there is still a bit more to do.
293
- *
294
- * - ...
295
- * - inherited_isr: regions in scope from the enclosing fn (if any)
296
- * - inherited: other fields inherited from the enclosing fn (if any)
297
- */
298
-
269
+ old_fcx : Option < @mut FnCtxt > ) {
299
270
let tcx = ccx. tcx ;
271
+ let indirect_ret = match fn_kind {
272
+ ForLoop => true , _ => false
273
+ } ;
300
274
301
275
// ______________________________________________________________________
302
276
// First, we have to replace any bound regions in the fn and self
303
277
// types with free ones. The free region references will be bound
304
278
// the node_id of the body block.
305
279
306
280
let ( isr, self_info, fn_sig) = {
307
- replace_bound_regions_in_fn_sig ( tcx, inherited_isr, self_info, fn_sig,
281
+ let old_isr = option:: map_default ( & old_fcx, @Nil ,
282
+ |fcx| fcx. in_scope_regions ) ;
283
+ replace_bound_regions_in_fn_sig ( tcx, old_isr, self_info, fn_sig,
308
284
|br| ty:: re_free ( body. node . id , br) )
309
285
} ;
310
286
@@ -320,13 +296,23 @@ pub fn check_fn(ccx: @mut CrateCtxt,
320
296
// Create the function context. This is either derived from scratch or,
321
297
// in the case of function expressions, based on the outer context.
322
298
let fcx: @mut FnCtxt = {
323
- // In a for-loop, you have an 'indirect return' because return
324
- // does not return out of the directly enclosing fn
325
- let indirect_ret_ty = match fn_kind {
326
- ForLoop ( t) => Some ( t) ,
327
- DoBlock | Vanilla => None
299
+ let ( purity, inherited) = match old_fcx {
300
+ None => ( purity, blank_inherited ( ccx) ) ,
301
+ Some ( fcx) => {
302
+ ( ty:: determine_inherited_purity ( fcx. purity , purity,
303
+ sigil. get ( ) ) ,
304
+ fcx. inh )
305
+ }
328
306
} ;
329
307
308
+ let indirect_ret_ty = if indirect_ret {
309
+ let ofcx = old_fcx. get ( ) ;
310
+ match ofcx. indirect_ret_ty {
311
+ Some ( t) => Some ( t) ,
312
+ None => Some ( ofcx. ret_ty )
313
+ }
314
+ } else { None } ;
315
+
330
316
@mut FnCtxt {
331
317
self_info : self_info,
332
318
ret_ty : ret_ty,
@@ -384,7 +370,15 @@ pub fn check_fn(ccx: @mut CrateCtxt,
384
370
fcx. write_ty ( input. id , * arg) ;
385
371
}
386
372
387
- return fcx;
373
+ // If we don't have any enclosing function scope, it is time to
374
+ // force any remaining type vars to be resolved.
375
+ // If we have an enclosing function scope, our type variables will be
376
+ // resolved when the enclosing scope finishes up.
377
+ if old_fcx. is_none ( ) {
378
+ vtable:: resolve_in_block ( fcx, body) ;
379
+ regionck:: regionck_fn ( fcx, body) ;
380
+ writeback:: resolve_type_vars_in_fn ( fcx, decl, body, self_info) ;
381
+ }
388
382
389
383
fn gather_locals ( fcx : @mut FnCtxt ,
390
384
decl : & ast:: fn_decl ,
@@ -909,7 +903,7 @@ pub impl FnCtxt {
909
903
a : ty:: t ,
910
904
err : & ty:: type_err ) {
911
905
match self . fn_kind {
912
- ForLoop ( _ ) if !ty:: type_is_bool ( e) && !ty:: type_is_nil ( a) =>
906
+ ForLoop if !ty:: type_is_bool ( e) && !ty:: type_is_nil ( a) =>
913
907
self . tcx ( ) . sess . span_err ( sp, fmt ! ( "A for-loop body must \
914
908
return (), but it returns %s here. \
915
909
Perhaps you meant to write a `do`-block?",
@@ -1673,15 +1667,10 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
1673
1667
1674
1668
fcx. write_ty( expr. id, fty) ;
1675
1669
1676
- let inherited_purity =
1677
- ty:: determine_inherited_purity( fcx. purity, purity,
1678
- fn_ty. sigil) ;
1679
-
1680
1670
// We inherit the same self info as the enclosing scope,
1681
1671
// since the function we're checking might capture `self`
1682
- check_fn( fcx. ccx, fcx. self_info, inherited_purity,
1683
- & fn_ty. sig, decl, body, fn_kind,
1684
- fcx. in_scope_regions, fcx. inh) ;
1672
+ check_fn( fcx. ccx, fcx. self_info, fn_ty. purity, Some ( fn_ty. sigil) ,
1673
+ & fn_ty. sig, decl, body, fn_kind, Some ( fcx) ) ;
1685
1674
}
1686
1675
1687
1676
@@ -2091,13 +2080,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
2091
2080
// derived errors. If we passed in ForLoop in the
2092
2081
// error case, we'd potentially emit a spurious error
2093
2082
// message because of the indirect_ret_ty.
2094
- let fn_kind = if err_happened {
2095
- Vanilla
2096
- } else {
2097
- let indirect_ret_ty =
2098
- fcx. indirect_ret_ty. get_or_default( fcx. ret_ty) ;
2099
- ForLoop ( indirect_ret_ty)
2100
- } ;
2083
+ let fn_kind = if err_happened { Vanilla} else { ForLoop } ;
2101
2084
check_expr_fn( fcx, loop_body, None ,
2102
2085
decl, body, fn_kind, Some ( inner_ty) ) ;
2103
2086
demand:: suptype ( fcx , loop_body . span,
0 commit comments