mirror of
https://github.com/rust-lang/rust.git
synced 2025-01-28 15:43:21 +00:00
rm obsolete for
support from the compiler
This commit is contained in:
parent
1008945528
commit
e7bb33aed8
@ -396,7 +396,6 @@ impl CFGBuilder {
|
||||
}
|
||||
|
||||
ast::expr_addr_of(_, e) |
|
||||
ast::expr_loop_body(e) |
|
||||
ast::expr_do_body(e) |
|
||||
ast::expr_cast(e, _) |
|
||||
ast::expr_unary(_, _, e) |
|
||||
|
@ -45,14 +45,6 @@ pub fn check_crate(tcx: ty::ctxt, crate: &Crate) {
|
||||
can_ret: false
|
||||
}, v));
|
||||
}
|
||||
expr_loop_body(@expr {node: expr_fn_block(_, ref b), _}) => {
|
||||
let sigil = ty::ty_closure_sigil(ty::expr_ty(tcx, e));
|
||||
let blk = (sigil == BorrowedSigil);
|
||||
(v.visit_block)(b, (Context {
|
||||
in_loop: true,
|
||||
can_ret: blk
|
||||
}, v));
|
||||
}
|
||||
expr_break(_) => {
|
||||
if !cx.in_loop {
|
||||
tcx.sess.span_err(e.span, "`break` outside of loop");
|
||||
|
@ -82,19 +82,8 @@ struct PropagationContext<'self, O> {
|
||||
changed: bool
|
||||
}
|
||||
|
||||
#[deriving(Eq)]
|
||||
enum LoopKind {
|
||||
/// A `while` or `loop` loop
|
||||
TrueLoop,
|
||||
|
||||
/// A `for` "loop" (i.e., really a func call where `break`, `return`,
|
||||
/// and `loop` all essentially perform an early return from the closure)
|
||||
ForLoop
|
||||
}
|
||||
|
||||
struct LoopScope<'self> {
|
||||
loop_id: ast::NodeId,
|
||||
loop_kind: LoopKind,
|
||||
break_bits: ~[uint]
|
||||
}
|
||||
|
||||
@ -509,7 +498,6 @@ impl<'self, O:DataFlowOperator> PropagationContext<'self, O> {
|
||||
|
||||
loop_scopes.push(LoopScope {
|
||||
loop_id: expr.id,
|
||||
loop_kind: ForLoop,
|
||||
break_bits: reslice(in_out).to_owned()
|
||||
});
|
||||
for input in decl.inputs.iter() {
|
||||
@ -574,7 +562,6 @@ impl<'self, O:DataFlowOperator> PropagationContext<'self, O> {
|
||||
let mut body_bits = reslice(in_out).to_owned();
|
||||
loop_scopes.push(LoopScope {
|
||||
loop_id: expr.id,
|
||||
loop_kind: TrueLoop,
|
||||
break_bits: reslice(in_out).to_owned()
|
||||
});
|
||||
self.walk_block(blk, body_bits, loop_scopes);
|
||||
@ -599,7 +586,6 @@ impl<'self, O:DataFlowOperator> PropagationContext<'self, O> {
|
||||
self.reset(in_out);
|
||||
loop_scopes.push(LoopScope {
|
||||
loop_id: expr.id,
|
||||
loop_kind: TrueLoop,
|
||||
break_bits: reslice(in_out).to_owned()
|
||||
});
|
||||
self.walk_block(blk, body_bits, loop_scopes);
|
||||
@ -646,20 +632,6 @@ impl<'self, O:DataFlowOperator> PropagationContext<'self, O> {
|
||||
|
||||
ast::expr_ret(o_e) => {
|
||||
self.walk_opt_expr(o_e, in_out, loop_scopes);
|
||||
|
||||
// is this a return from a `for`-loop closure?
|
||||
match loop_scopes.iter().position(|s| s.loop_kind == ForLoop) {
|
||||
Some(i) => {
|
||||
// if so, add the in_out bits to the state
|
||||
// upon exit. Remember that we cannot count
|
||||
// upon the `for` loop function not to invoke
|
||||
// the closure again etc.
|
||||
self.break_from_to(expr, &mut loop_scopes[i], in_out);
|
||||
}
|
||||
|
||||
None => {}
|
||||
}
|
||||
|
||||
self.reset(in_out);
|
||||
}
|
||||
|
||||
@ -671,22 +643,8 @@ impl<'self, O:DataFlowOperator> PropagationContext<'self, O> {
|
||||
|
||||
ast::expr_again(label) => {
|
||||
let scope = self.find_scope(expr, label, loop_scopes);
|
||||
|
||||
match scope.loop_kind {
|
||||
TrueLoop => {
|
||||
self.pop_scopes(expr, scope, in_out);
|
||||
self.add_to_entry_set(scope.loop_id, reslice(in_out));
|
||||
}
|
||||
|
||||
ForLoop => {
|
||||
// If this `loop` construct is looping back to a `for`
|
||||
// loop, then `loop` is really just a return from the
|
||||
// closure. Therefore, we treat it the same as `break`.
|
||||
// See case for `expr_fn_block` for more details.
|
||||
self.break_from_to(expr, scope, in_out);
|
||||
}
|
||||
}
|
||||
|
||||
self.pop_scopes(expr, scope, in_out);
|
||||
self.add_to_entry_set(scope.loop_id, reslice(in_out));
|
||||
self.reset(in_out);
|
||||
}
|
||||
|
||||
@ -756,7 +714,6 @@ impl<'self, O:DataFlowOperator> PropagationContext<'self, O> {
|
||||
}
|
||||
|
||||
ast::expr_addr_of(_, e) |
|
||||
ast::expr_loop_body(e) |
|
||||
ast::expr_do_body(e) |
|
||||
ast::expr_cast(e, _) |
|
||||
ast::expr_unary(_, _, e) |
|
||||
|
@ -512,7 +512,7 @@ fn visit_expr(expr: @expr, (this, vt): (@mut IrMaps, vt<@mut IrMaps>)) {
|
||||
// otherwise, live nodes are not required:
|
||||
expr_index(*) | expr_field(*) | expr_vstore(*) | expr_vec(*) |
|
||||
expr_call(*) | expr_method_call(*) | expr_tup(*) | expr_log(*) |
|
||||
expr_binary(*) | expr_addr_of(*) | expr_loop_body(*) |
|
||||
expr_binary(*) | expr_addr_of(*) |
|
||||
expr_do_body(*) | expr_cast(*) | expr_unary(*) | expr_break(_) |
|
||||
expr_again(_) | expr_lit(_) | expr_ret(*) | expr_block(*) |
|
||||
expr_assign(*) | expr_assign_op(*) | expr_mac(*) |
|
||||
@ -1209,7 +1209,6 @@ impl Liveness {
|
||||
}
|
||||
|
||||
expr_addr_of(_, e) |
|
||||
expr_loop_body(e) |
|
||||
expr_do_body(e) |
|
||||
expr_cast(e, _) |
|
||||
expr_unary(_, _, e) |
|
||||
@ -1483,7 +1482,7 @@ fn check_expr(expr: @expr, (this, vt): (@Liveness, vt<@Liveness>)) {
|
||||
expr_call(*) | expr_method_call(*) | expr_if(*) | expr_match(*) |
|
||||
expr_while(*) | expr_loop(*) | expr_index(*) | expr_field(*) |
|
||||
expr_vstore(*) | expr_vec(*) | expr_tup(*) | expr_log(*) |
|
||||
expr_binary(*) | expr_loop_body(*) | expr_do_body(*) |
|
||||
expr_binary(*) | expr_do_body(*) |
|
||||
expr_cast(*) | expr_unary(*) | expr_ret(*) | expr_break(*) |
|
||||
expr_again(*) | expr_lit(_) | expr_block(*) |
|
||||
expr_mac(*) | expr_addr_of(*) | expr_struct(*) | expr_repeat(*) |
|
||||
|
@ -423,7 +423,7 @@ impl mem_categorization_ctxt {
|
||||
|
||||
ast::expr_addr_of(*) | ast::expr_call(*) |
|
||||
ast::expr_assign(*) | ast::expr_assign_op(*) |
|
||||
ast::expr_fn_block(*) | ast::expr_ret(*) | ast::expr_loop_body(*) |
|
||||
ast::expr_fn_block(*) | ast::expr_ret(*) |
|
||||
ast::expr_do_body(*) | ast::expr_unary(*) |
|
||||
ast::expr_method_call(*) | ast::expr_cast(*) | ast::expr_vstore(*) |
|
||||
ast::expr_vec(*) | ast::expr_tup(*) | ast::expr_if(*) |
|
||||
|
@ -541,7 +541,6 @@ impl VisitContext {
|
||||
self.consume_expr(count, visitor);
|
||||
}
|
||||
|
||||
expr_loop_body(base) |
|
||||
expr_do_body(base) => {
|
||||
self.use_expr(base, comp_mode, visitor);
|
||||
}
|
||||
|
@ -41,7 +41,6 @@ pub fn trans_inline_asm(bcx: @mut Block, ia: &ast::inline_asm) -> @mut Block {
|
||||
ty::ByCopy,
|
||||
out,
|
||||
&mut cleanups,
|
||||
None,
|
||||
callee::DontAutorefArg)
|
||||
}));
|
||||
|
||||
@ -56,7 +55,6 @@ pub fn trans_inline_asm(bcx: @mut Block, ia: &ast::inline_asm) -> @mut Block {
|
||||
ty::ByCopy,
|
||||
e,
|
||||
&mut cleanups,
|
||||
None,
|
||||
callee::DontAutorefArg)
|
||||
})
|
||||
|
||||
@ -77,7 +75,6 @@ pub fn trans_inline_asm(bcx: @mut Block, ia: &ast::inline_asm) -> @mut Block {
|
||||
ty::ByCopy,
|
||||
input,
|
||||
&mut cleanups,
|
||||
None,
|
||||
callee::DontAutorefArg)
|
||||
})
|
||||
|
||||
|
@ -27,7 +27,6 @@ use middle::trans::base;
|
||||
use middle::trans::base::*;
|
||||
use middle::trans::build::*;
|
||||
use middle::trans::callee;
|
||||
use middle::trans::closure;
|
||||
use middle::trans::common;
|
||||
use middle::trans::common::*;
|
||||
use middle::trans::datum::*;
|
||||
@ -556,29 +555,9 @@ pub fn trans_call_inner(in_cx: @mut Block,
|
||||
autoref_arg: AutorefArg)
|
||||
-> Result {
|
||||
do base::with_scope_result(in_cx, call_info, "call") |cx| {
|
||||
let ret_in_loop = match args {
|
||||
ArgExprs(args) => {
|
||||
args.len() > 0u && match args.last().node {
|
||||
ast::expr_loop_body(@ast::expr {
|
||||
node: ast::expr_fn_block(_, ref body),
|
||||
_
|
||||
}) => body_contains_ret(body),
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
_ => false
|
||||
};
|
||||
|
||||
let callee = get_callee(cx);
|
||||
let mut bcx = callee.bcx;
|
||||
let ccx = cx.ccx();
|
||||
let ret_flag = if ret_in_loop {
|
||||
let flag = alloca(bcx, Type::bool(), "__ret_flag");
|
||||
Store(bcx, C_bool(false), flag);
|
||||
Some(flag)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let (llfn, llenv) = unsafe {
|
||||
match callee.data {
|
||||
@ -611,9 +590,7 @@ pub fn trans_call_inner(in_cx: @mut Block,
|
||||
}
|
||||
|
||||
llargs.push(llenv);
|
||||
bcx = trans_args(bcx, args, fn_expr_ty,
|
||||
ret_flag, autoref_arg, &mut llargs);
|
||||
|
||||
bcx = trans_args(bcx, args, fn_expr_ty, autoref_arg, &mut llargs);
|
||||
|
||||
// Now that the arguments have finished evaluating, we need to revoke
|
||||
// the cleanup for the self argument
|
||||
@ -667,20 +644,6 @@ pub fn trans_call_inner(in_cx: @mut Block,
|
||||
|
||||
if ty::type_is_bot(ret_ty) {
|
||||
Unreachable(bcx);
|
||||
} else if ret_in_loop {
|
||||
let ret_flag_result = bool_to_i1(bcx, Load(bcx, ret_flag.get()));
|
||||
bcx = do with_cond(bcx, ret_flag_result) |bcx| {
|
||||
{
|
||||
let r = bcx.fcx.loop_ret;
|
||||
for &(flagptr, _) in r.iter() {
|
||||
Store(bcx, C_bool(true), flagptr);
|
||||
Store(bcx, C_bool(false), bcx.fcx.llretptr.get());
|
||||
}
|
||||
}
|
||||
base::cleanup_and_leave(bcx, None, Some(bcx.fcx.get_llreturn()));
|
||||
Unreachable(bcx);
|
||||
bcx
|
||||
}
|
||||
}
|
||||
rslt(bcx, llresult)
|
||||
}
|
||||
@ -713,7 +676,6 @@ pub fn trans_ret_slot(bcx: @mut Block, fn_ty: ty::t, dest: Option<expr::Dest>)
|
||||
pub fn trans_args(cx: @mut Block,
|
||||
args: CallArgs,
|
||||
fn_ty: ty::t,
|
||||
ret_flag: Option<ValueRef>,
|
||||
autoref_arg: AutorefArg,
|
||||
llargs: &mut ~[ValueRef]) -> @mut Block
|
||||
{
|
||||
@ -728,7 +690,6 @@ pub fn trans_args(cx: @mut Block,
|
||||
// to cast her view of the arguments to the caller's view.
|
||||
match args {
|
||||
ArgExprs(arg_exprs) => {
|
||||
let last = arg_exprs.len() - 1u;
|
||||
for (i, arg_expr) in arg_exprs.iter().enumerate() {
|
||||
let arg_val = unpack_result!(bcx, {
|
||||
trans_arg_expr(bcx,
|
||||
@ -736,7 +697,6 @@ pub fn trans_args(cx: @mut Block,
|
||||
ty::ByCopy,
|
||||
*arg_expr,
|
||||
&mut temp_cleanups,
|
||||
if i == last { ret_flag } else { None },
|
||||
autoref_arg)
|
||||
});
|
||||
llargs.push(arg_val);
|
||||
@ -769,49 +729,17 @@ pub fn trans_arg_expr(bcx: @mut Block,
|
||||
self_mode: ty::SelfMode,
|
||||
arg_expr: @ast::expr,
|
||||
temp_cleanups: &mut ~[ValueRef],
|
||||
ret_flag: Option<ValueRef>,
|
||||
autoref_arg: AutorefArg) -> Result {
|
||||
let _icx = push_ctxt("trans_arg_expr");
|
||||
let ccx = bcx.ccx();
|
||||
|
||||
debug!("trans_arg_expr(formal_arg_ty=(%s), self_mode=%?, arg_expr=%s, \
|
||||
ret_flag=%?)",
|
||||
debug!("trans_arg_expr(formal_arg_ty=(%s), self_mode=%?, arg_expr=%s)",
|
||||
formal_arg_ty.repr(bcx.tcx()),
|
||||
self_mode,
|
||||
arg_expr.repr(bcx.tcx()),
|
||||
ret_flag.map(|v| bcx.val_to_str(*v)));
|
||||
arg_expr.repr(bcx.tcx()));
|
||||
|
||||
// translate the arg expr to a datum
|
||||
let arg_datumblock = match ret_flag {
|
||||
None => expr::trans_to_datum(bcx, arg_expr),
|
||||
|
||||
// If there is a ret_flag, this *must* be a loop body
|
||||
Some(_) => {
|
||||
match arg_expr.node {
|
||||
ast::expr_loop_body(
|
||||
blk @ @ast::expr {
|
||||
node: ast::expr_fn_block(ref decl, ref body),
|
||||
_
|
||||
}) => {
|
||||
let scratch_ty = expr_ty(bcx, arg_expr);
|
||||
let scratch = alloc_ty(bcx, scratch_ty, "__ret_flag");
|
||||
let arg_ty = expr_ty(bcx, arg_expr);
|
||||
let sigil = ty::ty_closure_sigil(arg_ty);
|
||||
let bcx = closure::trans_expr_fn(
|
||||
bcx, sigil, decl, body, arg_expr.id,
|
||||
blk.id, Some(ret_flag), expr::SaveIn(scratch));
|
||||
DatumBlock {bcx: bcx,
|
||||
datum: Datum {val: scratch,
|
||||
ty: scratch_ty,
|
||||
mode: ByRef(RevokeClean)}}
|
||||
}
|
||||
_ => {
|
||||
bcx.sess().impossible_case(
|
||||
arg_expr.span, "ret_flag with non-loop-body expr");
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
let arg_datumblock = expr::trans_to_datum(bcx, arg_expr);
|
||||
let arg_datum = arg_datumblock.datum;
|
||||
let bcx = arg_datumblock.bcx;
|
||||
|
||||
|
@ -605,27 +605,6 @@ fn trans_rvalue_dps_unadjusted(bcx: @mut Block, expr: @ast::expr,
|
||||
expr.id, expr.id,
|
||||
None, dest);
|
||||
}
|
||||
ast::expr_loop_body(blk) => {
|
||||
let expr_ty = expr_ty(bcx, expr);
|
||||
let sigil = ty::ty_closure_sigil(expr_ty);
|
||||
match blk.node {
|
||||
ast::expr_fn_block(ref decl, ref body) => {
|
||||
return closure::trans_expr_fn(bcx,
|
||||
sigil,
|
||||
decl,
|
||||
body,
|
||||
expr.id,
|
||||
blk.id,
|
||||
Some(None),
|
||||
dest);
|
||||
}
|
||||
_ => {
|
||||
bcx.sess().impossible_case(
|
||||
expr.span,
|
||||
"loop_body has the wrong kind of contents")
|
||||
}
|
||||
}
|
||||
}
|
||||
ast::expr_do_body(blk) => {
|
||||
return trans_into(bcx, blk, dest);
|
||||
}
|
||||
|
@ -137,7 +137,6 @@ pub fn trans_self_arg(bcx: @mut Block,
|
||||
mentry.self_mode,
|
||||
base,
|
||||
temp_cleanups,
|
||||
None,
|
||||
DontAutorefArg)
|
||||
}
|
||||
|
||||
|
@ -400,7 +400,7 @@ pub fn mark_for_expr(cx: &Context, e: &expr) {
|
||||
expr_match(*) | expr_block(_) | expr_if(*) | expr_while(*) |
|
||||
expr_break(_) | expr_again(_) | expr_unary(*) | expr_lit(_) |
|
||||
expr_mac(_) | expr_addr_of(*) | expr_ret(_) | expr_loop(*) |
|
||||
expr_loop_body(_) | expr_do_body(_) => (),
|
||||
expr_do_body(_) => (),
|
||||
|
||||
expr_for_loop(*) => fail!("non-desugared expr_for_loop")
|
||||
}
|
||||
|
@ -3192,7 +3192,6 @@ pub fn expr_kind(tcx: ctxt,
|
||||
ast::expr_if(*) |
|
||||
ast::expr_match(*) |
|
||||
ast::expr_fn_block(*) |
|
||||
ast::expr_loop_body(*) |
|
||||
ast::expr_do_body(*) |
|
||||
ast::expr_block(*) |
|
||||
ast::expr_repeat(*) |
|
||||
|
@ -170,10 +170,6 @@ pub struct inherited {
|
||||
|
||||
#[deriving(Clone)]
|
||||
pub enum FnKind {
|
||||
// This is a for-closure. The ty::t is the return type of the
|
||||
// enclosing function.
|
||||
ForLoop(ty::t),
|
||||
|
||||
// A do-closure.
|
||||
DoBlock,
|
||||
|
||||
@ -230,8 +226,6 @@ pub struct FnCtxt {
|
||||
err_count_on_creation: uint,
|
||||
|
||||
ret_ty: ty::t,
|
||||
// Used by loop bodies that return from the outer function
|
||||
indirect_ret_ty: Option<ty::t>,
|
||||
ps: PurityState,
|
||||
|
||||
// Sometimes we generate region pointers where the precise region
|
||||
@ -283,7 +277,6 @@ pub fn blank_fn_ctxt(ccx: @mut CrateCtxt,
|
||||
@mut FnCtxt {
|
||||
err_count_on_creation: ccx.tcx.sess.err_count(),
|
||||
ret_ty: rty,
|
||||
indirect_ret_ty: None,
|
||||
ps: PurityState::function(ast::impure_fn, 0),
|
||||
region_lb: region_bnd,
|
||||
in_scope_regions: @Nil,
|
||||
@ -390,17 +383,9 @@ pub fn check_fn(ccx: @mut CrateCtxt,
|
||||
// Create the function context. This is either derived from scratch or,
|
||||
// in the case of function expressions, based on the outer context.
|
||||
let fcx: @mut FnCtxt = {
|
||||
// In a for-loop, you have an 'indirect return' because return
|
||||
// does not return out of the directly enclosing fn
|
||||
let indirect_ret_ty = match fn_kind {
|
||||
ForLoop(t) => Some(t),
|
||||
DoBlock | Vanilla => None
|
||||
};
|
||||
|
||||
@mut FnCtxt {
|
||||
err_count_on_creation: err_count_on_creation,
|
||||
ret_ty: ret_ty,
|
||||
indirect_ret_ty: indirect_ret_ty,
|
||||
ps: PurityState::function(purity, id),
|
||||
region_lb: body.id,
|
||||
in_scope_regions: isr,
|
||||
@ -958,11 +943,6 @@ impl FnCtxt {
|
||||
return;
|
||||
}
|
||||
match self.fn_kind {
|
||||
ForLoop(_) if !ty::type_is_bool(e) && !ty::type_is_nil(a) =>
|
||||
self.tcx().sess.span_err(sp, fmt!("A for-loop body must \
|
||||
return (), but it returns %s here. \
|
||||
Perhaps you meant to write a `do`-block?",
|
||||
ppaux::ty_to_str(self.tcx(), a))),
|
||||
DoBlock if ty::type_is_bool(e) && ty::type_is_nil(a) =>
|
||||
// If we expected bool and got ()...
|
||||
self.tcx().sess.span_err(sp, fmt!("Do-block body must \
|
||||
@ -1274,7 +1254,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
|
||||
|
||||
for (i, arg) in args.iter().enumerate() {
|
||||
let is_block = match arg.node {
|
||||
ast::expr_fn_block(*) | ast::expr_loop_body(*) |
|
||||
ast::expr_fn_block(*) |
|
||||
ast::expr_do_body(*) => true,
|
||||
_ => false
|
||||
};
|
||||
@ -2126,121 +2106,6 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
|
||||
fcx.write_ty(id, enum_type);
|
||||
}
|
||||
|
||||
fn check_loop_body(fcx: @mut FnCtxt,
|
||||
expr: @ast::expr,
|
||||
expected: Option<ty::t>,
|
||||
loop_body: @ast::expr) {
|
||||
// a loop body is the special argument to a `for` loop. We know that
|
||||
// there will be an expected type in this context because it can only
|
||||
// appear in the context of a call, so we get the expected type of the
|
||||
// parameter. The catch here is that we need to validate two things:
|
||||
// 1. a closure that returns a bool is expected
|
||||
// 2. the closure that was given returns unit
|
||||
let tcx = fcx.tcx();
|
||||
let mut err_happened = false;
|
||||
let expected_sty = unpack_expected(fcx,
|
||||
expected,
|
||||
|x| Some((*x).clone()));
|
||||
let inner_ty = match expected_sty {
|
||||
Some(ty::ty_closure(ref fty)) => {
|
||||
match fcx.mk_subty(false, infer::Misc(expr.span),
|
||||
fty.sig.output, ty::mk_bool()) {
|
||||
result::Ok(_) => {
|
||||
ty::mk_closure(tcx, ty::ClosureTy {
|
||||
sig: FnSig {
|
||||
output: ty::mk_nil(),
|
||||
..fty.sig.clone()
|
||||
},
|
||||
..(*fty).clone()
|
||||
})
|
||||
}
|
||||
result::Err(_) => {
|
||||
fcx.type_error_message(
|
||||
expr.span,
|
||||
|actual| {
|
||||
let did_you_mean = {
|
||||
if ty::type_is_nil(fty.sig.output) {
|
||||
"\nDid you mean to use \
|
||||
`do` instead of `for`?"
|
||||
} else {
|
||||
""
|
||||
}
|
||||
};
|
||||
fmt!("A `for` loop iterator should expect a \
|
||||
closure that returns `bool`. This \
|
||||
iterator expects a closure that \
|
||||
returns `%s`.%s",
|
||||
actual, did_you_mean)
|
||||
},
|
||||
fty.sig.output,
|
||||
None);
|
||||
err_happened = true;
|
||||
fcx.write_error(expr.id);
|
||||
ty::mk_err()
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
match expected {
|
||||
Some(expected_t) => {
|
||||
fcx.type_error_message(
|
||||
expr.span,
|
||||
|actual| {
|
||||
fmt!("last argument in `for` call \
|
||||
has non-closure type: %s",
|
||||
actual)
|
||||
},
|
||||
expected_t, None);
|
||||
let err_ty = ty::mk_err();
|
||||
fcx.write_error(expr.id);
|
||||
err_happened = true;
|
||||
err_ty
|
||||
}
|
||||
None => fcx.tcx().sess.impossible_case(
|
||||
expr.span,
|
||||
"loop body must have an expected type")
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
match loop_body.node {
|
||||
ast::expr_fn_block(ref decl, ref body) => {
|
||||
// If an error occurred, we pretend this isn't a for
|
||||
// loop, so as to assign types to all nodes while also
|
||||
// propagating ty_err throughout so as to suppress
|
||||
// derived errors. If we passed in ForLoop in the
|
||||
// error case, we'd potentially emit a spurious error
|
||||
// message because of the indirect_ret_ty.
|
||||
let fn_kind = if err_happened {
|
||||
Vanilla
|
||||
} else {
|
||||
let indirect_ret_ty =
|
||||
fcx.indirect_ret_ty.get_or_default(fcx.ret_ty);
|
||||
ForLoop(indirect_ret_ty)
|
||||
};
|
||||
check_expr_fn(fcx, loop_body, None,
|
||||
decl, body, fn_kind, Some(inner_ty));
|
||||
demand::suptype(fcx, loop_body.span,
|
||||
inner_ty, fcx.expr_ty(loop_body));
|
||||
}
|
||||
ref n => {
|
||||
fail!("check_loop_body expected expr_fn_block, not %?", n)
|
||||
}
|
||||
}
|
||||
|
||||
let block_ty = structurally_resolved_type(
|
||||
fcx, expr.span, fcx.node_ty(loop_body.id));
|
||||
if err_happened {
|
||||
fcx.write_error(expr.id);
|
||||
fcx.write_error(loop_body.id);
|
||||
} else {
|
||||
let loop_body_ty =
|
||||
ty::replace_closure_return_type(
|
||||
tcx, block_ty, ty::mk_bool());
|
||||
fcx.write_ty(expr.id, loop_body_ty);
|
||||
}
|
||||
}
|
||||
|
||||
let tcx = fcx.ccx.tcx;
|
||||
let id = expr.id;
|
||||
match expr.node {
|
||||
@ -2494,9 +2359,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
|
||||
ast::expr_break(_) => { fcx.write_bot(id); }
|
||||
ast::expr_again(_) => { fcx.write_bot(id); }
|
||||
ast::expr_ret(expr_opt) => {
|
||||
let ret_ty = match fcx.indirect_ret_ty {
|
||||
Some(t) => t, None => fcx.ret_ty
|
||||
};
|
||||
let ret_ty = fcx.ret_ty;
|
||||
match expr_opt {
|
||||
None => match fcx.mk_eqty(false, infer::Misc(expr.span),
|
||||
ret_ty, ty::mk_nil()) {
|
||||
@ -2581,9 +2444,6 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
|
||||
check_expr_fn(fcx, expr, None,
|
||||
decl, body, Vanilla, expected);
|
||||
}
|
||||
ast::expr_loop_body(loop_body) => {
|
||||
check_loop_body(fcx, expr, expected, loop_body);
|
||||
}
|
||||
ast::expr_do_body(b) => {
|
||||
let expected_sty = unpack_expected(fcx,
|
||||
expected,
|
||||
|
@ -426,10 +426,6 @@ fn visit_expr(expr: @ast::expr, (rcx, v): (@mut Rcx, rvt)) {
|
||||
oldvisit::visit_expr(expr, (rcx, v));
|
||||
}
|
||||
|
||||
ast::expr_loop_body(subexpr) => {
|
||||
check_expr_fn_block(rcx, subexpr, v, true);
|
||||
}
|
||||
|
||||
ast::expr_fn_block(*) => {
|
||||
check_expr_fn_block(rcx, expr, v, false);
|
||||
}
|
||||
@ -1031,7 +1027,6 @@ pub mod guarantor {
|
||||
ast::expr_if(*) |
|
||||
ast::expr_match(*) |
|
||||
ast::expr_fn_block(*) |
|
||||
ast::expr_loop_body(*) |
|
||||
ast::expr_do_body(*) |
|
||||
ast::expr_block(*) |
|
||||
ast::expr_repeat(*) |
|
||||
|
@ -70,8 +70,7 @@ pub fn loop_query(b: &ast::Block, p: @fn(&ast::expr_) -> bool) -> bool {
|
||||
match e.node {
|
||||
// Skip inner loops, since a break in the inner loop isn't a
|
||||
// break inside the outer loop
|
||||
ast::expr_loop(*) | ast::expr_while(*)
|
||||
| ast::expr_loop_body(*) => {}
|
||||
ast::expr_loop(*) | ast::expr_while(*) => {}
|
||||
_ => oldvisit::visit_expr(e, (flag, v))
|
||||
}
|
||||
};
|
||||
|
@ -472,11 +472,6 @@ pub enum expr_ {
|
||||
expr_loop(Block, Option<ident>),
|
||||
expr_match(@expr, ~[arm]),
|
||||
expr_fn_block(fn_decl, Block),
|
||||
// Inner expr is always an expr_fn_block. We need the wrapping node to
|
||||
// easily type this (a function returning nil on the inside but bool on
|
||||
// the outside).
|
||||
expr_loop_body(@expr),
|
||||
// Like expr_loop_body but for 'do' blocks
|
||||
expr_do_body(@expr),
|
||||
expr_block(Block),
|
||||
|
||||
|
@ -541,7 +541,6 @@ pub fn noop_fold_expr(e: &expr_, fld: @ast_fold) -> expr_ {
|
||||
fld.fold_expr(ohs)
|
||||
)
|
||||
}
|
||||
expr_loop_body(f) => expr_loop_body(fld.fold_expr(f)),
|
||||
expr_do_body(f) => expr_do_body(fld.fold_expr(f)),
|
||||
expr_lit(_) => (*e).clone(),
|
||||
expr_cast(expr, ref ty) => {
|
||||
|
@ -501,7 +501,7 @@ pub fn visit_expr<E:Clone>(ex: @expr, (e, v): (E, vt<E>)) {
|
||||
(v.visit_expr)(b, (e.clone(), v));
|
||||
}
|
||||
expr_addr_of(_, x) | expr_unary(_, _, x) |
|
||||
expr_loop_body(x) | expr_do_body(x) => (v.visit_expr)(x, (e.clone(), v)),
|
||||
expr_do_body(x) => (v.visit_expr)(x, (e.clone(), v)),
|
||||
expr_lit(_) => (),
|
||||
expr_cast(x, ref t) => {
|
||||
(v.visit_expr)(x, (e.clone(), v));
|
||||
|
@ -1087,7 +1087,7 @@ pub fn print_call_post(s: @ps,
|
||||
nbsp(s);
|
||||
match blk.get().node {
|
||||
// need to handle closures specifically
|
||||
ast::expr_do_body(e) | ast::expr_loop_body(e) => {
|
||||
ast::expr_do_body(e) => {
|
||||
end(s); // we close our head box; closure
|
||||
// will create it's own.
|
||||
print_expr(s, e);
|
||||
@ -1338,9 +1338,6 @@ pub fn print_expr(s: @ps, expr: &ast::expr) {
|
||||
// empty box to satisfy the close.
|
||||
ibox(s, 0);
|
||||
}
|
||||
ast::expr_loop_body(body) => {
|
||||
print_expr(s, body);
|
||||
}
|
||||
ast::expr_do_body(body) => {
|
||||
print_expr(s, body);
|
||||
}
|
||||
|
@ -513,7 +513,6 @@ pub fn visit_expr<E:Clone>(visitor: @Visitor<E>, expression: @expr, env: E) {
|
||||
}
|
||||
expr_addr_of(_, subexpression) |
|
||||
expr_unary(_, _, subexpression) |
|
||||
expr_loop_body(subexpression) |
|
||||
expr_do_body(subexpression) => {
|
||||
visitor.visit_expr(subexpression, env.clone())
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user