Remove resources

Also fixed shapes for classes with dtors, as well as handling
offsets for classes with dtors correctly in take glue.

Closes #2485
This commit is contained in:
Tim Chevalier 2012-06-24 15:09:57 -07:00
parent 60a748a1d8
commit 487cbf8e90
49 changed files with 145 additions and 728 deletions

View file

@ -186,17 +186,6 @@ fn encode_module_item_paths(ebml_w: ebml::writer, ecx: @encode_ctxt,
encode_name_and_def_id(ebml_w, it.ident, it.id);
}
}
item_res(_, tps, _, _, ctor_id, _) {
ebml_w.wr_tag(tag_paths_data_item) {||
encode_name_and_def_id(ebml_w, it.ident, ctor_id);
}
// The same ident has to be added twice (with different positions)
// because it's for both the ctor and the dtor.
add_to_index(ebml_w, path, index, it.ident);
ebml_w.wr_tag(tag_paths_data_item) {||
encode_name_and_def_id(ebml_w, it.ident, it.id);
}
}
item_class(_, _, items, ctor, m_dtor, _) {
ebml_w.wr_tag(tag_paths_data_item) {||
encode_name_and_def_id(ebml_w, it.ident, it.id);
@ -698,34 +687,6 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
encode_index(ebml_w, bkts, write_int);
ebml_w.end_tag();
}
item_res(_, tps, _, _, ctor_id, rp) {
add_to_index();
let fn_ty = node_id_to_type(tcx, ctor_id);
ebml_w.start_tag(tag_items_data_item);
encode_def_id(ebml_w, local_def(ctor_id));
encode_family(ebml_w, 'y');
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);
ecx.encode_inlined_item(ecx, ebml_w, path, ii_item(item));
if (tps.len() == 0u) {
encode_symbol(ecx, ebml_w, item.id);
}
encode_path(ebml_w, path, ast_map::path_name(item.ident));
encode_region_param(ebml_w, rp);
ebml_w.end_tag();
*index += [{val: ctor_id, pos: ebml_w.writer.tell()}];
ebml_w.start_tag(tag_items_data_item);
encode_def_id(ebml_w, local_def(ctor_id));
encode_family(ebml_w, 'f');
encode_type_param_bounds(ebml_w, ecx, tps);
encode_type(ecx, ebml_w, fn_ty);
encode_parent_item(ebml_w, local_def(item.id));
encode_path(ebml_w, path, ast_map::path_name(item.ident));
ebml_w.end_tag();
}
item_impl(tps, rp, ifce, _, methods) {
add_to_index();
ebml_w.start_tag(tag_items_data_item);

View file

@ -338,14 +338,6 @@ fn parse_ty(st: @pstate, conv: conv_did) -> ty::t {
'f' {
parse_ty_rust_fn(st, conv)
}
'r' {
assert next(st) == '[';
let def = parse_def(st, conv);
let inner = parse_ty(st, conv);
let substs = parse_substs(st, conv);
assert next(st) == ']';
ret ty::mk_res(st.tcx, def, inner, substs);
}
'X' {
ret ty::mk_var(st.tcx, ty::tv_vid(parse_int(st) as uint));
}

View file

@ -265,14 +265,6 @@ fn enc_sty(w: io::writer, cx: @ctxt, st: ty::sty) {
ty::ty_fn(f) {
enc_ty_fn(w, cx, f);
}
ty::ty_res(def, ty, substs) {
w.write_str("r["/&);
w.write_str(cx.ds(def));
w.write_char('|');
enc_ty(w, cx, ty);
enc_substs(w, cx, substs);
w.write_char(']');
}
ty::ty_var(id) {
w.write_char('X');
w.write_uint(id.to_uint());

View file

@ -249,7 +249,6 @@ enum ptr_kind {uniq_ptr, gc_ptr, region_ptr, unsafe_ptr}
// structure accessible without a dereference":
enum comp_kind {
comp_tuple, // elt in a tuple
comp_res, // data for a resource
comp_variant(ast::def_id), // internals to a variant of given enum
comp_field(ast::ident, // name of field
ast::mutability), // declared mutability of field
@ -423,7 +422,6 @@ impl to_str_methods for borrowck_ctxt {
comp_field(fld, _) { *fld }
comp_index(*) { "[]" }
comp_tuple { "()" }
comp_res { "<res>" }
comp_variant(_) { "<enum>" }
}
}
@ -483,7 +481,6 @@ impl to_str_methods for borrowck_ctxt {
}
cat_comp(_, comp_field(*)) { mut_str + " field" }
cat_comp(_, comp_tuple) { "tuple content" }
cat_comp(_, comp_res) { "resource content" }
cat_comp(_, comp_variant(_)) { "enum content" }
cat_comp(_, comp_index(t, _)) {
alt ty::get(t).struct {
@ -530,7 +527,7 @@ impl to_str_methods for borrowck_ctxt {
// mutable structure.
fn inherent_mutability(ck: comp_kind) -> mutability {
alt ck {
comp_tuple | comp_res | comp_variant(_) {m_imm}
comp_tuple | comp_variant(_) {m_imm}
comp_field(_, m) | comp_index(_, m) {m}
}
}

View file

@ -71,10 +71,6 @@ fn opt_deref_kind(t: ty::t) -> option<deref_kind> {
some(deref_comp(comp_variant(did)))
}
ty::ty_res(*) {
some(deref_comp(comp_res))
}
ty::ty_evec(mt, ty::vstore_fixed(_)) {
some(deref_comp(comp_index(t, mt.mutbl)))
}

View file

@ -532,7 +532,7 @@ fn check_loans_in_fn(fk: visit::fn_kind, decl: ast::fn_decl, body: ast::blk,
}
visit::fk_anon(*) | visit::fk_fn_block(*) |
visit::fk_method(*) | visit::fk_item_fn(*) |
visit::fk_res(*) | visit::fk_dtor(*) {
visit::fk_dtor(*) {
self.in_ctor = false;
self.declared_purity = decl.purity;
self.fn_args = @decl.inputs.map({|i| i.id});

View file

@ -57,8 +57,7 @@ impl loan_methods for loan_ctxt {
}
cat_comp(cmt_base, comp_field(*)) |
cat_comp(cmt_base, comp_index(*)) |
cat_comp(cmt_base, comp_tuple) |
cat_comp(cmt_base, comp_res) {
cat_comp(cmt_base, comp_tuple) {
// For most components, the type of the embedded data is
// stable. Therefore, the base structure need only be
// const---unless the component must be immutable. In

View file

@ -43,8 +43,7 @@ impl public_methods for borrowck_ctxt {
}
cat_comp(cmt_base, comp_field(*)) |
cat_comp(cmt_base, comp_index(*)) |
cat_comp(cmt_base, comp_tuple) |
cat_comp(cmt_base, comp_res) {
cat_comp(cmt_base, comp_tuple) {
// Most embedded components: if the base is stable, the
// type never changes.
self.preserve(cmt_base, opt_scope_id)

View file

@ -22,8 +22,8 @@ import lint::{non_implicitly_copyable_typarams,implicit_copies};
// const: Things thare are deeply immutable. They are guaranteed never to
// change, and can be safely shared without copying between tasks.
//
// Send includes scalar types, resources and unique types containing only
// sendable types.
// Send includes scalar types as well as classes and unique types containing
// only sendable types.
//
// Copy includes boxes, closure and unique types containing copyable types.
//
@ -160,7 +160,7 @@ fn check_fn(fk: visit::fn_kind, decl: fn_decl, body: blk, sp: span,
let cap_clause = alt fk {
visit::fk_anon(_, cc) | visit::fk_fn_block(cc) { cc }
visit::fk_item_fn(*) | visit::fk_method(*) |
visit::fk_res(*) | visit::fk_ctor(*) | visit::fk_dtor(*) { @[] }
visit::fk_ctor(*) | visit::fk_dtor(*) { @[] }
};
let captured_vars = (*cap_clause).map { |cap_item|
let cap_def = cx.tcx.def_map.get(cap_item.id);

View file

@ -359,7 +359,7 @@ fn resolve_fn(fk: visit::fn_kind, decl: ast::fn_decl, body: ast::blk,
visitor: visit::vt<ctxt>) {
let fn_cx = alt fk {
visit::fk_item_fn(*) | visit::fk_method(*) | visit::fk_res(*) |
visit::fk_item_fn(*) | visit::fk_method(*) |
visit::fk_ctor(*) | visit::fk_dtor(*) {
// Top-level functions are a root scope.
{parent: some(id) with cx}

View file

@ -639,9 +639,8 @@ fn visit_fn_with_scope(e: @env, fk: visit::fn_kind, decl: ast::fn_decl,
// for f's constrs in the table.
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_dtor(tps, _, _) {
visit::fk_item_fn(_, tps) | visit::fk_method(_, tps, _)
| visit::fk_ctor(_, tps, _, _) | visit::fk_dtor(tps, _, _) {
scope_bare_fn(decl, id, tps) }
visit::fk_anon(ast::proto_bare, _) {
scope_bare_fn(decl, id, []) }
@ -1333,15 +1332,6 @@ fn found_def_item(i: @ast::item, ns: namespace) -> option<def> {
ast::item_ty(*) | item_iface(*) | item_enum(*) {
if ns == ns_type { ret some(ast::def_ty(local_def(i.id))); }
}
ast::item_res(_, _, _, _, ctor_id, _) {
alt ns {
ns_val {
ret some(ast::def_fn(local_def(ctor_id), ast::impure_fn));
}
ns_type { ret some(ast::def_ty(local_def(i.id))); }
_ { }
}
}
ast::item_class(_, _, _members, ct, _, _) {
alt ns {
ns_type {
@ -1644,7 +1634,7 @@ fn index_mod(md: ast::_mod) -> mod_index {
alt it.node {
ast::item_const(_, _) | ast::item_fn(_, _, _) | ast::item_mod(_) |
ast::item_native_mod(_) | ast::item_ty(_, _, _) |
ast::item_res(*) | ast::item_impl(*) | ast::item_iface(*) {
ast::item_impl(*) | ast::item_iface(*) {
add_to_index(index, it.ident, mie_item(it));
}
ast::item_enum(variants, _, _) {
@ -1868,10 +1858,6 @@ fn check_block(e: @env, b: ast::blk, &&x: (), v: vt<()>) {
ast::item_ty(*) | ast::item_iface(*) {
add_name(types, it.span, it.ident);
}
ast::item_res(*) {
add_name(types, it.span, it.ident);
add_name(values, it.span, it.ident);
}
_ { }
}
}

View file

@ -50,7 +50,7 @@ import type_of::type_of; // Issue #1873
import syntax::ast_map::{path, path_mod, path_name};
import std::smallintmap;
import option::is_none;
import option::{is_none, is_some};
// Destinations
@ -758,8 +758,7 @@ fn trans_class_drop(bcx: block, v0: ValueRef, dtor_did: ast::def_id,
// We have to cast v0
let classptr = GEPi(bcx, v0, [0u, 1u]);
// Find and call the actual destructor
let dtor_addr = get_res_dtor(bcx.ccx(), dtor_did, some(class_did),
substs.tps);
let dtor_addr = get_res_dtor(bcx.ccx(), dtor_did, class_did, substs.tps);
// The second argument is the "self" argument for drop
let params = lib::llvm::fn_ty_param_tys
(llvm::LLVMGetElementType
@ -799,9 +798,6 @@ fn make_drop_glue(bcx: block, v0: ValueRef, t: ty::t) {
ty::ty_unboxed_vec(_) {
tvec::make_drop_glue_unboxed(bcx, v0, t)
}
ty::ty_res(did, inner, substs) {
trans_res_drop(bcx, v0, did, inner, substs.tps)
}
ty::ty_class(did, substs) {
let tcx = bcx.tcx();
alt ty::ty_dtor(tcx, did) {
@ -835,10 +831,7 @@ fn make_drop_glue(bcx: block, v0: ValueRef, t: ty::t) {
}
fn get_res_dtor(ccx: @crate_ctxt, did: ast::def_id,
// Parent ID is an option because resources don't
// have one. We can make this a def_id when
// resources get removed.
opt_id: option<ast::def_id>, substs: [ty::t])
parent_id: ast::def_id, substs: [ty::t])
-> ValueRef {
let _icx = ccx.insn_ctxt("trans_res_dtor");
if (substs.len() > 0u) {
@ -850,54 +843,13 @@ fn get_res_dtor(ccx: @crate_ctxt, did: ast::def_id,
} else if did.crate == ast::local_crate {
get_item_val(ccx, did.node)
} else {
alt opt_id {
some(parent_id) {
let tcx = ccx.tcx;
let name = csearch::get_symbol(ccx.sess.cstore, did);
let class_ty = ty::subst_tps(tcx, substs,
ty::lookup_item_type(tcx, parent_id).ty);
let llty = type_of_dtor(ccx, class_ty);
get_extern_fn(ccx.externs, ccx.llmod, name, lib::llvm::CCallConv,
llty)
}
none {
let fty = ty::mk_fn(ccx.tcx, {purity: ast::impure_fn,
proto: ast::proto_bare,
inputs: [{mode: ast::expl(ast::by_ref),
ty: ty::mk_nil_ptr(ccx.tcx)}],
output: ty::mk_nil(ccx.tcx),
ret_style: ast::return_val,
constraints: []});
trans_external_path(ccx, did, fty)
}
}
}
}
fn trans_res_drop(bcx: block, rs: ValueRef, did: ast::def_id,
inner_t: ty::t, tps: [ty::t]) -> block {
let _icx = bcx.insn_ctxt("trans_res_drop");
let ccx = bcx.ccx();
let inner_t_s = ty::subst_tps(ccx.tcx, tps, inner_t);
let drop_flag = GEPi(bcx, rs, [0u, 0u]);
with_cond(bcx, IsNotNull(bcx, Load(bcx, drop_flag))) {|bcx|
let valptr = GEPi(bcx, rs, [0u, 1u]);
// Find and call the actual destructor.
let dtor_addr = get_res_dtor(ccx, did, none, tps);
let args = [bcx.fcx.llretptr, null_env_ptr(bcx)];
// Kludge to work around the fact that we know the precise type of the
// value here, but the dtor expects a type that might have opaque
// boxes and such.
let val_llty = lib::llvm::fn_ty_param_tys
(llvm::LLVMGetElementType
(llvm::LLVMTypeOf(dtor_addr)))[args.len()];
let val_cast = BitCast(bcx, valptr, val_llty);
Call(bcx, dtor_addr, args + [val_cast]);
let bcx = drop_ty(bcx, valptr, inner_t_s);
Store(bcx, C_u8(0u), drop_flag);
bcx
let tcx = ccx.tcx;
let name = csearch::get_symbol(ccx.sess.cstore, did);
let class_ty = ty::subst_tps(tcx, substs,
ty::lookup_item_type(tcx, parent_id).ty);
let llty = type_of_dtor(ccx, class_ty);
get_extern_fn(ccx.externs, ccx.llmod, name, lib::llvm::CCallConv,
llty)
}
}
@ -1086,12 +1038,6 @@ fn iter_structural_ty(cx: block, av: ValueRef, t: ty::t,
cx = f(cx, llfld_a, arg);
}
}
ty::ty_res(_, inner, substs) {
let tcx = cx.tcx();
let inner1 = ty::subst(tcx, substs, inner);
let llfld_a = GEPi(cx, av, [0u, 1u]);
ret f(cx, llfld_a, inner1);
}
ty::ty_enum(tid, substs) {
let variants = ty::enum_variants(cx.tcx(), tid);
let n_variants = (*variants).len();
@ -1130,10 +1076,15 @@ fn iter_structural_ty(cx: block, av: ValueRef, t: ty::t,
ret next_cx;
}
ty::ty_class(did, substs) {
// Take the drop bit into account
let classptr = if is_some(ty::ty_dtor(cx.tcx(), did)) {
GEPi(cx, av, [0u, 1u])
}
else { av };
for vec::eachi(ty::class_items_as_mutable_fields(cx.tcx(), did,
substs))
{|i, fld|
let llfld_a = GEPi(cx, av, [0u, i]);
let llfld_a = GEPi(cx, classptr, [0u, i]);
cx = f(cx, llfld_a, fld.mt.ty);
}
}
@ -1895,10 +1846,6 @@ fn autoderef(cx: block, e_id: ast::node_id,
t1 = mt.ty;
v1 = v;
}
ty::ty_res(did, inner, substs) {
t1 = ty::subst(ccx.tcx, substs, inner);
v1 = GEPi(cx, v1, [0u, 1u]);
}
ty::ty_enum(did, substs) {
let variants = ty::enum_variants(ccx.tcx, did);
if (*variants).len() != 1u || variants[0].args.len() != 1u {
@ -2221,15 +2168,7 @@ fn monomorphic_fn(ccx: @crate_ctxt, fn_id: ast::def_id, real_substs: [ty::t],
crate?)", fn_id)});
// Get the path so that we can create a symbol
let (pt, name, span) = alt map_node {
ast_map::node_item(i, pt) {
alt i.node {
ast::item_res(_, _, _, dtor_id, _, _) {
item_ty = ty::node_id_to_type(ccx.tcx, dtor_id);
}
_ {}
}
(pt, i.ident, i.span)
}
ast_map::node_item(i, pt) { (pt, i.ident, i.span) }
ast_map::node_variant(v, enm, pt) { (pt, v.node.name, enm.span) }
ast_map::node_method(m, _, pt) { (pt, m.ident, m.span) }
ast_map::node_native_item(i, ast::native_abi_rust_intrinsic, pt)
@ -2239,9 +2178,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(nm, _, ct, pt) { (pt, nm, alt ct {
ast_map::res_ctor(_, _, sp) { sp }
ast_map::class_ctor(ct_, _) { ct_.span }}) }
ast_map::node_ctor(nm, _, ct, _, pt) { (pt, nm, ct.span) }
ast_map::node_dtor(_, dtor, _, pt) {(pt, @"drop", dtor.span)}
ast_map::node_expr(*) { ccx.tcx.sess.bug("Can't monomorphize an expr") }
ast_map::node_export(*) {
@ -2285,12 +2222,6 @@ fn monomorphic_fn(ccx: @crate_ctxt, fn_id: ast::def_id, real_substs: [ty::t],
trans_fn(ccx, pt, decl, body, d, no_self, psubsts, fn_id.node);
d
}
ast_map::node_item(
@{node: ast::item_res(dt, _, body, d_id, _, _), _}, _) {
let d = mk_lldecl();
trans_fn(ccx, pt, dt, body, d, no_self, psubsts, d_id);
d
}
ast_map::node_item(*) {
ccx.tcx.sess.bug("Can't monomorphize this kind of item")
}
@ -2319,24 +2250,15 @@ fn monomorphic_fn(ccx: @crate_ctxt, fn_id: ast::def_id, real_substs: [ty::t],
impl_self(selfty), psubsts, fn_id.node);
d
}
ast_map::node_ctor(nm, tps, ct, _) {
ast_map::node_ctor(nm, tps, ctor, parent_id, _) {
// ctors don't have attrs, at least not right now
let d = mk_lldecl();
alt ct {
ast_map::res_ctor(decl,_, _) {
set_inline_hint(d);
trans_res_ctor(ccx, pt, decl, fn_id.node, psubsts, d);
d
}
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, d,
option::get_default(psubsts,
{tys:tp_tys, vtables: none, bounds: @[]}),
fn_id.node, parent_id, ctor.span);
d
}
}
let tp_tys: [ty::t] = 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);
d
}
ast_map::node_dtor(_, dtor, _, pt) {
let parent_id = alt ty::ty_to_def_id(ty::node_id_to_type(ccx.tcx,
@ -2412,9 +2334,6 @@ fn maybe_instantiate_inline(ccx: @crate_ctxt, fn_id: ast::def_id)
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)
@ -2639,8 +2558,13 @@ fn trans_rec_field_inner(bcx: block, val: ValueRef, ty: ty::t,
_ { bcx.tcx().sess.span_bug(sp, "trans_rec_field:\
base expr has non-record type"); }
};
// seems wrong? Doesn't take into account the field
// sizes
let ix = field_idx_strict(bcx.tcx(), sp, field, fields);
#debug("val = %s ix = %u", bcx.val_str(val), ix);
/* self is a class with a dtor, which means we
have to select out the object itself
(If any other code does the same thing, that's
@ -2789,9 +2713,6 @@ fn trans_lval(cx: block, e: @ast::expr) -> lval_result {
let non_gc_val = non_gc_box_cast(sub.bcx, sub.val);
GEPi(sub.bcx, non_gc_val, [0u, abi::box_field_body])
}
ty::ty_res(_, _, _) {
GEPi(sub.bcx, sub.val, [0u, 1u])
}
ty::ty_enum(_, _) {
let ety = expr_ty(cx, e);
let ellty = T_ptr(type_of(ccx, ety));
@ -4683,34 +4604,6 @@ fn trans_fn(ccx: @crate_ctxt,
}
}
fn trans_res_ctor(ccx: @crate_ctxt, path: path, dtor: ast::fn_decl,
ctor_id: ast::node_id,
param_substs: option<param_substs>, llfndecl: ValueRef) {
let _icx = ccx.insn_ctxt("trans_res_ctor");
// 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);
let mut 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;
let arg = alt fcx.llargs.find(dtor.inputs[0].id) {
some(local_mem(x)) { x }
_ { ccx.sess.bug("Someone forgot to document an invariant \
in trans_res_ctor"); }
};
let llretptr = fcx.llretptr;
let dst = GEPi(bcx, llretptr, [0u, 1u]);
memmove_ty(bcx, dst, arg, arg_t);
let flag = GEPi(bcx, llretptr, [0u, 0u]);
let one = C_u8(1u);
Store(bcx, one, flag);
build_return(bcx);
finish_fn(fcx, lltop);
}
fn trans_enum_variant(ccx: @crate_ctxt, enum_id: ast::node_id,
variant: ast::variant, disr: int, is_degen: bool,
param_substs: option<param_substs>,
@ -5029,16 +4922,6 @@ fn trans_item(ccx: @crate_ctxt, item: ast::item) {
ast::item_impl(tps, _rp, _, _, ms) {
impl::trans_impl(ccx, *path, item.ident, ms, tps);
}
ast::item_res(decl, tps, body, dtor_id, ctor_id, _) {
if tps.len() == 0u {
let llctor_decl = get_item_val(ccx, ctor_id);
trans_res_ctor(ccx, *path, decl, ctor_id, none, llctor_decl);
let lldtor_decl = get_item_val(ccx, item.id);
trans_fn(ccx, *path + [path_name(item.ident)], decl, body,
lldtor_decl, no_self, none, dtor_id);
}
}
ast::item_mod(m) {
trans_mod(ccx, m);
}
@ -5293,16 +5176,6 @@ fn get_item_val(ccx: @crate_ctxt, id: ast::node_id) -> ValueRef {
set_inline_hint_if_appr(i.attrs, llfn);
llfn
}
ast::item_res(_, _, _, dtor_id, _, _) {
// Note that the destructor is associated with the item's id,
// not the dtor_id. This is a bit counter-intuitive, but
// simplifies ty_res, which would have to carry around two
// def_ids otherwise -- 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")],
i.id, t)
}
}
}
ast_map::node_method(m, impl_id, pth) {
@ -5318,18 +5191,9 @@ 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(nm, tps, ct, pt) {
ast_map::node_ctor(nm, tps, ctor, _, 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_map::class_ctor(ctor, _) {
register_fn(ccx, ctor.span, my_path, ctor.node.id)
}
}
register_fn(ccx, ctor.span, my_path, ctor.node.id)
}
ast_map::node_dtor(tps, dt, parent_id, pt) {
/*

View file

@ -743,7 +743,7 @@ fn create_function(fcx: fn_ctxt) -> @metadata<subprogram_md> {
let (ident, ret_ty, id) = alt cx.tcx.items.get(fcx.id) {
ast_map::node_item(item, _) {
alt item.node {
ast::item_fn(decl, _, _) | ast::item_res(decl, _, _, _, _, _) {
ast::item_fn(decl, _, _) {
(item.ident, decl.output, item.id)
}
_ { fcx.ccx.sess.span_bug(item.span, "create_function: item \
@ -753,16 +753,9 @@ 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(nm, _, ct, _) {
alt ct {
ast_map::res_ctor(decl, ctor_id, _) {
(nm, decl.output, ctor_id)
}
ast_map::class_ctor(ctor,_) {
// FIXME: output type may be wrong (#2194)
(nm, ctor.node.dec.output, ctor.node.id)
}
}
ast_map::node_ctor(nm, _, ctor, _, _) {
// FIXME: output type may be wrong (#2194)
(nm, ctor.node.dec.output, ctor.node.id)
}
ast_map::node_expr(expr) {
alt expr.node {

View file

@ -69,8 +69,8 @@ fn traverse_def_id(cx: ctx, did: def_id) {
ast_map::node_method(_, impl_id, _) { traverse_def_id(cx, impl_id); }
ast_map::node_native_item(item, _, _) { cx.rmap.insert(item.id, ()); }
ast_map::node_variant(v, _, _) { cx.rmap.insert(v.node.id, ()); }
// If it's a class ctor, consider the parent reachable
ast_map::node_ctor(_, _, ast_map::class_ctor(_, parent_id), _) {
// If it's a ctor, consider the parent reachable
ast_map::node_ctor(_, _, _, parent_id, _) {
traverse_def_id(cx, parent_id);
}
_ {}
@ -94,10 +94,6 @@ fn traverse_public_item(cx: ctx, item: @item) {
for vec::each(nm.items) {|item| cx.rmap.insert(item.id, ()); }
}
}
item_res(_, tps, blk, _, _, _) {
// resources seem to be unconditionally inlined
traverse_inline_body(cx, blk);
}
item_fn(_, tps, blk) {
if tps.len() > 0u ||
attr::find_inline_attr(item.attrs) != attr::ia_none {
@ -209,10 +205,6 @@ fn traverse_all_resources(cx: ctx, crate_mod: _mod) {
visit_item: {|i, cx, v|
visit::visit_item(i, cx, v);
alt i.node {
item_res(*) {
traverse_public_item(cx, i);
}
// Classes with dtors too!
item_class(_, _, _, _, some(_), _) {
traverse_public_item(cx, i);
}

View file

@ -255,7 +255,6 @@ impl methods for reflector {
// Miscallaneous extra types
ty::ty_iface(_, _) { self.leaf("iface") }
ty::ty_res(_, t, _) { self.bracketed_t("res", t, []) }
ty::ty_var(_) { self.leaf("var") }
ty::ty_var_integral(_) { self.leaf("var_integral") }
ty::ty_param(n, _) { self.visit("param", [self.c_uint(n)]) }

View file

@ -335,7 +335,6 @@ fn shape_of(ccx: @crate_ctxt, t: ty::t) -> [u8] {
[shape_res]
}
else { [shape_struct] };
let mut sub = [];
option::iter(m_dtor_did) {|dtor_did|
let ri = @{did: dtor_did, parent_id: some(did), tps: tps};
let id = interner::intern(ccx.shape_cx.resources, ri);
@ -346,9 +345,8 @@ fn shape_of(ccx: @crate_ctxt, t: ty::t) -> [u8] {
add_u16(s, 0_u16);
};
for ty::class_items_as_mutable_fields(ccx.tcx, did, substs).each {|f|
sub += shape_of(ccx, f.mt.ty);
add_substr(s, shape_of(ccx, f.mt.ty));
}
add_substr(s, sub);
s
}
ty::ty_rptr(_, mt) {
@ -356,25 +354,6 @@ fn shape_of(ccx: @crate_ctxt, t: ty::t) -> [u8] {
add_substr(s, shape_of(ccx, mt.ty));
s
}
ty::ty_res(did, raw_subt, substs) {
#debug["ty_res(%?, %?, %?)",
did,
ty_to_str(ccx.tcx, raw_subt),
substs.tps.map({|t| ty_to_str(ccx.tcx, t) })];
for substs.tps.each() {|t| assert !ty::type_has_params(t); }
let subt = ty::subst(ccx.tcx, substs, raw_subt);
let tps = substs.tps;
let ri = @{did: did, parent_id: none, tps: tps};
let id = interner::intern(ccx.shape_cx.resources, ri);
let mut s = [shape_res];
add_u16(s, id as u16);
// Hack: always encode 0 tps, since the shape glue format
// hasn't changed since we started monomorphizing.
add_u16(s, 0_u16);
add_substr(s, shape_of(ccx, subt));
s
}
ty::ty_param(*) {
ccx.tcx.sess.bug("non-monomorphized type parameter");
}
@ -599,8 +578,9 @@ fn gen_resource_shapes(ccx: @crate_ctxt) -> ValueRef {
for uint::range(0u, len) {|i|
let ri = interner::get(ccx.shape_cx.resources, i);
for ri.tps.each() {|s| assert !ty::type_has_params(s); }
dtors += [trans::base::get_res_dtor(ccx, ri.did, ri.parent_id,
ri.tps)];
option::iter(ri.parent_id) {|id|
dtors += [trans::base::get_res_dtor(ccx, ri.did, id, ri.tps)];
}
}
ret mk_global(ccx, "resource_shapes", C_struct(dtors), true);
}
@ -744,10 +724,6 @@ fn simplify_type(tcx: ty::ctxt, typ: ty::t) -> ty::t {
ty::ty_estr(ty::vstore_uniq) | ty::ty_estr(ty::vstore_box) |
ty::ty_ptr(_) | ty::ty_rptr(_,_) { nilptr(tcx) }
ty::ty_fn(_) { ty::mk_tup(tcx, [nilptr(tcx), nilptr(tcx)]) }
ty::ty_res(_, sub, substs) {
let sub1 = ty::subst(tcx, substs, sub);
ty::mk_tup(tcx, [ty::mk_int(tcx), simplify_type(tcx, sub1)])
}
ty::ty_evec(_, ty::vstore_slice(_)) |
ty::ty_estr(ty::vstore_slice(_)) {
ty::mk_tup(tcx, [nilptr(tcx), ty::mk_int(tcx)])

View file

@ -141,10 +141,6 @@ fn type_of(cx: @crate_ctxt, t: ty::t) -> TypeRef {
}
ty::ty_fn(_) { T_fn_pair(cx, type_of_fn_from_ty(cx, t)) }
ty::ty_iface(_, _) { T_opaque_iface(cx) }
ty::ty_res(_, sub, substs) {
let sub1 = ty::subst(cx.tcx, substs, sub);
ret T_struct([T_i8(), type_of(cx, sub1)]);
}
ty::ty_type { T_ptr(cx.tydesc_type) }
ty::ty_tup(elts) {
let mut tys = [];

View file

@ -66,11 +66,9 @@ fn type_uses_for(ccx: @crate_ctxt, fn_id: def_id, n_tps: uint)
};
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(_, _, ast_map::res_ctor(_, _, _), _) |
ast_map::node_variant(_, _, _) {
for uint::range(0u, n_tps) {|n| cx.uses[n] |= use_repr;}
}
@ -88,7 +86,7 @@ fn type_uses_for(ccx: @crate_ctxt, fn_id: def_id, n_tps: uint)
for uint::range(0u, n_tps) {|n| cx.uses[n] |= flags;}
}
}
ast_map::node_ctor(_, _, ast_map::class_ctor(ctor, _), _){
ast_map::node_ctor(_, _, ctor, _, _){
handle_body(cx, ctor.node.body);
}
ast_map::node_dtor(_, dtor, _, _){

View file

@ -49,14 +49,6 @@ fn find_pre_post_item(ccx: crate_ctxt, i: item) {
item_mod(m) { find_pre_post_mod(m); }
item_native_mod(nm) { find_pre_post_native_mod(nm); }
item_ty(*) | item_enum(*) | item_iface(*) { ret; }
item_res(_, _, body, dtor_id, _, _) {
let fcx =
{enclosing: ccx.fm.get(dtor_id),
id: dtor_id,
name: i.ident,
ccx: ccx};
find_pre_post_fn(fcx, body);
}
item_class(*) {
fail "find_pre_post_item: shouldn't be called on item_class";
}

View file

@ -93,7 +93,6 @@ export ty_unboxed_vec, mk_unboxed_vec, mk_mut_unboxed_vec;
export vstore, vstore_fixed, vstore_uniq, vstore_box, vstore_slice;
export ty_nil, mk_nil, type_is_nil;
export ty_iface, mk_iface;
export ty_res, mk_res;
export ty_param, mk_param, ty_params_to_tys;
export ty_ptr, mk_ptr, mk_mut_ptr, mk_imm_ptr, mk_nil_ptr, type_is_unsafe_ptr;
export ty_rptr, mk_rptr;
@ -366,7 +365,6 @@ enum sty {
ty_fn(fn_ty),
ty_iface(def_id, substs),
ty_class(def_id, substs),
ty_res(def_id, t, substs),
ty_tup([t]),
ty_var(tv_vid), // type variable during typechecking
@ -598,11 +596,6 @@ fn mk_t_with_id(cx: ctxt, st: sty, o_def_id: option<ast::def_id>) -> t {
for f.inputs.each {|a| flags |= get(a.ty).flags; }
flags |= get(f.output).flags;
}
ty_res(_, tt, substs) {
flags |= (has_resources as uint);
flags |= get(tt).flags;
flags |= sflags(substs);
}
ty_constr(tt, _) {
flags |= get(tt).flags;
}
@ -716,11 +709,6 @@ fn mk_class(cx: ctxt, class_id: ast::def_id, substs: substs) -> t {
mk_t(cx, ty_class(class_id, substs))
}
fn mk_res(cx: ctxt, did: ast::def_id,
inner: t, substs: substs) -> t {
mk_t(cx, ty_res(did, inner, substs))
}
fn mk_var(cx: ctxt, v: tv_vid) -> t { mk_t(cx, ty_var(v)) }
fn mk_var_integral(cx: ctxt, v: tvi_vid) -> t {
@ -795,10 +783,6 @@ fn maybe_walk_ty(ty: t, f: fn(t) -> bool) {
for ft.inputs.each {|a| maybe_walk_ty(a.ty, f); }
maybe_walk_ty(ft.output, f);
}
ty_res(_, sub, substs) {
maybe_walk_ty(sub, f);
for substs.tps.each {|tp| maybe_walk_ty(tp, f); }
}
ty_constr(sub, _) { maybe_walk_ty(sub, f); }
ty_uniq(tm) { maybe_walk_ty(tm.ty, f); }
}
@ -860,10 +844,6 @@ fn fold_sty(sty: sty, fldop: fn(t) -> t) -> sty {
let new_output = fldop(f.output);
ty_fn({inputs: new_args, output: new_output with f})
}
ty_res(did, subty, substs) {
ty_res(did, fldop(subty),
fold_substs(substs, fldop))
}
ty_rptr(r, tm) {
ty_rptr(r, {ty: fldop(tm.ty), mutbl: tm.mutbl})
}
@ -944,10 +924,6 @@ fn fold_regions_and_ty(
ty_iface(def_id, substs) {
ty::mk_iface(cx, def_id, fold_substs(substs, fldr, fldt))
}
ty_res(def_id, t, substs) {
ty::mk_res(cx, def_id, fldt(t),
fold_substs(substs, fldr, fldt))
}
sty @ ty_fn(_) {
fold_sty_to_ty(cx, sty) {|t|
fldfnt(t)
@ -1100,8 +1076,8 @@ fn type_is_bool(ty: t) -> bool { get(ty).struct == ty_bool }
fn type_is_structural(ty: t) -> bool {
alt get(ty).struct {
ty_rec(_) | ty_class(_, _) | ty_tup(_) | ty_enum(_, _) | ty_fn(_) |
ty_iface(_, _) | ty_res(_, _, _) | ty_evec(_, vstore_fixed(_))
ty_rec(_) | ty_class(*) | ty_tup(_) | ty_enum(*) | ty_fn(_) |
ty_iface(*) | ty_evec(_, vstore_fixed(_))
| ty_estr(vstore_fixed(_)) { true }
_ { false }
}
@ -1318,7 +1294,7 @@ fn type_needs_unwind_cleanup_(cx: ctxt, ty: t,
}
!needs_unwind_cleanup
}
ty_uniq(_) | ty_str | ty_vec(_) | ty_res(_, _, _) |
ty_uniq(_) | ty_str | ty_vec(_) |
ty_estr(vstore_uniq) |
ty_estr(vstore_box) |
ty_evec(_, vstore_uniq) |
@ -1605,10 +1581,6 @@ fn type_kind(cx: ctxt, ty: t) -> kind {
}
lowest
}
ty_res(did, inner, tps) {
let inner = subst(cx, tps, inner);
(kind_const() | kind_send_only()) & type_kind(cx, inner)
}
ty_param(_, did) {
param_bounds_to_kind(cx.ty_param_bounds.get(did.node))
}
@ -1713,18 +1685,6 @@ fn is_instantiable(cx: ctxt, r_ty: t) -> bool {
r
}
ty_res(did, _, _) if vec::contains(*seen, did) {
false
}
ty_res(did, sub, substs) {
vec::push(*seen, did);
let sty = subst(cx, substs, sub);
let r = type_requires(cx, seen, r_ty, sty);
vec::pop(*seen);
r
}
ty_tup(ts) {
vec::any(ts) {|t|
type_requires(cx, seen, r_ty, t)
@ -1787,10 +1747,6 @@ fn type_structurally_contains(cx: ctxt, ty: t, test: fn(sty) -> bool) ->
}
ret false;
}
ty_res(_, sub, substs) {
let sty = subst(cx, substs, sub);
ret type_structurally_contains(cx, sty, test);
}
ty_evec(mt, vstore_fixed(_)) {
ret type_structurally_contains(cx, mt.ty, test);
}
@ -1895,9 +1851,6 @@ fn type_is_pod(cx: ctxt, ty: t) -> bool {
ty_evec(mt, vstore_fixed(_)) | ty_unboxed_vec(mt) {
result = type_is_pod(cx, mt.ty);
}
ty_res(_, inner, substs) {
result = type_is_pod(cx, subst(cx, substs, inner));
}
ty_constr(subt, _) { result = type_is_pod(cx, subt); }
ty_param(_, _) { result = false; }
ty_opaque_closure_ptr(_) { result = true; }
@ -1966,11 +1919,6 @@ fn deref_sty(cx: ctxt, sty: sty, expl: bool) -> option<mt> {
some(mt)
}
ty_res(_, inner, substs) {
let inner = subst(cx, substs, inner);
some({ty: inner, mutbl: ast::m_imm})
}
ty_enum(did, substs) {
let variants = enum_variants(cx, did);
if vec::len(*variants) == 1u && vec::len(variants[0].args) == 1u {
@ -2111,10 +2059,6 @@ fn hash_type_structure(st: sty) -> uint {
h
}
ty_uniq(mt) { hash_subty(37u, mt.ty) }
ty_res(did, sub, substs) {
let mut h = hash_subty(hash_def(38u, did), sub);
hash_substs(h, substs)
}
ty_iface(did, substs) {
let mut h = hash_def(40u, did);
hash_substs(h, substs)
@ -2452,7 +2396,6 @@ fn ty_sort_str(cx: ctxt, t: t) -> str {
ty_fn(_) { "fn" }
ty_iface(id, _) { #fmt["iface %s", item_path_str(cx, id)] }
ty_class(id, _) { #fmt["class %s", item_path_str(cx, id)] }
ty_res(id, _, _) { #fmt["resource %s", item_path_str(cx, id)] }
ty_tup(_) { "tuple" }
ty_var(_) { "variable" }
ty_var_integral(_) { "integral variable" }
@ -2606,7 +2549,7 @@ fn impl_iface(cx: ctxt, id: ast::def_id) -> option<t> {
fn ty_to_def_id(ty: t) -> option<ast::def_id> {
alt get(ty).struct {
ty_iface(id, _) | ty_class(id, _) | ty_res(id, _, _) | ty_enum(id, _) {
ty_iface(id, _) | ty_class(id, _) | ty_enum(id, _) {
some(id)
}
_ { none }
@ -2685,7 +2628,7 @@ 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(nm, _, _, path) {
ast_map::node_ctor(nm, _, _, _, path) {
*path + [ast_map::path_name(nm)]
}
ast_map::node_dtor(_, _, _, path) {

View file

@ -354,10 +354,6 @@ fn check_item(ccx: @crate_ctxt, it: @ast::item) {
ast::item_fn(decl, tps, body) {
check_bare_fn(ccx, decl, body, it.id, none);
}
ast::item_res(decl, tps, body, dtor_id, _, rp) {
check_instantiable(ccx.tcx, it.span, it.id);
check_bare_fn(ccx, decl, body, dtor_id, none);
}
ast::item_impl(tps, rp, _, ty, ms) {
let self_ty = ccx.to_ty(rscope::type_rscope(rp), ty);
for ms.each {|m| check_method(ccx, m, self_ty);}

View file

@ -261,11 +261,6 @@ fn convert_class_item(ccx: @crate_ctxt,
rp: ast::region_param,
bounds: @[ty::param_bounds],
v: ast_util::ivar) {
/* we want to do something here, b/c within the
scope of the class, it's ok to refer to fields &
methods unqualified */
/* they have these types *within the scope* of the
class. outside the class, it's done with expr_field */
let tt = ccx.to_ty(type_rscope(rp), v.ty);
write_ty_to_tcx(ccx.tcx, v.id, tt);
/* add the field to the tcache */
@ -322,37 +317,6 @@ fn convert(ccx: @crate_ctxt, it: @ast::item) {
check_methods_against_iface(ccx, tps, rp, selfty, t, cms);
}
}
ast::item_res(decl, tps, _, dtor_id, ctor_id, rp) {
let {bounds, substs} = mk_substs(ccx, tps, rp);
let def_id = local_def(it.id);
let t_arg = ty_of_arg(ccx, type_rscope(rp),
decl.inputs[0], none);
let t_res = ty::mk_res(tcx, def_id, t_arg.ty, substs);
let t_ctor = ty::mk_fn(tcx, {
purity: ast::pure_fn,
proto: ast::proto_box,
inputs: [{mode: ast::expl(ast::by_copy), ty: t_arg.ty}],
output: t_res,
ret_style: ast::return_val, constraints: []
});
let t_dtor = ty::mk_fn(tcx, {
purity: ast::impure_fn,
proto: ast::proto_box,
inputs: [t_arg], output: ty::mk_nil(tcx),
ret_style: ast::return_val, constraints: []
});
write_ty_to_tcx(tcx, it.id, t_res);
write_ty_to_tcx(tcx, ctor_id, t_ctor);
tcx.tcache.insert(local_def(ctor_id),
{bounds: bounds,
rp: rp,
ty: t_ctor});
tcx.tcache.insert(def_id, {bounds: bounds,
rp: rp,
ty: t_res});
write_ty_to_tcx(tcx, dtor_id, t_dtor);
}
ast::item_iface(*) {
let tpt = ty_of_item(ccx, it);
#debug["item_iface(it.id=%d, tpt.ty=%s)",
@ -366,11 +330,21 @@ fn convert(ccx: @crate_ctxt, it: @ast::item) {
write_ty_to_tcx(tcx, it.id, tpt.ty);
tcx.tcache.insert(local_def(it.id), tpt);
// Write the ctor type
let t_ctor =
ty::mk_fn(
tcx,
ty_of_fn_decl(ccx, type_rscope(rp), ast::proto_any,
ctor.node.dec, none));
let t_args = ctor.node.dec.inputs.map {|a|
ty_of_arg(ccx, type_rscope(rp), a, none)};
let t_res = ty::mk_class(tcx, local_def(it.id),
{self_r: alt rp {
ast::rp_none { none }
ast::rp_self { some(ty::re_bound(ty::br_self)) }
},
self_ty: none,
tps: ty::ty_params_to_tys(tcx, tps)});
let t_ctor = ty::mk_fn(tcx, {purity: ast::impure_fn,
proto: ast::proto_any,
inputs: t_args,
output: t_res,
ret_style: ast::return_val,
constraints: []}); // tjc TODO
write_ty_to_tcx(tcx, ctor.node.id, t_ctor);
tcx.tcache.insert(local_def(ctor.node.id),
{bounds: tpt.bounds,
@ -538,15 +512,6 @@ fn ty_of_item(ccx: @crate_ctxt, it: @ast::item)
tcx.tcache.insert(local_def(it.id), tpt);
ret tpt;
}
ast::item_res(decl, tps, _, _, _, rp) {
let {bounds, substs} = mk_substs(ccx, tps, rp);
let t_arg = ty_of_arg(ccx, type_rscope(rp),
decl.inputs[0], none);
let t = ty::mk_res(tcx, local_def(it.id), t_arg.ty, substs);
let t_res = {bounds: bounds, rp: rp, ty: t};
tcx.tcache.insert(local_def(it.id), t_res);
ret t_res;
}
ast::item_enum(_, tps, rp) {
// Create a new generic polytype.
let {bounds, substs} = mk_substs(ccx, tps, rp);

View file

@ -1851,16 +1851,6 @@ fn super_tys<C:combine>(
}
}
(ty::ty_res(a_id, a_t, a_substs),
ty::ty_res(b_id, b_t, b_substs))
if a_id == b_id {
self.tys(a_t, b_t).chain {|t|
self.substs(a_substs, b_substs).chain {|substs|
ok(ty::mk_res(tcx, a_id, t, substs))
}
}
}
(ty::ty_rec(as), ty::ty_rec(bs)) {
if check vec::same_length(as, bs) {
map_vec2(as, bs) {|a,b|

View file

@ -6,7 +6,7 @@ import middle::ty::{mt, re_bound, re_free, re_scope, re_var, region, t};
import middle::ty::{ty_bool, ty_bot, ty_box, ty_class, ty_constr, ty_enum};
import middle::ty::{ty_estr, ty_evec, ty_float, ty_fn, ty_iface, ty_int};
import middle::ty::{ty_nil, ty_opaque_box, ty_opaque_closure_ptr, ty_param};
import middle::ty::{ty_ptr, ty_rec, ty_res, ty_rptr, ty_self, ty_str, ty_tup};
import middle::ty::{ty_ptr, ty_rec, ty_rptr, ty_self, ty_str, ty_tup};
import middle::ty::{ty_type, ty_uniq, ty_uint, ty_var, ty_var_integral};
import middle::ty::{ty_vec, ty_unboxed_vec, vid};
import metadata::encoder;
@ -208,7 +208,7 @@ fn ty_to_str(cx: ctxt, typ: t) -> str {
"'" + str::from_bytes([('a' as u8) + (id as u8)])
}
ty_self { "self" }
ty_enum(did, substs) | ty_res(did, _, substs) | ty_class(did, substs) {
ty_enum(did, substs) | ty_class(did, substs) {
let path = ty::item_path(cx, did);
let base = ast_map::path_to_str(path);
parameterized(cx, base, substs.self_r, substs.tps)