rustc: Make function types have vstores in them
This commit is contained in:
parent
99942ae430
commit
0101125a96
@ -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) == '[');
|
||||
|
@ -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('[');
|
||||
|
@ -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");
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
|
@ -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 => {
|
||||
|
@ -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"
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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"
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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"
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -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),
|
||||
|
@ -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,
|
||||
|
@ -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")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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, _) |
|
||||
|
@ -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;
|
||||
|
@ -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,_)) => {
|
||||
|
@ -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}
|
||||
}
|
||||
|
@ -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});
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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; }
|
||||
_ => { }
|
||||
|
Loading…
x
Reference in New Issue
Block a user