Pass bounds to trans::type_of_fn

This commit is contained in:
Marijn Haverbeke 2012-01-02 12:00:40 +01:00
parent 664a0443ad
commit 270b4273e7
6 changed files with 65 additions and 50 deletions

View File

@ -83,7 +83,7 @@ fn type_of_explicit_args(cx: @crate_ctxt, sp: span, inputs: [ty::arg]) ->
// - trans_args
fn type_of_fn(cx: @crate_ctxt, sp: span,
is_method: bool, inputs: [ty::arg],
output: ty::t, ty_param_count: uint)
output: ty::t, params: [ty::param_bounds])
: non_ty_var(cx, output) -> TypeRef {
let atys: [TypeRef] = [];
@ -100,8 +100,10 @@ fn type_of_fn(cx: @crate_ctxt, sp: span,
// Args >2: ty params, if not acquired via capture...
if !is_method {
let i = 0u;
while i < ty_param_count { atys += [T_ptr(cx.tydesc_type)]; i += 1u; }
// FIXME[impl] Also add args for the dicts
for _param in params {
atys += [T_ptr(cx.tydesc_type)];
}
}
// ... then explicit args.
atys += type_of_explicit_args(cx, sp, inputs);
@ -110,7 +112,7 @@ fn type_of_fn(cx: @crate_ctxt, sp: span,
// Given a function type and a count of ty params, construct an llvm type
fn type_of_fn_from_ty(cx: @crate_ctxt, sp: span, fty: ty::t,
ty_param_count: uint)
param_bounds: [ty::param_bounds])
: returns_non_ty_var(cx, fty) -> TypeRef {
// FIXME: Check should be unnecessary, b/c it's implied
// by returns_non_ty_var(t). Make that a postcondition
@ -118,7 +120,7 @@ fn type_of_fn_from_ty(cx: @crate_ctxt, sp: span, fty: ty::t,
let ret_ty = ty::ty_fn_ret(cx.tcx, fty);
check non_ty_var(cx, ret_ty);
ret type_of_fn(cx, sp, false, ty::ty_fn_args(cx.tcx, fty),
ret_ty, ty_param_count);
ret_ty, param_bounds);
}
fn type_of_inner(cx: @crate_ctxt, sp: span, t: ty::t)
@ -171,10 +173,10 @@ fn type_of_inner(cx: @crate_ctxt, sp: span, t: ty::t)
ty::ty_fn(_) {
// FIXME: could be a constraint on ty_fn
check returns_non_ty_var(cx, t);
T_fn_pair(cx, type_of_fn_from_ty(cx, sp, t, 0u))
T_fn_pair(cx, type_of_fn_from_ty(cx, sp, t, []))
}
ty::ty_native_fn(args, out) {
let nft = native_fn_wrapper_type(cx, sp, 0u, t);
let nft = native_fn_wrapper_type(cx, sp, [], t);
T_fn_pair(cx, nft)
}
ty::ty_obj(meths) { cx.rust_object_type }
@ -234,7 +236,7 @@ fn type_of_ty_param_bounds_and_ty(lcx: @local_ctxt, sp: span,
alt ty::struct(cx.tcx, t) {
ty::ty_fn(_) | ty::ty_native_fn(_, _) {
check returns_non_ty_var(cx, t);
ret type_of_fn_from_ty(cx, sp, t, vec::len(tpt.bounds));
ret type_of_fn_from_ty(cx, sp, t, tpt.bounds);
}
_ {
// fall through
@ -2562,7 +2564,8 @@ fn trans_do_while(cx: @block_ctxt, body: ast::blk, cond: @ast::expr) ->
type generic_info =
{item_type: ty::t,
static_tis: [option::t<@tydesc_info>],
tydescs: [ValueRef]};
tydescs: [ValueRef],
param_bounds: [ty::param_bounds]};
tag lval_kind {
temporary; //< Temporary value passed by value if of immediate type
@ -2608,18 +2611,19 @@ fn trans_external_path(cx: @block_ctxt, did: ast::def_id,
fn lval_static_fn(bcx: @block_ctxt, fn_id: ast::def_id, id: ast::node_id)
-> lval_maybe_callee {
let tpt = ty::lookup_item_type(bcx_tcx(bcx), fn_id);
let ccx = bcx_ccx(bcx);
let tpt = ty::lookup_item_type(ccx.tcx, fn_id);
let val = if fn_id.crate == ast::local_crate {
// Internal reference.
assert (bcx_ccx(bcx).item_ids.contains_key(fn_id.node));
bcx_ccx(bcx).item_ids.get(fn_id.node)
assert (ccx.item_ids.contains_key(fn_id.node));
ccx.item_ids.get(fn_id.node)
} else {
// External reference.
trans_external_path(bcx, fn_id, tpt)
};
let tys = ty::node_id_to_type_params(bcx_tcx(bcx), id);
let tys = ty::node_id_to_type_params(ccx.tcx, id);
let gen = none, bcx = bcx;
if vec::len::<ty::t>(tys) != 0u {
if vec::len(tys) != 0u {
let tydescs = [], tis = [];
for t in tys {
// TODO: Doesn't always escape.
@ -2629,7 +2633,11 @@ fn lval_static_fn(bcx: @block_ctxt, fn_id: ast::def_id, id: ast::node_id)
bcx = td.bcx;
tydescs += [td.val];
}
gen = some({item_type: tpt.ty, static_tis: tis, tydescs: tydescs});
let bounds = ty::lookup_item_type(ccx.tcx, fn_id).bounds;
gen = some({item_type: tpt.ty,
static_tis: tis,
tydescs: tydescs,
param_bounds: bounds});
}
ret {bcx: bcx, val: val, kind: owned, env: null_env, generic: gen};
}
@ -2767,7 +2775,7 @@ fn trans_object_field_inner(bcx: @block_ctxt, o: ValueRef,
check non_ty_var(ccx, ret_ty);
let ll_fn_ty = type_of_fn(ccx, bcx.sp, true,
ty::ty_fn_args(tcx, fn_ty), ret_ty, 0u);
ty::ty_fn_args(tcx, fn_ty), ret_ty, []);
v = Load(bcx, PointerCast(bcx, v, T_ptr(T_ptr(ll_fn_ty))));
ret {bcx: bcx, mthptr: v, objptr: o};
}
@ -5084,13 +5092,17 @@ fn register_fn(ccx: @crate_ctxt, sp: span, path: [str], flav: str,
register_fn_full(ccx, sp, path, flav, ty_params, node_id, t);
}
fn param_bounds(ccx: @crate_ctxt, tp: ast::ty_param) -> ty::param_bounds {
ccx.tcx.ty_param_bounds.get(ast_util::local_def(tp.id))
}
fn register_fn_full(ccx: @crate_ctxt, sp: span, path: [str], _flav: str,
ty_params: [ast::ty_param], node_id: ast::node_id,
tps: [ast::ty_param], node_id: ast::node_id,
node_type: ty::t)
: returns_non_ty_var(ccx, node_type) {
let path = path;
let llfty =
type_of_fn_from_ty(ccx, sp, node_type, vec::len(ty_params));
let llfty = type_of_fn_from_ty(ccx, sp, node_type,
vec::map(tps, {|p| param_bounds(ccx, p)}));
let ps: str = mangle_exported_name(ccx, path, node_type);
let llfn: ValueRef = decl_cdecl_fn(ccx.llmod, ps, llfty);
ccx.item_ids.insert(node_id, llfn);
@ -5128,7 +5140,7 @@ fn create_main_wrapper(ccx: @crate_ctxt, sp: span, main_llfn: ValueRef,
let nt = ty::mk_nil(ccx.tcx);
check non_ty_var(ccx, nt);
let llfty = type_of_fn(ccx, sp, false, [vecarg_ty], nt, 0u);
let llfty = type_of_fn(ccx, sp, false, [vecarg_ty], nt, []);
let llfdecl = decl_fn(ccx.llmod, "_rust_main",
lib::llvm::LLVMCCallConv, llfty);
@ -5221,12 +5233,13 @@ fn native_fn_ty_param_count(cx: @crate_ctxt, id: ast::node_id) -> uint {
ret count;
}
fn native_fn_wrapper_type(cx: @crate_ctxt, sp: span, ty_param_count: uint,
fn native_fn_wrapper_type(cx: @crate_ctxt, sp: span,
param_bounds: [ty::param_bounds],
x: ty::t) -> TypeRef {
alt ty::struct(cx.tcx, x) {
ty::ty_native_fn(args, out) {
check non_ty_var(cx, out);
ret type_of_fn(cx, sp, false, args, out, ty_param_count);
ret type_of_fn(cx, sp, false, args, out, param_bounds);
}
}
}
@ -5273,10 +5286,10 @@ fn collect_native_item(ccx: @crate_ctxt,
ast::native_abi_rust_intrinsic. {
// For intrinsics: link the function directly to the intrinsic
// function itself.
let num_ty_param = vec::len(tps);
check returns_non_ty_var(ccx, node_type);
let fn_type = type_of_fn_from_ty(ccx, sp, node_type,
num_ty_param);
let fn_type = type_of_fn_from_ty(
ccx, sp, node_type,
vec::map(tps, {|p| param_bounds(ccx, p)}));
let ri_name = "rust_intrinsic_" + link_name(i);
let llnativefn = get_extern_fn(
ccx.externs, ccx.llmod, ri_name,

View File

@ -383,7 +383,7 @@ fn trans_expr_fn(bcx: @block_ctxt,
let ccx = bcx_ccx(bcx), bcx = bcx;
let fty = node_id_type(ccx, id);
check returns_non_ty_var(ccx, fty);
let llfnty = type_of_fn_from_ty(ccx, sp, fty, 0u);
let llfnty = type_of_fn_from_ty(ccx, sp, fty, []);
let sub_cx = extend_path(bcx.fcx.lcx, ccx.names.next("anon"));
let s = mangle_internal_name_by_path(ccx, sub_cx.path);
let llfn = decl_internal_cdecl_fn(ccx.llmod, s, llfnty);
@ -436,16 +436,13 @@ fn trans_bind_1(cx: @block_ctxt, outgoing_fty: ty::t,
}
// Figure out which tydescs we need to pass, if any.
let outgoing_fty_real; // the type with typarams still in it
let lltydescs: [ValueRef];
alt f_res.generic {
none. { outgoing_fty_real = outgoing_fty; lltydescs = []; }
let (outgoing_fty_real, lltydescs, param_bounds) = alt f_res.generic {
none. { (outgoing_fty, [], []) }
some(ginfo) {
lazily_emit_all_generic_info_tydesc_glues(cx, ginfo);
outgoing_fty_real = ginfo.item_type;
lltydescs = ginfo.tydescs;
(ginfo.item_type, ginfo.tydescs, ginfo.param_bounds)
}
}
};
let ty_param_count = vec::len(lltydescs);
if vec::len(bound) == 0u && ty_param_count == 0u {
@ -487,7 +484,7 @@ fn trans_bind_1(cx: @block_ctxt, outgoing_fty: ty::t,
// Make thunk
let llthunk =
trans_bind_thunk(cx.fcx.lcx, cx.sp, pair_ty, outgoing_fty_real, args,
box_ty, ty_param_count, target_res);
box_ty, param_bounds, target_res);
// Fill the function pair
fill_fn_pair(bcx, get_dest_addr(dest), llthunk.val, llbox);
@ -558,7 +555,7 @@ fn trans_bind_thunk(cx: @local_ctxt,
outgoing_fty: ty::t,
args: [option::t<@ast::expr>],
boxed_closure_ty: ty::t,
ty_param_count: uint,
param_bounds: [ty::param_bounds],
target_fn: option::t<ValueRef>)
-> {val: ValueRef, ty: TypeRef} {
// If we supported constraints on record fields, we could make the
@ -667,7 +664,8 @@ fn trans_bind_thunk(cx: @local_ctxt,
let llargs: [ValueRef] = [llretptr, lltargetenv];
// Copy in the type parameters.
let i: uint = 0u;
// FIXME[impl] This will also have to copy the dicts
let i = 0u, ty_param_count = vec::len(param_bounds);
while i < ty_param_count {
// Silly check
check type_is_tup_like(load_env_bcx, boxed_closure_ty);
@ -739,11 +737,10 @@ fn trans_bind_thunk(cx: @local_ctxt,
check returns_non_ty_var(ccx, outgoing_fty);
let lltargetty =
type_of_fn_from_ty(ccx, sp, outgoing_fty, ty_param_count);
type_of_fn_from_ty(ccx, sp, outgoing_fty, param_bounds);
lltargetfn = PointerCast(bcx, lltargetfn, T_ptr(lltargetty));
Call(bcx, lltargetfn, llargs);
build_return(bcx);
finish_fn(fcx, lltop);
ret {val: llthunk, ty: llthunk_ty};
}

View File

@ -320,13 +320,13 @@ fn get_res_dtor(ccx: @crate_ctxt, sp: span, did: ast::def_id, inner_t: ty::t)
}
}
let params = csearch::get_type_param_count(ccx.sess.get_cstore(), did);
let param_bounds = ty::lookup_item_type(ccx.tcx, did).bounds;
let nil_res = ty::mk_nil(ccx.tcx);
// FIXME: Silly check -- mk_nil should have a postcondition
check non_ty_var(ccx, nil_res);
let f_t = type_of_fn(ccx, sp, false,
[{mode: ast::by_ref, ty: inner_t}],
nil_res, params);
nil_res, param_bounds);
ret trans::get_extern_const(ccx.externs, ccx.llmod,
csearch::get_symbol(ccx.sess.get_cstore(),
did), f_t);

View File

@ -880,8 +880,9 @@ fn process_normal_mthd(cx: @local_ctxt, m: @ast::method, self_ty: ty::t,
ty::ty_fn(f) {
let out = f.output;
check non_ty_var(ccx, out);
llfnty = type_of_fn(ccx, m.span, true, f.inputs, out,
vec::len(ty_params));
llfnty = type_of_fn(
ccx, m.span, true, f.inputs, out,
vec::map(ty_params, {|p| param_bounds(ccx, p)}));
}
}
let mcx: @local_ctxt =
@ -933,7 +934,8 @@ fn type_of_meth(ccx: @crate_ctxt, sp: span, m: @ty::method,
tps: [ast::ty_param]) -> TypeRef {
let out_ty = m.fty.output;
check non_ty_var(ccx, out_ty);
type_of_fn(ccx, sp, true, m.fty.inputs, out_ty, vec::len(tps))
type_of_fn(ccx, sp, true, m.fty.inputs, out_ty,
vec::map(tps, {|p| param_bounds(ccx, p)}))
}
//

View File

@ -185,7 +185,7 @@ export closure_kind;
export closure_block;
export closure_shared;
export closure_send;
export param_bound, bound_copy, bound_send, bound_iface;
export param_bound, param_bounds, bound_copy, bound_send, bound_iface;
export param_bounds_to_kind;
// Data types
@ -194,7 +194,9 @@ type arg = {mode: mode, ty: t};
type field = {ident: ast::ident, mt: mt};
type method = {ident: ast::ident, tps: [@[param_bound]], fty: fn_ty};
type param_bounds = @[param_bound];
type method = {ident: ast::ident, tps: [param_bounds], fty: fn_ty};
type constr_table = hashmap<ast::node_id, [constr]>;
@ -220,7 +222,7 @@ type ctxt =
ast_ty_to_ty_cache: hashmap<@ast::ty, option::t<t>>,
tag_var_cache: hashmap<def_id, @[variant_info]>,
iface_method_cache: hashmap<def_id, @[method]>,
ty_param_bounds: hashmap<def_id, @[param_bound]>};
ty_param_bounds: hashmap<def_id, param_bounds>};
type ty_ctxt = ctxt;
@ -308,7 +310,7 @@ tag param_bound {
bound_iface(t);
}
fn param_bounds_to_kind(bounds: @[param_bound]) -> kind {
fn param_bounds_to_kind(bounds: param_bounds) -> kind {
let kind = kind_noncopyable;
for bound in *bounds {
alt bound {
@ -322,7 +324,7 @@ fn param_bounds_to_kind(bounds: @[param_bound]) -> kind {
kind
}
type ty_param_bounds_and_ty = @{bounds: [@[param_bound]], ty: t};
type ty_param_bounds_and_ty = @{bounds: [param_bounds], ty: t};
type type_cache = hashmap<ast::def_id, ty_param_bounds_and_ty>;

View File

@ -504,7 +504,7 @@ fn ty_of_native_fn_decl(tcx: ty::ctxt, mode: mode, decl: ast::fn_decl,
ret tpt;
}
fn ty_param_bounds(tcx: ty::ctxt, mode: mode, params: [ast::ty_param])
-> [@[ty::param_bound]] {
-> [ty::param_bounds] {
let result = [];
for param in params {
result += [alt tcx.ty_param_bounds.find(local_def(param.id)) {
@ -626,7 +626,7 @@ mod write {
}
fn mk_ty_params(tcx: ty::ctxt, atps: [ast::ty_param])
-> {bounds: [@[ty::param_bound]], params: [ty::t]} {
-> {bounds: [ty::param_bounds], params: [ty::t]} {
let i = 0u, bounds = ty_param_bounds(tcx, m_collect, atps);
{bounds: bounds,
params: vec::map(atps, {|atp|
@ -2896,6 +2896,7 @@ fn resolve_vtables(tcx: ty::ctxt, impl_map: resolve::impl_map,
ty::ty_iface(did, _) { did }
_ { ret; }
};
// FIXME check against bounded param types
let found = false;
std::list::iter(isc) {|impls|
if found { ret; }