diff options
| author | Tim Chevalier <chevalier@alum.wellesley.edu> | 2012-04-10 10:52:06 -0700 |
|---|---|---|
| committer | Tim Chevalier <chevalier@alum.wellesley.edu> | 2012-04-10 11:01:36 -0700 |
| commit | fd26743bedbd10f4c1cad7aecff50de6282d32dd (patch) | |
| tree | 3ce0e7a34633a86f91f177ae84683232fcf971de /src/rustc | |
| parent | b2ec26c15283def5d5d8bcdd74bfdd84e918c46e (diff) | |
| download | rust-fd26743bedbd10f4c1cad7aecff50de6282d32dd.tar.gz rust-fd26743bedbd10f4c1cad7aecff50de6282d32dd.zip | |
Generic classes and generic class methods work cross-crate
Classes can have ty params now. So can methods inside classes. That was probably true before, but now it should still work if you call methods in a class that's defined in a different crate. Yay!
Diffstat (limited to 'src/rustc')
| -rw-r--r-- | src/rustc/metadata/astencode.rs | 29 | ||||
| -rw-r--r-- | src/rustc/metadata/encoder.rs | 26 | ||||
| -rw-r--r-- | src/rustc/middle/ast_map.rs | 29 | ||||
| -rw-r--r-- | src/rustc/middle/mutbl.rs | 18 | ||||
| -rw-r--r-- | src/rustc/middle/resolve.rs | 2 | ||||
| -rw-r--r-- | src/rustc/middle/trans/base.rs | 51 | ||||
| -rw-r--r-- | src/rustc/middle/trans/common.rs | 4 | ||||
| -rw-r--r-- | src/rustc/middle/trans/debuginfo.rs | 15 | ||||
| -rw-r--r-- | src/rustc/middle/trans/type_use.rs | 11 | ||||
| -rw-r--r-- | src/rustc/middle/tstate/ck.rs | 2 | ||||
| -rw-r--r-- | src/rustc/middle/ty.rs | 10 | ||||
| -rw-r--r-- | src/rustc/middle/typeck.rs | 28 |
12 files changed, 153 insertions, 72 deletions
diff --git a/src/rustc/metadata/astencode.rs b/src/rustc/metadata/astencode.rs index b2aa4fe312f..1b007b348af 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 197f8be6f02..4587c1c740d 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<int>]) -> [entry<int>] { @@ -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<inlined_item>, 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 46709abaa40..b4a6e194b38 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<node_id, ast_node>; 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 633960f9351..d6488334311 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 fc4ea88581e..611a3e36d05 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 93f88b158c2..fcb983a7291 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::<int>(), + class_ctors: int_hash::<ast::def_id>(), mut do_not_commit_warning_issued: false}; diff --git a/src/rustc/middle/trans/common.rs b/src/rustc/middle/trans/common.rs index c089361bda0..36c75398b99 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<debuginfo::debug_ctxt>, // Mapping from class constructors to parent class -- // used in base::trans_closure - class_ctors: hashmap<ast::node_id, ast::node_id>, + // parent_class must be a def_id because ctors can be + // inlined, so the parent may be in a different crate + class_ctors: hashmap<ast::node_id, ast::def_id>, 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 42f762ac1b5..5406ec7ce98 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<subprogram_md> { 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 b220f30a5ac..cbed8a0dbc5 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 decf1af6401..c04d9ad1e75 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 094d2f90d5d..f4d134459be 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 83b07b9e86c..f89a34e668f 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 <none> 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<int,char>(), 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<self_subst>}> { - #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, |
