diff --git a/src/comp/metadata/astencode.rs b/src/comp/metadata/astencode.rs index c24c80cf74b..bd1309c7c86 100644 --- a/src/comp/metadata/astencode.rs +++ b/src/comp/metadata/astencode.rs @@ -2,6 +2,7 @@ import syntax::ast; import syntax::fold; import syntax::visit; import syntax::ast_util; +import syntax::ast_util::inlined_item_methods; import syntax::codemap::span; import std::map::map; import std::smallintmap::map; @@ -31,8 +32,6 @@ import syntax::print::pprust; export encode_inlined_item; export decode_inlined_item; -export encode_inlined_method; -export decode_inlined_method; type decode_ctxt = @{ cdata: cstore::crate_metadata, @@ -53,123 +52,49 @@ iface tr { // ______________________________________________________________________ // Top-level methods. -// The type inline_fn should be a type that can represent both methods -// and top-level items. As it happens, the type ast::method is perfect -// for this purpose, but I use this typedef just to keep clear when -// the thing may not, in fact, be an actual method in the AST but -// rather some sort of function. -enum inline_fn = @ast::method; - fn encode_inlined_item(ecx: @e::encode_ctxt, ebml_w: ebml::writer, path: ast_map::path, - item: @ast::item) { - let ifn = inline_fn(alt item.node { - ast::item_fn(decl, tps, body) { - @{ident: item.ident, - attrs: item.attrs, - tps: tps, - decl: decl, - body: body, - id: item.id, - span: item.span} - } + ii: ast::inlined_item) { + #debug["> Encoding inlined item: %s::%s (%u)", + ast_map::path_to_str(path), ii.ident(), + ebml_w.writer.tell()]; - _ { - ecx.ccx.sess.span_bug(item.span, "Cannot inline non-function") - } - }); + let id_range = compute_id_range(ii); + ebml_w.wr_tag(c::tag_ast as uint) {|| + encode_id_range(ebml_w, id_range); + encode_ast(ebml_w, ii); + encode_side_tables_for_ii(ecx, ebml_w, ii); + } - encode_inlined_fn(ecx, ebml_w, path, ifn); + #debug["< Encoded inlined fn: %s::%s (%u)", + ast_map::path_to_str(path), ii.ident(), + ebml_w.writer.tell()]; } fn decode_inlined_item(cdata: cstore::crate_metadata, tcx: ty::ctxt, maps: maps, path: ast_map::path, - par_doc: ebml::doc) -> option<@ast::item> { - let oifn = decode_inlined_fn(cdata, tcx, maps, path, par_doc); - option::map(oifn) {|ifn| - let item = @{ident: ifn.ident, - attrs: ifn.attrs, - id: ifn.id, - node: ast::item_fn(ifn.decl, ifn.tps, ifn.body), - span: ifn.span}; - ast_map::map_decoded_item(tcx.items, path, item); - item - } -} - -fn encode_inlined_method(ecx: @e::encode_ctxt, - ebml_w: ebml::writer, - path: ast_map::path, - mthd: @ast::method) { - encode_inlined_fn(ecx, ebml_w, path, inline_fn(mthd)) -} - -fn decode_inlined_method(cdata: cstore::crate_metadata, - tcx: ty::ctxt, - maps: maps, - path: ast_map::path, - par_doc: ebml::doc) -> option<@ast::method> { - let oifn = decode_inlined_fn(cdata, tcx, maps, path, par_doc); - option::map(oifn) {|ifn| - ast_map::map_decoded_method(tcx.items, path, *ifn); - *ifn - } -} - -fn encode_inlined_fn(ecx: @e::encode_ctxt, - ebml_w: ebml::writer, - path: ast_map::path, - ifn: inline_fn) { - - #debug["> Encoding inlined item: %s::%s (%u)", - ast_map::path_to_str(path), - ifn.ident, - ebml_w.writer.tell()]; - - let id_range = compute_id_range(ifn); - ebml_w.wr_tag(c::tag_ast as uint) {|| - encode_id_range(ebml_w, id_range); - encode_ast(ebml_w, ifn); - encode_side_tables_for_ifn(ecx, ebml_w, ifn); - } - - #debug["< Encoded inlined fn: %s::%s (%u)", - ast_map::path_to_str(path), - ifn.ident, - ebml_w.writer.tell()]; -} - -// Decodes the inlined function and associated side tables. Does -// *not* insert the function into the ast_map, since the correct way -// to do this depends on whether this is an inlined item or method; -// therefore, you ought to be invoking decode_inlined_item() or -// decode_inlined_method() and not this helper function. -fn decode_inlined_fn(cdata: cstore::crate_metadata, - tcx: ty::ctxt, - maps: maps, - path: ast_map::path, - par_doc: ebml::doc) -> option { + par_doc: ebml::doc) -> option { let dcx = @{cdata: cdata, tcx: tcx, maps: maps}; alt par_doc.opt_child(c::tag_ast) { none { none } some(ast_doc) { - #debug["> Decoding inlined fn: %s", ast_map::path_to_str(path)]; + #debug["> Decoding inlined fn: %s::?", ast_map::path_to_str(path)]; let from_id_range = decode_id_range(ast_doc); let to_id_range = reserve_id_range(dcx.tcx.sess, from_id_range); let xcx = @{dcx: dcx, from_id_range: from_id_range, to_id_range: to_id_range}; - let raw_ifn = decode_ast(ast_doc); - let ifn = renumber_ast(xcx, raw_ifn); - #debug["Fn named: %s", ifn.ident]; + let raw_ii = decode_ast(ast_doc); + let ii = renumber_ast(xcx, raw_ii); + ast_map::map_decoded_item(dcx.tcx.items, path, ii); + #debug["Fn named: %s", ii.ident()]; decode_side_tables(xcx, ast_doc); #debug["< Decoded inlined fn: %s::%s", - ast_map::path_to_str(path), - ifn.ident]; - some(ifn) + ast_map::path_to_str(path), ii.ident()]; + some(ii) } } } @@ -183,7 +108,7 @@ fn empty(range: id_range) -> bool { range.min >= range.max } -fn visit_ids(ifn: inline_fn, vfn: fn@(ast::node_id)) { +fn visit_ids(item: ast::inlined_item, vfn: fn@(ast::node_id)) { let visitor = visit::mk_simple_visitor(@{ visit_mod: fn@(_m: ast::_mod, _sp: span, id: ast::node_id) { vfn(id) @@ -292,13 +217,13 @@ fn visit_ids(ifn: inline_fn, vfn: fn@(ast::node_id)) { } }); - visit::visit_method_helper(*ifn, (), visitor); + item.accept((), visitor) } -fn compute_id_range(ifn: inline_fn) -> id_range { +fn compute_id_range(item: ast::inlined_item) -> id_range { let min = @mutable int::max_value; let max = @mutable int::min_value; - visit_ids(ifn) {|id| + visit_ids(item) {|id| *min = int::min(*min, id); *max = int::max(*max, id + 1); } @@ -395,25 +320,34 @@ impl deserializer_helpers for D { // We also have to adjust the spans: for now we just insert a dummy span, // but eventually we should add entries to the local codemap as required. -fn encode_ast(ebml_w: ebml::writer, ifn: inline_fn) { +fn encode_ast(ebml_w: ebml::writer, item: ast::inlined_item) { ebml_w.wr_tag(c::tag_tree as uint) {|| - astencode_gen::serialize_syntax_ast_method(ebml_w, **ifn) + astencode_gen::serialize_syntax_ast_inlined_item(ebml_w, item) } } -fn decode_ast(par_doc: ebml::doc) -> inline_fn { +fn decode_ast(par_doc: ebml::doc) -> ast::inlined_item { let chi_doc = par_doc[c::tag_tree]; let d = serialization::mk_ebml_deserializer(chi_doc); - inline_fn(@astencode_gen::deserialize_syntax_ast_method(d)) + astencode_gen::deserialize_syntax_ast_inlined_item(d) } -fn renumber_ast(xcx: extended_decode_ctxt, ifn: inline_fn) -> inline_fn { +fn renumber_ast(xcx: extended_decode_ctxt, ii: ast::inlined_item) + -> ast::inlined_item { let fld = fold::make_fold({ new_id: xcx.tr_id(_), new_span: xcx.tr_span(_) with *fold::default_ast_fold() }); - inline_fn(fld.fold_method(*ifn)) + + alt ii { + ast::ii_item(i) { + ast::ii_item(fld.fold_item(i)) + } + ast::ii_method(d, m) { + ast::ii_method(xcx.tr_def_id(d), fld.fold_method(m)) + } + } } // ______________________________________________________________________ @@ -664,11 +598,11 @@ impl writer for ebml::writer { } } -fn encode_side_tables_for_ifn(ecx: @e::encode_ctxt, - ebml_w: ebml::writer, - ifn: inline_fn) { +fn encode_side_tables_for_ii(ecx: @e::encode_ctxt, + ebml_w: ebml::writer, + ii: ast::inlined_item) { ebml_w.wr_tag(c::tag_table as uint) {|| - visit_ids(ifn, fn@(id: ast::node_id) { + visit_ids(ii, fn@(id: ast::node_id) { // Note: this will cause a copy of ebml_w, which is bad as // it has mutable fields. But I believe it's harmless since // we generate balanced EBML. diff --git a/src/comp/metadata/astencode_gen.rs b/src/comp/metadata/astencode_gen.rs index abbe7376e1b..1c413de261c 100644 --- a/src/comp/metadata/astencode_gen.rs +++ b/src/comp/metadata/astencode_gen.rs @@ -8748,12 +8748,84 @@ fn deserialize_syntax_ast_def_id(s: S) -> syntax::ast::def_id { deserialize_162(s) } -fn serialize_syntax_ast_method(s: S, - v: - syntax::ast::method) { - serialize_160(s, v); +/*syntax::ast::inlined_item*/ +fn serialize_168(s: S, + v: + syntax::ast::inlined_item) { + s.emit_enum("syntax::ast::inlined_item", + /*@syntax::ast::item*/ + /*syntax::ast::def_id*//*@syntax::ast::method*/ + {|| + alt v { + syntax::ast::ii_item(v0) { + s.emit_enum_variant("syntax::ast::ii_item", 0u, 1u, + {|| + { + s.emit_enum_variant_arg(0u, + {|| + serialize_117(s, + v0) + }) + } + }) + } + syntax::ast::ii_method(v0, v1) { + s.emit_enum_variant("syntax::ast::ii_method", 1u, 2u, + {|| + { + s.emit_enum_variant_arg(0u, + {|| + serialize_162(s, + v0) + }); + s.emit_enum_variant_arg(1u, + {|| + serialize_159(s, + v1) + }) + } + }) + } + } + }); } -fn deserialize_syntax_ast_method(s: S) -> - syntax::ast::method { - deserialize_160(s) +fn serialize_syntax_ast_inlined_item(s: S, + v: + syntax::ast::inlined_item) { + serialize_168(s, v); +} +/*syntax::ast::inlined_item*/ +fn deserialize_168(s: S) -> + syntax::ast::inlined_item { + s.read_enum("syntax::ast::inlined_item", + /*@syntax::ast::item*/ + + /*syntax::ast::def_id*//*@syntax::ast::method*/ + {|| + s.read_enum_variant({|v_id| + alt check v_id { + 0u { + syntax::ast::ii_item(s.read_enum_variant_arg(0u, + {|| + deserialize_117(s) + })) + } + 1u { + syntax::ast::ii_method(s.read_enum_variant_arg(0u, + {|| + deserialize_162(s) + }), + s.read_enum_variant_arg(1u, + {|| + deserialize_159(s) + })) + } + } + }) + }) +} +fn deserialize_syntax_ast_inlined_item(s: + S) + -> syntax::ast::inlined_item { + deserialize_168(s) } diff --git a/src/comp/metadata/csearch.rs b/src/comp/metadata/csearch.rs index 646ba5ea751..7dbf8dde75a 100644 --- a/src/comp/metadata/csearch.rs +++ b/src/comp/metadata/csearch.rs @@ -79,7 +79,7 @@ fn get_item_path(tcx: ty::ctxt, def: ast::def_id) -> ast_map::path { // 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<@ast::item> { + -> option { 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/comp/metadata/decoder.rs b/src/comp/metadata/decoder.rs index 6b741189c48..196789ee58c 100644 --- a/src/comp/metadata/decoder.rs +++ b/src/comp/metadata/decoder.rs @@ -264,7 +264,7 @@ 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<@ast::item> { + id: ast::node_id) -> option { 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) diff --git a/src/comp/metadata/encoder.rs b/src/comp/metadata/encoder.rs index 705848b48ff..57507b8d8f9 100644 --- a/src/comp/metadata/encoder.rs +++ b/src/comp/metadata/encoder.rs @@ -352,7 +352,7 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item, encode_symbol(ecx, ebml_w, item.id); encode_path(ebml_w, path, ast_map::path_name(item.ident)); if should_inline(path, item) { - astencode::encode_inlined_item(ecx, ebml_w, path, item); + astencode::encode_inlined_item(ecx, ebml_w, path, ii_item(item)); } ebml_w.end_tag(); } diff --git a/src/comp/middle/ast_map.rs b/src/comp/middle/ast_map.rs index b5944402bb2..673b3649191 100644 --- a/src/comp/middle/ast_map.rs +++ b/src/comp/middle/ast_map.rs @@ -1,6 +1,7 @@ import std::map; import syntax::ast::*; import syntax::ast_util; +import syntax::ast_util::inlined_item_methods; import syntax::{visit, codemap}; enum path_elt { path_mod(str), path_name(str) } @@ -23,7 +24,7 @@ fn path_to_str(p: path) -> str { enum ast_node { node_item(@item, @path), node_native_item(@native_item, @path), - node_method(@method, node_id, @path), + node_method(@method, def_id, @path), node_variant(variant, def_id, @path), node_expr(@expr), // Locals are numbered, because the alias analysis needs to know in which @@ -59,7 +60,7 @@ fn map_crate(c: crate) -> map { // Used for items loaded from external crate that are being inlined into this // crate: -fn map_decoded_item(map: map, path: path, i: @item) { +fn map_decoded_item(map: map, path: path, ii: inlined_item) { // I believe it is ok for the local IDs of inlined items from other crates // to overlap with the local ids from this crate, so just generate the ids // starting from 0. (In particular, I think these ids are only used in @@ -70,16 +71,7 @@ fn map_decoded_item(map: map, path: path, i: @item) { mutable path: path, mutable local_id: 0u}; let v = mk_ast_map_visitor(); - v.visit_item(i, cx, v); -} - -fn map_decoded_method(map: map, path: path, m: @method) { - // As above. - let cx = {map: map, - mutable path: path, - mutable local_id: 0u}; - let v = mk_ast_map_visitor(); - visit::visit_method_helper(m, cx, v); + ii.accept(cx, v); } fn map_fn(fk: visit::fn_kind, decl: fn_decl, body: blk, @@ -117,7 +109,8 @@ fn map_item(i: @item, cx: ctx, v: vt) { cx.map.insert(i.id, node_item(i, @cx.path)); alt i.node { item_impl(_, _, _, ms) { - for m in ms { cx.map.insert(m.id, node_method(m, i.id, @cx.path)); } + let implid = ast_util::local_def(i.id); + for m in ms { cx.map.insert(m.id, node_method(m, implid, @cx.path)); } } item_res(_, _, _, dtor_id, ctor_id) { cx.map.insert(ctor_id, node_res_ctor(i)); diff --git a/src/comp/middle/inline.rs b/src/comp/middle/inline.rs index 9c05823f6ec..91d69168faf 100644 --- a/src/comp/middle/inline.rs +++ b/src/comp/middle/inline.rs @@ -1,6 +1,7 @@ import std::map::hashmap; import syntax::ast; import syntax::ast_util; +import syntax::ast_util::inlined_item_methods; import syntax::visit; import middle::typeck::method_map; import middle::trans::common::maps; @@ -9,13 +10,13 @@ import metadata::csearch; export inline_map; export instantiate_inlines; -type inline_map = hashmap; +type inline_map = hashmap; enum ctxt = { tcx: ty::ctxt, maps: maps, inline_map: inline_map, - mutable to_process: [@ast::item] + mut to_process: [ast::inlined_item] }; fn instantiate_inlines(enabled: bool, @@ -37,7 +38,9 @@ fn instantiate_inlines(enabled: bool, let to_process = []; to_process <-> cx.to_process; #debug["Recursively looking at inlined items"]; - vec::iter(to_process, {|i| visit::visit_item(i, cx, vt)}); + vec::iter(to_process) {|ii| + ii.accept(cx, vt); + } } ret inline_map; } @@ -78,20 +81,20 @@ impl methods for ctxt { #debug["No AST attached to def %s", ty::item_path_str(self.tcx, did)]; } - some(item) { /* Found an AST, add to table: */ + some(ii) { /* Found an AST, add to table: */ #debug["Inlining def %s", ty::item_path_str(self.tcx, did)]; - self.to_process += [item]; - self.inline_map.insert(did, item); + self.to_process += [ii]; + self.inline_map.insert(did, ii); } } } - fn maybe_enqueue_impl_method(_origin: typeck::method_origin) { - // alt method_origin { - // method_static(did) { self.maybe_enqueue_fn(did); } - // method_param(_, _, _, _) | method_iface(_, _) { - // /* fallthrough */ - // } - // } + fn maybe_enqueue_impl_method(method_origin: typeck::method_origin) { + alt method_origin { + typeck::method_static(did) { self.maybe_enqueue_fn(did); } + typeck::method_param(_, _, _, _) | typeck::method_iface(_, _) { + /* fallthrough */ + } + } } } diff --git a/src/comp/middle/trans/base.rs b/src/comp/middle/trans/base.rs index 479def401fb..846417fcb44 100644 --- a/src/comp/middle/trans/base.rs +++ b/src/comp/middle/trans/base.rs @@ -23,6 +23,7 @@ import front::attr; import middle::inline::inline_map; import back::{link, abi, upcall}; import syntax::{ast, ast_util, codemap}; +import ast_util::inlined_item_methods; import ast_util::local_def; import syntax::visit; import syntax::codemap::span; @@ -2105,8 +2106,8 @@ fn monomorphic_fn(ccx: crate_ctxt, fn_id: ast::def_id, substs: [ty::t], trans_enum_variant(ccx, enum_id.node, v, this_tv.disr_val, (*tvs).len() == 1u, [], psubsts, lldecl); } - ast_map::node_method(mth, impl_id, _) { - let selfty = ty::node_id_to_type(ccx.tcx, impl_id); + ast_map::node_method(mth, impl_def_id, _) { + let selfty = ty::lookup_item_type(ccx.tcx, impl_def_id).ty; let selfty = ty::substitute_type_params(ccx.tcx, substs, selfty); trans_fn(ccx, pt, mth.decl, mth.body, lldecl, impl_self(selfty), [], psubsts, fn_id.node); @@ -2131,12 +2132,12 @@ fn lval_static_fn(bcx: block, fn_id: ast::def_id, id: ast::node_id, } else { alt ccx.inline_map.find(fn_id) { none { fn_id } - some(item) { + some(ii) { #debug["Found inlined version of %s with id %d", ty::item_path_str(tcx, fn_id), - item.id]; + ii.id()]; {crate: ast::local_crate, - node: item.id} + node: ii.id()} } } } @@ -3882,8 +3883,10 @@ fn new_fn_ctxt(ccx: crate_ctxt, path: path, llfndecl: ValueRef, // spaces that have been created for them (by code in the llallocas field of // the function's fn_ctxt). create_llargs_for_fn_args populates the llargs // field of the fn_ctxt with -fn create_llargs_for_fn_args(cx: fn_ctxt, ty_self: self_arg, - args: [ast::arg], ty_params: [ast::ty_param]) { +fn create_llargs_for_fn_args(cx: fn_ctxt, + ty_self: self_arg, + args: [ast::arg], + tps_bounds: [ty::param_bounds]) { // Skip the implicit arguments 0, and 1. let arg_n = first_tp_arg; alt ty_self { @@ -3892,11 +3895,11 @@ fn create_llargs_for_fn_args(cx: fn_ctxt, ty_self: self_arg, } no_self {} } - for tp in ty_params { + for bounds in tps_bounds { let lltydesc = llvm::LLVMGetParam(cx.llfn, arg_n as c_uint); let dicts = none; arg_n += 1u; - for bound in *cx.ccx.tcx.ty_param_bounds.get(tp.id) { + for bound in *bounds { alt bound { ty::bound_iface(_) { let dict = llvm::LLVMGetParam(cx.llfn, arg_n as c_uint); @@ -3983,7 +3986,8 @@ enum self_arg { impl_self(ty::t), no_self, } // returned. fn trans_closure(ccx: crate_ctxt, path: path, decl: ast::fn_decl, body: ast::blk, llfndecl: ValueRef, - ty_self: self_arg, ty_params: [ast::ty_param], + ty_self: self_arg, + tps_bounds: [ty::param_bounds], param_substs: option, id: ast::node_id, maybe_load_env: fn(fn_ctxt)) { set_uwtable(llfndecl); @@ -3991,7 +3995,7 @@ fn trans_closure(ccx: crate_ctxt, path: path, decl: ast::fn_decl, // Set up arguments to the function. let fcx = new_fn_ctxt_w_id(ccx, path, llfndecl, id, param_substs, some(body.span)); - create_llargs_for_fn_args(fcx, ty_self, decl.inputs, ty_params); + create_llargs_for_fn_args(fcx, ty_self, decl.inputs, tps_bounds); // Create the first basic block in the function and keep a handle on it to // pass to finish_fn later. @@ -4023,15 +4027,20 @@ fn trans_closure(ccx: crate_ctxt, path: path, decl: ast::fn_decl, // trans_fn: creates an LLVM function corresponding to a source language // function. -fn trans_fn(ccx: crate_ctxt, path: path, decl: ast::fn_decl, - body: ast::blk, llfndecl: ValueRef, ty_self: self_arg, - ty_params: [ast::ty_param], param_substs: option, +fn trans_fn(ccx: crate_ctxt, + path: path, + decl: ast::fn_decl, + body: ast::blk, + llfndecl: ValueRef, + ty_self: self_arg, + tps_bounds: [ty::param_bounds], + param_substs: option, id: ast::node_id) { let do_time = ccx.sess.opts.stats; let start = if do_time { time::get_time() } else { {sec: 0u32, usec: 0u32} }; trans_closure(ccx, path, decl, body, llfndecl, ty_self, - ty_params, param_substs, id, {|fcx| + tps_bounds, param_substs, id, {|fcx| if ccx.sess.opts.extra_debuginfo { debuginfo::create_function(fcx); } @@ -4043,12 +4052,12 @@ fn trans_fn(ccx: crate_ctxt, path: path, decl: ast::fn_decl, } fn trans_res_ctor(ccx: crate_ctxt, path: path, dtor: ast::fn_decl, - ctor_id: ast::node_id, ty_params: [ast::ty_param], + ctor_id: ast::node_id, tps_bounds: [ty::param_bounds], param_substs: option, llfndecl: ValueRef) { // Create a function for the constructor let fcx = new_fn_ctxt_w_id(ccx, path, llfndecl, ctor_id, param_substs, none); - create_llargs_for_fn_args(fcx, no_self, dtor.inputs, ty_params); + create_llargs_for_fn_args(fcx, no_self, dtor.inputs, tps_bounds); let bcx = top_scope_block(fcx, none), lltop = bcx.llbb; let fty = node_id_type(bcx, ctor_id); let arg_t = ty::ty_fn_args(fty)[0].ty; @@ -4091,7 +4100,8 @@ fn trans_enum_variant(ccx: crate_ctxt, enum_id: ast::node_id, } let fcx = new_fn_ctxt_w_id(ccx, [], llfndecl, variant.node.id, param_substs, none); - create_llargs_for_fn_args(fcx, no_self, fn_args, ty_params); + create_llargs_for_fn_args(fcx, no_self, fn_args, + param_bounds(ccx, ty_params)); let ty_param_substs = alt param_substs { some(substs) { substs.tys } none { @@ -4248,7 +4258,8 @@ fn trans_item(ccx: crate_ctxt, item: ast::item) { }; if decl.purity != ast::crust_fn { trans_fn(ccx, *path + [path_name(item.ident)], decl, body, - llfndecl, no_self, tps, none, item.id); + llfndecl, no_self, param_bounds(ccx, tps), + none, item.id); } else { native::trans_crust_fn(ccx, *path + [path_name(item.ident)], decl, body, llfndecl, item.id); @@ -4259,13 +4270,15 @@ fn trans_item(ccx: crate_ctxt, item: ast::item) { } ast::item_res(decl, tps, body, dtor_id, ctor_id) { let llctor_decl = ccx.item_ids.get(ctor_id); - trans_res_ctor(ccx, *path, decl, ctor_id, tps, none, llctor_decl); + trans_res_ctor(ccx, *path, decl, ctor_id, + param_bounds(ccx, tps), none, llctor_decl); // Create a function for the destructor alt ccx.item_ids.find(item.id) { some(lldtor_decl) { trans_fn(ccx, *path + [path_name(item.ident)], decl, body, - lldtor_decl, no_self, tps, none, dtor_id); + lldtor_decl, no_self, param_bounds(ccx, tps), + none, dtor_id); } _ { ccx.sess.span_fatal(item.span, "unbound dtor in trans_item"); @@ -4309,9 +4322,34 @@ fn trans_mod(ccx: crate_ctxt, m: ast::_mod) { for item in m.items { trans_item(ccx, *item); } } +fn compute_ii_method_info(ccx: crate_ctxt, + impl_did: ast::def_id, + m: @ast::method, + f: fn(ty::t, [ty::param_bounds], ast_map::path)) { + let {bounds: impl_bnds, ty: impl_ty} = + ty::lookup_item_type(ccx.tcx, impl_did); + let m_bounds = *impl_bnds + param_bounds(ccx, m.tps); + let impl_path = ty::item_path(ccx.tcx, impl_did); + let m_path = impl_path + [path_name(m.ident)]; + f(impl_ty, m_bounds, m_path); +} + fn trans_inlined_items(ccx: crate_ctxt, inline_map: inline_map) { - inline_map.values {|item| - trans_item(ccx, *item) + inline_map.values {|ii| + alt ii { + ast::ii_item(item) { + trans_item(ccx, *item) + } + ast::ii_method(impl_did, m) { + compute_ii_method_info(ccx, impl_did, m) { + |impl_ty, m_bounds, m_path| + let llfndecl = ccx.item_ids.get(m.id); + trans_fn(ccx, m_path, m.decl, m.body, + llfndecl, impl_self(impl_ty), m_bounds, + none, m.id); + } + } + } } } @@ -4323,18 +4361,18 @@ fn get_pair_fn_ty(llpairty: TypeRef) -> TypeRef { fn register_fn(ccx: crate_ctxt, sp: span, path: path, flav: str, ty_params: [ast::ty_param], node_id: ast::node_id) { let t = ty::node_id_to_type(ccx.tcx, node_id); - register_fn_full(ccx, sp, path, flav, ty_params, node_id, t); + let bnds = param_bounds(ccx, ty_params); + register_fn_full(ccx, sp, path, flav, bnds, node_id, t); } -fn param_bounds(ccx: crate_ctxt, tp: ast::ty_param) -> ty::param_bounds { - ccx.tcx.ty_param_bounds.get(tp.id) +fn param_bounds(ccx: crate_ctxt, tps: [ast::ty_param]) -> [ty::param_bounds] { + vec::map(tps) {|tp| ccx.tcx.ty_param_bounds.get(tp.id) } } fn register_fn_full(ccx: crate_ctxt, sp: span, path: path, flav: str, - tps: [ast::ty_param], node_id: ast::node_id, + bnds: [ty::param_bounds], node_id: ast::node_id, node_type: ty::t) { - let llfty = type_of_fn_from_ty(ccx, node_type, - vec::map(tps, {|p| param_bounds(ccx, p)})); + let llfty = type_of_fn_from_ty(ccx, node_type, bnds); register_fn_fuller(ccx, sp, path, flav, node_id, node_type, lib::llvm::CCallConv, llfty); } @@ -4480,8 +4518,7 @@ fn collect_native_item(ccx: crate_ctxt, // For intrinsics: link the function directly to the intrinsic // function itself. let fn_type = type_of_fn_from_ty( - ccx, node_type, - vec::map(tps, {|p| param_bounds(ccx, p)})); + ccx, node_type, param_bounds(ccx, tps)); let ri_name = "rust_intrinsic_" + native::link_name(i); let llnativefn = get_extern_fn( ccx.externs, ccx.llmod, ri_name, @@ -4555,7 +4592,7 @@ fn collect_item(ccx: crate_ctxt, abi: @mutable option, // -- one to identify the type, and one to find the dtor symbol. let t = ty::node_id_to_type(ccx.tcx, dtor_id); register_fn_full(ccx, i.span, my_path + [path_name("dtor")], - "res_dtor", tps, i.id, t); + "res_dtor", param_bounds(ccx, tps), i.id, t); } ast::item_enum(variants, tps) { for variant in variants { @@ -4581,14 +4618,26 @@ fn collect_items(ccx: crate_ctxt, crate: @ast::crate) { fn collect_inlined_items(ccx: crate_ctxt, inline_map: inline::inline_map) { let abi = @mutable none::; - inline_map.values {|item| - collect_item(ccx, abi, item); - - alt item.node { - ast::item_fn(_, _, _) { - set_always_inline(ccx.item_ids.get(item.id)); + inline_map.values {|ii| + alt ii { + ast::ii_item(item) { + collect_item(ccx, abi, item); + alt item.node { + ast::item_fn(_, _, _) { + set_always_inline(ccx.item_ids.get(item.id)); + } + _ { /* fallthrough */ } + } + } + + ast::ii_method(impl_did, m) { + compute_ii_method_info(ccx, impl_did, m) { + |_impl_ty, m_bounds, m_path| + let mthd_ty = ty::node_id_to_type(ccx.tcx, m.id); + register_fn_full(ccx, m.span, m_path, "impl_method", + m_bounds, m.id, mthd_ty); + } } - _ { /* fallthrough */ } } } } diff --git a/src/comp/middle/trans/impl.rs b/src/comp/middle/trans/impl.rs index 9dfd72cc59b..b3660e3f672 100644 --- a/src/comp/middle/trans/impl.rs +++ b/src/comp/middle/trans/impl.rs @@ -49,9 +49,10 @@ fn trans_impl(ccx: crate_ctxt, path: path, name: ast::ident, for m in methods { alt ccx.item_ids.find(m.id) { some(llfn) { + let m_bounds = param_bounds(ccx, tps + m.tps); trans_fn(ccx, sub_path + [path_name(m.ident)], m.decl, m.body, llfn, impl_self(ty::node_id_to_type(ccx.tcx, id)), - tps + m.tps, none, m.id); + m_bounds, none, m.id); } _ { ccx.sess.bug("Unbound id in trans_impl"); @@ -337,13 +338,13 @@ fn trans_impl_vtable(ccx: crate_ctxt, pt: path, tps: [ast::ty_param], it: @ast::item) { let new_pt = pt + [path_name(it.ident), path_name(int::str(it.id)), path_name("wrap")]; - let extra_tps = vec::map(tps, {|p| param_bounds(ccx, p)}); + let extra_tps = param_bounds(ccx, tps); let ptrs = vec::map(*ty::iface_methods(ccx.tcx, iface_id), {|im| alt vec::find(ms, {|m| m.ident == im.ident}) { some(m) { let target = ccx.item_ids.get(m.id); - trans_impl_wrapper(ccx, new_pt + [path_name(m.ident)], extra_tps, - target) + trans_impl_wrapper(ccx, new_pt + [path_name(m.ident)], + extra_tps, target) } _ { ccx.sess.span_bug(it.span, "No matching method \ diff --git a/src/comp/syntax/ast.rs b/src/comp/syntax/ast.rs index edc5ade4062..eea47191eef 100644 --- a/src/comp/syntax/ast.rs +++ b/src/comp/syntax/ast.rs @@ -534,6 +534,14 @@ enum native_item_ { native_item_fn(fn_decl, [ty_param]), } +// The data we save and restore about an inlined item or method. This is not +// part of the AST that we parse from a file, but it becomes part of the tree +// that we trans. +enum inlined_item { + ii_item(@item), + ii_method(def_id /* impl id */, @method) +} + // // Local Variables: // mode: rust diff --git a/src/comp/syntax/ast_util.rs b/src/comp/syntax/ast_util.rs index 5f303b8c4a8..04bd4236c9b 100644 --- a/src/comp/syntax/ast_util.rs +++ b/src/comp/syntax/ast_util.rs @@ -411,6 +411,29 @@ pure fn class_item_ident(ci: @class_item) -> ident { } } +impl inlined_item_methods for inlined_item { + fn ident() -> ident { + alt self { + ii_item(i) { i.ident } + ii_method(_, m) { m.ident } + } + } + + fn id() -> ast::node_id { + alt self { + ii_item(i) { i.id } + ii_method(_, m) { m.id } + } + } + + fn accept(e: E, v: visit::vt) { + alt self { + ii_item(i) { v.visit_item(i, e, v) } + ii_method(_, m) { visit::visit_method_helper(m, e, v) } + } + } +} + // Local Variables: // mode: rust // fill-column: 78; diff --git a/src/comp/syntax/fold.rs b/src/comp/syntax/fold.rs index 94a0ff6b879..7ceae548769 100644 --- a/src/comp/syntax/fold.rs +++ b/src/comp/syntax/fold.rs @@ -750,7 +750,6 @@ fn make_fold(afp: ast_fold_precursor) -> ast_fold { ret result; } - // // Local Variables: // mode: rust diff --git a/src/etc/gen-astencode b/src/etc/gen-astencode index 2be64dab784..79316c23dca 100755 --- a/src/etc/gen-astencode +++ b/src/etc/gen-astencode @@ -17,7 +17,7 @@ function msg { M=src/comp/metadata GEN_TYPES="syntax::ast::item syntax::ast::def middle::typeck::method_origin \ middle::freevars::freevar_entry syntax::ast::def_id - syntax::ast::method" + syntax::ast::inlined_item" # Find serializer tool: for S in build/*/stage1/bin/serializer; do