diff options
| author | Marijn Haverbeke <marijnh@gmail.com> | 2011-10-06 12:26:12 +0200 |
|---|---|---|
| committer | Marijn Haverbeke <marijnh@gmail.com> | 2011-10-07 09:09:50 +0200 |
| commit | f9fbd86f52cf597b85359ade1ca60b8d6ebf7286 (patch) | |
| tree | d6f0cdd039642052f3ccb4ba8f3b9821bb7cbaaf /src/comp/middle | |
| parent | 4709038d641ad009b44ed2bf5980fa3a252d6927 (diff) | |
Parse and typecheck by-value and by-ref arg specs
Add sprinkle && throughout the compiler to make it typecheck again. Issue #1008
Diffstat (limited to 'src/comp/middle')
| -rw-r--r-- | src/comp/middle/alias.rs | 4 | ||||
| -rw-r--r-- | src/comp/middle/ast_map.rs | 2 | ||||
| -rw-r--r-- | src/comp/middle/check_alt.rs | 4 | ||||
| -rw-r--r-- | src/comp/middle/freevars.rs | 4 | ||||
| -rw-r--r-- | src/comp/middle/mut.rs | 6 | ||||
| -rw-r--r-- | src/comp/middle/resolve.rs | 10 | ||||
| -rw-r--r-- | src/comp/middle/trans.rs | 20 | ||||
| -rw-r--r-- | src/comp/middle/trans_objects.rs | 5 | ||||
| -rw-r--r-- | src/comp/middle/tstate/pre_post_conditions.rs | 10 | ||||
| -rw-r--r-- | src/comp/middle/ty.rs | 34 | ||||
| -rw-r--r-- | src/comp/middle/typeck.rs | 59 |
11 files changed, 90 insertions, 68 deletions
diff --git a/src/comp/middle/alias.rs b/src/comp/middle/alias.rs index 03a060a57fd..5d9d736f209 100644 --- a/src/comp/middle/alias.rs +++ b/src/comp/middle/alias.rs @@ -251,10 +251,8 @@ fn check_call(cx: ctx, f: @ast::expr, args: [@ast::expr]) -> [binding] { mutable ok: valid, mutable copied: alt arg_t.mode { ast::by_move. { copied } - ast::by_ref. { - i + 1u == by_ref ? not_allowed : not_copied - } ast::by_mut_ref. { not_allowed } + _ { i + 1u == by_ref ? not_allowed : not_copied } }}]; i += 1u; } diff --git a/src/comp/middle/ast_map.rs b/src/comp/middle/ast_map.rs index ce8c983c0f9..9b89ec63331 100644 --- a/src/comp/middle/ast_map.rs +++ b/src/comp/middle/ast_map.rs @@ -76,7 +76,7 @@ fn map_expr(cx: ctx, ex: @expr) { } fn new_smallintmap_int_adapter<@V>() -> std::map::hashmap<int, V> { - let key_idx = fn (key: int) -> uint { key as uint }; + let key_idx = fn (&&key: int) -> uint { key as uint }; let idx_key = fn (idx: uint) -> int { idx as int }; ret new_smallintmap_adapter(key_idx, idx_key); } diff --git a/src/comp/middle/check_alt.rs b/src/comp/middle/check_alt.rs index 236b0403358..a3b58cf1600 100644 --- a/src/comp/middle/check_alt.rs +++ b/src/comp/middle/check_alt.rs @@ -11,7 +11,7 @@ fn check_crate(tcx: ty::ctxt, crate: @crate) { tcx.sess.abort_if_errors(); } -fn check_expr(tcx: ty::ctxt, ex: @expr, s: (), v: visit::vt<()>) { +fn check_expr(tcx: ty::ctxt, ex: @expr, &&s: (), v: visit::vt<()>) { visit::visit_expr(ex, s, v); alt ex.node { expr_alt(_, arms) { check_arms(tcx, arms); } _ { } } } @@ -123,7 +123,7 @@ fn pattern_supersedes(tcx: ty::ctxt, a: @pat, b: @pat) -> bool { } } -fn check_local(tcx: ty::ctxt, loc: @local, s: (), v: visit::vt<()>) { +fn check_local(tcx: ty::ctxt, loc: @local, &&s: (), v: visit::vt<()>) { visit::visit_local(loc, s, v); if is_refutable(tcx, loc.node.pat) { tcx.sess.span_err(loc.node.pat.span, diff --git a/src/comp/middle/freevars.rs b/src/comp/middle/freevars.rs index e0a05a9f63e..5a6ed3283e7 100644 --- a/src/comp/middle/freevars.rs +++ b/src/comp/middle/freevars.rs @@ -29,10 +29,10 @@ fn collect_freevars(def_map: resolve::def_map, walker: fn(visit::vt<int>)) -> let seen = new_int_hash(); let refs = @mutable []; - fn ignore_item(_i: @ast::item, _depth: int, _v: visit::vt<int>) { } + fn ignore_item(_i: @ast::item, &&_depth: int, _v: visit::vt<int>) { } let walk_expr = - lambda (expr: @ast::expr, depth: int, v: visit::vt<int>) { + lambda (expr: @ast::expr, &&depth: int, v: visit::vt<int>) { alt expr.node { ast::expr_fn(f) { if f.proto == ast::proto_block || diff --git a/src/comp/middle/mut.rs b/src/comp/middle/mut.rs index 7952353ca2f..836f6de87e3 100644 --- a/src/comp/middle/mut.rs +++ b/src/comp/middle/mut.rs @@ -131,7 +131,7 @@ fn mk_err(cx: @ctx, span: syntax::codemap::span, msg: msg, name: str) { }); } -fn visit_decl(cx: @ctx, d: @decl, e: (), v: visit::vt<()>) { +fn visit_decl(cx: @ctx, d: @decl, &&e: (), v: visit::vt<()>) { visit::visit_decl(d, e, v); alt d.node { decl_local(locs) { @@ -148,7 +148,7 @@ fn visit_decl(cx: @ctx, d: @decl, e: (), v: visit::vt<()>) { } } -fn visit_expr(cx: @ctx, ex: @expr, e: (), v: visit::vt<()>) { +fn visit_expr(cx: @ctx, ex: @expr, &&e: (), v: visit::vt<()>) { alt ex.node { expr_call(f, args) { check_call(cx, f, args); } expr_swap(lhs, rhs) { @@ -225,7 +225,7 @@ fn check_call(cx: @ctx, f: @expr, args: [@expr]) { alt arg_t.mode { by_mut_ref. { check_lval(cx, args[i], msg_mut_ref); } by_move. { check_lval(cx, args[i], msg_move_out); } - by_ref. {} + _ {} } i += 1u; } diff --git a/src/comp/middle/resolve.rs b/src/comp/middle/resolve.rs index 7018f8d1a85..fe95ecc0b85 100644 --- a/src/comp/middle/resolve.rs +++ b/src/comp/middle/resolve.rs @@ -1239,7 +1239,7 @@ fn mie_span(mie: mod_index_entry) -> span { }; } -fn check_item(e: @env, i: @ast::item, x: (), v: vt<()>) { +fn check_item(e: @env, i: @ast::item, &&x: (), v: vt<()>) { fn typaram_names(tps: [ast::ty_param]) -> [ident] { let x: [ast::ident] = []; for tp: ast::ty_param in tps { x += [tp.ident]; } @@ -1276,7 +1276,7 @@ fn check_pat(ch: checker, p: @ast::pat) { } } -fn check_arm(e: @env, a: ast::arm, x: (), v: vt<()>) { +fn check_arm(e: @env, a: ast::arm, &&x: (), v: vt<()>) { visit::visit_arm(a, x, v); let ch0 = checker(*e, "binding"); check_pat(ch0, a.pats[0]); @@ -1306,7 +1306,7 @@ fn check_arm(e: @env, a: ast::arm, x: (), v: vt<()>) { } } -fn check_block(e: @env, b: ast::blk, x: (), v: vt<()>) { +fn check_block(e: @env, b: ast::blk, &&x: (), v: vt<()>) { visit::visit_block(b, x, v); let values = checker(*e, "value"); let types = checker(*e, "type"); @@ -1359,7 +1359,7 @@ fn check_fn(e: env, sp: span, f: ast::_fn) { ensure_unique(e, sp, f.decl.inputs, arg_name, "argument"); } -fn check_expr(e: @env, ex: @ast::expr, x: (), v: vt<()>) { +fn check_expr(e: @env, ex: @ast::expr, &&x: (), v: vt<()>) { alt ex.node { ast::expr_rec(fields, _) { fn field_name(f: ast::field) -> ident { ret f.node.ident; } @@ -1370,7 +1370,7 @@ fn check_expr(e: @env, ex: @ast::expr, x: (), v: vt<()>) { visit::visit_expr(ex, x, v); } -fn check_ty(e: @env, ty: @ast::ty, x: (), v: vt<()>) { +fn check_ty(e: @env, ty: @ast::ty, &&x: (), v: vt<()>) { alt ty.node { ast::ty_rec(fields) { fn field_name(f: ast::ty_field) -> ident { ret f.node.ident; } diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 10418cdfc54..294c9dfd15e 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -3699,7 +3699,7 @@ fn trans_arg_expr(cx: @block_ctxt, arg: ty::arg, lldestty0: TypeRef, // be inspected. It's important for the value // to have type lldestty0 (the callee's expected type). val = llvm::LLVMGetUndef(lldestty0); - } else if arg.mode == ast::by_ref { + } else if arg.mode == ast::by_ref || arg.mode == ast::by_val { let copied = false; if !lv.is_mem && type_is_immediate(ccx, e_ty) { val = do_spill_noroot(bcx, val); @@ -4439,9 +4439,9 @@ fn lval_to_dps(bcx: @block_ctxt, e: @ast::expr, dest: dest) -> @block_ctxt { // latter group "immediates" and, in some circumstances when we know we have a // pointer (or need one), perform load/store operations based on the // immediate-ness of the type. +// FIXME simply call the version in ty.rs immediately fn type_is_immediate(ccx: @crate_ctxt, t: ty::t) -> bool { - ret ty::type_is_scalar(ccx.tcx, t) || ty::type_is_boxed(ccx.tcx, t) || - ty::type_is_unique_box(ccx.tcx, t) || ty::type_is_native(ccx.tcx, t); + ty::type_is_immediate(ccx.tcx, t) } fn do_spill(cx: @block_ctxt, v: ValueRef, t: ty::t) -> result { @@ -5144,7 +5144,11 @@ fn copy_args_to_allocas(fcx: @fn_ctxt, bcx: @block_ctxt, args: [ast::arg], for aarg: ast::arg in args { let arg_ty = arg_tys[arg_n].ty; alt aarg.mode { - ast::by_ref. { + ast::by_move. { + add_clean(bcx, fcx.llargs.get(aarg.id), arg_ty); + } + ast::by_mut_ref. { } + _ { let mutated = !ignore_mut && fcx.lcx.ccx.mut_map.contains_key(aarg.id); @@ -5160,10 +5164,6 @@ fn copy_args_to_allocas(fcx: @fn_ctxt, bcx: @block_ctxt, args: [ast::arg], add_clean(bcx, alloc, arg_ty); } } - ast::by_move. { - add_clean(bcx, fcx.llargs.get(aarg.id), arg_ty); - } - _ { } } arg_n += 1u; } @@ -5790,7 +5790,7 @@ fn register_native_fn(ccx: @crate_ctxt, sp: span, path: [str], name: str, } fn convert_arg_to_i32(cx: @block_ctxt, v: ValueRef, t: ty::t, mode: ty::mode) -> ValueRef { - if mode == ast::by_ref { + if mode == ast::by_ref || mode == ast::by_val { if ty::type_is_integral(bcx_tcx(cx), t) { // FIXME: would be nice to have a postcondition that says // if a type is integral, then it has static size (#586) @@ -5845,7 +5845,7 @@ fn register_native_fn(ccx: @crate_ctxt, sp: span, path: [str], name: str, let i = arg_n; for arg: ty::arg in args { let llarg = llvm::LLVMGetParam(fcx.llfn, i); - if arg.mode == ast::by_ref { + if arg.mode == ast::by_ref || arg.mode == ast::by_val { llarg = load_if_immediate(bcx, llarg, arg.ty); } assert (llarg as int != 0); diff --git a/src/comp/middle/trans_objects.rs b/src/comp/middle/trans_objects.rs index 3c42ce473dd..b9152d30ad2 100644 --- a/src/comp/middle/trans_objects.rs +++ b/src/comp/middle/trans_objects.rs @@ -41,7 +41,8 @@ fn trans_obj(cx: @local_ctxt, sp: span, ob: ast::_obj, ctor_id: ast::node_id, // we're creating. let fn_args: [ast::arg] = []; for f: ast::obj_field in ob.fields { - fn_args += [{mode: ast::by_ref, ty: f.ty, ident: f.ident, id: f.id}]; + fn_args += [{mode: ast::by_ref, ty: f.ty, ident: f.ident, + id: f.id}]; } let fcx = new_fn_ctxt(cx, sp, llctor_decl); @@ -397,7 +398,7 @@ tag vtbl_mthd { } // Alphabetize ast::methods by ident. A helper for create_vtbl. -fn ast_mthd_lteq(a: @ast::method, b: @ast::method) -> bool { +fn ast_mthd_lteq(&&a: @ast::method, &&b: @ast::method) -> bool { ret str::lteq(a.node.ident, b.node.ident); } diff --git a/src/comp/middle/tstate/pre_post_conditions.rs b/src/comp/middle/tstate/pre_post_conditions.rs index 9f2f1307478..036cf8ab0ce 100644 --- a/src/comp/middle/tstate/pre_post_conditions.rs +++ b/src/comp/middle/tstate/pre_post_conditions.rs @@ -99,10 +99,10 @@ fn find_pre_post_exprs(fcx: fn_ctxt, args: [@expr], id: node_id) { fn get_pp(ccx: crate_ctxt, e: @expr) -> pre_and_post { ret expr_pp(ccx, e); } - let pps = vec::map::<@expr, pre_and_post>(bind get_pp(fcx.ccx, _), args); + let pps = vec::map_imm(bind get_pp(fcx.ccx, _), args); set_pre_and_post(fcx.ccx, id, seq_preconds(fcx, pps), - seq_postconds(fcx, vec::map(get_post, pps))); + seq_postconds(fcx, vec::map_imm(get_post, pps))); } fn find_pre_post_loop(fcx: fn_ctxt, l: @local, index: @expr, body: blk, @@ -476,8 +476,8 @@ fn find_pre_post_expr(fcx: fn_ctxt, e: @expr) { } let alt_pps = []; for a: arm in alts { alt_pps += [do_an_alt(fcx, a)]; } - fn combine_pp(antec: pre_and_post, fcx: fn_ctxt, pp: pre_and_post, - next: pre_and_post) -> pre_and_post { + fn combine_pp(antec: pre_and_post, fcx: fn_ctxt, &&pp: pre_and_post, + &&next: pre_and_post) -> pre_and_post { union(pp.precondition, seq_preconds(fcx, [antec, next])); intersect(pp.postcondition, next.postcondition); ret pp; @@ -694,7 +694,7 @@ fn find_pre_post_block(fcx: fn_ctxt, b: blk) { */ } for s: @stmt in b.node.stmts { do_one_(fcx, s); } - fn do_inner_(fcx: fn_ctxt, e: @expr) { find_pre_post_expr(fcx, e); } + fn do_inner_(fcx: fn_ctxt, &&e: @expr) { find_pre_post_expr(fcx, e); } let do_inner = bind do_inner_(fcx, _); option::map::<@expr, ()>(do_inner, b.node.expr); diff --git a/src/comp/middle/ty.rs b/src/comp/middle/ty.rs index ec9821d6d26..faf11cb691a 100644 --- a/src/comp/middle/ty.rs +++ b/src/comp/middle/ty.rs @@ -160,6 +160,7 @@ export type_is_native; export type_is_nil; export type_is_pod; export type_is_scalar; +export type_is_immediate; export type_is_sequence; export type_is_signed; export type_is_structural; @@ -916,6 +917,12 @@ pure fn type_is_scalar(cx: ctxt, ty: t) -> bool { } } +// FIXME maybe inline this for speed? +fn type_is_immediate(cx: ctxt, ty: t) -> bool { + ret type_is_scalar(cx, ty) || type_is_boxed(cx, ty) || + type_is_unique_box(cx, ty) || type_is_native(cx, ty); +} + fn type_has_pointers(cx: ctxt, ty: t) -> bool { alt cx.has_pointer_cache.find(ty) { some(result) { ret result; } @@ -924,14 +931,8 @@ fn type_has_pointers(cx: ctxt, ty: t) -> bool { let result = false; alt struct(cx, ty) { - - - // scalar types - ty_nil. { - /* no-op */ - - } + ty_nil. {/* no-op */ } ty_bot. {/* no-op */ } ty_bool. {/* no-op */ } ty_int. {/* no-op */ } @@ -1446,14 +1447,14 @@ fn hash_type_info(st: sty, cname_opt: option::t<str>) -> uint { ret h; } -fn hash_raw_ty(rt: @raw_t) -> uint { ret rt.hash; } +fn hash_raw_ty(&&rt: @raw_t) -> uint { ret rt.hash; } -fn hash_ty(typ: t) -> uint { ret typ; } +fn hash_ty(&&typ: t) -> uint { ret typ; } // Type equality. This function is private to this module (and slow); external // users should use `eq_ty()` instead. -fn eq_int(x: uint, y: uint) -> bool { ret x == y; } +fn eq_int(&&x: uint, &&y: uint) -> bool { ret x == y; } fn arg_eq<T>(eq: fn(T, T) -> bool, a: @sp_constr_arg<T>, b: @sp_constr_arg<T>) -> bool { @@ -1495,7 +1496,7 @@ fn constrs_eq(cs: [@constr], ds: [@constr]) -> bool { // An expensive type equality function. This function is private to this // module. -fn eq_raw_ty(a: @raw_t, b: @raw_t) -> bool { +fn eq_raw_ty(&&a: @raw_t, &&b: @raw_t) -> bool { // Check hashes (fast path). if a.hash != b.hash { ret false; } @@ -1518,7 +1519,7 @@ fn eq_raw_ty(a: @raw_t, b: @raw_t) -> bool { // This is the equality function the public should use. It works as long as // the types are interned. -fn eq_ty(a: t, b: t) -> bool { ret a == b; } +fn eq_ty(&&a: t, &&b: t) -> bool { ret a == b; } // Type lookups @@ -1954,12 +1955,15 @@ mod unify { let actual_input = actual_inputs[i]; // Unify the result modes. - let result_mode; - if expected_input.mode != actual_input.mode { + let result_mode = if expected_input.mode == ast::mode_infer { + actual_input.mode + } else if actual_input.mode == ast::mode_infer { + expected_input.mode + } else if expected_input.mode != actual_input.mode { ret fn_common_res_err (ures_err(terr_mode_mismatch(expected_input.mode, actual_input.mode))); - } else { result_mode = expected_input.mode; } + } else { expected_input.mode }; let result = unify_step(cx, expected_input.ty, actual_input.ty); alt result { ures_ok(rty) { result_ins += [{mode: result_mode, ty: rty}]; } diff --git a/src/comp/middle/typeck.rs b/src/comp/middle/typeck.rs index bdf8b91c8ff..088e6eec6f5 100644 --- a/src/comp/middle/typeck.rs +++ b/src/comp/middle/typeck.rs @@ -224,7 +224,27 @@ fn type_is_scalar(fcx: @fn_ctxt, sp: span, typ: ty::t) -> bool { // Parses the programmer's textual representation of a type into our internal // notion of a type. `getter` is a function that returns the type // corresponding to a definition ID: +fn default_arg_mode_for_ty(tcx: ty::ctxt, m: ast::mode, + ty: ty::t) -> ast::mode { + alt m { + ast::mode_infer. { + alt ty::struct(tcx, ty) { + ty::ty_var(_) { ast::mode_infer } + _ { + if ty::type_is_immediate(tcx, ty) { ast::by_val } + else { ast::by_ref } + } + } + } + _ { m } + } +} fn ast_ty_to_ty(tcx: ty::ctxt, getter: ty_getter, ast_ty: @ast::ty) -> ty::t { + fn ast_arg_to_arg(tcx: ty::ctxt, getter: ty_getter, arg: ast::ty_arg) + -> {mode: ty::mode, ty: ty::t} { + let ty = ast_ty_to_ty(tcx, getter, arg.node.ty); + ret {mode: default_arg_mode_for_ty(tcx, arg.node.mode, ty), ty: ty}; + } alt tcx.ast_ty_to_ty_cache.find(ast_ty) { some(some(ty)) { ret ty; } some(none.) { @@ -237,10 +257,6 @@ fn ast_ty_to_ty(tcx: ty::ctxt, getter: ty_getter, ast_ty: @ast::ty) -> ty::t { } /* go on */ tcx.ast_ty_to_ty_cache.insert(ast_ty, none::<ty::t>); - fn ast_arg_to_arg(tcx: ty::ctxt, getter: ty_getter, arg: ast::ty_arg) -> - {mode: ty::mode, ty: ty::t} { - ret {mode: arg.node.mode, ty: ast_ty_to_ty(tcx, getter, arg.node.ty)}; - } fn ast_mt_to_mt(tcx: ty::ctxt, getter: ty_getter, mt: ast::mt) -> ty::mt { ret {ty: ast_ty_to_ty(tcx, getter, mt.ty), mut: mt.mut}; } @@ -295,7 +311,7 @@ fn ast_ty_to_ty(tcx: ty::ctxt, getter: ty_getter, ast_ty: @ast::ty) -> ty::t { typ = ty::mk_ptr(tcx, ast_mt_to_mt(tcx, getter, mt)); } ast::ty_tup(fields) { - let flds = vec::map(bind ast_ty_to_ty(tcx, getter, _), fields); + let flds = vec::map_imm(bind ast_ty_to_ty(tcx, getter, _), fields); typ = ty::mk_tup(tcx, flds); } ast::ty_rec(fields) { @@ -550,9 +566,8 @@ mod collect { ret tpt; } fn ty_of_arg(cx: @ctxt, a: ast::arg) -> ty::arg { - let f = bind getter(cx, _); - let tt = ast_ty_to_ty(cx.tcx, f, a.ty); - ret {mode: a.mode, ty: tt}; + let ty = ast_ty_to_ty(cx.tcx, bind getter(cx, _), a.ty); + {mode: default_arg_mode_for_ty(cx.tcx, a.mode, ty), ty: ty} } fn ty_of_method(cx: @ctxt, m: @ast::method) -> ty::method { let get = bind getter(cx, _); @@ -1216,7 +1231,7 @@ fn gather_locals(ccx: @crate_ctxt, f: ast::_fn, id: ast::node_id, // Add explicitly-declared locals. let visit_local = - lambda (local: @ast::local, e: (), v: visit::vt<()>) { + lambda (local: @ast::local, &&e: (), v: visit::vt<()>) { let local_ty = ast_ty_to_ty_crate_infer(ccx, local.node.ty); assign(local.node.id, ident_for_local(local), local_ty); visit::visit_local(local, e, v); @@ -1224,7 +1239,7 @@ fn gather_locals(ccx: @crate_ctxt, f: ast::_fn, id: ast::node_id, // Add pattern bindings. let visit_pat = - lambda (p: @ast::pat, e: (), v: visit::vt<()>) { + lambda (p: @ast::pat, &&e: (), v: visit::vt<()>) { alt p.node { ast::pat_bind(ident) { assign(p.id, ident, none); } _ {/* no-op */ } @@ -2022,16 +2037,16 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier, write::ty_only_fixup(fcx, id, result_ty); } ast::expr_fn(f) { - let cx = @{tcx: tcx}; let convert = bind ast_ty_to_ty_crate_tyvar(fcx, _); - let ty_of_arg = - lambda (a: ast::arg) -> ty::arg { - let tt = ast_ty_to_ty_crate_tyvar(fcx, a.ty); - ret {mode: a.mode, ty: tt}; - }; - let fty = - collect::ty_of_fn_decl(cx, convert, ty_of_arg, f.decl, f.proto, - [], none).ty; + let ty_of_arg = lambda (a: ast::arg) -> ty::arg { + let tt = ast_ty_to_ty_crate_tyvar(fcx, a.ty); + ret {mode: default_arg_mode_for_ty(fcx.ccx.tcx, a.mode, tt), + ty: tt}; + }; + let cx = @{tcx: tcx}; + let fty = collect::ty_of_fn_decl(cx, convert, ty_of_arg, f.decl, + f.proto, [], none).ty; + write::ty_only_fixup(fcx, id, fty); // Unify the type of the function with the expected type before we @@ -2041,6 +2056,9 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier, unify(fcx, expr.span, expected, fty); check_fn(fcx.ccx, f, id, some(fcx)); + if f.proto == ast::proto_block { + write::ty_only_fixup(fcx, id, expected); + } } ast::expr_block(b) { // If this is an unchecked block, turn off purity-checking @@ -2301,7 +2319,8 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier, // FIXME: These next three functions are largely ripped off from // similar ones in collect::. Is there a better way to do this? fn ty_of_arg(ccx: @crate_ctxt, a: ast::arg) -> ty::arg { - ret {mode: a.mode, ty: ast_ty_to_ty_crate(ccx, a.ty)}; + let ty = ast_ty_to_ty_crate(ccx, a.ty); + ret {mode: default_arg_mode_for_ty(ccx.tcx, a.mode, ty), ty: ty}; } fn ty_of_method(ccx: @crate_ctxt, m: @ast::method) -> ty::method { |
