@@ -162,7 +162,17 @@ pub struct inherited {
162162 adjustments : HashMap < ast:: node_id , @ty:: AutoAdjustment >
163163}
164164
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+ }
166176
167177pub struct FnCtxt {
168178 // var_bindings, locals and next_var_id are shared
@@ -250,8 +260,14 @@ pub fn check_bare_fn(ccx: @mut CrateCtxt,
250260 let fty = ty:: node_id_to_type ( ccx. tcx , id) ;
251261 match ty:: get ( fty) . sty {
252262 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) ;
255271 }
256272 _ => ccx. tcx . sess . impossible_case ( body. span ,
257273 "check_bare_fn: function type expected" )
@@ -261,26 +277,34 @@ pub fn check_bare_fn(ccx: @mut CrateCtxt,
261277pub fn check_fn ( ccx : @mut CrateCtxt ,
262278 +self_info : Option < SelfInfo > ,
263279 purity : ast:: purity ,
264- sigil : Option < ast:: Sigil > ,
265280 fn_sig : & ty:: FnSig ,
266281 decl : & ast:: fn_decl ,
267282 body : & ast:: blk ,
268283 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+
270299 let tcx = ccx. tcx ;
271- let indirect_ret = match fn_kind {
272- ForLoop => true , _ => false
273- } ;
274300
275301 // ______________________________________________________________________
276302 // First, we have to replace any bound regions in the fn and self
277303 // types with free ones. The free region references will be bound
278304 // the node_id of the body block.
279305
280306 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,
284308 |br| ty:: re_free ( body. node . id , br) )
285309 } ;
286310
@@ -296,23 +320,13 @@ pub fn check_fn(ccx: @mut CrateCtxt,
296320 // Create the function context. This is either derived from scratch or,
297321 // in the case of function expressions, based on the outer context.
298322 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
306328 } ;
307329
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-
316330 @mut FnCtxt {
317331 self_info : self_info,
318332 ret_ty : ret_ty,
@@ -370,15 +384,7 @@ pub fn check_fn(ccx: @mut CrateCtxt,
370384 fcx. write_ty ( input. id , * arg) ;
371385 }
372386
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;
382388
383389 fn gather_locals ( fcx : @mut FnCtxt ,
384390 decl : & ast:: fn_decl ,
@@ -903,7 +909,7 @@ pub impl FnCtxt {
903909 a : ty:: t ,
904910 err : & ty:: type_err ) {
905911 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) =>
907913 self . tcx ( ) . sess . span_err ( sp, fmt ! ( "A for-loop body must \
908914 return (), but it returns %s here. \
909915 Perhaps you meant to write a `do`-block?",
@@ -1667,10 +1673,15 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
16671673
16681674 fcx. write_ty( expr. id, fty) ;
16691675
1676+ let inherited_purity =
1677+ ty:: determine_inherited_purity( fcx. purity, purity,
1678+ fn_ty. sigil) ;
1679+
16701680 // We inherit the same self info as the enclosing scope,
16711681 // 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) ;
16741685 }
16751686
16761687
@@ -2080,7 +2091,13 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
20802091 // derived errors. If we passed in ForLoop in the
20812092 // error case, we'd potentially emit a spurious error
20822093 // 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+ } ;
20842101 check_expr_fn( fcx, loop_body, None ,
20852102 decl, body, fn_kind, Some ( inner_ty) ) ;
20862103 demand:: suptype ( fcx , loop_body . span,
0 commit comments