From 0101125a962abae18525d6014cd26ad10bbb96e6 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Fri, 10 Aug 2012 16:21:34 -0700 Subject: [PATCH] rustc: Make function types have vstores in them --- src/rustc/metadata/tydecode.rs | 14 +++-- src/rustc/metadata/tyencode.rs | 15 +++--- src/rustc/middle/block_use.rs | 2 +- src/rustc/middle/borrowck/check_loans.rs | 5 +- src/rustc/middle/capture.rs | 12 +++-- src/rustc/middle/check_loop.rs | 3 +- src/rustc/middle/kind.rs | 10 ++-- src/rustc/middle/mem_categorization.rs | 8 ++- src/rustc/middle/trans/base.rs | 10 ++-- src/rustc/middle/trans/closure.rs | 33 +++++++----- src/rustc/middle/trans/foreign.rs | 2 +- src/rustc/middle/trans/reflect.rs | 10 ++-- src/rustc/middle/trans/shape.rs | 22 +++++--- src/rustc/middle/trans/type_use.rs | 7 ++- src/rustc/middle/ty.rs | 65 +++++++++++++++++++----- src/rustc/middle/typeck.rs | 2 +- src/rustc/middle/typeck/astconv.rs | 4 +- src/rustc/middle/typeck/check.rs | 49 ++++++++++++++---- src/rustc/middle/typeck/check/method.rs | 6 ++- src/rustc/middle/typeck/collect.rs | 7 +-- src/rustc/middle/typeck/infer.rs | 53 +++++++++++-------- src/rustc/util/ppaux.rs | 12 ++++- 22 files changed, 237 insertions(+), 114 deletions(-) diff --git a/src/rustc/metadata/tydecode.rs b/src/rustc/metadata/tydecode.rs index e66d0cef71ba..80c64430ec37 100644 --- a/src/rustc/metadata/tydecode.rs +++ b/src/rustc/metadata/tydecode.rs @@ -85,13 +85,11 @@ fn parse_ty_rust_fn(st: @pstate, conv: conv_did) -> ty::t { return ty::mk_fn(st.tcx, parse_ty_fn(st, conv)); } -fn parse_proto(c: char) -> ast::proto { - match c { - '~' => ast::proto_uniq, - '@' => ast::proto_box, - '&' => ast::proto_block, - 'n' => ast::proto_bare, - _ => fail ~"illegal fn type kind " + str::from_char(c) +fn parse_proto(st: @pstate) -> ty::fn_proto { + match next(st) { + 'n' => ty::proto_bare, + 'v' => ty::proto_vstore(parse_vstore(st)), + c => fail ~"illegal proto type kind " + str::from_char(c) } } @@ -360,7 +358,7 @@ fn parse_purity(c: char) -> purity { } fn parse_ty_fn(st: @pstate, conv: conv_did) -> ty::fn_ty { - let proto = parse_proto(next(st)); + let proto = parse_proto(st); let purity = parse_purity(next(st)); let bounds = parse_bounds(st, conv); assert (next(st) == '['); diff --git a/src/rustc/metadata/tyencode.rs b/src/rustc/metadata/tyencode.rs index 9e67157b1811..30b2a21167ab 100644 --- a/src/rustc/metadata/tyencode.rs +++ b/src/rustc/metadata/tyencode.rs @@ -306,12 +306,15 @@ fn enc_sty(w: io::writer, cx: @ctxt, st: ty::sty) { } } } -fn enc_proto(w: io::writer, proto: proto) { + +fn enc_proto(w: io::writer, cx: @ctxt, proto: ty::fn_proto) { + w.write_str(&"f"); match proto { - proto_uniq => w.write_str(&"f~"), - proto_box => w.write_str(&"f@"), - proto_block => w.write_str(~"f&"), - proto_bare => w.write_str(&"fn") + ty::proto_bare => w.write_str(&"n"), + ty::proto_vstore(vstore) => { + w.write_str(&"v"); + enc_vstore(w, cx, vstore); + } } } @@ -335,7 +338,7 @@ fn enc_purity(w: io::writer, p: purity) { } fn enc_ty_fn(w: io::writer, cx: @ctxt, ft: ty::fn_ty) { - enc_proto(w, ft.proto); + enc_proto(w, cx, ft.proto); enc_purity(w, ft.purity); enc_bounds(w, cx, ft.bounds); w.write_char('['); diff --git a/src/rustc/middle/block_use.rs b/src/rustc/middle/block_use.rs index 2896ad32d6ae..bb33b8c92a89 100644 --- a/src/rustc/middle/block_use.rs +++ b/src/rustc/middle/block_use.rs @@ -14,7 +14,7 @@ fn check_crate(tcx: ty::ctxt, crate: @crate) { fn visit_expr(ex: @expr, cx: ctx, v: visit::vt) { if !cx.allow_block { match ty::get(ty::expr_ty(cx.tcx, ex)).struct { - ty::ty_fn({proto: p, _}) if is_blockish(p) => { + ty::ty_fn({proto: p, _}) if ty::is_blockish(p) => { cx.tcx.sess.span_err(ex.span, ~"expressions with stack closure type \ can only appear in callee or (by-ref) argument position"); diff --git a/src/rustc/middle/borrowck/check_loans.rs b/src/rustc/middle/borrowck/check_loans.rs index 301c78aa1094..4c3ee9eb4dd1 100644 --- a/src/rustc/middle/borrowck/check_loans.rs +++ b/src/rustc/middle/borrowck/check_loans.rs @@ -218,10 +218,7 @@ impl check_loan_ctxt { fn is_stack_closure(id: ast::node_id) -> bool { let fn_ty = ty::node_id_to_type(self.tcx(), id); let proto = ty::ty_fn_proto(fn_ty); - match proto { - ast::proto_block => true, - ast::proto_bare | ast::proto_uniq | ast::proto_box => false - } + return ty::is_blockish(proto); } fn is_allowed_pure_arg(expr: @ast::expr) -> bool { diff --git a/src/rustc/middle/capture.rs b/src/rustc/middle/capture.rs index 266c31b2805d..b45064db88d3 100644 --- a/src/rustc/middle/capture.rs +++ b/src/rustc/middle/capture.rs @@ -59,7 +59,7 @@ fn check_capture_clause(tcx: ty::ctxt, fn compute_capture_vars(tcx: ty::ctxt, fn_expr_id: ast::node_id, - fn_proto: ast::proto, + fn_proto: ty::fn_proto, cap_clause: ast::capture_clause) -> ~[capture_var] { let freevars = freevars::get_freevars(tcx, fn_expr_id); let cap_map = map::int_hash(); @@ -101,10 +101,12 @@ fn compute_capture_vars(tcx: ty::ctxt, // now go through anything that is referenced but was not explicitly // named and add that - let implicit_mode = match fn_proto { - ast::proto_block => cap_ref, - ast::proto_bare | ast::proto_box | ast::proto_uniq => cap_copy - }; + let implicit_mode; + if ty::is_blockish(fn_proto) { + implicit_mode = cap_ref; + } else { + implicit_mode = cap_copy; + } do vec::iter(*freevars) |fvar| { let fvar_def_id = ast_util::def_id_of_def(fvar.def).node; diff --git a/src/rustc/middle/check_loop.rs b/src/rustc/middle/check_loop.rs index dad51ed48b4b..a105ce685290 100644 --- a/src/rustc/middle/check_loop.rs +++ b/src/rustc/middle/check_loop.rs @@ -25,7 +25,8 @@ fn check_crate(tcx: ty::ctxt, crate: @crate) { v.visit_block(b, {in_loop: false, can_ret: false}, v); } expr_loop_body(@{node: expr_fn_block(_, b, _), _}) => { - let blk = is_blockish(ty::ty_fn_proto(ty::expr_ty(tcx, e))); + let blk = ty::is_blockish(ty::ty_fn_proto(ty::expr_ty(tcx, + e))); v.visit_block(b, {in_loop: true, can_ret: blk}, v); } expr_break => { diff --git a/src/rustc/middle/kind.rs b/src/rustc/middle/kind.rs index 61d9938e3882..9968318292c6 100644 --- a/src/rustc/middle/kind.rs +++ b/src/rustc/middle/kind.rs @@ -144,10 +144,12 @@ fn with_appropriate_checker(cx: ctx, id: node_id, b: fn(check_fn)) { let fty = ty::node_id_to_type(cx.tcx, id); match ty::ty_fn_proto(fty) { - proto_uniq => b(check_for_uniq), - proto_box => b(check_for_box), - proto_bare => b(check_for_bare), - proto_block => b(check_for_block) + ty::proto_vstore(ty::vstore_uniq) => b(check_for_uniq), + ty::proto_vstore(ty::vstore_box) => b(check_for_box), + ty::proto_bare => b(check_for_bare), + ty::proto_vstore(ty::vstore_slice(_)) => b(check_for_block), + ty::proto_vstore(ty::vstore_fixed(_)) => + fail ~"fixed vstore not allowed here" } } diff --git a/src/rustc/middle/mem_categorization.rs b/src/rustc/middle/mem_categorization.rs index d600f63246a9..cf9ee1bc190e 100644 --- a/src/rustc/middle/mem_categorization.rs +++ b/src/rustc/middle/mem_categorization.rs @@ -383,18 +383,22 @@ impl &mem_categorization_ctxt { let ty = ty::node_id_to_type(self.tcx, fn_node_id); let proto = ty::ty_fn_proto(ty); match proto { - ast::proto_block => { + ty::proto_vstore(ty::vstore_slice(_)) => { let upcmt = self.cat_def(id, span, expr_ty, *inner); @{id:id, span:span, cat:cat_stack_upvar(upcmt), lp:upcmt.lp, mutbl:upcmt.mutbl, ty:upcmt.ty} } - ast::proto_bare | ast::proto_uniq | ast::proto_box => { + ty::proto_bare | + ty::proto_vstore(ty::vstore_uniq) | + ty::proto_vstore(ty::vstore_box) => { // FIXME #2152 allow mutation of moved upvars @{id:id, span:span, cat:cat_special(sk_heap_upvar), lp:none, mutbl:m_imm, ty:expr_ty} } + ty::proto_vstore(ty::vstore_fixed(_)) => + fail ~"fixed vstore not allowed here" } } diff --git a/src/rustc/middle/trans/base.rs b/src/rustc/middle/trans/base.rs index 9054b5a46110..0c7d04d143eb 100644 --- a/src/rustc/middle/trans/base.rs +++ b/src/rustc/middle/trans/base.rs @@ -2043,7 +2043,8 @@ fn normalize_for_monomorphization(tcx: ty::ctxt, ty: ty::t) -> option { } ty::ty_trait(_, _) => { some(ty::mk_fn(tcx, {purity: ast::impure_fn, - proto: ast::proto_box, + proto: ty::proto_vstore(ty::vstore_slice + (ty::re_static)), bounds: @~[], inputs: ~[], output: ty::mk_nil(tcx), @@ -3774,8 +3775,11 @@ fn trans_expr(bcx: block, e: @ast::expr, dest: dest) -> block { } ast::expr_addr_of(_, x) => { return trans_addr_of(bcx, x, dest); } ast::expr_fn(proto, decl, body, cap_clause) => { - return closure::trans_expr_fn(bcx, proto, decl, body, e.id, - cap_clause, none, dest); + // XXX: This syntax should be reworked a bit (in the parser I + // guess?); @fn() { ... } won't work. + return closure::trans_expr_fn(bcx, ty::ast_proto_to_proto(proto), + decl, body, e.id, cap_clause, none, + dest); } ast::expr_fn_block(decl, body, cap_clause) => { match check ty::get(expr_ty(bcx, e)).struct { diff --git a/src/rustc/middle/trans/closure.rs b/src/rustc/middle/trans/closure.rs index 80fde9955d0b..997991a5aa28 100644 --- a/src/rustc/middle/trans/closure.rs +++ b/src/rustc/middle/trans/closure.rs @@ -347,7 +347,7 @@ fn load_environment(fcx: fn_ctxt, } fn trans_expr_fn(bcx: block, - proto: ast::proto, + proto: ty::fn_proto, decl: ast::fn_decl, body: ast::blk, id: ast::node_id, @@ -364,8 +364,8 @@ fn trans_expr_fn(bcx: block, let llfn = decl_internal_cdecl_fn(ccx.llmod, s, llfnty); let trans_closure_env = fn@(ck: ty::closure_kind) -> result { - let cap_vars = capture::compute_capture_vars( - ccx.tcx, id, proto, cap_clause); + let cap_vars = capture::compute_capture_vars(ccx.tcx, id, proto, + cap_clause); let ret_handle = match is_loop_body { some(x) => x, none => none }; let {llbox, cdata_ty, bcx} = build_closure(bcx, cap_vars, ck, id, ret_handle); @@ -382,14 +382,19 @@ fn trans_expr_fn(bcx: block, }; let {bcx: bcx, val: closure} = match proto { - ast::proto_block => trans_closure_env(ty::ck_block), - ast::proto_box => trans_closure_env(ty::ck_box), - ast::proto_uniq => trans_closure_env(ty::ck_uniq), - ast::proto_bare => { + ty::proto_vstore(ty::vstore_slice(_)) => + trans_closure_env(ty::ck_block), + ty::proto_vstore(ty::vstore_box) => + trans_closure_env(ty::ck_box), + ty::proto_vstore(ty::vstore_uniq) => + trans_closure_env(ty::ck_uniq), + ty::proto_bare => { trans_closure(ccx, sub_path, decl, body, llfn, no_self, none, id, |_fcx| { }, |_bcx| { }); {bcx: bcx, val: C_null(T_opaque_box_ptr(ccx))} } + ty::proto_vstore(ty::vstore_fixed(_)) => + fail ~"vstore_fixed unexpected" }; fill_fn_pair(bcx, get_dest_addr(dest), llfn, closure); @@ -416,11 +421,15 @@ fn make_fn_glue( }; return match ty::get(t).struct { - ty::ty_fn({proto: ast::proto_bare, _}) | - ty::ty_fn({proto: ast::proto_block, _}) => bcx, - ty::ty_fn({proto: ast::proto_uniq, _}) => fn_env(ty::ck_uniq), - ty::ty_fn({proto: ast::proto_box, _}) => fn_env(ty::ck_box), - _ => fail ~"make_fn_glue invoked on non-function type" + ty::ty_fn({proto: ty::proto_bare, _}) | + ty::ty_fn({proto: ty::proto_vstore(ty::vstore_slice(_)), _}) => + bcx, + ty::ty_fn({proto: ty::proto_vstore(ty::vstore_uniq), _}) => + fn_env(ty::ck_uniq), + ty::ty_fn({proto: ty::proto_vstore(ty::vstore_box), _}) => + fn_env(ty::ck_box), + _ => + fail ~"make_fn_glue invoked on non-function type" }; } diff --git a/src/rustc/middle/trans/foreign.rs b/src/rustc/middle/trans/foreign.rs index 3eac4a7e663f..a81e665356fc 100644 --- a/src/rustc/middle/trans/foreign.rs +++ b/src/rustc/middle/trans/foreign.rs @@ -960,7 +960,7 @@ fn trans_intrinsic(ccx: @crate_ctxt, decl: ValueRef, item: @ast::foreign_item, let frameaddress_val = Call(bcx, frameaddress, ~[C_i32(0i32)]); let fty = ty::mk_fn(bcx.tcx(), { purity: ast::impure_fn, - proto: ast::proto_block, + proto: ty::proto_vstore(ty::vstore_slice(ty::re_static)), bounds: @~[], inputs: ~[{ mode: ast::expl(ast::by_val), diff --git a/src/rustc/middle/trans/reflect.rs b/src/rustc/middle/trans/reflect.rs index ae93021583bc..7f8752c84d49 100644 --- a/src/rustc/middle/trans/reflect.rs +++ b/src/rustc/middle/trans/reflect.rs @@ -185,10 +185,12 @@ impl reflector { ast::extern_fn => 3u }; let protoval = match fty.proto { - ast::proto_bare => 0u, - ast::proto_uniq => 2u, - ast::proto_box => 3u, - ast::proto_block => 4u + ty::proto_bare => 0u, + ty::proto_vstore(ty::vstore_uniq) => 2u, + ty::proto_vstore(ty::vstore_box) => 3u, + ty::proto_vstore(ty::vstore_slice(_)) => 4u, + ty::proto_vstore(ty::vstore_fixed(_)) => + fail ~"fixed unexpected" }; let retval = match fty.ret_style { ast::noreturn => 0u, diff --git a/src/rustc/middle/trans/shape.rs b/src/rustc/middle/trans/shape.rs index 4246defbe0f7..68bddb8d151e 100644 --- a/src/rustc/middle/trans/shape.rs +++ b/src/rustc/middle/trans/shape.rs @@ -351,14 +351,20 @@ fn shape_of(ccx: @crate_ctxt, t: ty::t) -> ~[u8] { ty::ty_param(*) => { ccx.tcx.sess.bug(~"non-monomorphized type parameter"); } - ty::ty_fn({proto: ast::proto_box, _}) => ~[shape_box_fn], - ty::ty_fn({proto: ast::proto_uniq, _}) => ~[shape_uniq_fn], - ty::ty_fn({proto: ast::proto_block, _}) => ~[shape_stack_fn], - ty::ty_fn({proto: ast::proto_bare, _}) => ~[shape_bare_fn], - ty::ty_opaque_closure_ptr(_) => ~[shape_opaque_closure_ptr], - ty::ty_var(_) | ty::ty_var_integral(_) | ty::ty_self => { - ccx.sess.bug(~"shape_of: unexpected type struct found"); - } + ty::ty_fn({proto: ty::proto_vstore(ty::vstore_box), _}) => + ~[shape_box_fn], + ty::ty_fn({proto: ty::proto_vstore(ty::vstore_uniq), _}) => + ~[shape_uniq_fn], + ty::ty_fn({proto: ty::proto_vstore(ty::vstore_slice(_)), _}) => + ~[shape_stack_fn], + ty::ty_fn({proto: ty::proto_vstore(ty::vstore_fixed(_)), _}) => + fail ~"fixed vstore is impossible", + ty::ty_fn({proto: ty::proto_bare, _}) => + ~[shape_bare_fn], + ty::ty_opaque_closure_ptr(_) => + ~[shape_opaque_closure_ptr], + ty::ty_var(_) | ty::ty_var_integral(_) | ty::ty_self => + ccx.sess.bug(~"shape_of: unexpected type struct found") } } diff --git a/src/rustc/middle/trans/type_use.rs b/src/rustc/middle/trans/type_use.rs index c21ad7c992b6..d630653ef272 100644 --- a/src/rustc/middle/trans/type_use.rs +++ b/src/rustc/middle/trans/type_use.rs @@ -202,13 +202,16 @@ fn mark_for_expr(cx: ctx, e: @expr) { } expr_fn(*) | expr_fn_block(*) => { match ty::ty_fn_proto(ty::expr_ty(cx.ccx.tcx, e)) { - proto_bare | proto_uniq => {} - proto_box | proto_block => { + ty::proto_bare | ty::proto_vstore(ty::vstore_uniq) => {} + ty::proto_vstore(ty::vstore_box) | + ty::proto_vstore(ty::vstore_slice(_)) => { for vec::each(*freevars::get_freevars(cx.ccx.tcx, e.id)) |fv| { let node_id = ast_util::def_id_of_def(fv.def).node; node_type_needs(cx, use_repr, node_id); } } + ty::proto_vstore(ty::vstore_fixed(_)) => + fail ~"vstore_fixed not allowed here" } } expr_assign(val, _) | expr_swap(val, _) | expr_assign_op(_, val, _) | diff --git a/src/rustc/middle/ty.rs b/src/rustc/middle/ty.rs index 90ea9b3a6b14..b74dad6cda92 100644 --- a/src/rustc/middle/ty.rs +++ b/src/rustc/middle/ty.rs @@ -171,9 +171,13 @@ export terr_sorts, terr_vec, terr_str, terr_record_size, terr_tuple_size; export terr_regions_differ, terr_mutability, terr_purity_mismatch; export terr_proto_mismatch; export terr_ret_style_mismatch; +export terr_fn; export purity_to_str; export param_tys_in_type; export eval_repeat_count; +export fn_proto, proto_bare, proto_vstore; +export ast_proto_to_proto; +export is_blockish; // Data types @@ -316,6 +320,11 @@ enum closure_kind { ck_uniq, } +enum fn_proto { + proto_bare, // supertype of all other protocols + proto_vstore(vstore) +} + /// Innards of a function type: /// /// - `purity` is the function's effect (pure, impure, unsafe). @@ -325,7 +334,7 @@ enum closure_kind { /// - `output` is the return type. /// - `ret_style` indicates whether the function returns a value or fails. type fn_ty = {purity: ast::purity, - proto: ast::proto, + proto: fn_proto, bounds: @~[param_bound], inputs: ~[arg], output: t, @@ -442,7 +451,7 @@ enum sty { } enum terr_vstore_kind { - terr_vec, terr_str + terr_vec, terr_str, terr_fn } // Data structures used in type unification @@ -451,7 +460,7 @@ enum type_err { terr_ret_style_mismatch(ast::ret_style, ast::ret_style), terr_purity_mismatch(purity, purity), terr_mutability, - terr_proto_mismatch(ast::proto, ast::proto), + terr_proto_mismatch(ty::fn_proto, ty::fn_proto), terr_box_mutability, terr_ptr_mutability, terr_ref_mutability, @@ -1308,7 +1317,7 @@ fn type_needs_drop(cx: ctxt, ty: t) -> bool { } ty_fn(ref fty) => { match fty.proto { - proto_bare | proto_block => false, + proto_bare | proto_vstore(vstore_slice(_)) => false, _ => true } } @@ -1548,13 +1557,18 @@ pure fn kind_is_owned(k: kind) -> bool { *k & KIND_MASK_OWNED == KIND_MASK_OWNED } -fn proto_kind(p: proto) -> kind { +fn proto_kind(p: fn_proto) -> kind { match p { - ast::proto_block => kind_noncopyable() | kind_(KIND_MASK_DEFAULT_MODE), - ast::proto_box => kind_safe_for_default_mode() | kind_owned(), - ast::proto_uniq => kind_send_copy() | kind_owned(), - ast::proto_bare => kind_safe_for_default_mode_send() | kind_const() | - kind_owned() + proto_vstore(vstore_slice(_)) => + kind_noncopyable() | kind_(KIND_MASK_DEFAULT_MODE), + proto_vstore(vstore_box) => + kind_safe_for_default_mode() | kind_owned(), + proto_vstore(vstore_uniq) => + kind_send_copy() | kind_owned(), + proto_vstore(vstore_fixed(_)) => + fail ~"fixed vstore protos are not allowed", + proto_bare => + kind_safe_for_default_mode_send() | kind_const() | kind_owned() } } @@ -2293,7 +2307,7 @@ fn ty_fn_args(fty: t) -> ~[arg] { } } -fn ty_fn_proto(fty: t) -> ast::proto { +fn ty_fn_proto(fty: t) -> fn_proto { match get(fty).struct { ty_fn(ref f) => f.proto, _ => fail ~"ty_fn_proto() called on non-fn type" @@ -2576,7 +2590,11 @@ fn ty_sort_str(cx: ctxt, t: t) -> ~str { fn type_err_to_str(cx: ctxt, err: &type_err) -> ~str { fn terr_vstore_kind_to_str(k: terr_vstore_kind) -> ~str { - match k { terr_vec => ~"[]", terr_str => ~"str" } + match k { + terr_vec => ~"[]", + terr_str => ~"str", + terr_fn => ~"fn" + } } match *err { @@ -2597,7 +2615,8 @@ fn type_err_to_str(cx: ctxt, err: &type_err) -> ~str { } terr_proto_mismatch(e, a) => { return fmt!{"closure protocol mismatch (%s vs %s)", - proto_to_str(e), proto_to_str(a)}; + util::ppaux::proto_ty_to_str(cx, e), + util::ppaux::proto_ty_to_str(cx, a)}; } terr_mutability => return ~"values differ in mutability", terr_box_mutability => return ~"boxed values differ in mutability", @@ -3254,6 +3273,26 @@ fn eval_repeat_count(tcx: ctxt, count_expr: @ast::expr, span: span) -> uint { } } +fn ast_proto_to_proto(ast_proto: ast::proto) -> ty::fn_proto { + match ast_proto { + ast::proto_bare => ty::proto_bare, + ast::proto_uniq => ty::proto_vstore(ty::vstore_uniq), + ast::proto_box => ty::proto_vstore(ty::vstore_box), + ast::proto_block => ty::proto_vstore(ty::vstore_slice(ty::re_static)) + } +} + +pure fn is_blockish(proto: fn_proto) -> bool { + match proto { + proto_vstore(vstore_slice(_)) => + true, + proto_vstore(vstore_box) | proto_vstore(vstore_uniq) | proto_bare => + false, + proto_vstore(vstore_fixed(_)) => + fail ~"fixed vstore not allowed here" + } +} + // Local Variables: // mode: rust // fill-column: 78; diff --git a/src/rustc/middle/typeck.rs b/src/rustc/middle/typeck.rs index 35ef1d5406e4..88469c33516e 100644 --- a/src/rustc/middle/typeck.rs +++ b/src/rustc/middle/typeck.rs @@ -251,7 +251,7 @@ fn check_main_fn_ty(ccx: @crate_ctxt, let tcx = ccx.tcx; let main_t = ty::node_id_to_type(tcx, main_id); match ty::get(main_t).struct { - ty::ty_fn({purity: ast::impure_fn, proto: ast::proto_bare, bounds, + ty::ty_fn({purity: ast::impure_fn, proto: ty::proto_bare, bounds, inputs, output, ret_style: ast::return_val}) => { match tcx.items.find(main_id) { some(ast_map::node_item(it,_)) => { diff --git a/src/rustc/middle/typeck/astconv.rs b/src/rustc/middle/typeck/astconv.rs index 124c5154a464..c6ede5bf8177 100644 --- a/src/rustc/middle/typeck/astconv.rs +++ b/src/rustc/middle/typeck/astconv.rs @@ -423,7 +423,7 @@ type expected_tys = option<{inputs: ~[ty::arg], fn ty_of_fn_decl( self: AC, rscope: RS, - proto: ast::proto, + ast_proto: ast::proto, bounds: @~[ty::param_bound], decl: ast::fn_decl, expected_tys: expected_tys) -> ty::fn_ty { @@ -450,6 +450,8 @@ fn ty_of_fn_decl( _ => ast_ty_to_ty(self, rb, decl.output) }; + let proto = ty::ast_proto_to_proto(ast_proto); + {purity: decl.purity, proto: proto, bounds: bounds, inputs: input_tys, output: output_ty, ret_style: decl.cf} } diff --git a/src/rustc/middle/typeck/check.rs b/src/rustc/middle/typeck/check.rs index 8dea6d6cfba4..3bb2d0974ec3 100644 --- a/src/rustc/middle/typeck/check.rs +++ b/src/rustc/middle/typeck/check.rs @@ -1116,9 +1116,14 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, } } + enum fn_or_ast_proto { + foap_fn_proto(ty::fn_proto), + foap_ast_proto(ast::proto) + } + fn check_expr_fn(fcx: @fn_ctxt, expr: @ast::expr, - proto: ast::proto, + fn_or_ast_proto: fn_or_ast_proto, decl: ast::fn_decl, body: ast::blk, is_loop_body: bool, @@ -1143,9 +1148,29 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, } }; + let ast_proto; + match fn_or_ast_proto { + foap_fn_proto(fn_proto) => { + // Generate a fake AST prototype. We'll fill in the type with + // the real one later. + // XXX: This is a hack. + ast_proto = ast::proto_box; + } + foap_ast_proto(existing_ast_proto) => { + ast_proto = existing_ast_proto; + } + } + // construct the function type - let fn_ty = astconv::ty_of_fn_decl(fcx, fcx, proto, @~[], - decl, expected_tys); + let mut fn_ty = astconv::ty_of_fn_decl(fcx, fcx, ast_proto, @~[], + decl, expected_tys); + + // Patch up the function declaration, if necessary. + match fn_or_ast_proto { + foap_fn_proto(fn_proto) => fn_ty.proto = fn_proto, + foap_ast_proto(_) => {} + } + let fty = ty::mk_fn(tcx, fn_ty); debug!{"check_expr_fn_with_unifier %s fty=%s", @@ -1485,15 +1510,17 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, bot = alt::check_alt(fcx, expr, discrim, arms); } ast::expr_fn(proto, decl, body, cap_clause) => { - check_expr_fn(fcx, expr, proto, decl, body, false, expected); + check_expr_fn(fcx, expr, foap_ast_proto(proto), decl, body, false, + expected); capture::check_capture_clause(tcx, expr.id, cap_clause); } ast::expr_fn_block(decl, body, cap_clause) => { // Take the prototype from the expected type, but default to block: let proto = unpack_expected(fcx, expected, |sty| match sty { ty::ty_fn({proto, _}) => some(proto), _ => none } - ).get_default(ast::proto_box); - check_expr_fn(fcx, expr, proto, decl, body, false, expected); + ).get_default(ty::proto_vstore(ty::vstore_box)); + check_expr_fn(fcx, expr, foap_fn_proto(proto), decl, body, false, + expected); capture::check_capture_clause(tcx, expr.id, cap_clause); } ast::expr_loop_body(b) => { @@ -1525,7 +1552,8 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, }; match check b.node { ast::expr_fn_block(decl, body, cap_clause) => { - check_expr_fn(fcx, b, proto, decl, body, true, some(inner_ty)); + check_expr_fn(fcx, b, foap_fn_proto(proto), decl, body, true, + some(inner_ty)); demand::suptype(fcx, b.span, inner_ty, fcx.expr_ty(b)); capture::check_capture_clause(tcx, b.id, cap_clause); } @@ -1553,7 +1581,8 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, }; match check b.node { ast::expr_fn_block(decl, body, cap_clause) => { - check_expr_fn(fcx, b, proto, decl, body, true, some(inner_ty)); + check_expr_fn(fcx, b, foap_fn_proto(proto), decl, body, true, + some(inner_ty)); demand::suptype(fcx, b.span, inner_ty, fcx.expr_ty(b)); capture::check_capture_clause(tcx, b.id, cap_clause); } @@ -2438,7 +2467,7 @@ fn check_intrinsic_type(ccx: @crate_ctxt, it: @ast::foreign_item) { ~"frame_address" => { let fty = ty::mk_fn(ccx.tcx, { purity: ast::impure_fn, - proto: ast::proto_block, + proto: ty::proto_vstore(ty::vstore_slice(ty::re_static)), bounds: @~[], inputs: ~[{ mode: ast::expl(ast::by_val), @@ -2458,7 +2487,7 @@ fn check_intrinsic_type(ccx: @crate_ctxt, it: @ast::foreign_item) { } }; let fty = ty::mk_fn(tcx, {purity: ast::impure_fn, - proto: ast::proto_bare, + proto: ty::proto_bare, bounds: @~[], inputs: inputs, output: output, ret_style: ast::return_val}); diff --git a/src/rustc/middle/typeck/check/method.rs b/src/rustc/middle/typeck/check/method.rs index 3091e28d556b..274eab9242e5 100644 --- a/src/rustc/middle/typeck/check/method.rs +++ b/src/rustc/middle/typeck/check/method.rs @@ -334,7 +334,8 @@ class lookup { fn ty_from_did(did: ast::def_id) -> ty::t { match check ty::get(ty::lookup_item_type(self.tcx(), did).ty).struct { ty::ty_fn(fty) => { - ty::mk_fn(self.tcx(), {proto: ast::proto_box with fty}) + ty::mk_fn(self.tcx(), + {proto: ty::proto_vstore(ty::vstore_box) with fty}) } } /* @@ -416,7 +417,8 @@ class lookup { // a bit hokey, but the method unbound has a bare protocol, whereas // a.b has a protocol like fn@() (perhaps eventually fn&()): - let fty = ty::mk_fn(tcx, {proto: ast::proto_box with m.fty}); + let fty = ty::mk_fn(tcx, {proto: ty::proto_vstore(ty::vstore_box) + with m.fty}); self.candidates.push( {self_ty: self.self_ty, diff --git a/src/rustc/middle/typeck/collect.rs b/src/rustc/middle/typeck/collect.rs index 477ea6d0e344..0eaa435e32d7 100644 --- a/src/rustc/middle/typeck/collect.rs +++ b/src/rustc/middle/typeck/collect.rs @@ -126,7 +126,8 @@ fn get_enum_variant_types(ccx: @crate_ctxt, }); result_ty = some(ty::mk_fn(tcx, {purity: ast::pure_fn, - proto: ast::proto_box, + proto: ty::proto_vstore + (ty::vstore_box), bounds: @~[], inputs: args, output: enum_ty, @@ -474,7 +475,7 @@ fn convert_struct(ccx: @crate_ctxt, rp: bool, struct_def: @ast::struct_def, tps: ty::ty_params_to_tys(tcx, tps)}); let t_ctor = ty::mk_fn( tcx, {purity: ast::impure_fn, - proto: ast::proto_block, + proto: ty::proto_vstore(ty::vstore_slice(ty::re_static)), bounds: @~[], inputs: t_args, output: t_res, @@ -726,7 +727,7 @@ fn ty_of_foreign_fn_decl(ccx: @crate_ctxt, let output_ty = ast_ty_to_ty(ccx, rb, decl.output); let t_fn = ty::mk_fn(ccx.tcx, {purity: decl.purity, - proto: ast::proto_bare, + proto: ty::proto_bare, bounds: @~[], inputs: input_tys, output: output_ty, diff --git a/src/rustc/middle/typeck/infer.rs b/src/rustc/middle/typeck/infer.rs index 38913a5b6053..13735e2f6d04 100644 --- a/src/rustc/middle/typeck/infer.rs +++ b/src/rustc/middle/typeck/infer.rs @@ -172,7 +172,7 @@ import std::smallintmap::smallintmap; import std::map::hashmap; import middle::ty; import middle::ty::{tv_vid, tvi_vid, region_vid, vid, - ty_int, ty_uint, get}; + ty_int, ty_uint, get, terr_fn}; import syntax::{ast, ast_util}; import syntax::ast::{ret_style, purity}; import util::ppaux::{ty_to_str, mt_to_str}; @@ -1552,7 +1552,7 @@ trait combine { fn flds(a: ty::field, b: ty::field) -> cres; fn modes(a: ast::mode, b: ast::mode) -> cres; fn args(a: ty::arg, b: ty::arg) -> cres; - fn protos(p1: ast::proto, p2: ast::proto) -> cres; + fn protos(p1: ty::fn_proto, p2: ty::fn_proto) -> cres; fn ret_styles(r1: ret_style, r2: ret_style) -> cres; fn purities(f1: purity, f2: purity) -> cres; fn contraregions(a: ty::region, b: ty::region) -> cres; @@ -1945,7 +1945,7 @@ impl sub: combine { } } - fn protos(a: ast::proto, b: ast::proto) -> cres { + fn protos(a: ty::fn_proto, b: ty::fn_proto) -> cres { (&self.lub()).protos(a, b).compare(b, || { ty::terr_proto_mismatch(b, a) }) @@ -2103,15 +2103,20 @@ impl lub: combine { glb(self.infcx()).tys(a, b) } - fn protos(p1: ast::proto, p2: ast::proto) -> cres { - if p1 == ast::proto_bare { - ok(p2) - } else if p2 == ast::proto_bare { - ok(p1) - } else if p1 == p2 { - ok(p1) - } else { - ok(ast::proto_block) + fn protos(p1: ty::fn_proto, p2: ty::fn_proto) -> cres { + match (p1, p2) { + (ty::proto_bare, _) => ok(p2), + (_, ty::proto_bare) => ok(p1), + (ty::proto_vstore(v1), ty::proto_vstore(v2)) => { + self.infcx().try(|| { + do self.vstores(terr_fn, v1, v2).chain |vs| { + ok(ty::proto_vstore(vs)) + } + }).chain_err(|_err| { + // XXX: Totally unsound, but fixed up later. + ok(ty::proto_vstore(ty::vstore_slice(ty::re_static))) + }) + } } } @@ -2300,15 +2305,21 @@ impl glb: combine { lub(self.infcx()).tys(a, b) } - fn protos(p1: ast::proto, p2: ast::proto) -> cres { - if p1 == ast::proto_block { - ok(p2) - } else if p2 == ast::proto_block { - ok(p1) - } else if p1 == p2 { - ok(p1) - } else { - ok(ast::proto_bare) + fn protos(p1: ty::fn_proto, p2: ty::fn_proto) -> cres { + match (p1, p2) { + (ty::proto_vstore(ty::vstore_slice(_)), _) => ok(p2), + (_, ty::proto_vstore(ty::vstore_slice(_))) => ok(p1), + (ty::proto_vstore(v1), ty::proto_vstore(v2)) => { + self.infcx().try(|| { + do self.vstores(terr_fn, v1, v2).chain |vs| { + ok(ty::proto_vstore(vs)) + } + }).chain_err(|_err| { + // XXX: Totally unsound, but fixed up later. + ok(ty::proto_bare) + }) + } + _ => ok(ty::proto_bare) } } diff --git a/src/rustc/util/ppaux.rs b/src/rustc/util/ppaux.rs index b64c72321373..c43a76d6a423 100644 --- a/src/rustc/util/ppaux.rs +++ b/src/rustc/util/ppaux.rs @@ -188,6 +188,13 @@ fn vstore_ty_to_str(cx: ctxt, ty: ~str, vs: ty::vstore) -> ~str { } } +fn proto_ty_to_str(cx: ctxt, proto: ty::fn_proto) -> ~str { + match proto { + ty::proto_bare => ~"", + ty::proto_vstore(vstore) => vstore_to_str(cx, vstore) + } +} + fn tys_to_str(cx: ctxt, ts: ~[t]) -> ~str { let mut rs = ~""; for ts.each |t| { rs += ty_to_str(cx, t); } @@ -211,7 +218,7 @@ fn ty_to_str(cx: ctxt, typ: t) -> ~str { }; modestr + ty_to_str(cx, ty) } - fn fn_to_str(cx: ctxt, purity: ast::purity, proto: ast::proto, + fn fn_to_str(cx: ctxt, purity: ast::purity, proto: ty::fn_proto, ident: option, inputs: ~[arg], output: t, cf: ast::ret_style) -> ~str { let mut s; @@ -220,7 +227,8 @@ fn ty_to_str(cx: ctxt, typ: t) -> ~str { ast::impure_fn => ~"", _ => purity_to_str(purity) + ~" " }; - s += proto_to_str(proto); + + s += proto_ty_to_str(cx, proto); match ident { some(i) => { s += ~" "; s += *i; } _ => { }