Skip to content

Commit 1d8596d

Browse files
committed
auto merge of #5309 : nikomatsakis/rust/simplify_check_fn, r=nikomatsakis
Simplify the interface to check_fn by pulling some of the madness out to its callers. rs=refactor
2 parents 267f6c2 + 62aa8d7 commit 1d8596d

File tree

1 file changed

+56
-39
lines changed
  • src/librustc/middle/typeck/check

1 file changed

+56
-39
lines changed

src/librustc/middle/typeck/check/mod.rs

Lines changed: 56 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -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

167177
pub 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,
261277
pub 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

Comments
 (0)