diff --git a/src/librustsyntax/ast.rs b/src/librustsyntax/ast.rs index b2e0583c61b1..44a37066a56e 100644 --- a/src/librustsyntax/ast.rs +++ b/src/librustsyntax/ast.rs @@ -643,7 +643,7 @@ enum item_ { item_native_mod(native_mod), item_ty(@ty, [ty_param]), item_enum([variant], [ty_param]), - item_res(fn_decl /* dtor */, [ty_param], blk, + item_res(fn_decl /* dtor */, [ty_param], blk /* dtor body */, node_id /* dtor id */, node_id /* ctor id */), item_class([ty_param], /* ty params for class */ [@class_member], /* methods, etc. */ @@ -703,6 +703,7 @@ enum inlined_item { ii_item(@item), ii_method(def_id /* impl id */, @method), ii_native(@native_item), + ii_ctor(class_ctor, ident, [ty_param], def_id /* parent id */) } // diff --git a/src/librustsyntax/ast_util.rs b/src/librustsyntax/ast_util.rs index 63c46b63341e..f81f09b2c52f 100644 --- a/src/librustsyntax/ast_util.rs +++ b/src/librustsyntax/ast_util.rs @@ -302,6 +302,7 @@ impl inlined_item_methods for inlined_item { ii_item(i) { i.ident } ii_native(i) { i.ident } ii_method(_, m) { m.ident } + ii_ctor(_, nm, _, _) { nm } } } @@ -310,6 +311,7 @@ impl inlined_item_methods for inlined_item { ii_item(i) { i.id } ii_native(i) { i.id } ii_method(_, m) { m.id } + ii_ctor(ctor, _, _, _) { ctor.node.id } } } @@ -318,6 +320,9 @@ impl inlined_item_methods for inlined_item { ii_item(i) { v.visit_item(i, e, v) } ii_native(i) { v.visit_native_item(i, e, v) } ii_method(_, m) { visit::visit_method_helper(m, e, v) } + ii_ctor(ctor, nm, tps, parent_id) { + visit::visit_class_ctor_helper(ctor, nm, tps, parent_id, e, v); + } } } } diff --git a/src/librustsyntax/fold.rs b/src/librustsyntax/fold.rs index 07411a3051d4..ec6d871472bc 100644 --- a/src/librustsyntax/fold.rs +++ b/src/librustsyntax/fold.rs @@ -14,6 +14,8 @@ export noop_fold_ty; export noop_fold_block; export wrap; export fold_ty_param; +export fold_ty_params; +export fold_fn_decl; type ast_fold = @mut a_f; @@ -270,10 +272,12 @@ fn noop_fold_item_underscore(i: item_, fld: ast_fold) -> item_ { item_class(typms, items, ctor) { let ctor_body = fld.fold_block(ctor.node.body); let ctor_decl = fold_fn_decl(ctor.node.dec, fld); + let ctor_id = fld.new_id(ctor.node.id); item_class(typms, vec::map(items, fld.fold_class_item), {node: {body: ctor_body, - dec: ctor_decl with ctor.node} + dec: ctor_decl, + id: ctor_id with ctor.node} with ctor}) } item_impl(tps, ifce, ty, methods) { diff --git a/src/librustsyntax/visit.rs b/src/librustsyntax/visit.rs index 6250c9dc7c9f..b4ffce0730df 100644 --- a/src/librustsyntax/visit.rs +++ b/src/librustsyntax/visit.rs @@ -18,13 +18,14 @@ enum fn_kind { fk_res(ident, [ty_param]), fk_anon(proto), //< an anonymous function like fn@(...) fk_fn_block, //< a block {||...} - fk_ctor(ident, [ty_param]) // class constructor + fk_ctor(ident, [ty_param], node_id /* self id */, + def_id /* parent class id */) // class constructor } fn name_of_fn(fk: fn_kind) -> ident { alt fk { fk_item_fn(name, _) | fk_method(name, _, _) | fk_res(name, _) - | fk_ctor(name, _) { name } + | fk_ctor(name, _, _, _) { name } fk_anon(_) | fk_fn_block { "anon" } } } @@ -32,7 +33,7 @@ fn name_of_fn(fk: fn_kind) -> ident { fn tps_of_fn(fk: fn_kind) -> [ty_param] { alt fk { fk_item_fn(_, tps) | fk_method(_, tps, _) | fk_res(_, tps) - | fk_ctor(_, tps) { tps } + | fk_ctor(_, tps, _, _) { tps } fk_anon(_) | fk_fn_block { [] } } } @@ -141,9 +142,8 @@ fn visit_item(i: @item, e: E, v: vt) { for members.each {|m| v.visit_class_item(m, e, v); } - // make up a fake fn so as to call visit_fn on the ctor - v.visit_fn(fk_ctor(i.ident, tps), ctor.node.dec, - ctor.node.body, ctor.span, ctor.node.id, e, v); + visit_class_ctor_helper(ctor, i.ident, tps, + ast_util::local_def(i.id), e, v); } item_iface(tps, methods) { v.visit_ty_params(tps, e, v); @@ -270,6 +270,15 @@ fn visit_method_helper(m: @method, e: E, v: vt) { m.id, e, v); } +// Similar logic to the comment on visit_method_helper - Tim +fn visit_class_ctor_helper(ctor: class_ctor, nm: ident, tps: [ty_param], + parent_id: def_id, e: E, v: vt) { + v.visit_fn(visit::fk_ctor(nm, tps, ctor.node.self_id, + parent_id), ctor.node.dec, + ctor.node.body, ctor.span, ctor.node.id, e, v) + +} + fn visit_fn(fk: fn_kind, decl: fn_decl, body: blk, _sp: span, _id: node_id, e: E, v: vt) { visit_fn_decl(decl, e, v); diff --git a/src/rustc/metadata/astencode.rs b/src/rustc/metadata/astencode.rs index b2aa4fe312f0..1b007b348afa 100644 --- a/src/rustc/metadata/astencode.rs +++ b/src/rustc/metadata/astencode.rs @@ -1,3 +1,5 @@ +import util::ppaux::ty_to_str; + import syntax::ast; import syntax::fold; import syntax::visit; @@ -200,8 +202,14 @@ fn visit_ids(item: ast::inlined_item, vfn: fn@(ast::node_id)) { vfn(id); alt fk { + visit::fk_ctor(nm, tps, self_id, parent_id) { + vec::iter(tps) {|tp| vfn(tp.id)} + vfn(id); + vfn(self_id); + vfn(parent_id.node); + } visit::fk_item_fn(_, tps) | - visit::fk_res(_, tps) | visit::fk_ctor(_, tps) { + visit::fk_res(_, tps) { vec::iter(tps) {|tp| vfn(tp.id)} } visit::fk_method(_, tps, m) { @@ -376,6 +384,13 @@ fn simplify_ast(ii: ast::inlined_item) -> ast::inlined_item { ast::ii_native(i) { ast::ii_native(fld.fold_native_item(i)) } + ast::ii_ctor(ctor, nm, tps, parent_id) { + let ctor_body = fld.fold_block(ctor.node.body); + let ctor_decl = fold::fold_fn_decl(ctor.node.dec, fld); + ast::ii_ctor({node: {body: ctor_body, dec: ctor_decl + with ctor.node} + with ctor}, nm, tps, parent_id) + } } } @@ -403,7 +418,17 @@ fn renumber_ast(xcx: extended_decode_ctxt, ii: ast::inlined_item) ast::ii_native(i) { ast::ii_native(fld.fold_native_item(i)) } - } + ast::ii_ctor(ctor, nm, tps, parent_id) { + let ctor_body = fld.fold_block(ctor.node.body); + let ctor_decl = fold::fold_fn_decl(ctor.node.dec, fld); + let new_params = fold::fold_ty_params(tps, fld); + let ctor_id = fld.new_id(ctor.node.id); + let new_parent = xcx.tr_def_id(parent_id); + ast::ii_ctor({node: {body: ctor_body, dec: ctor_decl, id: ctor_id + with ctor.node} + with ctor}, nm, new_params, new_parent) + } + } } // ______________________________________________________________________ diff --git a/src/rustc/metadata/encoder.rs b/src/rustc/metadata/encoder.rs index 197f8be6f02c..4587c1c740df 100644 --- a/src/rustc/metadata/encoder.rs +++ b/src/rustc/metadata/encoder.rs @@ -368,6 +368,7 @@ fn encode_privacy(ebml_w: ebml::writer, privacy: privacy) { /* Returns an index of items in this class */ fn encode_info_for_class(ecx: @encode_ctxt, ebml_w: ebml::writer, id: node_id, path: ast_map::path, + class_tps: [ty_param], items: [@class_member], global_index: @mut[entry]) -> [entry] { @@ -397,13 +398,10 @@ fn encode_info_for_class(ecx: @encode_ctxt, ebml_w: ebml::writer, but it works for now -- tjc */ *global_index += [{val: m.id, pos: ebml_w.writer.tell()}]; let impl_path = path + [ast_map::path_name(m.ident)]; - /* - Recall methods are (currently) monomorphic, and we don't - repeat the class's ty params in the method decl - */ #debug("encode_info_for_class: doing %s %d", m.ident, m.id); encode_info_for_method(ecx, ebml_w, impl_path, - should_inline(m.attrs), id, m, []); + should_inline(m.attrs), id, m, + class_tps + m.tps); } _ { /* don't encode private methods */ } } @@ -415,7 +413,8 @@ fn encode_info_for_class(ecx: @encode_ctxt, ebml_w: ebml::writer, fn encode_info_for_fn(ecx: @encode_ctxt, ebml_w: ebml::writer, id: node_id, ident: ident, path: ast_map::path, - item: option<@item>, tps: [ty_param], decl: fn_decl) { + item: option, tps: [ty_param], + decl: fn_decl) { ebml_w.start_tag(tag_items_data_item); encode_name(ebml_w, ident); encode_def_id(ebml_w, local_def(id)); @@ -428,7 +427,7 @@ fn encode_info_for_fn(ecx: @encode_ctxt, ebml_w: ebml::writer, encode_path(ebml_w, path, ast_map::path_name(ident)); alt item { some(it) { - astencode::encode_inlined_item(ecx, ebml_w, path, ii_item(it)); + astencode::encode_inlined_item(ecx, ebml_w, path, it); } none { encode_symbol(ecx, ebml_w, id); @@ -441,7 +440,7 @@ fn encode_info_for_method(ecx: @encode_ctxt, ebml_w: ebml::writer, impl_path: ast_map::path, should_inline: bool, parent_id: node_id, m: @method, all_tps: [ty_param]) { - #debug("encode_info_for_method: %d %s", m.id, m.ident); + #debug("encode_info_for_method: %d %s %u", m.id, m.ident, all_tps.len()); ebml_w.start_tag(tag_items_data_item); encode_def_id(ebml_w, local_def(m.id)); encode_family(ebml_w, purity_fn_family(m.decl.purity)); @@ -562,8 +561,8 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item, These come first because we need to write them to make the index, and the index needs to be in the item for the class itself */ - let idx = encode_info_for_class(ecx, ebml_w, item.id, path, items, - index); + let idx = encode_info_for_class(ecx, ebml_w, item.id, path, tps, + items, index); /* Index the class*/ add_to_index(); /* Now, make an item for the class itself */ @@ -594,6 +593,7 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item, #debug("Writing %s %d", m.ident, m.id); encode_family(ebml_w, purity_fn_family(m.decl.purity)); encode_name(ebml_w, m.ident); + encode_type_param_bounds(ebml_w, ecx, tps + m.tps); encode_type(ecx, ebml_w, node_id_to_type(tcx, m.id)); encode_def_id(ebml_w, local_def(m.id)); ebml_w.end_tag(); @@ -727,7 +727,6 @@ fn encode_info_for_items(ecx: @encode_ctxt, ebml_w: ebml::writer, alt check ecx.ccx.tcx.items.get(i.id) { ast_map::node_item(_, pt) { encode_info_for_item(ecx, ebml_w, i, index, *pt); - /* TODO: encode info for class items! */ /* encode ctor, then encode items */ alt i.node { item_class(tps,_,ctor) { @@ -737,7 +736,10 @@ fn encode_info_for_items(ecx: @encode_ctxt, ebml_w: ebml::writer, ctor.node.id); *index += [{val: ctor.node.id, pos: ebml_w.writer.tell()}]; encode_info_for_fn(ecx, ebml_w, ctor.node.id, i.ident, - *pt, none, tps, ctor.node.dec) + *pt, if tps.len() > 0u { + some(ii_ctor(ctor, i.ident, tps, + local_def(i.id))) } + else { none }, tps, ctor.node.dec) } _ {} } diff --git a/src/rustc/middle/ast_map.rs b/src/rustc/middle/ast_map.rs index 46709abaa408..b4a6e194b38c 100644 --- a/src/rustc/middle/ast_map.rs +++ b/src/rustc/middle/ast_map.rs @@ -44,10 +44,16 @@ enum ast_node { // order they are introduced. node_arg(arg, uint), node_local(uint), - node_ctor(@item, @path), + // Constructor for either a resource or a class + node_ctor(ident, [ty_param], a_ctor, @path), node_block(blk), } +enum a_ctor { + res_ctor(fn_decl, node_id, codemap::span), + class_ctor(@class_ctor, def_id /* ID for parent class */), +} + type map = std::map::hashmap; type ctx = {map: map, mut path: path, mut local_id: uint, sess: session}; @@ -99,7 +105,7 @@ fn map_decoded_item(sess: session, map: map, path: path, ii: inlined_item) { // don't decode and instantiate the impl, but just the method, we have to // add it to the table now: alt ii { - ii_item(i) { /* fallthrough */ } + ii_item(_) | ii_ctor(_,_,_,_) { /* fallthrough */ } ii_native(i) { cx.map.insert(i.id, node_native_item(i, native_abi_rust_intrinsic, @path)); @@ -119,6 +125,16 @@ fn map_fn(fk: visit::fn_kind, decl: fn_decl, body: blk, cx.map.insert(a.id, node_arg(a, cx.local_id)); cx.local_id += 1u; } + alt fk { + visit::fk_ctor(nm, tps, self_id, parent_id) { + let ct = @{node: {id: id, self_id: self_id, + dec: decl, body: body}, + span: sp}; + cx.map.insert(id, node_ctor(nm, tps, class_ctor(ct, parent_id), + @cx.path)); + } + _ {} + } visit::visit_fn(fk, decl, body, sp, id, cx, v); } @@ -166,8 +182,10 @@ fn map_item(i: @item, cx: ctx, v: vt) { map_method(impl_did, extend(cx, i.ident), m, cx); } } - item_res(_, _, _, dtor_id, ctor_id) { - cx.map.insert(ctor_id, node_ctor(i, item_path)); + item_res(decl, tps, _, dtor_id, ctor_id) { + cx.map.insert(ctor_id, node_ctor(i.ident, tps, + res_ctor(decl, ctor_id, i.span), + item_path)); cx.map.insert(dtor_id, node_item(i, item_path)); } item_enum(vs, _) { @@ -186,7 +204,6 @@ fn map_item(i: @item, cx: ctx, v: vt) { } } item_class(_, items, ctor) { - cx.map.insert(ctor.node.id, node_ctor(i, item_path)); let d_id = ast_util::local_def(i.id); let p = extend(cx, i.ident); for items.each {|ci| @@ -267,7 +284,7 @@ fn node_id_to_str(map: map, id: node_id) -> str { some(node_local(_)) { // FIXME: add more info here #fmt["local (id=%?)", id] } - some(node_ctor(_, _)) { // FIXME: add more info here + some(node_ctor(_, _, _, _)) { // FIXME: add more info here #fmt["node_ctor (id=%?)", id] } some(node_block(_)) { diff --git a/src/rustc/middle/mutbl.rs b/src/rustc/middle/mutbl.rs index 633960f93515..d6488334311e 100644 --- a/src/rustc/middle/mutbl.rs +++ b/src/rustc/middle/mutbl.rs @@ -214,15 +214,15 @@ fn visit_expr(ex: @expr, &&cx: @ctx, v: visit::vt<@ctx>) { fn visit_item(item: @item, &&cx: @ctx, v: visit::vt<@ctx>) { alt item.node { - item_class(tps, items, ctor) { - v.visit_ty_params(tps, cx, v); - vec::map::<@class_member, ()>(items, - {|i| v.visit_class_item(i, cx, v); }); - v.visit_fn(visit::fk_ctor(item.ident, tps), ctor.node.dec, - ctor.node.body, ctor.span, ctor.node.id, - @{in_ctor: some(ctor.node.self_id) with *cx}, v); - } - _ { visit::visit_item(item, cx, v); } + item_class(tps, items, ctor) { + v.visit_ty_params(tps, cx, v); + vec::map::<@class_member, ()>(items, + {|i| v.visit_class_item(i, cx, v); }); + visit::visit_class_ctor_helper(ctor, item.ident, tps, + ast_util::local_def(item.id), + @{in_ctor: some(ctor.node.self_id) with *cx}, v); + } + _ { visit::visit_item(item, cx, v); } } } diff --git a/src/rustc/middle/resolve.rs b/src/rustc/middle/resolve.rs index fc4ea88581eb..611a3e36d051 100644 --- a/src/rustc/middle/resolve.rs +++ b/src/rustc/middle/resolve.rs @@ -572,7 +572,7 @@ fn visit_fn_with_scope(e: @env, fk: visit::fn_kind, decl: ast::fn_decl, for decl.constraints.each {|c| resolve_constr(e, c, sc, v); } let scope = alt fk { visit::fk_item_fn(_, tps) | visit::fk_res(_, tps) | - visit::fk_method(_, tps, _) | visit::fk_ctor(_, tps) + visit::fk_method(_, tps, _) | visit::fk_ctor(_, tps, _, _) { scope_bare_fn(decl, id, tps) } visit::fk_anon(ast::proto_bare) { scope_bare_fn(decl, id, []) } visit::fk_anon(_) | visit::fk_fn_block { scope_fn_expr(decl, id, []) } diff --git a/src/rustc/middle/trans/base.rs b/src/rustc/middle/trans/base.rs index 93f88b158c2a..fcb983a7291f 100644 --- a/src/rustc/middle/trans/base.rs +++ b/src/rustc/middle/trans/base.rs @@ -1906,11 +1906,7 @@ fn monomorphic_fn(ccx: @crate_ctxt, fn_id: ast::def_id, real_substs: [ty::t], ret {val: get_item_val(ccx, fn_id.node), must_cast: true}; } - ast_map::node_ctor(i, _) { - alt check ccx.tcx.items.get(i.id) { - ast_map::node_item(i, pt) { (pt, i.ident) } - } - } + ast_map::node_ctor(nm, _, _, pt) { (pt, nm) } _ { fail "unexpected node type"; } }; let mono_ty = ty::substitute_type_params(ccx.tcx, substs, item_ty); @@ -1950,19 +1946,19 @@ fn monomorphic_fn(ccx: @crate_ctxt, fn_id: ast::def_id, real_substs: [ty::t], trans_fn(ccx, pt, mth.decl, mth.body, lldecl, impl_self(selfty), psubsts, fn_id.node); } - ast_map::node_ctor(i, _) { - alt check i.node { - ast::item_res(decl, _, _, _, _) { + ast_map::node_ctor(nm, tps, ct, _) { + alt ct { + ast_map::res_ctor(decl,_, _) { set_inline_hint(lldecl); trans_res_ctor(ccx, pt, decl, fn_id.node, psubsts, lldecl); } - ast::item_class(tps, _, ctor) { - set_inline_hint_if_appr(i.attrs, lldecl); + ast_map::class_ctor(ctor, parent_id) { + // ctors don't have attrs, at least not right now let tp_tys: [ty::t] = ty::ty_params_to_tys(ccx.tcx, tps); trans_class_ctor(ccx, pt, ctor.node.dec, ctor.node.body, lldecl, option::get_or_default(psubsts, {tys:tp_tys, vtables: none, bounds: @[]}), - fn_id.node, i.id, ctor.span); + fn_id.node, parent_id, ctor.span); } } } @@ -1992,6 +1988,10 @@ fn maybe_instantiate_inline(ccx: @crate_ctxt, fn_id: ast::def_id) trans_item(ccx, *item); local_def(item.id) } + csearch::found(ast::ii_ctor(ctor, nm, tps, parent_id)) { + ccx.external.insert(fn_id, some(ctor.node.id)); + local_def(ctor.node.id) + } csearch::found(ast::ii_native(item)) { ccx.external.insert(fn_id, some(item.id)); local_def(item.id) @@ -4256,17 +4256,17 @@ fn trans_const(ccx: @crate_ctxt, e: @ast::expr, id: ast::node_id) { fn trans_class_ctor(ccx: @crate_ctxt, path: path, decl: ast::fn_decl, body: ast::blk, llctor_decl: ValueRef, psubsts: param_substs, ctor_id: ast::node_id, - parent_id: ast::node_id, sp: span) { + parent_id: ast::def_id, sp: span) { // Add ctor to the ctor map ccx.class_ctors.insert(ctor_id, parent_id); + // Translate the ctor // Set up the type for the result of the ctor // kludgy -- this wouldn't be necessary if the typechecker // special-cased constructors, then we could just look up // the ctor's return type. - let rslt_ty = ty::mk_class(ccx.tcx, local_def(parent_id), - psubsts.tys); + let rslt_ty = ty::mk_class(ccx.tcx, parent_id, psubsts.tys); // Make the fn context let fcx = new_fn_ctxt_w_id(ccx, path, llctor_decl, ctor_id, some(psubsts), some(sp)); @@ -4280,10 +4280,10 @@ fn trans_class_ctor(ccx: @crate_ctxt, path: path, decl: ast::fn_decl, // We *don't* want self to be passed to the ctor -- that // wouldn't make sense // So we initialize it here + let selfptr = alloc_ty(bcx_top, rslt_ty); // initialize fields to zero - let fields = ty::class_items_as_fields(bcx_top.tcx(), - local_def(parent_id), + let fields = ty::class_items_as_fields(bcx_top.tcx(), parent_id, psubsts.tys); let mut bcx = bcx_top; // Initialize fields to zero so init assignments can validly @@ -4381,7 +4381,7 @@ fn trans_item(ccx: @crate_ctxt, item: ast::item) { bounds: @[]}; trans_class_ctor(ccx, *path, ctor.node.dec, ctor.node.body, get_item_val(ccx, ctor.node.id), psubsts, - ctor.node.id, item.id, ctor.span); + ctor.node.id, local_def(item.id), ctor.span); } // If there are ty params, the ctor will get monomorphized @@ -4542,6 +4542,7 @@ fn item_path(ccx: @crate_ctxt, i: @ast::item) -> path { } fn get_item_val(ccx: @crate_ctxt, id: ast::node_id) -> ValueRef { + #debug("get_item_val: %d", id); alt ccx.item_vals.find(id) { some(v) { v } none { @@ -4593,16 +4594,16 @@ fn get_item_val(ccx: @crate_ctxt, id: ast::node_id) -> ValueRef { exprt = true; register_fn(ccx, ni.span, *pth + [path_name(ni.ident)], ni.id) } - ast_map::node_ctor(i, _) { - alt check i.node { - ast::item_res(_, _, _, _, _) { - let my_path = item_path(ccx, i); - let llctor = register_fn(ccx, i.span, my_path, id); + ast_map::node_ctor(nm, tps, ct, pt) { + let my_path = *pt + [path_name(nm)]; + alt ct { + ast_map::res_ctor(_,_,sp) { + let llctor = register_fn(ccx, sp, my_path, id); set_inline_hint(llctor); llctor } - ast::item_class(_, _, ctor) { - register_fn(ccx, i.span, item_path(ccx, i), id) + ast_map::class_ctor(ctor, _) { + register_fn(ccx, ctor.span, my_path, ctor.node.id) } } } @@ -4923,7 +4924,7 @@ fn trans_crate(sess: session::session, crate: @ast::crate, tcx: ty::ctxt, shape_cx: mk_ctxt(llmod), crate_map: crate_map, dbg_cx: dbg_cx, - class_ctors: int_hash::(), + class_ctors: int_hash::(), mut do_not_commit_warning_issued: false}; diff --git a/src/rustc/middle/trans/common.rs b/src/rustc/middle/trans/common.rs index c089361bda04..36c75398b994 100644 --- a/src/rustc/middle/trans/common.rs +++ b/src/rustc/middle/trans/common.rs @@ -121,7 +121,9 @@ type crate_ctxt = { dbg_cx: option, // Mapping from class constructors to parent class -- // used in base::trans_closure - class_ctors: hashmap, + // parent_class must be a def_id because ctors can be + // inlined, so the parent may be in a different crate + class_ctors: hashmap, mut do_not_commit_warning_issued: bool}; // Types used for llself. diff --git a/src/rustc/middle/trans/debuginfo.rs b/src/rustc/middle/trans/debuginfo.rs index 42f762ac1b53..5406ec7ce98a 100644 --- a/src/rustc/middle/trans/debuginfo.rs +++ b/src/rustc/middle/trans/debuginfo.rs @@ -757,13 +757,14 @@ fn create_function(fcx: fn_ctxt) -> @metadata { ast_map::node_method(method, _, _) { (method.ident, method.decl.output, method.id) } - ast_map::node_ctor(item, _) { - alt item.node { - ast::item_res(decl, _, _, _, ctor_id) { - (item.ident, decl.output, ctor_id) - } - _ { fcx.ccx.sess.span_bug(item.span, "create_function: \ - expected an item_res here"); } + ast_map::node_ctor(nm, _, ct, _) { + alt ct { + ast_map::res_ctor(decl, ctor_id, _) { + (nm, decl.output, ctor_id) + } + ast_map::class_ctor(ctor,_) { + fcx.ccx.sess.span_bug(ctor.span, "create_function: \ + expected a resource ctor here"); } } } ast_map::node_expr(expr) { diff --git a/src/rustc/middle/trans/type_use.rs b/src/rustc/middle/trans/type_use.rs index b220f30a5ac3..cbed8a0dbc55 100644 --- a/src/rustc/middle/trans/type_use.rs +++ b/src/rustc/middle/trans/type_use.rs @@ -58,13 +58,18 @@ fn type_uses_for(ccx: @crate_ctxt, fn_id: def_id, n_tps: uint) ccx.type_use_cache.insert(fn_id, uses); ret uses; } - alt check ccx.tcx.items.get(fn_id_loc.node) { + let map_node = alt ccx.tcx.items.find(fn_id_loc.node) { + some(x) { x } + none { ccx.sess.bug(#fmt("type_uses_for: unbound item ID %?", + fn_id_loc)); } + }; + alt check map_node { ast_map::node_item(@{node: item_fn(_, _, body), _}, _) | ast_map::node_item(@{node: item_res(_, _, body, _, _), _}, _) | ast_map::node_method(@{body, _}, _, _) { handle_body(cx, body); } - ast_map::node_ctor(@{node: item_res(_, _, _, _, _), _},_) | + ast_map::node_ctor(_, _, ast_map::res_ctor(_, _, _), _) | ast_map::node_variant(_, _, _) { uint::range(0u, n_tps) {|n| cx.uses[n] |= use_repr;} } @@ -79,7 +84,7 @@ fn type_uses_for(ccx: @crate_ctxt, fn_id: def_id, n_tps: uint) uint::range(0u, n_tps) {|n| cx.uses[n] |= flags;} } } - ast_map::node_ctor(@{node: item_class(_, _, ctor), _}, _) { + ast_map::node_ctor(_, _, ast_map::class_ctor(ctor, _), _){ handle_body(cx, ctor.node.body); } } diff --git a/src/rustc/middle/tstate/ck.rs b/src/rustc/middle/tstate/ck.rs index decf1af6401c..c04d9ad1e758 100644 --- a/src/rustc/middle/tstate/ck.rs +++ b/src/rustc/middle/tstate/ck.rs @@ -111,7 +111,7 @@ fn check_states_against_conditions(fcx: fn_ctxt, /* Check that the return value is initialized */ let post = aux::block_poststate(fcx.ccx, f_body); - let is_ctor = alt fk { visit::fk_ctor(_,_) { true } _ { false } }; + let is_ctor = alt fk { visit::fk_ctor(_,_,_,_) { true } _ { false } }; if !is_ctor && !promises(fcx, post, fcx.enclosing.i_return) && !ty::type_is_nil(ty::ty_fn_ret(ty::node_id_to_type( fcx.ccx.tcx, id))) && diff --git a/src/rustc/middle/ty.rs b/src/rustc/middle/ty.rs index 094d2f90d5d9..f4d134459be0 100644 --- a/src/rustc/middle/ty.rs +++ b/src/rustc/middle/ty.rs @@ -2043,8 +2043,8 @@ fn item_path(cx: ctxt, id: ast::def_id) -> ast_map::path { vec::init(*path) + [ast_map::path_name(variant.node.name)] } - ast_map::node_ctor(i, path) { - *path + [ast_map::path_name(i.ident)] + ast_map::node_ctor(nm, _, _, path) { + *path + [ast_map::path_name(nm)] } ast_map::node_expr(_) | ast_map::node_arg(_, _) | @@ -2121,7 +2121,6 @@ fn lookup_item_type(cx: ctxt, did: ast::def_id) -> ty_param_bounds_and_ty { alt cx.tcache.find(did) { some(tpt) { ret tpt; } none { - #debug("lookup_item_type: looking up %?", did); // The item is in this crate. The caller should have added it to the // type cache already assert did.crate != ast::local_crate; @@ -2168,7 +2167,10 @@ fn lookup_class_fields(cx: ctxt, did: ast::def_id) -> [field_ty] { _ { cx.sess.bug("class ID bound to non-class"); } } } - _ { cx.sess.bug("class ID not bound to an item"); } + _ { + cx.sess.bug(#fmt("class ID not bound to an item: %s", + ast_map::node_id_to_str(cx.items, did.node))); + } } } else { diff --git a/src/rustc/middle/typeck.rs b/src/rustc/middle/typeck.rs index 83b07b9e86c6..f89a34e668ff 100644 --- a/src/rustc/middle/typeck.rs +++ b/src/rustc/middle/typeck.rs @@ -2149,6 +2149,20 @@ fn impl_self_ty(tcx: ty::ctxt, did: ast::def_id) -> {n_tps: uint, ty: ty::t} { } } +/* + Takes arguments describing a method, and returns either its origin, + or if it's unbound. + + expr: the entire method reference + node_id: the method's ID + name: the method's name + ty: the type of the base expression + tps: the ty substitutions that are part of the field expr + (for example: in foo.bar(), tps would be + [int, char]) + include_private: true if we're inside the same class and should + search private methods + */ fn lookup_method(fcx: @fn_ctxt, expr: @ast::expr, node_id: ast::node_id, name: ast::ident, ty: ty::t, tps: [ty::t], include_private: bool) @@ -2159,7 +2173,12 @@ fn lookup_method(fcx: @fn_ctxt, expr: @ast::expr, node_id: ast::node_id, let mut substs = substs; let n_tps = vec::len(substs), n_tys = vec::len(tps); let has_self = ty::type_has_vars(fty); + /* If either the method was declared to have ty params, + or ty arguments were provided, or both... */ if method_n_tps + n_tps > 0u { + /* If no type arguments were given, + or a different number of them were given than the + method's declared types... */ if n_tys == 0u || n_tys != method_n_tps { if n_tys != 0u { tcx.sess.span_err @@ -2167,12 +2186,18 @@ fn lookup_method(fcx: @fn_ctxt, expr: @ast::expr, node_id: ast::node_id, parameters given for this method"); } + /* If not enough types were given, make some ty vars */ substs += vec::from_fn(method_n_tps, {|_i| ty::mk_var(tcx, next_ty_var_id(fcx)) }); } else { + /* If the right number of types were given, just add them on */ substs += tps; } + /* + For a class method, "substs" here begins with the class ty + params + */ fcx.write_ty_substs(node_id, fty, substs); } else { if n_tys > 0u { @@ -2209,7 +2234,6 @@ fn lookup_method_inner_(tcx: ty::ctxt, ms: [ty::method], include_private: bool) -> option<{method_ty: ty::t, n_tps: uint, substs: [ty::t], origin: method_origin, self_sub: option}> { - #debug("lookup_method_inner_: %? %? %s", ms, parent, name); let mut i = 0u; for ms.each {|m| if m.ident == name { @@ -2228,6 +2252,8 @@ fn lookup_method_inner_(tcx: ty::ctxt, ms: [ty::method], sp, "Call to private method not allowed outside \ its defining class"); } + #debug("lookup_method_inner_: %s has %u ty params, by its \ + declaration", name, vec::len(*m.tps)); ret some({method_ty: fty, n_tps: vec::len(*m.tps), substs: tps, diff --git a/src/test/auxiliary/cci_class_6.rs b/src/test/auxiliary/cci_class_6.rs new file mode 100644 index 000000000000..15fa3e3e7855 --- /dev/null +++ b/src/test/auxiliary/cci_class_6.rs @@ -0,0 +1,21 @@ +mod kitties { + +class cat { + priv { + let mut info : [U]; + let mut meows : uint; + } + + let how_hungry : int; + + new(in_x : uint, in_y : int, -in_info: [U]) + { self.meows = in_x; self.how_hungry = in_y; + self.info <- in_info; } + + fn speak(stuff: [T]) { + self.meows += stuff.len(); + } + fn meow_count() -> uint { self.meows } +} + +} diff --git a/src/test/run-pass/class-poly-methods-cross-crate.rs b/src/test/run-pass/class-poly-methods-cross-crate.rs new file mode 100644 index 000000000000..28ddbfdd1e2f --- /dev/null +++ b/src/test/run-pass/class-poly-methods-cross-crate.rs @@ -0,0 +1,15 @@ +// xfail-fast +// aux-build:cci_class_6.rs +use cci_class_6; +import cci_class_6::kitties::*; + +fn main() { + let nyan : cat = cat::(52u, 99, ['p']); + let kitty = cat(1000u, 2, ["tabby"]); + assert(nyan.how_hungry == 99); + assert(kitty.how_hungry == 2); + nyan.speak([1u,2u,3u]); + assert(nyan.meow_count() == 55u); + kitty.speak(["meow", "mew", "purr", "chirp"]); + assert(kitty.meow_count() == 1004u); +} diff --git a/src/test/run-pass/class-poly-methods.rs b/src/test/run-pass/class-poly-methods.rs index 0a96b1754d5d..0d738913ee56 100644 --- a/src/test/run-pass/class-poly-methods.rs +++ b/src/test/run-pass/class-poly-methods.rs @@ -1,5 +1,3 @@ -// xfail-test -// needs metadata encoding on Windows class cat { priv { let mut info : [U];