rustc: Make function types have vstores in them

This commit is contained in:
Patrick Walton 2012-08-10 16:21:34 -07:00
parent 99942ae430
commit 0101125a96
22 changed files with 237 additions and 114 deletions

View File

@ -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) == '[');

View File

@ -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('[');

View File

@ -14,7 +14,7 @@ fn check_crate(tcx: ty::ctxt, crate: @crate) {
fn visit_expr(ex: @expr, cx: ctx, v: visit::vt<ctx>) {
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");

View File

@ -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 {

View File

@ -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;

View File

@ -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 => {

View File

@ -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"
}
}

View File

@ -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"
}
}

View File

@ -2043,7 +2043,8 @@ fn normalize_for_monomorphization(tcx: ty::ctxt, ty: ty::t) -> option<ty::t> {
}
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 {

View File

@ -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"
};
}

View File

@ -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),

View File

@ -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,

View File

@ -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")
}
}

View File

@ -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, _) |

View File

@ -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;

View File

@ -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,_)) => {

View File

@ -423,7 +423,7 @@ type expected_tys = option<{inputs: ~[ty::arg],
fn ty_of_fn_decl<AC: ast_conv, RS: region_scope copy owned>(
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<AC: ast_conv, RS: region_scope copy owned>(
_ => 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}
}

View File

@ -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});

View File

@ -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,

View File

@ -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,

View File

@ -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<ty::field>;
fn modes(a: ast::mode, b: ast::mode) -> cres<ast::mode>;
fn args(a: ty::arg, b: ty::arg) -> cres<ty::arg>;
fn protos(p1: ast::proto, p2: ast::proto) -> cres<ast::proto>;
fn protos(p1: ty::fn_proto, p2: ty::fn_proto) -> cres<ty::fn_proto>;
fn ret_styles(r1: ret_style, r2: ret_style) -> cres<ret_style>;
fn purities(f1: purity, f2: purity) -> cres<purity>;
fn contraregions(a: ty::region, b: ty::region) -> cres<ty::region>;
@ -1945,7 +1945,7 @@ impl sub: combine {
}
}
fn protos(a: ast::proto, b: ast::proto) -> cres<ast::proto> {
fn protos(a: ty::fn_proto, b: ty::fn_proto) -> cres<ty::fn_proto> {
(&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<ast::proto> {
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<ty::fn_proto> {
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<ast::proto> {
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<ty::fn_proto> {
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)
}
}

View File

@ -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<ast::ident>,
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; }
_ => { }