parent
050170d2af
commit
0ce40f60e7
@ -251,11 +251,6 @@ fn parse_ty(st: @pstate, sd: str_def) -> ty::t {
|
||||
ret ty::mk_fn(st.tcx, ast::proto_bare, func.args, func.ty, func.cf,
|
||||
func.cs);
|
||||
}
|
||||
'W' {
|
||||
let func = parse_ty_fn(st, sd);
|
||||
ret ty::mk_fn(st.tcx, ast::proto_iter, func.args, func.ty, func.cf,
|
||||
func.cs);
|
||||
}
|
||||
'B' {
|
||||
let func = parse_ty_fn(st, sd);
|
||||
ret ty::mk_fn(st.tcx, ast::proto_block, func.args, func.ty, func.cf,
|
||||
@ -281,7 +276,6 @@ fn parse_ty(st: @pstate, sd: str_def) -> ty::t {
|
||||
while peek(st) as char != ']' {
|
||||
let proto;
|
||||
alt next(st) as char {
|
||||
'W' { proto = ast::proto_iter; }
|
||||
'f' { proto = ast::proto_bare; }
|
||||
}
|
||||
let name = "";
|
||||
|
@ -194,7 +194,6 @@ fn enc_sty(w: io::writer, cx: @ctxt, st: ty::sty) {
|
||||
}
|
||||
fn enc_proto(w: io::writer, proto: proto) {
|
||||
alt proto {
|
||||
proto_iter. { w.write_char('W'); }
|
||||
proto_shared(_) { w.write_char('F'); }
|
||||
proto_block. { w.write_char('B'); }
|
||||
proto_bare. { w.write_char('f'); }
|
||||
|
@ -98,23 +98,6 @@ fn visit_expr(cx: @ctx, ex: @ast::expr, sc: scope, v: vt<scope>) {
|
||||
handled = false;
|
||||
}
|
||||
ast::expr_alt(input, arms) { check_alt(*cx, input, arms, sc, v); }
|
||||
ast::expr_put(val) {
|
||||
alt val {
|
||||
some(ex) {
|
||||
let root = expr_root(*cx, ex, false);
|
||||
if !is_none(root.mut) {
|
||||
cx.tcx.sess.span_err(ex.span,
|
||||
"result of put must be" +
|
||||
" immutably rooted");
|
||||
}
|
||||
visit_expr(cx, ex, sc, v);
|
||||
}
|
||||
_ { }
|
||||
}
|
||||
}
|
||||
ast::expr_for_each(decl, call, blk) {
|
||||
check_for_each(*cx, decl, call, blk, sc, v);
|
||||
}
|
||||
ast::expr_for(decl, seq, blk) { check_for(*cx, decl, seq, blk, sc, v); }
|
||||
ast::expr_path(pt) {
|
||||
check_var(*cx, ex, pt, ex.id, false, sc);
|
||||
@ -424,21 +407,6 @@ fn check_alt(cx: ctx, input: @ast::expr, arms: [ast::arm], sc: scope,
|
||||
}
|
||||
}
|
||||
|
||||
fn check_for_each(cx: ctx, local: @ast::local, call: @ast::expr,
|
||||
blk: ast::blk, sc: scope, v: vt<scope>) {
|
||||
v.visit_expr(call, sc, v);
|
||||
alt call.node {
|
||||
ast::expr_call(f, args) {
|
||||
let new_bs = sc.bs + check_call(cx, f, args);
|
||||
for proot in pattern_roots(cx.tcx, none, local.node.pat) {
|
||||
new_bs += [mk_binding(cx, proot.id, proot.span, none,
|
||||
unsafe_set(proot.mut))];
|
||||
}
|
||||
visit::visit_block(blk, {bs: new_bs with sc}, v);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn check_for(cx: ctx, local: @ast::local, seq: @ast::expr, blk: ast::blk,
|
||||
sc: scope, v: vt<scope>) {
|
||||
v.visit_expr(seq, sc, v);
|
||||
|
@ -41,11 +41,6 @@ fn collect_freevars(def_map: resolve::def_map, walker: fn@(visit::vt<int>)) ->
|
||||
visit::visit_expr(expr, depth + 1, v);
|
||||
}
|
||||
}
|
||||
ast::expr_for_each(dcl, x, b) {
|
||||
v.visit_local(dcl, depth, v);
|
||||
v.visit_expr(x, depth, v);
|
||||
v.visit_block(b, depth + 1, v);
|
||||
}
|
||||
ast::expr_path(path) {
|
||||
let def = def_map.get(expr.id), i = 0;
|
||||
while i < depth {
|
||||
@ -91,21 +86,9 @@ fn annotate_freevars(def_map: resolve::def_map, crate: @ast::crate) ->
|
||||
let vars = collect_freevars(def_map, start_walk);
|
||||
freevars.insert(nid, vars);
|
||||
};
|
||||
let walk_expr =
|
||||
lambda (expr: @ast::expr) {
|
||||
alt expr.node {
|
||||
ast::expr_for_each(local, _, body) {
|
||||
let start_walk =
|
||||
lambda (v: visit::vt<int>) { v.visit_block(body, 1, v); };
|
||||
let vars = collect_freevars(def_map, start_walk);
|
||||
freevars.insert(body.node.id, vars);
|
||||
}
|
||||
_ { }
|
||||
}
|
||||
};
|
||||
|
||||
let visitor =
|
||||
visit::mk_simple_visitor(@{visit_fn: walk_fn, visit_expr: walk_expr
|
||||
visit::mk_simple_visitor(@{visit_fn: walk_fn
|
||||
with *visit::default_simple_visitor()});
|
||||
visit::visit_crate(*crate, (), visitor);
|
||||
|
||||
|
@ -37,7 +37,7 @@ tag scope {
|
||||
scope_item(@ast::item);
|
||||
scope_fn(ast::fn_decl, ast::proto, [ast::ty_param]);
|
||||
scope_native_item(@ast::native_item);
|
||||
scope_loop(@ast::local, bool); // there's only 1 decl per loop.
|
||||
scope_loop(@ast::local); // there's only 1 decl per loop.
|
||||
|
||||
scope_block(ast::blk, @mutable uint, @mutable uint);
|
||||
scope_arm(ast::arm);
|
||||
@ -381,9 +381,8 @@ fn visit_arm_with_scope(a: ast::arm, sc: scopes, v: vt<scopes>) {
|
||||
|
||||
fn visit_expr_with_scope(x: @ast::expr, sc: scopes, v: vt<scopes>) {
|
||||
alt x.node {
|
||||
ast::expr_for(decl, coll, blk) | ast::expr_for_each(decl, coll, blk) {
|
||||
let f_e = alt x.node { expr_for_each(_, _, _) { true } _ { false } };
|
||||
let new_sc = cons(scope_loop(decl, f_e), @sc);
|
||||
ast::expr_for(decl, coll, blk) {
|
||||
let new_sc = cons(scope_loop(decl), @sc);
|
||||
v.visit_expr(coll, sc, v);
|
||||
v.visit_local(decl, new_sc, v);
|
||||
v.visit_block(blk, new_sc, v);
|
||||
@ -589,7 +588,6 @@ fn lookup_in_scope_strict(e: env, sc: scopes, sp: span, name: ident,
|
||||
|
||||
fn scope_is_fn(sc: scope) -> bool {
|
||||
ret alt sc {
|
||||
scope_fn(_, ast::proto_iter., _) |
|
||||
scope_fn(_, ast::proto_bare., _) |
|
||||
scope_native_item(_) {
|
||||
true
|
||||
@ -600,7 +598,7 @@ fn scope_is_fn(sc: scope) -> bool {
|
||||
|
||||
fn scope_closes(sc: scope) -> option::t<bool> {
|
||||
alt sc {
|
||||
scope_fn(_, ast::proto_block., _) | scope_loop(_, true) { some(true) }
|
||||
scope_fn(_, ast::proto_block., _) { some(true) }
|
||||
scope_fn(_, ast::proto_shared(_), _) { some(false) }
|
||||
_ { none }
|
||||
}
|
||||
@ -662,7 +660,7 @@ fn lookup_in_scope(e: env, sc: scopes, sp: span, name: ident, ns: namespace)
|
||||
scope_fn(decl, _, ty_params) {
|
||||
ret lookup_in_fn(name, decl, ty_params, ns);
|
||||
}
|
||||
scope_loop(local, _) {
|
||||
scope_loop(local) {
|
||||
if ns == ns_value {
|
||||
alt lookup_in_pat(name, local.node.pat) {
|
||||
some(did) { ret some(ast::def_binding(did)); }
|
||||
|
@ -82,7 +82,7 @@ fn type_of_explicit_args(cx: @crate_ctxt, sp: span, inputs: [ty::arg]) ->
|
||||
// - create_llargs_for_fn_args.
|
||||
// - new_fn_ctxt
|
||||
// - trans_args
|
||||
fn type_of_fn(cx: @crate_ctxt, sp: span, proto: ast::proto,
|
||||
fn type_of_fn(cx: @crate_ctxt, sp: span,
|
||||
is_method: bool, ret_ref: bool, inputs: [ty::arg],
|
||||
output: ty::t, ty_param_count: uint)
|
||||
: non_ty_var(cx, output) -> TypeRef {
|
||||
@ -102,18 +102,6 @@ fn type_of_fn(cx: @crate_ctxt, sp: span, proto: ast::proto,
|
||||
let i = 0u;
|
||||
while i < ty_param_count { atys += [T_ptr(cx.tydesc_type)]; i += 1u; }
|
||||
}
|
||||
if proto == ast::proto_iter {
|
||||
// If it's an iter, the 'output' type of the iter is actually the
|
||||
// *input* type of the function we're given as our iter-block
|
||||
// argument.
|
||||
let iter_body_ty = ty::mk_iter_body_fn(cx.tcx, output);
|
||||
// FIXME: this check could be avoided pretty easily if we had
|
||||
// postconditions
|
||||
// (or better yet, just use a constraiend type that expresses
|
||||
// non-ty-var things)
|
||||
check non_ty_var(cx, iter_body_ty);
|
||||
atys += [type_of_inner(cx, sp, iter_body_ty)];
|
||||
}
|
||||
// ... then explicit args.
|
||||
atys += type_of_explicit_args(cx, sp, inputs);
|
||||
ret T_fn(atys, llvm::LLVMVoidType());
|
||||
@ -129,8 +117,7 @@ fn type_of_fn_from_ty(cx: @crate_ctxt, sp: span, fty: ty::t,
|
||||
// (see Issue #586)
|
||||
let ret_ty = ty::ty_fn_ret(cx.tcx, fty);
|
||||
check non_ty_var(cx, ret_ty);
|
||||
ret type_of_fn(cx, sp, ty::ty_fn_proto(cx.tcx, fty),
|
||||
false, by_ref, ty::ty_fn_args(cx.tcx, fty),
|
||||
ret type_of_fn(cx, sp, false, by_ref, ty::ty_fn_args(cx.tcx, fty),
|
||||
ret_ty, ty_param_count);
|
||||
}
|
||||
|
||||
@ -2739,12 +2726,7 @@ fn build_environment(bcx: @block_ctxt, lltydescs: [ValueRef],
|
||||
fn build_closure(cx: @block_ctxt, upvars: @[ast::def], copying: bool) ->
|
||||
{ptr: ValueRef, ptrty: ty::t, bcx: @block_ctxt} {
|
||||
// If we need to, package up the iterator body to call
|
||||
let env_vals = alt cx.fcx.lliterbody {
|
||||
some(body) when !copying {
|
||||
[env_direct(body, option::get(cx.fcx.iterbodyty), true)]
|
||||
}
|
||||
_ { [] }
|
||||
};
|
||||
let env_vals = [];
|
||||
// Package up the upvars
|
||||
for def in *upvars {
|
||||
let lv = trans_local_var(cx, def);
|
||||
@ -2819,17 +2801,6 @@ fn load_environment(enclosing_cx: @block_ctxt, fcx: @fn_ctxt, envty: ty::t,
|
||||
// Populate the upvars from the environment.
|
||||
let path = [0, abi::box_rc_field_body, abi::closure_elt_bindings];
|
||||
i = 0u;
|
||||
// If this is an aliasing closure/for-each body, we need to load
|
||||
// the iterbody.
|
||||
if !copying && !option::is_none(enclosing_cx.fcx.lliterbody) {
|
||||
// Silly check
|
||||
check type_is_tup_like(bcx, ty);
|
||||
let iterbodyptr = GEP_tup_like(bcx, ty, llclosure, path + [0]);
|
||||
fcx.lliterbody = some(Load(bcx, iterbodyptr.val));
|
||||
bcx = iterbodyptr.bcx;
|
||||
i += 1u;
|
||||
}
|
||||
|
||||
// Load the actual upvars.
|
||||
for upvar_def in *upvars {
|
||||
// Silly check
|
||||
@ -2844,86 +2815,6 @@ fn load_environment(enclosing_cx: @block_ctxt, fcx: @fn_ctxt, envty: ty::t,
|
||||
}
|
||||
}
|
||||
|
||||
fn trans_for_each(cx: @block_ctxt, local: @ast::local, seq: @ast::expr,
|
||||
body: ast::blk) -> @block_ctxt {
|
||||
/*
|
||||
* The translation is a little .. complex here. Code like:
|
||||
*
|
||||
* let ty1 p = ...;
|
||||
*
|
||||
* let ty1 q = ...;
|
||||
*
|
||||
* foreach (ty v in foo(a,b)) { body(p,q,v) }
|
||||
*
|
||||
*
|
||||
* Turns into a something like so (C/Rust mishmash):
|
||||
*
|
||||
* type env = { *ty1 p, *ty2 q, ... };
|
||||
*
|
||||
* let env e = { &p, &q, ... };
|
||||
*
|
||||
* fn foreach123_body(env* e, ty v) { body(*(e->p),*(e->q),v) }
|
||||
*
|
||||
* foo([foreach123_body, env*], a, b);
|
||||
*
|
||||
*/
|
||||
|
||||
// Step 1: Generate code to build an environment containing pointers
|
||||
// to all of the upvars
|
||||
let lcx = cx.fcx.lcx;
|
||||
let ccx = lcx.ccx;
|
||||
|
||||
// FIXME: possibly support alias-mode here?
|
||||
let decl_ty = node_id_type(ccx, local.node.id);
|
||||
let upvars = get_freevars(ccx.tcx, body.node.id);
|
||||
|
||||
let llenv = build_closure(cx, upvars, false);
|
||||
|
||||
// Step 2: Declare foreach body function.
|
||||
let s: str =
|
||||
mangle_internal_name_by_path_and_seq(ccx, lcx.path, "foreach");
|
||||
|
||||
// The 'env' arg entering the body function is a fake env member (as in
|
||||
// the env-part of the normal rust calling convention) that actually
|
||||
// points to a stack allocated env in this frame. We bundle that env
|
||||
// pointer along with the foreach-body-fn pointer into a 'normal' fn pair
|
||||
// and pass it in as a first class fn-arg to the iterator.
|
||||
let iter_body_fn = ty::mk_iter_body_fn(ccx.tcx, decl_ty);
|
||||
// FIXME: should be a postcondition on mk_iter_body_fn
|
||||
check returns_non_ty_var(ccx, iter_body_fn);
|
||||
let iter_body_llty =
|
||||
type_of_fn_from_ty(ccx, cx.sp, iter_body_fn, 0u);
|
||||
let lliterbody: ValueRef =
|
||||
decl_internal_cdecl_fn(ccx.llmod, s, iter_body_llty);
|
||||
let fcx = new_fn_ctxt_w_id(lcx, cx.sp, lliterbody, body.node.id,
|
||||
ast::return_val);
|
||||
fcx.iterbodyty = cx.fcx.iterbodyty;
|
||||
|
||||
// Generate code to load the environment out of the
|
||||
// environment pointer.
|
||||
load_environment(cx, fcx, llenv.ptrty, upvars, false);
|
||||
|
||||
let bcx = new_top_block_ctxt(fcx);
|
||||
// Add bindings for the loop variable alias.
|
||||
bcx = trans_alt::bind_irrefutable_pat(bcx, local.node.pat,
|
||||
llvm::LLVMGetParam(fcx.llfn, 2u),
|
||||
false);
|
||||
let lltop = bcx.llbb;
|
||||
bcx = trans_block(bcx, body);
|
||||
finish_fn(fcx, lltop);
|
||||
|
||||
build_return(bcx);
|
||||
|
||||
// Step 3: Call iter passing [lliterbody, llenv], plus other args.
|
||||
alt seq.node {
|
||||
ast::expr_call(f, args) {
|
||||
let pair =
|
||||
create_real_fn_pair(cx, iter_body_llty, lliterbody, llenv.ptr);
|
||||
ret trans_call(cx, f, some(pair), args, seq.id, ignore);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn trans_while(cx: @block_ctxt, cond: @ast::expr, body: ast::blk)
|
||||
-> @block_ctxt {
|
||||
let next_cx = new_sub_block_ctxt(cx, "while next");
|
||||
@ -3151,9 +3042,8 @@ fn trans_object_field_inner(bcx: @block_ctxt, o: ValueRef,
|
||||
// FIXME: constrain ty_obj?
|
||||
check non_ty_var(ccx, ret_ty);
|
||||
|
||||
let ll_fn_ty = type_of_fn(ccx, bcx.sp, ty::ty_fn_proto(tcx, fn_ty),
|
||||
true, ret_ref, ty::ty_fn_args(tcx, fn_ty),
|
||||
ret_ty, 0u);
|
||||
let ll_fn_ty = type_of_fn(ccx, bcx.sp, true, ret_ref,
|
||||
ty::ty_fn_args(tcx, fn_ty), ret_ty, 0u);
|
||||
v = Load(bcx, PointerCast(bcx, v, T_ptr(T_ptr(ll_fn_ty))));
|
||||
ret {bcx: bcx, mthptr: v, objptr: o};
|
||||
}
|
||||
@ -3310,7 +3200,7 @@ fn trans_lval(cx: @block_ctxt, e: @ast::expr) -> lval_result {
|
||||
// This is a by-ref returning call. Regular calls are not lval
|
||||
ast::expr_call(f, args) {
|
||||
let cell = empty_dest_cell();
|
||||
let bcx = trans_call(cx, f, none, args, e.id, by_val(cell));
|
||||
let bcx = trans_call(cx, f, args, e.id, by_val(cell));
|
||||
ret lval_owned(bcx, *cell);
|
||||
}
|
||||
_ { bcx_ccx(cx).sess.span_bug(e.span, "non-lval in trans_lval"); }
|
||||
@ -3762,8 +3652,7 @@ fn trans_arg_expr(cx: @block_ctxt, arg: ty::arg, lldestty0: TypeRef,
|
||||
// - new_fn_ctxt
|
||||
// - trans_args
|
||||
fn trans_args(cx: @block_ctxt, outer_cx: @block_ctxt, llenv: ValueRef,
|
||||
gen: option::t<generic_info>,
|
||||
lliterbody: option::t<ValueRef>, es: [@ast::expr], fn_ty: ty::t,
|
||||
gen: option::t<generic_info>, es: [@ast::expr], fn_ty: ty::t,
|
||||
dest: dest)
|
||||
-> {bcx: @block_ctxt,
|
||||
outer_cx: @block_ctxt,
|
||||
@ -3802,8 +3691,7 @@ fn trans_args(cx: @block_ctxt, outer_cx: @block_ctxt, llenv: ValueRef,
|
||||
} else {
|
||||
alt dest {
|
||||
ignore. {
|
||||
if ty::type_is_nil(tcx, retty) ||
|
||||
!option::is_none(lliterbody) {
|
||||
if ty::type_is_nil(tcx, retty) {
|
||||
llvm::LLVMGetUndef(T_ptr(llretty))
|
||||
} else { alloca(cx, llretty) }
|
||||
}
|
||||
@ -3830,21 +3718,6 @@ fn trans_args(cx: @block_ctxt, outer_cx: @block_ctxt, llenv: ValueRef,
|
||||
// Args >2: ty_params ...
|
||||
llargs += lltydescs;
|
||||
|
||||
// ... then possibly an lliterbody argument.
|
||||
alt lliterbody {
|
||||
none. { }
|
||||
some(lli) {
|
||||
let lli =
|
||||
if ty::type_contains_params(tcx, retty) {
|
||||
let body_ty = ty::mk_iter_body_fn(tcx, retty);
|
||||
check non_ty_var(ccx, body_ty);
|
||||
let body_llty = type_of_inner(ccx, cx.sp, body_ty);
|
||||
PointerCast(bcx, lli, T_ptr(body_llty))
|
||||
} else { lli };
|
||||
llargs += [Load(cx, lli)];
|
||||
}
|
||||
}
|
||||
|
||||
// ... then explicit args.
|
||||
|
||||
// First we figure out the caller's view of the types of the arguments.
|
||||
@ -3873,8 +3746,8 @@ fn trans_args(cx: @block_ctxt, outer_cx: @block_ctxt, llenv: ValueRef,
|
||||
}
|
||||
|
||||
fn trans_call(in_cx: @block_ctxt, f: @ast::expr,
|
||||
lliterbody: option::t<ValueRef>, args: [@ast::expr],
|
||||
id: ast::node_id, dest: dest) -> @block_ctxt {
|
||||
args: [@ast::expr], id: ast::node_id, dest: dest)
|
||||
-> @block_ctxt {
|
||||
// NB: 'f' isn't necessarily a function; it might be an entire self-call
|
||||
// expression because of the hack that allows us to process self-calls
|
||||
// with trans_call.
|
||||
@ -3911,8 +3784,7 @@ fn trans_call(in_cx: @block_ctxt, f: @ast::expr,
|
||||
|
||||
let ret_ty = ty::node_id_to_type(tcx, id);
|
||||
let args_res =
|
||||
trans_args(bcx, in_cx, llenv, f_res.generic, lliterbody, args,
|
||||
fn_expr_ty, dest);
|
||||
trans_args(bcx, in_cx, llenv, f_res.generic, args, fn_expr_ty, dest);
|
||||
Br(args_res.outer_cx, cx.llbb);
|
||||
bcx = args_res.bcx;
|
||||
let llargs = args_res.args;
|
||||
@ -4304,7 +4176,7 @@ fn trans_expr(bcx: @block_ctxt, e: @ast::expr, dest: dest) -> @block_ctxt {
|
||||
ret trans_anon_obj(bcx, e.span, anon_obj, e.id, dest);
|
||||
}
|
||||
ast::expr_call(f, args) {
|
||||
ret trans_call(bcx, f, none, args, e.id, dest);
|
||||
ret trans_call(bcx, f, args, e.id, dest);
|
||||
}
|
||||
ast::expr_field(_, _) {
|
||||
fail "Taking the value of a method does not work yet (issue #435)";
|
||||
@ -4331,10 +4203,6 @@ fn trans_expr(bcx: @block_ctxt, e: @ast::expr, dest: dest) -> @block_ctxt {
|
||||
check (ast_util::is_call_expr(ex));
|
||||
ret trans_be(bcx, ex);
|
||||
}
|
||||
ast::expr_put(ex) {
|
||||
assert dest == ignore;
|
||||
ret trans_put(bcx, ex);
|
||||
}
|
||||
ast::expr_fail(expr) {
|
||||
assert dest == ignore;
|
||||
ret trans_fail_expr(bcx, some(e.span), expr);
|
||||
@ -4375,10 +4243,6 @@ fn trans_expr(bcx: @block_ctxt, e: @ast::expr, dest: dest) -> @block_ctxt {
|
||||
assert dest == ignore;
|
||||
ret trans_for(bcx, decl, seq, body);
|
||||
}
|
||||
ast::expr_for_each(decl, seq, body) {
|
||||
assert dest == ignore;
|
||||
ret trans_for_each(bcx, decl, seq, body);
|
||||
}
|
||||
ast::expr_while(cond, body) {
|
||||
assert dest == ignore;
|
||||
ret trans_while(bcx, cond, body);
|
||||
@ -4591,47 +4455,6 @@ fn trans_fail_value(bcx: @block_ctxt, sp_opt: option::t<span>,
|
||||
ret bcx;
|
||||
}
|
||||
|
||||
fn trans_put(in_cx: @block_ctxt, e: option::t<@ast::expr>) -> @block_ctxt {
|
||||
let cx = new_scope_block_ctxt(in_cx, "put");
|
||||
Br(in_cx, cx.llbb);
|
||||
let llcallee = C_nil();
|
||||
let llenv = C_nil();
|
||||
alt cx.fcx.lliterbody {
|
||||
some(lli) {
|
||||
let slot = alloca(cx, val_ty(lli));
|
||||
Store(cx, lli, slot);
|
||||
llcallee = GEP(cx, slot, [C_int(0), C_int(abi::fn_field_code)]);
|
||||
llcallee = Load(cx, llcallee);
|
||||
llenv = GEP(cx, slot, [C_int(0), C_int(abi::fn_field_box)]);
|
||||
llenv = Load(cx, llenv);
|
||||
}
|
||||
}
|
||||
let bcx = cx;
|
||||
let dummy_retslot = alloca(bcx, T_nil());
|
||||
let llargs: [ValueRef] = [dummy_retslot, llenv];
|
||||
alt e {
|
||||
none. {
|
||||
llargs += [C_null(T_ptr(T_nil()))];
|
||||
}
|
||||
some(x) {
|
||||
let e_ty = ty::expr_ty(bcx_tcx(cx), x);
|
||||
let arg = {mode: ast::by_ref, ty: e_ty};
|
||||
let arg_tys = type_of_explicit_args(bcx_ccx(cx), x.span, [arg]);
|
||||
let z = [];
|
||||
let k = [];
|
||||
let r = trans_arg_expr(bcx, arg, arg_tys[0], z, k, x);
|
||||
bcx = r.bcx;
|
||||
llargs += [r.val];
|
||||
}
|
||||
}
|
||||
bcx = invoke(bcx, llcallee, llargs);
|
||||
bcx = trans_block_cleanups(bcx, cx);
|
||||
let next_cx = new_sub_block_ctxt(in_cx, "next");
|
||||
if bcx.unreachable { Unreachable(next_cx); }
|
||||
Br(bcx, next_cx.llbb);
|
||||
ret next_cx;
|
||||
}
|
||||
|
||||
fn trans_break_cont(sp: span, bcx: @block_ctxt, to_end: bool)
|
||||
-> @block_ctxt {
|
||||
// Locate closest loop block, outputting cleanup as we go.
|
||||
@ -5086,8 +4909,6 @@ fn new_fn_ctxt_w_id(cx: @local_ctxt, sp: span, llfndecl: ValueRef,
|
||||
mutable llreturn: llbbs.rt,
|
||||
mutable llobstacktoken: none::<ValueRef>,
|
||||
mutable llself: none::<val_self_pair>,
|
||||
mutable lliterbody: none::<ValueRef>,
|
||||
mutable iterbodyty: none::<ty::t>,
|
||||
llargs: new_int_hash::<local_val>(),
|
||||
llobjfields: new_int_hash::<ValueRef>(),
|
||||
lllocals: new_int_hash::<local_val>(),
|
||||
@ -5118,8 +4939,7 @@ fn new_fn_ctxt(cx: @local_ctxt, sp: span, llfndecl: ValueRef) -> @fn_ctxt {
|
||||
// spaces that have been created for them (by code in the llallocas field of
|
||||
// the function's fn_ctxt). create_llargs_for_fn_args populates the llargs
|
||||
// field of the fn_ctxt with
|
||||
fn create_llargs_for_fn_args(cx: @fn_ctxt, proto: ast::proto,
|
||||
ty_self: option::t<ty::t>, ret_ty: ty::t,
|
||||
fn create_llargs_for_fn_args(cx: @fn_ctxt, ty_self: option::t<ty::t>,
|
||||
args: [ast::arg], ty_params: [ast::ty_param]) {
|
||||
// Skip the implicit arguments 0, and 1. TODO: Pull out 2u and define
|
||||
// it as a constant, since we're using it in several places in trans this
|
||||
@ -5139,17 +4959,6 @@ fn create_llargs_for_fn_args(cx: @fn_ctxt, proto: ast::proto,
|
||||
}
|
||||
}
|
||||
|
||||
// If the function is actually an iter, populate the lliterbody field of
|
||||
// the function context with the ValueRef that we get from
|
||||
// llvm::LLVMGetParam for the iter's body.
|
||||
if proto == ast::proto_iter {
|
||||
cx.iterbodyty = some(ty::mk_iter_body_fn(fcx_tcx(cx), ret_ty));
|
||||
let llarg = llvm::LLVMGetParam(cx.llfn, arg_n);
|
||||
assert (llarg as int != 0);
|
||||
cx.lliterbody = some::<ValueRef>(llarg);
|
||||
arg_n += 1u;
|
||||
}
|
||||
|
||||
// Populate the llargs field of the function context with the ValueRefs
|
||||
// that we get from llvm::LLVMGetParam for each argument.
|
||||
for arg: ast::arg in args {
|
||||
@ -5282,9 +5091,7 @@ fn trans_closure(cx: @local_ctxt, sp: span, f: ast::_fn, llfndecl: ValueRef,
|
||||
|
||||
// Set up arguments to the function.
|
||||
let fcx = new_fn_ctxt_w_id(cx, sp, llfndecl, id, f.decl.cf);
|
||||
create_llargs_for_fn_args(fcx, f.proto, ty_self,
|
||||
ty::ret_ty_of_fn(cx.ccx.tcx, id), f.decl.inputs,
|
||||
ty_params);
|
||||
create_llargs_for_fn_args(fcx, ty_self, f.decl.inputs, ty_params);
|
||||
alt fcx.llself {
|
||||
some(llself) { populate_fn_ctxt_from_llself(fcx, llself); }
|
||||
_ { }
|
||||
@ -5307,7 +5114,6 @@ fn trans_closure(cx: @local_ctxt, sp: span, f: ast::_fn, llfndecl: ValueRef,
|
||||
// (trans_block, trans_expr, et cetera).
|
||||
if ty::type_is_bot(cx.ccx.tcx, block_ty) ||
|
||||
ty::type_is_nil(cx.ccx.tcx, block_ty) ||
|
||||
f.proto == ast::proto_iter ||
|
||||
option::is_none(f.body.node.expr) {
|
||||
bcx = trans_block_dps(bcx, f.body, ignore);
|
||||
} else if ty::type_is_immediate(cx.ccx.tcx, block_ty) {
|
||||
@ -5349,9 +5155,7 @@ fn trans_res_ctor(cx: @local_ctxt, sp: span, dtor: ast::_fn,
|
||||
}
|
||||
let fcx = new_fn_ctxt(cx, sp, llctor_decl);
|
||||
let ret_t = ty::ret_ty_of_fn(cx.ccx.tcx, ctor_id);
|
||||
create_llargs_for_fn_args(fcx, ast::proto_shared(ast::sugar_normal),
|
||||
none::<ty::t>, ret_t,
|
||||
dtor.decl.inputs, ty_params);
|
||||
create_llargs_for_fn_args(fcx, none, dtor.decl.inputs, ty_params);
|
||||
let bcx = new_top_block_ctxt(fcx);
|
||||
let lltop = bcx.llbb;
|
||||
let arg_t = arg_tys_of_fn(cx.ccx, ctor_id)[0].ty;
|
||||
@ -5410,10 +5214,7 @@ fn trans_tag_variant(cx: @local_ctxt, tag_id: ast::node_id,
|
||||
}
|
||||
}
|
||||
let fcx = new_fn_ctxt(cx, variant.span, llfndecl);
|
||||
create_llargs_for_fn_args(fcx, ast::proto_shared(ast::sugar_normal),
|
||||
none::<ty::t>,
|
||||
ty::ret_ty_of_fn(cx.ccx.tcx, variant.node.id),
|
||||
fn_args, ty_params);
|
||||
create_llargs_for_fn_args(fcx, none, fn_args, ty_params);
|
||||
let ty_param_substs: [ty::t] = [];
|
||||
i = 0u;
|
||||
for tp: ast::ty_param in ty_params {
|
||||
@ -5573,11 +5374,10 @@ fn register_fn_full(ccx: @crate_ctxt, sp: span, path: [str], _flav: str,
|
||||
let llfty =
|
||||
type_of_fn_from_ty(ccx, sp, node_type, std::vec::len(ty_params));
|
||||
alt ty::struct(ccx.tcx, node_type) {
|
||||
ty::ty_fn(proto, inputs, output, rs, _) {
|
||||
ty::ty_fn(_, inputs, output, rs, _) {
|
||||
check non_ty_var(ccx, output);
|
||||
llfty = type_of_fn(ccx, sp, proto, false,
|
||||
ast_util::ret_by_ref(rs), inputs, output,
|
||||
vec::len(ty_params));
|
||||
llfty = type_of_fn(ccx, sp, false, ast_util::ret_by_ref(rs), inputs,
|
||||
output, vec::len(ty_params));
|
||||
}
|
||||
_ { ccx.sess.bug("register_fn(): fn item doesn't have fn type!"); }
|
||||
}
|
||||
@ -5618,9 +5418,7 @@ fn create_main_wrapper(ccx: @crate_ctxt, sp: span, main_llfn: ValueRef,
|
||||
let nt = ty::mk_nil(ccx.tcx);
|
||||
check non_ty_var(ccx, nt);
|
||||
|
||||
let llfty = type_of_fn(ccx, sp, ast::proto_shared(ast::sugar_normal),
|
||||
false, false,
|
||||
[vecarg_ty], nt, 0u);
|
||||
let llfty = type_of_fn(ccx, sp, false, false, [vecarg_ty], nt, 0u);
|
||||
let llfdecl = decl_fn(ccx.llmod, "_rust_main",
|
||||
lib::llvm::LLVMCCallConv, llfty);
|
||||
|
||||
@ -5732,9 +5530,7 @@ fn native_fn_wrapper_type(cx: @crate_ctxt, sp: span, ty_param_count: uint,
|
||||
alt ty::struct(cx.tcx, x) {
|
||||
ty::ty_native_fn(abi, args, out) {
|
||||
check non_ty_var(cx, out);
|
||||
ret type_of_fn(cx, sp, ast::proto_shared(ast::sugar_normal),
|
||||
false, false, args, out,
|
||||
ty_param_count);
|
||||
ret type_of_fn(cx, sp, false, false, args, out, ty_param_count);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -191,12 +191,6 @@ type fn_ctxt =
|
||||
// If this function is actually a iter, a block containing the
|
||||
// code called whenever the iter calls 'put'.
|
||||
|
||||
// If this function is actually a iter, the type of the function
|
||||
// that that we call when we call 'put'. Having to track this is
|
||||
// pretty irritating. We have to do it because we need the type if
|
||||
// we are going to put the iterbody into a closure (if it appears
|
||||
// in a for-each inside of an iter).
|
||||
|
||||
// The next four items: hash tables mapping from AST def_ids to
|
||||
// LLVM-stuff-in-the-frame.
|
||||
|
||||
@ -245,8 +239,6 @@ type fn_ctxt =
|
||||
mutable llreturn: BasicBlockRef,
|
||||
mutable llobstacktoken: option::t<ValueRef>,
|
||||
mutable llself: option::t<val_self_pair>,
|
||||
mutable lliterbody: option::t<ValueRef>,
|
||||
mutable iterbodyty: option::t<ty::t>,
|
||||
llargs: hashmap<ast::node_id, local_val>,
|
||||
llobjfields: hashmap<ast::node_id, ValueRef>,
|
||||
lllocals: hashmap<ast::node_id, local_val>,
|
||||
@ -340,8 +332,7 @@ fn get_res_dtor(ccx: @crate_ctxt, sp: span, did: ast::def_id, inner_t: ty::t)
|
||||
let nil_res = ty::mk_nil(ccx.tcx);
|
||||
// FIXME: Silly check -- mk_nil should have a postcondition
|
||||
check non_ty_var(ccx, nil_res);
|
||||
let f_t = type_of_fn(ccx, sp, ast::proto_shared(ast::sugar_normal),
|
||||
false, false,
|
||||
let f_t = type_of_fn(ccx, sp, false, false,
|
||||
[{mode: ast::by_ref, ty: inner_t}],
|
||||
nil_res, params);
|
||||
ret trans::get_extern_const(ccx.externs, ccx.llmod,
|
||||
|
@ -52,10 +52,7 @@ fn trans_obj(cx: @local_ctxt, sp: span, ob: ast::_obj, ctor_id: ast::node_id,
|
||||
let lltop = bcx.llbb;
|
||||
|
||||
// Both regular arguments and type parameters are handled here.
|
||||
create_llargs_for_fn_args(fcx, ast::proto_shared(ast::sugar_normal),
|
||||
none::<ty::t>,
|
||||
ty::ret_ty_of_fn(ccx.tcx, ctor_id), fn_args,
|
||||
ty_params);
|
||||
create_llargs_for_fn_args(fcx, none::<ty::t>, fn_args, ty_params);
|
||||
let arg_tys: [ty::arg] = arg_tys_of_fn(ccx, ctor_id);
|
||||
bcx = copy_args_to_allocas(fcx, bcx, fn_args, arg_tys, true);
|
||||
|
||||
@ -888,9 +885,9 @@ fn process_normal_mthd(cx: @local_ctxt, m: @ast::method, self_ty: ty::t,
|
||||
let llfnty = T_nil();
|
||||
let ccx = cx.ccx;
|
||||
alt ty::struct(cx.ccx.tcx, node_id_type(cx.ccx, m.node.id)) {
|
||||
ty::ty_fn(proto, inputs, output, rs, _) {
|
||||
ty::ty_fn(_, inputs, output, rs, _) {
|
||||
check non_ty_var(ccx, output);
|
||||
llfnty = type_of_fn(ccx, m.span, proto, true,
|
||||
llfnty = type_of_fn(ccx, m.span, true,
|
||||
ast_util::ret_by_ref(rs), inputs, output,
|
||||
vec::len(ty_params));
|
||||
}
|
||||
@ -944,7 +941,7 @@ fn type_of_meth(ccx: @crate_ctxt, sp: span, m: @ty::method,
|
||||
tps: [ast::ty_param]) -> TypeRef {
|
||||
let out_ty = m.output;
|
||||
check non_ty_var(ccx, out_ty);
|
||||
type_of_fn(ccx, sp, m.proto, true, ast_util::ret_by_ref(m.cf),
|
||||
type_of_fn(ccx, sp, true, ast_util::ret_by_ref(m.cf),
|
||||
m.inputs, out_ty, vec::len(tps))
|
||||
}
|
||||
|
||||
|
@ -117,10 +117,9 @@ fn check_states_against_conditions(fcx: fn_ctxt, f: _fn, tps: [ast::ty_param],
|
||||
|
||||
/* Check that the return value is initialized */
|
||||
let post = aux::block_poststate(fcx.ccx, f.body);
|
||||
if f.proto != ast::proto_iter &&
|
||||
!promises(fcx, post, fcx.enclosing.i_return) &&
|
||||
!type_is_nil(fcx.ccx.tcx, ret_ty_of_fn(fcx.ccx.tcx, id)) &&
|
||||
f.decl.cf == return_val {
|
||||
if !promises(fcx, post, fcx.enclosing.i_return) &&
|
||||
!type_is_nil(fcx.ccx.tcx, ret_ty_of_fn(fcx.ccx.tcx, id)) &&
|
||||
f.decl.cf == return_val {
|
||||
fcx.ccx.tcx.sess.span_err(f.body.span,
|
||||
"In function " + fcx.name +
|
||||
", not all control paths \
|
||||
|
@ -343,15 +343,6 @@ fn find_pre_post_expr(fcx: fn_ctxt, e: @expr) {
|
||||
find_pre_post_expr(fcx, arg);
|
||||
copy_pre_post(fcx.ccx, e.id, arg);
|
||||
}
|
||||
expr_put(opt) {
|
||||
alt opt {
|
||||
some(arg) {
|
||||
find_pre_post_expr(fcx, arg);
|
||||
copy_pre_post(fcx.ccx, e.id, arg);
|
||||
}
|
||||
none. { clear_pp(expr_pp(fcx.ccx, e)); }
|
||||
}
|
||||
}
|
||||
expr_fn(f) {
|
||||
let rslt = expr_pp(fcx.ccx, e);
|
||||
clear_pp(rslt);
|
||||
@ -459,14 +450,6 @@ fn find_pre_post_expr(fcx: fn_ctxt, e: @expr) {
|
||||
expr_for(d, index, body) {
|
||||
find_pre_post_loop(fcx, d, index, body, e.id);
|
||||
}
|
||||
expr_for_each(d, index, body) {
|
||||
find_pre_post_loop(fcx, d, index, body, e.id);
|
||||
let rslt = expr_pp(fcx.ccx, e);
|
||||
clear_pp(rslt);
|
||||
for def in *freevars::get_freevars(fcx.ccx.tcx, body.node.id) {
|
||||
handle_var_def(fcx, rslt, def, "upvar");
|
||||
}
|
||||
}
|
||||
expr_index(val, sub) { find_pre_post_exprs(fcx, [val, sub], e.id); }
|
||||
expr_alt(ex, alts) {
|
||||
find_pre_post_expr(fcx, ex);
|
||||
|
@ -361,14 +361,6 @@ fn find_pre_post_state_expr(fcx: fn_ctxt, pres: prestate, e: @expr) -> bool {
|
||||
ret find_pre_post_state_sub(fcx, pres, ex, e.id, none);
|
||||
}
|
||||
expr_mac(_) { fcx.ccx.tcx.sess.bug("unexpanded macro"); }
|
||||
expr_put(maybe_e) {
|
||||
alt maybe_e {
|
||||
some(arg) {
|
||||
ret find_pre_post_state_sub(fcx, pres, arg, e.id, none);
|
||||
}
|
||||
none. { ret pure_exp(fcx.ccx, e.id, pres); }
|
||||
}
|
||||
}
|
||||
expr_lit(l) { ret pure_exp(fcx.ccx, e.id, pres); }
|
||||
expr_fn(f) { ret pure_exp(fcx.ccx, e.id, pres); }
|
||||
expr_block(b) {
|
||||
@ -530,9 +522,6 @@ fn find_pre_post_state_expr(fcx: fn_ctxt, pres: prestate, e: @expr) -> bool {
|
||||
expr_for(d, index, body) {
|
||||
ret find_pre_post_state_loop(fcx, pres, d, index, body, e.id);
|
||||
}
|
||||
expr_for_each(d, index, body) {
|
||||
ret find_pre_post_state_loop(fcx, pres, d, index, body, e.id);
|
||||
}
|
||||
expr_index(val, sub) {
|
||||
ret find_pre_post_state_two(fcx, pres, val, sub, e.id, oper_pure);
|
||||
}
|
||||
|
@ -1010,7 +1010,6 @@ fn type_kind(cx: ctxt, ty: t) -> ast::kind {
|
||||
// here yet, leading to weirdness around closure.
|
||||
ty_fn(proto, _, _, _, _) {
|
||||
result = alt proto {
|
||||
ast::proto_iter. { ast::kind_shared }
|
||||
ast::proto_block. { ast::kind_pinned }
|
||||
ast::proto_shared(_) { ast::kind_shared }
|
||||
ast::proto_bare. { ast::kind_unique }
|
||||
@ -2042,14 +2041,7 @@ mod unify {
|
||||
}
|
||||
}
|
||||
|
||||
ret if (e_proto == ast::proto_iter
|
||||
|| a_proto == ast::proto_iter) {
|
||||
if e_proto != a_proto {
|
||||
some(ures_err(terr_mismatch))
|
||||
} else {
|
||||
none
|
||||
}
|
||||
} else if e_proto == a_proto {
|
||||
ret if e_proto == a_proto {
|
||||
none
|
||||
} else if variance == invariant {
|
||||
if e_proto != a_proto {
|
||||
|
@ -1560,8 +1560,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier,
|
||||
// A generic function to factor out common logic from call and bind
|
||||
// expressions.
|
||||
fn check_call_or_bind(fcx: @fn_ctxt, sp: span, f: @ast::expr,
|
||||
args: [option::t<@ast::expr>], call_kind: call_kind)
|
||||
-> bool {
|
||||
args: [option::t<@ast::expr>]) -> bool {
|
||||
// Check the function.
|
||||
let bot = check_expr(fcx, f);
|
||||
|
||||
@ -1570,22 +1569,6 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier,
|
||||
|
||||
let sty = structure_of(fcx, sp, fty);
|
||||
|
||||
// Check that we aren't confusing iter calls and fn calls
|
||||
alt sty {
|
||||
ty::ty_fn(ast::proto_iter., _, _, _, _) {
|
||||
if call_kind != kind_for_each {
|
||||
fcx.ccx.tcx.sess.span_err
|
||||
(sp, "calling iter outside of for each loop");
|
||||
}
|
||||
}
|
||||
_ {
|
||||
if call_kind == kind_for_each {
|
||||
fcx.ccx.tcx.sess.span_err
|
||||
(sp, "calling non-iter as sequence of for each loop");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Grab the argument types
|
||||
let arg_tys =
|
||||
alt sty {
|
||||
@ -1669,27 +1652,26 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier,
|
||||
}
|
||||
|
||||
// A generic function for checking call expressions
|
||||
fn check_call(fcx: @fn_ctxt, sp: span, f: @ast::expr, args: [@ast::expr],
|
||||
call_kind: call_kind) -> bool {
|
||||
fn check_call(fcx: @fn_ctxt, sp: span, f: @ast::expr, args: [@ast::expr])
|
||||
-> bool {
|
||||
let args_opt_0: [option::t<@ast::expr>] = [];
|
||||
for arg: @ast::expr in args {
|
||||
args_opt_0 += [some::<@ast::expr>(arg)];
|
||||
}
|
||||
|
||||
// Call the generic checker.
|
||||
ret check_call_or_bind(fcx, sp, f, args_opt_0, call_kind);
|
||||
ret check_call_or_bind(fcx, sp, f, args_opt_0);
|
||||
}
|
||||
|
||||
// A generic function for doing all of the checking for call expressions
|
||||
fn check_call_full(fcx: @fn_ctxt, sp: span, f: @ast::expr,
|
||||
args: [@ast::expr], call_kind: call_kind,
|
||||
id: ast::node_id) -> bool {
|
||||
args: [@ast::expr], id: ast::node_id) -> bool {
|
||||
/* here we're kind of hosed, as f can be any expr
|
||||
need to restrict it to being an explicit expr_path if we're
|
||||
inside a pure function, and need an environment mapping from
|
||||
function name onto purity-designation */
|
||||
require_pure_call(fcx.ccx, fcx.purity, f, sp);
|
||||
let bot = check_call(fcx, sp, f, args, call_kind);
|
||||
let bot = check_call(fcx, sp, f, args);
|
||||
|
||||
// Pull the return type out of the type of the function.
|
||||
let rt_1;
|
||||
@ -1707,9 +1689,9 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier,
|
||||
}
|
||||
|
||||
// A generic function for checking for or for-each loops
|
||||
fn check_for_or_for_each(fcx: @fn_ctxt, local: @ast::local,
|
||||
element_ty: ty::t, body: ast::blk,
|
||||
node_id: ast::node_id) -> bool {
|
||||
fn check_for(fcx: @fn_ctxt, local: @ast::local,
|
||||
element_ty: ty::t, body: ast::blk,
|
||||
node_id: ast::node_id) -> bool {
|
||||
let locid = lookup_local(fcx, local.span, local.node.id);
|
||||
element_ty =
|
||||
demand::simple(fcx, local.span, element_ty,
|
||||
@ -1893,23 +1875,6 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier,
|
||||
}
|
||||
write::bot_ty(tcx, id);
|
||||
}
|
||||
ast::expr_put(expr_opt) {
|
||||
require_impure(tcx.sess, fcx.purity, expr.span);
|
||||
if fcx.proto != ast::proto_iter {
|
||||
tcx.sess.span_err(expr.span, "put in non-iterator");
|
||||
}
|
||||
alt expr_opt {
|
||||
none. {
|
||||
let nil = ty::mk_nil(tcx);
|
||||
if !are_compatible(fcx, fcx.ret_ty, nil) {
|
||||
tcx.sess.span_err(expr.span,
|
||||
"put; in iterator yielding non-nil");
|
||||
}
|
||||
}
|
||||
some(e) { bot = check_expr_with(fcx, e, fcx.ret_ty); }
|
||||
}
|
||||
write::nil_ty(tcx, id);
|
||||
}
|
||||
ast::expr_be(e) {
|
||||
// FIXME: prove instead of assert
|
||||
assert (ast_util::is_call_expr(e));
|
||||
@ -1979,21 +1944,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier,
|
||||
+ "but found " + ty_to_str(tcx, ety));
|
||||
}
|
||||
}
|
||||
bot |= check_for_or_for_each(fcx, decl, elt_ty, body, id);
|
||||
}
|
||||
ast::expr_for_each(decl, seq, body) {
|
||||
alt seq.node {
|
||||
ast::expr_call(f, args) {
|
||||
bot =
|
||||
check_call_full(fcx, seq.span, f, args, kind_for_each,
|
||||
seq.id);
|
||||
}
|
||||
_ {
|
||||
tcx.sess.span_fatal(expr.span,
|
||||
"sequence in for each loop not a call");
|
||||
}
|
||||
}
|
||||
bot |= check_for_or_for_each(fcx, decl, expr_ty(tcx, seq), body, id);
|
||||
bot |= check_for(fcx, decl, elt_ty, body, id);
|
||||
}
|
||||
ast::expr_while(cond, body) {
|
||||
bot = check_expr_with(fcx, cond, ty::mk_bool(tcx));
|
||||
@ -2069,7 +2020,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier,
|
||||
}
|
||||
ast::expr_bind(f, args) {
|
||||
// Call the generic checker.
|
||||
bot = check_call_or_bind(fcx, expr.span, f, args, kind_bind);
|
||||
bot = check_call_or_bind(fcx, expr.span, f, args);
|
||||
|
||||
// Pull the argument and return types out.
|
||||
let proto, arg_tys, rt, cf, constrs;
|
||||
@ -2122,7 +2073,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier,
|
||||
write::ty_only_fixup(fcx, id, ft);
|
||||
}
|
||||
ast::expr_call(f, args) {
|
||||
bot = check_call_full(fcx, expr.span, f, args, kind_call, expr.id);
|
||||
bot = check_call_full(fcx, expr.span, f, args, expr.id);
|
||||
}
|
||||
ast::expr_self_method(ident) {
|
||||
let t = ty::mk_nil(tcx);
|
||||
@ -2716,16 +2667,12 @@ fn check_fn(ccx: @crate_ctxt, f: ast::_fn, id: ast::node_id,
|
||||
check_constraints(fcx, decl.constraints, decl.inputs);
|
||||
check_block(fcx, body);
|
||||
|
||||
// For non-iterator fns, we unify the tail expr's type with the
|
||||
// We unify the tail expr's type with the
|
||||
// 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.
|
||||
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);
|
||||
}
|
||||
let tail_expr_ty = expr_ty(ccx.tcx, tail_expr);
|
||||
demand::simple(fcx, tail_expr.span, fcx.ret_ty, tail_expr_ty);
|
||||
}
|
||||
none. { }
|
||||
}
|
||||
|
@ -109,7 +109,6 @@ tag proto_sugar {
|
||||
}
|
||||
|
||||
tag proto {
|
||||
proto_iter;
|
||||
proto_bare;
|
||||
proto_shared(proto_sugar);
|
||||
proto_block;
|
||||
@ -197,7 +196,6 @@ tag expr_ {
|
||||
expr_ternary(@expr, @expr, @expr);
|
||||
expr_while(@expr, blk);
|
||||
expr_for(@local, @expr, blk);
|
||||
expr_for_each(@local, @expr, blk);
|
||||
expr_do_while(blk, @expr);
|
||||
expr_alt(@expr, [arm]);
|
||||
expr_fn(_fn);
|
||||
@ -219,7 +217,6 @@ tag expr_ {
|
||||
expr_break;
|
||||
expr_cont;
|
||||
expr_ret(option::t<@expr>);
|
||||
expr_put(option::t<@expr>);
|
||||
expr_be(@expr);
|
||||
expr_log(int, @expr);
|
||||
|
||||
|
@ -377,10 +377,6 @@ fn noop_fold_expr(e: expr_, fld: ast_fold) -> expr_ {
|
||||
expr_for(fld.fold_local(decl), fld.fold_expr(expr),
|
||||
fld.fold_block(blk))
|
||||
}
|
||||
expr_for_each(decl, expr, blk) {
|
||||
expr_for_each(fld.fold_local(decl), fld.fold_expr(expr),
|
||||
fld.fold_block(blk))
|
||||
}
|
||||
expr_do_while(blk, expr) {
|
||||
expr_do_while(fld.fold_block(blk), fld.fold_expr(expr))
|
||||
}
|
||||
@ -413,7 +409,6 @@ fn noop_fold_expr(e: expr_, fld: ast_fold) -> expr_ {
|
||||
expr_break. { e }
|
||||
expr_cont. { e }
|
||||
expr_ret(e) { expr_ret(option::map(fld.fold_expr, e)) }
|
||||
expr_put(e) { expr_put(option::map(fld.fold_expr, e)) }
|
||||
expr_be(e) { expr_be(fld.fold_expr(e)) }
|
||||
expr_log(lv, e) { expr_log(lv, fld.fold_expr(e)) }
|
||||
expr_assert(e) { expr_assert(fld.fold_expr(e)) }
|
||||
|
@ -148,10 +148,8 @@ fn bad_expr_word_table() -> hashmap<str, ()> {
|
||||
words.insert("do", ());
|
||||
words.insert("alt", ());
|
||||
words.insert("for", ());
|
||||
words.insert("each", ());
|
||||
words.insert("break", ());
|
||||
words.insert("cont", ());
|
||||
words.insert("put", ());
|
||||
words.insert("ret", ());
|
||||
words.insert("be", ());
|
||||
words.insert("fail", ());
|
||||
@ -160,13 +158,11 @@ fn bad_expr_word_table() -> hashmap<str, ()> {
|
||||
words.insert("check", ());
|
||||
words.insert("assert", ());
|
||||
words.insert("claim", ());
|
||||
words.insert("prove", ());
|
||||
words.insert("native", ());
|
||||
words.insert("fn", ());
|
||||
words.insert("lambda", ());
|
||||
words.insert("pure", ());
|
||||
words.insert("unsafe", ());
|
||||
words.insert("iter", ());
|
||||
words.insert("block", ());
|
||||
words.insert("import", ());
|
||||
words.insert("export", ());
|
||||
@ -566,9 +562,6 @@ fn parse_ty(p: parser, colons_before_params: bool) -> @ast::ty {
|
||||
} else if eat_word(p, "block") {
|
||||
t = parse_ty_fn(ast::proto_block, p);
|
||||
alt t { ast::ty_fn(_, _, out, _, _) { hi = out.span.hi; } }
|
||||
} else if eat_word(p, "iter") {
|
||||
t = parse_ty_fn(ast::proto_iter, p);
|
||||
alt t { ast::ty_fn(_, _, out, _, _) { hi = out.span.hi; } }
|
||||
} else if eat_word(p, "obj") {
|
||||
t = parse_ty_obj(p, hi);
|
||||
} else if p.peek() == token::MOD_SEP || is_ident(p.peek()) {
|
||||
@ -964,15 +957,6 @@ fn parse_bottom_expr(p: parser) -> @ast::expr {
|
||||
} else if eat_word(p, "cont") {
|
||||
ex = ast::expr_cont;
|
||||
hi = p.get_hi_pos();
|
||||
} else if eat_word(p, "put") {
|
||||
alt p.peek() {
|
||||
token::SEMI. { ex = ast::expr_put(none); }
|
||||
_ {
|
||||
let e = parse_expr(p);
|
||||
hi = e.span.hi;
|
||||
ex = ast::expr_put(some(e));
|
||||
}
|
||||
}
|
||||
} else if eat_word(p, "be") {
|
||||
let e = parse_expr(p);
|
||||
|
||||
@ -1341,15 +1325,12 @@ fn parse_else_expr(p: parser) -> @ast::expr {
|
||||
|
||||
fn parse_for_expr(p: parser) -> @ast::expr {
|
||||
let lo = p.get_last_lo_pos();
|
||||
let is_each = eat_word(p, "each");
|
||||
let decl = parse_local(p, false);
|
||||
expect_word(p, "in");
|
||||
let seq = parse_expr(p);
|
||||
let body = parse_block_no_value(p);
|
||||
let hi = body.span.hi;
|
||||
if is_each {
|
||||
ret mk_expr(p, lo, hi, ast::expr_for_each(decl, seq, body));
|
||||
} else { ret mk_expr(p, lo, hi, ast::expr_for(decl, seq, body)); }
|
||||
ret mk_expr(p, lo, hi, ast::expr_for(decl, seq, body));
|
||||
}
|
||||
|
||||
fn parse_while_expr(p: parser) -> @ast::expr {
|
||||
@ -1640,8 +1621,7 @@ fn expr_has_value(e: @ast::expr) -> bool {
|
||||
found_expr
|
||||
}
|
||||
ast::expr_block(blk) | ast::expr_while(_, blk) |
|
||||
ast::expr_for(_, _, blk) | ast::expr_for_each(_, _, blk) |
|
||||
ast::expr_do_while(blk, _) {
|
||||
ast::expr_for(_, _, blk) | ast::expr_do_while(blk, _) {
|
||||
!option::is_none(blk.node.expr)
|
||||
}
|
||||
_ { true }
|
||||
@ -1837,7 +1817,7 @@ fn mk_item(p: parser, lo: uint, hi: uint, ident: ast::ident, node: ast::item_,
|
||||
span: ast_util::mk_sp(lo, hi)};
|
||||
}
|
||||
|
||||
fn parse_item_fn_or_iter(p: parser, purity: ast::purity, proto: ast::proto,
|
||||
fn parse_item_fn(p: parser, purity: ast::purity, proto: ast::proto,
|
||||
attrs: [ast::attribute], il: ast::inlineness) ->
|
||||
@ast::item {
|
||||
let lo = p.get_last_lo_pos();
|
||||
@ -2167,9 +2147,7 @@ fn parse_fn_anon_proto(p: parser) -> ast::proto {
|
||||
}
|
||||
|
||||
fn parse_method_proto(p: parser) -> ast::proto {
|
||||
if eat_word(p, "iter") {
|
||||
ret ast::proto_iter;
|
||||
} else if eat_word(p, "fn") {
|
||||
if eat_word(p, "fn") {
|
||||
ret ast::proto_bare;
|
||||
} else { unexpected(p, p.peek()); }
|
||||
}
|
||||
@ -2180,27 +2158,24 @@ fn parse_item(p: parser, attrs: [ast::attribute]) -> option::t<@ast::item> {
|
||||
} else if eat_word(p, "inline") {
|
||||
expect_word(p, "fn");
|
||||
let proto = parse_fn_item_proto(p);
|
||||
ret some(parse_item_fn_or_iter(p, ast::impure_fn, proto,
|
||||
ret some(parse_item_fn(p, ast::impure_fn, proto,
|
||||
attrs, ast::il_inline));
|
||||
} else if is_word(p, "fn") && p.look_ahead(1u) != token::LPAREN {
|
||||
p.bump();
|
||||
let proto = parse_fn_item_proto(p);
|
||||
ret some(parse_item_fn_or_iter(p, ast::impure_fn, proto,
|
||||
attrs, ast::il_normal));
|
||||
ret some(parse_item_fn(p, ast::impure_fn, proto,
|
||||
attrs, ast::il_normal));
|
||||
} else if eat_word(p, "pure") {
|
||||
expect_word(p, "fn");
|
||||
let proto = parse_fn_item_proto(p);
|
||||
ret some(parse_item_fn_or_iter(p, ast::pure_fn, proto, attrs,
|
||||
ast::il_normal));
|
||||
ret some(parse_item_fn(p, ast::pure_fn, proto, attrs,
|
||||
ast::il_normal));
|
||||
} else if is_word(p, "unsafe") && p.look_ahead(1u) != token::LBRACE {
|
||||
p.bump();
|
||||
expect_word(p, "fn");
|
||||
let proto = parse_fn_item_proto(p);
|
||||
ret some(parse_item_fn_or_iter(p, ast::unsafe_fn, proto,
|
||||
attrs, ast::il_normal));
|
||||
} else if eat_word(p, "iter") {
|
||||
ret some(parse_item_fn_or_iter(p, ast::impure_fn, ast::proto_iter,
|
||||
attrs, ast::il_normal));
|
||||
ret some(parse_item_fn(p, ast::unsafe_fn, proto,
|
||||
attrs, ast::il_normal));
|
||||
} else if eat_word(p, "mod") {
|
||||
ret some(parse_item_mod(p, attrs));
|
||||
} else if eat_word(p, "native") {
|
||||
|
@ -606,8 +606,7 @@ fn print_possibly_embedded_block(s: ps, blk: ast::blk, embedded: embed_type,
|
||||
// alt, do, & while unambiguously without being parenthesized
|
||||
fn print_maybe_parens_discrim(s: ps, e: @ast::expr) {
|
||||
let disambig = alt e.node {
|
||||
ast::expr_ret(none.) | ast::expr_put(none.) |
|
||||
ast::expr_fail(none.) { true }
|
||||
ast::expr_ret(none.) | ast::expr_fail(none.) { true }
|
||||
_ { false }
|
||||
};
|
||||
if disambig { popen(s); }
|
||||
@ -796,12 +795,6 @@ fn print_expr(s: ps, &&expr: @ast::expr) {
|
||||
space(s.s);
|
||||
print_block(s, blk);
|
||||
}
|
||||
ast::expr_for_each(decl, expr, blk) {
|
||||
head(s, "for each");
|
||||
print_for_decl(s, decl, expr);
|
||||
space(s.s);
|
||||
print_block(s, blk);
|
||||
}
|
||||
ast::expr_do_while(blk, expr) {
|
||||
head(s, "do");
|
||||
space(s.s);
|
||||
@ -924,13 +917,6 @@ fn print_expr(s: ps, &&expr: @ast::expr) {
|
||||
_ { }
|
||||
}
|
||||
}
|
||||
ast::expr_put(result) {
|
||||
word(s.s, "put");
|
||||
alt result {
|
||||
some(expr) { word(s.s, " "); print_expr(s, expr); }
|
||||
_ { }
|
||||
}
|
||||
}
|
||||
ast::expr_be(result) { word_nbsp(s, "be"); print_expr(s, result); }
|
||||
ast::expr_log(lvl, expr) {
|
||||
alt lvl { 1 { word_nbsp(s, "log"); } 0 { word_nbsp(s, "log_err"); } }
|
||||
@ -1005,7 +991,7 @@ fn print_expr(s: ps, &&expr: @ast::expr) {
|
||||
|
||||
fn print_expr_parens_if_not_bot(s: ps, ex: @ast::expr) {
|
||||
let parens = alt ex.node {
|
||||
ast::expr_fail(_) | ast::expr_ret(_) | ast::expr_put(_) |
|
||||
ast::expr_fail(_) | ast::expr_ret(_) |
|
||||
ast::expr_binary(_, _, _) | ast::expr_unary(_, _) |
|
||||
ast::expr_ternary(_, _, _) | ast::expr_move(_, _) |
|
||||
ast::expr_copy(_) | ast::expr_assign(_, _) | ast::expr_be(_) |
|
||||
@ -1319,7 +1305,6 @@ fn need_parens(expr: @ast::expr, outer_prec: int) -> bool {
|
||||
ast::expr_swap(_, _) { true }
|
||||
ast::expr_assign_op(_, _, _) { true }
|
||||
ast::expr_ret(_) { true }
|
||||
ast::expr_put(_) { true }
|
||||
ast::expr_be(_) { true }
|
||||
ast::expr_assert(_) { true }
|
||||
ast::expr_check(_, _) { true }
|
||||
@ -1643,7 +1628,6 @@ fn ast_fn_constrs_str(decl: ast::fn_decl, constrs: [@ast::constr]) -> str {
|
||||
|
||||
fn proto_to_str(p: ast::proto) -> str {
|
||||
ret alt p {
|
||||
ast::proto_iter. { "iter" }
|
||||
ast::proto_bare. { "fn" }
|
||||
ast::proto_block. { "block" }
|
||||
ast::proto_shared(ast::sugar_normal.) { "fn@" }
|
||||
@ -1679,7 +1663,7 @@ fn ends_in_lit_int(ex: @ast::expr) -> bool {
|
||||
ast::expr_assign_op(_, _, sub) | ast::expr_swap(_, sub) |
|
||||
ast::expr_log(_, sub) | ast::expr_assert(sub) |
|
||||
ast::expr_check(_, sub) { ends_in_lit_int(sub) }
|
||||
ast::expr_fail(osub) | ast::expr_ret(osub) | ast::expr_put(osub) {
|
||||
ast::expr_fail(osub) | ast::expr_ret(osub) {
|
||||
alt osub {
|
||||
some(ex) { ends_in_lit_int(ex) }
|
||||
_ { false }
|
||||
|
@ -274,7 +274,7 @@ fn visit_expr<E>(ex: @expr, e: E, v: vt<E>) {
|
||||
v.visit_expr(el, e, v);
|
||||
}
|
||||
expr_while(x, b) { v.visit_expr(x, e, v); v.visit_block(b, e, v); }
|
||||
expr_for(dcl, x, b) | expr_for_each(dcl, x, b) {
|
||||
expr_for(dcl, x, b) {
|
||||
v.visit_local(dcl, e, v);
|
||||
v.visit_expr(x, e, v);
|
||||
v.visit_block(b, e, v);
|
||||
@ -301,7 +301,6 @@ fn visit_expr<E>(ex: @expr, e: E, v: vt<E>) {
|
||||
expr_break. { }
|
||||
expr_cont. { }
|
||||
expr_ret(eo) { visit_expr_opt(eo, e, v); }
|
||||
expr_put(eo) { visit_expr_opt(eo, e, v); }
|
||||
expr_be(x) { v.visit_expr(x, e, v); }
|
||||
expr_log(_, x) { v.visit_expr(x, e, v); }
|
||||
expr_check(_, x) { v.visit_expr(x, e, v); }
|
||||
|
@ -271,17 +271,6 @@ fn lit_eq(l: @ast::lit, m: @ast::lit) -> bool {
|
||||
}
|
||||
}
|
||||
|
||||
tag call_kind { kind_call; kind_spawn; kind_bind; kind_for_each; }
|
||||
|
||||
fn call_kind_str(c: call_kind) -> str {
|
||||
alt c {
|
||||
kind_call. { "Call" }
|
||||
kind_spawn. { "Spawn" }
|
||||
kind_bind. { "Bind" }
|
||||
kind_for_each. { "For-Each" }
|
||||
}
|
||||
}
|
||||
|
||||
fn is_main_name(path: [ast::ident]) -> bool {
|
||||
str::eq(option::get(std::vec::last(path)), "main")
|
||||
}
|
||||
|
@ -49,7 +49,6 @@ fn common_exprs() -> [ast::expr] {
|
||||
dse(ast::expr_fail(option::none)),
|
||||
dse(ast::expr_fail(option::some(@dse(ast::expr_lit(@dsl(ast::lit_str("boo"))))))),
|
||||
dse(ast::expr_ret(option::none)),
|
||||
dse(ast::expr_put(option::none)),
|
||||
dse(ast::expr_lit(@dsl(ast::lit_nil))),
|
||||
dse(ast::expr_lit(@dsl(ast::lit_bool(false)))),
|
||||
dse(ast::expr_lit(@dsl(ast::lit_bool(true)))),
|
||||
@ -74,7 +73,6 @@ pure fn safe_to_use_expr(e: ast::expr, tm: test_mode) -> bool {
|
||||
ast::expr_block(_) { false }
|
||||
ast::expr_alt(_, _) { false }
|
||||
ast::expr_for(_, _, _) { false }
|
||||
ast::expr_for_each(_, _, _) { false }
|
||||
ast::expr_while(_, _) { false }
|
||||
|
||||
// https://github.com/graydon/rust/issues/955
|
||||
@ -89,7 +87,6 @@ pure fn safe_to_use_expr(e: ast::expr, tm: test_mode) -> bool {
|
||||
|
||||
ast::expr_fail(option::none.) { false }
|
||||
ast::expr_ret(option::none.) { false }
|
||||
ast::expr_put(option::none.) { false }
|
||||
|
||||
// https://github.com/graydon/rust/issues/953
|
||||
ast::expr_fail(option::some(_)) { false }
|
||||
|
Loading…
x
Reference in New Issue
Block a user