From 270b4273e79aac33f424673caf455f839da2bb40 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Mon, 2 Jan 2012 12:00:40 +0100 Subject: [PATCH] Pass bounds to trans::type_of_fn --- src/comp/middle/trans.rs | 63 +++++++++++++++++++------------- src/comp/middle/trans_closure.rs | 23 +++++------- src/comp/middle/trans_common.rs | 4 +- src/comp/middle/trans_objects.rs | 8 ++-- src/comp/middle/ty.rs | 12 +++--- src/comp/middle/typeck.rs | 5 ++- 6 files changed, 65 insertions(+), 50 deletions(-) diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index c843f6e524d4..9e85d02a648c 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -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::(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, diff --git a/src/comp/middle/trans_closure.rs b/src/comp/middle/trans_closure.rs index 7205dd27c1c4..18552e84237a 100644 --- a/src/comp/middle/trans_closure.rs +++ b/src/comp/middle/trans_closure.rs @@ -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) -> {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}; } - diff --git a/src/comp/middle/trans_common.rs b/src/comp/middle/trans_common.rs index 9d0f14e6bd1c..c8f561859878 100644 --- a/src/comp/middle/trans_common.rs +++ b/src/comp/middle/trans_common.rs @@ -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); diff --git a/src/comp/middle/trans_objects.rs b/src/comp/middle/trans_objects.rs index db50c28b85a0..8b8a4b018d4e 100644 --- a/src/comp/middle/trans_objects.rs +++ b/src/comp/middle/trans_objects.rs @@ -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)})) } // diff --git a/src/comp/middle/ty.rs b/src/comp/middle/ty.rs index dad0a1609f41..c6e68c7777ef 100644 --- a/src/comp/middle/ty.rs +++ b/src/comp/middle/ty.rs @@ -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; @@ -220,7 +222,7 @@ type ctxt = ast_ty_to_ty_cache: hashmap<@ast::ty, option::t>, tag_var_cache: hashmap, iface_method_cache: hashmap, - ty_param_bounds: hashmap}; + ty_param_bounds: hashmap}; 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; diff --git a/src/comp/middle/typeck.rs b/src/comp/middle/typeck.rs index a86a29d9f1a2..3901c808bcff 100644 --- a/src/comp/middle/typeck.rs +++ b/src/comp/middle/typeck.rs @@ -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; }