diff --git a/src/rustc/metadata/astencode.rs b/src/rustc/metadata/astencode.rs index 3d54ffe39442d41720958b1b52c666725bbec2b4..ee0afc22fb4fcc7b0f865af98384506b530c3f27 100644 --- a/src/rustc/metadata/astencode.rs +++ b/src/rustc/metadata/astencode.rs @@ -137,6 +137,7 @@ fn visit_ids(item: ast::inlined_item, vfn: fn@(ast::node_id)) { vfn(i.id); alt i.node { ast::item_res(_, _, _, d_id, c_id) { vfn(d_id); vfn(c_id); } + ast::item_enum(vs, _) { for v in vs { vfn(v.node.id); } } _ {} } }, diff --git a/src/rustc/metadata/common.rs b/src/rustc/metadata/common.rs index 3d3a3fff48f393bc5681b618476cd0ab685e9115..db3dc4078ed0389817f49d4b4a9dd75d4ad41654 100644 --- a/src/rustc/metadata/common.rs +++ b/src/rustc/metadata/common.rs @@ -28,7 +28,7 @@ const tag_items_data_item_variant: uint = 0x0eu; -const tag_items_data_item_enum_id: uint = 0x0fu; +const tag_items_data_parent_item: uint = 0x0fu; const tag_index: uint = 0x11u; @@ -62,6 +62,8 @@ const tag_crate_hash: uint = 0x28u; +const tag_parent_item: uint = 0x29u; + const tag_mod_impl: uint = 0x30u; const tag_item_method: uint = 0x31u; diff --git a/src/rustc/metadata/csearch.rs b/src/rustc/metadata/csearch.rs index 6a336da1e52f9ff453497626bbdf06e8f86527bc..6be4124d5e6c47e971ac58910c6235d4f7959863 100644 --- a/src/rustc/metadata/csearch.rs +++ b/src/rustc/metadata/csearch.rs @@ -19,7 +19,7 @@ export get_impl_iface; export get_impl_method; export get_item_path; -export maybe_get_item_ast; +export maybe_get_item_ast, found_ast, found, found_parent, not_found; fn get_symbol(cstore: cstore::cstore, def: ast::def_id) -> str { let cdata = cstore::get_crate_data(cstore, def.crate).data; @@ -80,11 +80,17 @@ fn get_item_path(tcx: ty::ctxt, def: ast::def_id) -> ast_map::path { [ast_map::path_mod(cdata.name)] + path } +enum found_ast { + found(ast::inlined_item), + found_parent(ast::def_id, ast::inlined_item), + not_found, +} + // Finds the AST for this item in the crate metadata, if any. If the item was // not marked for inlining, then the AST will not be present and hence none // will be returned. fn maybe_get_item_ast(tcx: ty::ctxt, maps: maps, def: ast::def_id) - -> option { + -> found_ast { let cstore = tcx.sess.cstore; let cdata = cstore::get_crate_data(cstore, def.crate); decoder::maybe_get_item_ast(cdata, tcx, maps, def.node) diff --git a/src/rustc/metadata/decoder.rs b/src/rustc/metadata/decoder.rs index f78c0ade6f1e4cbb704df71dc7eb5ee4549cb3ba..ac6e32f292d6d2534ecdabc8520821ccbe5af614 100644 --- a/src/rustc/metadata/decoder.rs +++ b/src/rustc/metadata/decoder.rs @@ -96,9 +96,12 @@ fn item_symbol(item: ebml::doc) -> str { ret str::from_bytes(ebml::doc_data(sym)); } -fn variant_enum_id(d: ebml::doc) -> ast::def_id { - let tagdoc = ebml::get_doc(d, tag_items_data_item_enum_id); - ret parse_def_id(ebml::doc_data(tagdoc)); +fn item_parent_item(d: ebml::doc) -> option { + let found = none; + ebml::tagged_docs(d, tag_items_data_parent_item) {|did| + found = some(parse_def_id(ebml::doc_data(did))); + } + found } fn variant_disr_val(d: ebml::doc) -> option { @@ -230,7 +233,7 @@ fn lookup_def(cnum: ast::crate_num, data: @[u8], did_: ast::def_id) -> 'm' { ast::def_mod(did) } 'n' { ast::def_native_mod(did) } 'v' { - let tid = variant_enum_id(item); + let tid = option::get(item_parent_item(item)); tid = {crate: cnum, node: tid.node}; ast::def_variant(tid, did) } @@ -278,10 +281,26 @@ fn get_item_path(cdata: cmd, id: ast::node_id) -> ast_map::path { } fn maybe_get_item_ast(cdata: cmd, tcx: ty::ctxt, maps: maps, - id: ast::node_id) -> option { + id: ast::node_id) -> csearch::found_ast { let item_doc = lookup_item(id, cdata.data); let path = vec::init(item_path(item_doc)); - astencode::decode_inlined_item(cdata, tcx, maps, path, item_doc) + alt astencode::decode_inlined_item(cdata, tcx, maps, path, item_doc) { + some(ii) { csearch::found(ii) } + none { + alt item_parent_item(item_doc) { + some(did) { + let did = translate_def_id(cdata, did); + let parent_item = lookup_item(did.node, cdata.data); + alt astencode::decode_inlined_item(cdata, tcx, maps, path, + parent_item) { + some(ii) { csearch::found_parent(did, ii) } + none { csearch::not_found } + } + } + none { csearch::not_found } + } + } + } } fn get_enum_variants(cdata: cmd, id: ast::node_id, tcx: ty::ctxt) diff --git a/src/rustc/metadata/encoder.rs b/src/rustc/metadata/encoder.rs index 6a8a77b119119124c4c2e9500398076403fb42e5..ae9ab788ac0b40e2efdac0cb9584e56abab2c658 100644 --- a/src/rustc/metadata/encoder.rs +++ b/src/rustc/metadata/encoder.rs @@ -241,8 +241,8 @@ fn encode_disr_val(_ecx: @encode_ctxt, ebml_w: ebml::writer, disr_val: int) { ebml_w.end_tag(); } -fn encode_enum_id(ebml_w: ebml::writer, id: def_id) { - ebml_w.start_tag(tag_items_data_item_enum_id); +fn encode_parent_item(ebml_w: ebml::writer, id: def_id) { + ebml_w.start_tag(tag_items_data_parent_item); ebml_w.writer.write(str::bytes(def_to_str(id))); ebml_w.end_tag(); } @@ -260,7 +260,7 @@ fn encode_enum_variant_info(ecx: @encode_ctxt, ebml_w: ebml::writer, encode_def_id(ebml_w, local_def(variant.node.id)); encode_family(ebml_w, 'v'); encode_name(ebml_w, variant.node.name); - encode_enum_id(ebml_w, local_def(id)); + encode_parent_item(ebml_w, local_def(id)); encode_type(ecx, ebml_w, node_id_to_type(ecx.ccx.tcx, variant.node.id)); if vec::len(variant.node.args) > 0u && ty_params.len() == 0u { @@ -397,6 +397,7 @@ fn should_inline(attrs: [attribute]) -> bool { for v: variant in variants { encode_variant_id(ebml_w, local_def(v.node.id)); } + astencode::encode_inlined_item(ecx, ebml_w, path, ii_item(item)); encode_path(ebml_w, path, ast_map::path_name(item.ident)); ebml_w.end_tag(); encode_enum_variant_info(ecx, ebml_w, item.id, variants, @@ -414,11 +415,7 @@ fn should_inline(attrs: [attribute]) -> bool { encode_type_param_bounds(ebml_w, ecx, tps); encode_type(ecx, ebml_w, ty::ty_fn_ret(fn_ty)); encode_name(ebml_w, item.ident); - if tps.len() == 0u { - encode_symbol(ecx, ebml_w, item.id); - } else { - astencode::encode_inlined_item(ecx, ebml_w, path, ii_item(item)); - } + astencode::encode_inlined_item(ecx, ebml_w, path, ii_item(item)); encode_path(ebml_w, path, ast_map::path_name(item.ident)); ebml_w.end_tag(); @@ -428,9 +425,7 @@ fn should_inline(attrs: [attribute]) -> bool { encode_family(ebml_w, 'f'); encode_type_param_bounds(ebml_w, ecx, tps); encode_type(ecx, ebml_w, fn_ty); - if tps.len() == 0u { - encode_symbol(ecx, ebml_w, ctor_id); - } + encode_parent_item(ebml_w, local_def(item.id)); encode_path(ebml_w, path, ast_map::path_name(item.ident)); ebml_w.end_tag(); } diff --git a/src/rustc/middle/trans/base.rs b/src/rustc/middle/trans/base.rs index 0dde3983dbd14e2a1d24d61bee3ea20649606493..c3d2f886d42b8d4f096a8557af4ac464f5689f57 100644 --- a/src/rustc/middle/trans/base.rs +++ b/src/rustc/middle/trans/base.rs @@ -864,17 +864,8 @@ fn get_res_dtor(ccx: @crate_ctxt, did: ast::def_id, substs: [ty::t]) let did = if did.crate != ast::local_crate && substs.len() > 0u { maybe_instantiate_inline(ccx, did) } else { did }; - if did.crate == ast::local_crate { - option::get(monomorphic_fn(ccx, did, substs, none)) - } else { - assert substs.len() == 0u; - let nil = ty::mk_nil(ccx.tcx); - let arg = {mode: ast::expl(ast::by_ref), - ty: ty::mk_mut_ptr(ccx.tcx, nil)}; - let f_t = type_of::type_of_fn(ccx, [arg], nil, 0u); - get_extern_const(ccx.externs, ccx.llmod, - csearch::get_symbol(ccx.sess.cstore, did), f_t) - } + assert did.crate == ast::local_crate; + option::get(monomorphic_fn(ccx, did, substs, none)) } fn trans_res_drop(bcx: block, rs: ValueRef, did: ast::def_id, @@ -2094,22 +2085,34 @@ fn maybe_instantiate_inline(ccx: @crate_ctxt, fn_id: ast::def_id) } some(none) { fn_id } // Not inlinable none { // Not seen yet - alt csearch::maybe_get_item_ast(ccx.tcx, ccx.maps, fn_id) { - none { ccx.external.insert(fn_id, none); fn_id } - some(ast::ii_item(item)) { - #debug["maybe_instantiate_inline(%s): inlining to local id %d", - ty::item_path_str(ccx.tcx, fn_id), - item.id]; + alt check csearch::maybe_get_item_ast(ccx.tcx, ccx.maps, fn_id) { + csearch::not_found { + ccx.external.insert(fn_id, none); + fn_id + } + csearch::found(ast::ii_item(item)) { ccx.external.insert(fn_id, some(item.id)); trans_item(ccx, *item); local_def(item.id) } - some(ast::ii_method(impl_did, mth)) { - #debug["maybe_instantiate_inline(%s): \ - inlining method of %s to %d", - ty::item_path_str(ccx.tcx, fn_id), - ty::item_path_str(ccx.tcx, impl_did), - mth.id]; + csearch::found_parent(parent_id, ast::ii_item(item)) { + ccx.external.insert(parent_id, some(item.id)); + let my_id = 0; + alt check item.node { + ast::item_enum(_, _) { + let vs_here = ty::enum_variants(ccx.tcx, local_def(item.id)); + let vs_there = ty::enum_variants(ccx.tcx, parent_id); + vec::iter2(*vs_here, *vs_there) {|here, there| + if there.id == fn_id { my_id = here.id.node; } + ccx.external.insert(there.id, some(here.id.node)); + } + } + ast::item_res(_, _, _, _, ctor_id) { my_id = ctor_id; } + } + trans_item(ccx, *item); + local_def(my_id) + } + csearch::found(ast::ii_method(impl_did, mth)) { ccx.external.insert(fn_id, some(mth.id)); compute_ii_method_info(ccx, impl_did, mth) {|ty, bounds, path| if bounds.len() == 0u { @@ -2143,8 +2146,7 @@ fn lval_static_fn(bcx: block, fn_id: ast::def_id, id: ast::node_id, // monomorphized and non-monomorphized functions at the moment. If // monomorphizing becomes the only approach, this'll be much simpler. if (option::is_some(substs) || tys.len() > 0u) && - fn_id.crate == ast::local_crate && - !vec::any(tys, {|t| ty::type_has_params(t)}) { + fn_id.crate == ast::local_crate { let mono = alt substs { some((stys, vtables)) { if (stys.len() + tys.len()) > 0u {