diff options
Diffstat (limited to 'src/rustc/middle/trans/monomorphize.rs')
| -rw-r--r-- | src/rustc/middle/trans/monomorphize.rs | 84 |
1 files changed, 56 insertions, 28 deletions
diff --git a/src/rustc/middle/trans/monomorphize.rs b/src/rustc/middle/trans/monomorphize.rs index 17eaf591c9f..c2f106f631b 100644 --- a/src/rustc/middle/trans/monomorphize.rs +++ b/src/rustc/middle/trans/monomorphize.rs @@ -5,7 +5,7 @@ use syntax::ast_map::{path, path_mod, path_name}; use base::{trans_item, get_item_val, no_self, self_arg, trans_fn, impl_self, decl_internal_cdecl_fn, set_inline_hint_if_appr, set_inline_hint, - trans_enum_variant, trans_class_ctor, trans_class_dtor, + trans_enum_variant, trans_class_dtor, get_insn_ctxt}; use syntax::parse::token::special_idents; use type_of::type_of_fn_from_ty; @@ -16,9 +16,9 @@ fn monomorphic_fn(ccx: @crate_ctxt, fn_id: ast::def_id, real_substs: ~[ty::t], vtables: Option<typeck::vtable_res>, - ref_id: Option<ast::node_id>) - -> {val: ValueRef, must_cast: bool} -{ + impl_did_opt: Option<ast::def_id>, + ref_id: Option<ast::node_id>) -> + {val: ValueRef, must_cast: bool} { let _icx = ccx.insn_ctxt("monomorphic_fn"); let mut must_cast = false; let substs = vec::map(real_substs, |t| { @@ -31,17 +31,18 @@ fn monomorphic_fn(ccx: @crate_ctxt, for real_substs.each() |s| { assert !ty::type_has_params(*s); } for substs.each() |s| { assert !ty::type_has_params(*s); } let param_uses = type_use::type_uses_for(ccx, fn_id, substs.len()); - let hash_id = make_mono_id(ccx, fn_id, substs, vtables, Some(param_uses)); + let hash_id = make_mono_id(ccx, fn_id, substs, vtables, impl_did_opt, + Some(param_uses)); if vec::any(hash_id.params, |p| match *p { mono_precise(_, _) => false, _ => true }) { must_cast = true; } - #debug["monomorphic_fn(fn_id=%? (%s), real_substs=%?, substs=%?, \ + debug!("monomorphic_fn(fn_id=%? (%s), real_substs=%?, substs=%?, \ hash_id = %?", fn_id, ty::item_path_str(ccx.tcx, fn_id), real_substs.map(|s| ty_to_str(ccx.tcx, *s)), - substs.map(|s| ty_to_str(ccx.tcx, *s)), hash_id]; + substs.map(|s| ty_to_str(ccx.tcx, *s)), hash_id); match ccx.monomorphized.find(hash_id) { Some(val) => { @@ -71,11 +72,13 @@ fn monomorphic_fn(ccx: @crate_ctxt, return {val: get_item_val(ccx, fn_id.node), must_cast: true}; } - ast_map::node_ctor(nm, _, ct, _, pt) => (pt, nm, ct.span), ast_map::node_dtor(_, dtor, _, pt) => (pt, special_idents::dtor, dtor.span), - ast_map::node_trait_method(*) => { - ccx.tcx.sess.bug(~"Can't monomorphize a trait method") + ast_map::node_trait_method(@ast::provided(m), _, pt) => { + (pt, m.ident, m.span) + } + ast_map::node_trait_method(@ast::required(_), _, _) => { + ccx.tcx.sess.bug(~"Can't monomorphize a required trait method") } ast_map::node_expr(*) => { ccx.tcx.sess.bug(~"Can't monomorphize an expr") @@ -94,12 +97,23 @@ fn monomorphic_fn(ccx: @crate_ctxt, ccx.tcx.sess.bug(~"Can't monomorphize a local") } }; - let mono_ty = ty::subst_tps(ccx.tcx, substs, llitem_ty); + + // Look up the impl type if we're translating a default method. + // XXX: Generics. + let impl_ty_opt; + match impl_did_opt { + None => impl_ty_opt = None, + Some(impl_did) => { + impl_ty_opt = Some(ty::lookup_item_type(ccx.tcx, impl_did).ty); + } + } + + let mono_ty = ty::subst_tps(ccx.tcx, substs, impl_ty_opt, llitem_ty); let llfty = type_of_fn_from_ty(ccx, mono_ty); ccx.stats.n_monos += 1; - let depth = option::get_default(&ccx.monomorphizing.find(fn_id), 0u); + let depth = option::get_default(ccx.monomorphizing.find(fn_id), 0u); // Random cut-off -- code that needs to instantiate the same function // recursively more than ten times can probably safely be assumed to be // causing an infinite expansion. @@ -119,12 +133,18 @@ fn monomorphic_fn(ccx: @crate_ctxt, lldecl }; - let psubsts = Some({tys: substs, vtables: vtables, bounds: tpt.bounds}); + let psubsts = Some({ + tys: substs, + vtables: vtables, + bounds: tpt.bounds, + self_ty: impl_ty_opt + }); + let lldecl = match map_node { ast_map::node_item(i@@{node: ast::item_fn(decl, _, _, body), _}, _) => { let d = mk_lldecl(); set_inline_hint_if_appr(i.attrs, d); - trans_fn(ccx, pt, decl, body, d, no_self, psubsts, fn_id.node); + trans_fn(ccx, pt, decl, body, d, no_self, psubsts, fn_id.node, None); d } ast_map::node_item(*) => { @@ -138,7 +158,7 @@ fn monomorphic_fn(ccx: @crate_ctxt, } ast_map::node_variant(v, enum_item, _) => { let tvs = ty::enum_variants(ccx.tcx, local_def(enum_item.id)); - let this_tv = option::get(&vec::find(*tvs, |tv| { + let this_tv = option::get(vec::find(*tvs, |tv| { tv.id.node == fn_id.node})); let d = mk_lldecl(); set_inline_hint(d); @@ -155,21 +175,19 @@ fn monomorphic_fn(ccx: @crate_ctxt, } d } - ast_map::node_method(mth, _, _) => { + ast_map::node_method(mth, supplied_impl_did, _) => { // XXX: What should the self type be here? let d = mk_lldecl(); set_inline_hint_if_appr(mth.attrs, d); - meth::trans_method(ccx, pt, mth, psubsts, None, d); - d - } - ast_map::node_ctor(_, tps, ctor, parent_id, _) => { - // ctors don't have attrs, at least not right now - let d = mk_lldecl(); - let tp_tys = ty::ty_params_to_tys(ccx.tcx, tps); - trans_class_ctor(ccx, pt, ctor.node.dec, ctor.node.body, d, - option::get_default(&psubsts, - {tys:tp_tys, vtables: None, bounds: @~[]}), - fn_id.node, parent_id, ctor.span); + + // Override the impl def ID if necessary. + let impl_did; + match impl_did_opt { + None => impl_did = supplied_impl_did, + Some(override_impl_did) => impl_did = override_impl_did + } + + meth::trans_method(ccx, pt, mth, psubsts, None, d, impl_did); d } ast_map::node_dtor(_, dtor, _, pt) => { @@ -182,6 +200,15 @@ fn monomorphic_fn(ccx: @crate_ctxt, trans_class_dtor(ccx, *pt, dtor.node.body, dtor.node.id, psubsts, Some(hash_id), parent_id) } + ast_map::node_trait_method(@ast::provided(mth), _, pt) => { + let d = mk_lldecl(); + set_inline_hint_if_appr(mth.attrs, d); + debug!("monomorphic_fn impl_did_opt is %?", impl_did_opt); + meth::trans_method(ccx, *pt, mth, psubsts, None, d, + impl_did_opt.get()); + d + } + // Ugh -- but this ensures any new variants won't be forgotten ast_map::node_expr(*) | ast_map::node_stmt(*) | @@ -237,6 +264,7 @@ fn normalize_for_monomorphization(tcx: ty::ctxt, ty: ty::t) -> Option<ty::t> { fn make_mono_id(ccx: @crate_ctxt, item: ast::def_id, substs: ~[ty::t], vtables: Option<typeck::vtable_res>, + impl_did_opt: Option<ast::def_id>, param_uses: Option<~[type_use::type_uses]>) -> mono_id { let precise_param_ids = match vtables { Some(vts) => { @@ -306,5 +334,5 @@ fn make_mono_id(ccx: @crate_ctxt, item: ast::def_id, substs: ~[ty::t], }) } }; - @{def: item, params: param_ids} + @{def: item, params: param_ids, impl_did_opt: impl_did_opt} } |
