@@ -162,7 +162,17 @@ pub struct inherited {
162
162
adjustments : HashMap < ast:: node_id , @ty:: AutoAdjustment >
163
163
}
164
164
165
- pub enum FnKind { ForLoop , DoBlock , Vanilla }
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
+ }
166
176
167
177
pub struct FnCtxt {
168
178
// var_bindings, locals and next_var_id are shared
@@ -250,8 +260,14 @@ pub fn check_bare_fn(ccx: @mut CrateCtxt,
250
260
let fty = ty:: node_id_to_type ( ccx. tcx , id) ;
251
261
match ty:: get ( fty) . sty {
252
262
ty:: ty_bare_fn( ref fn_ty) => {
253
- check_fn ( ccx, self_info, fn_ty. purity , None ,
254
- & fn_ty. sig , decl, body, Vanilla , None )
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) ;
255
271
}
256
272
_ => ccx. tcx . sess . impossible_case ( body. span ,
257
273
"check_bare_fn: function type expected" )
@@ -261,26 +277,34 @@ pub fn check_bare_fn(ccx: @mut CrateCtxt,
261
277
pub fn check_fn ( ccx : @mut CrateCtxt ,
262
278
+self_info : Option < SelfInfo > ,
263
279
purity : ast:: purity ,
264
- sigil : Option < ast:: Sigil > ,
265
280
fn_sig : & ty:: FnSig ,
266
281
decl : & ast:: fn_decl ,
267
282
body : & ast:: blk ,
268
283
fn_kind : FnKind ,
269
- old_fcx : Option < @mut FnCtxt > ) {
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
+
270
299
let tcx = ccx. tcx ;
271
- let indirect_ret = match fn_kind {
272
- ForLoop => true , _ => false
273
- } ;
274
300
275
301
// ______________________________________________________________________
276
302
// First, we have to replace any bound regions in the fn and self
277
303
// types with free ones. The free region references will be bound
278
304
// the node_id of the body block.
279
305
280
306
let ( 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,
307
+ replace_bound_regions_in_fn_sig ( tcx, inherited_isr, self_info, fn_sig,
284
308
|br| ty:: re_free ( body. node . id , br) )
285
309
} ;
286
310
@@ -296,23 +320,13 @@ pub fn check_fn(ccx: @mut CrateCtxt,
296
320
// Create the function context. This is either derived from scratch or,
297
321
// in the case of function expressions, based on the outer context.
298
322
let fcx: @mut FnCtxt = {
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
- }
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
306
328
} ;
307
329
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
-
316
330
@mut FnCtxt {
317
331
self_info : self_info,
318
332
ret_ty : ret_ty,
@@ -370,15 +384,7 @@ pub fn check_fn(ccx: @mut CrateCtxt,
370
384
fcx. write_ty ( input. id , * arg) ;
371
385
}
372
386
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
- }
387
+ return fcx;
382
388
383
389
fn gather_locals ( fcx : @mut FnCtxt ,
384
390
decl : & ast:: fn_decl ,
@@ -903,7 +909,7 @@ pub impl FnCtxt {
903
909
a : ty:: t ,
904
910
err : & ty:: type_err ) {
905
911
match self . fn_kind {
906
- ForLoop if !ty:: type_is_bool ( e) && !ty:: type_is_nil ( a) =>
912
+ ForLoop ( _ ) if !ty:: type_is_bool ( e) && !ty:: type_is_nil ( a) =>
907
913
self . tcx ( ) . sess . span_err ( sp, fmt ! ( "A for-loop body must \
908
914
return (), but it returns %s here. \
909
915
Perhaps you meant to write a `do`-block?",
@@ -1667,10 +1673,15 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
1667
1673
1668
1674
fcx. write_ty( expr. id, fty) ;
1669
1675
1676
+ let inherited_purity =
1677
+ ty:: determine_inherited_purity( fcx. purity, purity,
1678
+ fn_ty. sigil) ;
1679
+
1670
1680
// We inherit the same self info as the enclosing scope,
1671
1681
// since the function we're checking might capture `self`
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) ) ;
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) ;
1674
1685
}
1675
1686
1676
1687
@@ -2080,7 +2091,13 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
2080
2091
// derived errors. If we passed in ForLoop in the
2081
2092
// error case, we'd potentially emit a spurious error
2082
2093
// message because of the indirect_ret_ty.
2083
- let fn_kind = if err_happened { Vanilla} else { ForLoop } ;
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
+ } ;
2084
2101
check_expr_fn( fcx, loop_body, None ,
2085
2102
decl, body, fn_kind, Some ( inner_ty) ) ;
2086
2103
demand:: suptype ( fcx , loop_body . span,
0 commit comments