Get rid of the hack that ignores () typed things in fn tail position.
Closes #868. Unfortunately, this causes certain invalid programs to fail type-checking instead of failing type-state when a type-state error message would probably be more intuitive. (Although, by any reasonable interpretation of the static semantics, it technically ought to be a type error.)
This commit is contained in:
parent
498e38b705
commit
722fa00681
5 changed files with 15 additions and 30 deletions
|
@ -5271,8 +5271,7 @@ fn trans_closure(bcx_maybe: &option::t<@block_ctxt>,
|
|||
// trans_mod, trans_item, trans_obj, et cetera) and those that do
|
||||
// (trans_block, trans_expr, et cetera).
|
||||
let rslt =
|
||||
if !ty::type_is_nil(cx.ccx.tcx, block_ty) &&
|
||||
!ty::type_is_bot(cx.ccx.tcx, block_ty) &&
|
||||
if !ty::type_is_bot(cx.ccx.tcx, block_ty) &&
|
||||
f.proto != ast::proto_iter {
|
||||
trans_block(bcx, f.body, save_in(fcx.llretptr))
|
||||
} else { trans_block(bcx, f.body, return) };
|
||||
|
|
|
@ -716,7 +716,6 @@ fn find_pre_post_state_block(fcx: &fn_ctxt, pres0: &prestate, b: &blk) ->
|
|||
}
|
||||
|
||||
fn find_pre_post_state_fn(fcx: &fn_ctxt, f: &_fn) -> bool {
|
||||
|
||||
let num_constrs = num_constraints(fcx.enclosing);
|
||||
// All constraints are considered false until proven otherwise.
|
||||
// This ensures that intersect works correctly.
|
||||
|
@ -729,25 +728,20 @@ fn find_pre_post_state_fn(fcx: &fn_ctxt, f: &_fn) -> bool {
|
|||
}
|
||||
|
||||
// Instantiate any constraints on the arguments so we can use them
|
||||
let tsc;
|
||||
for c: @constr in f.decl.constraints {
|
||||
tsc = ast_constr_to_ts_constr(fcx.ccx.tcx, f.decl.inputs, c);
|
||||
let tsc = ast_constr_to_ts_constr(fcx.ccx.tcx, f.decl.inputs, c);
|
||||
set_in_prestate_constr(fcx, tsc, block_pre);
|
||||
}
|
||||
|
||||
let changed = find_pre_post_state_block(fcx, block_pre, f.body);
|
||||
// Treat the tail expression as a return statement
|
||||
|
||||
// Treat the tail expression as a return statement
|
||||
alt f.body.node.expr {
|
||||
some(tailexpr) {
|
||||
let tailty = expr_ty(fcx.ccx.tcx, tailexpr);
|
||||
|
||||
// Since blocks and alts and ifs that don't have results
|
||||
// implicitly result in nil, we have to be careful to not
|
||||
// interpret nil-typed block results as the result of a
|
||||
// function with some other return type
|
||||
if !type_is_nil(fcx.ccx.tcx, tailty) &&
|
||||
!type_is_bot(fcx.ccx.tcx, tailty) {
|
||||
// We don't want to clear the diverges bit for bottom typed things,
|
||||
// which really do diverge. I feel like there is a cleaner way
|
||||
// to do this than checking the type.
|
||||
if !type_is_bot(fcx.ccx.tcx, expr_ty(fcx.ccx.tcx, tailexpr)) {
|
||||
let post = false_postcond(num_constrs);
|
||||
// except for the "diverges" bit...
|
||||
kill_poststate_(fcx, fcx.enclosing.i_diverge, post);
|
||||
|
|
|
@ -2692,22 +2692,14 @@ fn check_fn(ccx: &@crate_ctxt, f: &ast::_fn, id: &ast::node_id,
|
|||
// function result type, if there is a tail expr.
|
||||
// We don't do this check for an iterator, as the tail expr doesn't
|
||||
// have to have the result type of the iterator.
|
||||
if option::is_some(body.node.expr) && f.proto != ast::proto_iter {
|
||||
let tail_expr = option::get(body.node.expr);
|
||||
// The use of resolve_type_vars_if_possible makes me very
|
||||
// afraid :-(
|
||||
let tail_expr_ty =
|
||||
resolve_type_vars_if_possible(fcx, expr_ty(ccx.tcx, tail_expr));
|
||||
|
||||
// Hacky compromise: use eq and not are_compatible
|
||||
// This allows things like while loops and ifs with no
|
||||
// else to appear in tail position without a trailing
|
||||
// semicolon when the return type is non-nil, while
|
||||
// making sure to unify the tailexpr-type with the result
|
||||
// type when the tailexpr-type is just a type variable.
|
||||
if !ty::eq_ty(tail_expr_ty, ty::mk_nil(ccx.tcx)) {
|
||||
alt (body.node.expr) {
|
||||
some(tail_expr) {
|
||||
if f.proto != ast::proto_iter {
|
||||
let tail_expr_ty = expr_ty(ccx.tcx, tail_expr);
|
||||
demand::simple(fcx, tail_expr.span, fcx.ret_ty, tail_expr_ty);
|
||||
}
|
||||
}
|
||||
none. {}
|
||||
}
|
||||
|
||||
// If we don't have any enclosing function scope, it is time to
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// -*- rust -*-
|
||||
// error-pattern: not all control paths return
|
||||
// error-pattern: mismatched types
|
||||
|
||||
fn god_exists(a: int) -> bool { be god_exists(a); }
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// error-pattern: return
|
||||
// error-pattern: mismatched types
|
||||
|
||||
fn f() -> int {
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue