1
Fork 0

make nominal types optionally parameterized by a self region.

Issue #2201.
This commit is contained in:
Niko Matsakis 2012-04-18 21:26:25 -07:00
parent f3f34bf09b
commit 3c995fb8f3
45 changed files with 1324 additions and 932 deletions

View file

@ -645,21 +645,29 @@ type iface_ref = {path: @path, id: node_id};
type item = {ident: ident, attrs: [attribute], type item = {ident: ident, attrs: [attribute],
id: node_id, node: item_, span: span}; id: node_id, node: item_, span: span};
#[auto_serialize]
enum region_param {
rp_none,
rp_self
}
#[auto_serialize] #[auto_serialize]
enum item_ { enum item_ {
item_const(@ty, @expr), item_const(@ty, @expr),
item_fn(fn_decl, [ty_param], blk), item_fn(fn_decl, [ty_param], blk),
item_mod(_mod), item_mod(_mod),
item_native_mod(native_mod), item_native_mod(native_mod),
item_ty(@ty, [ty_param]), item_ty(@ty, [ty_param], region_param),
item_enum([variant], [ty_param]), item_enum([variant], [ty_param], region_param),
item_res(fn_decl /* dtor */, [ty_param], blk /* dtor body */, item_res(fn_decl /* dtor */, [ty_param], blk /* dtor body */,
node_id /* dtor id */, node_id /* ctor id */), node_id /* dtor id */, node_id /* ctor id */,
region_param),
item_class([ty_param], /* ty params for class */ item_class([ty_param], /* ty params for class */
[iface_ref], /* ifaces this class implements */ [iface_ref], /* ifaces this class implements */
[@class_member], /* methods, etc. */ [@class_member], /* methods, etc. */
/* (not including ctor) */ /* (not including ctor) */
class_ctor class_ctor,
region_param
), ),
item_iface([ty_param], [ty_method]), item_iface([ty_param], [ty_method]),
item_impl([ty_param], option<@ty> /* iface */, item_impl([ty_param], option<@ty> /* iface */,

View file

@ -149,7 +149,7 @@ fn is_exported(i: ident, m: _mod) -> bool {
for m.items.each {|it| for m.items.each {|it|
if it.ident == i { local = true; } if it.ident == i { local = true; }
alt it.node { alt it.node {
item_enum(variants, _) { item_enum(variants, _, _) {
for variants.each {|v| for variants.each {|v|
if v.node.name == i { if v.node.name == i {
local = true; local = true;

View file

@ -102,11 +102,11 @@ fn expand(cx: ext_ctxt,
vec::flat_map(in_items) {|in_item| vec::flat_map(in_items) {|in_item|
alt in_item.node { alt in_item.node {
ast::item_ty(ty, tps) { ast::item_ty(ty, tps, _) {
[filter_attrs(in_item)] + ty_fns(cx, in_item.ident, ty, tps) [filter_attrs(in_item)] + ty_fns(cx, in_item.ident, ty, tps)
} }
ast::item_enum(variants, tps) { ast::item_enum(variants, tps, _) {
[filter_attrs(in_item)] + enum_fns(cx, in_item.ident, [filter_attrs(in_item)] + enum_fns(cx, in_item.ident,
in_item.span, variants, tps) in_item.span, variants, tps)
} }

View file

@ -265,36 +265,42 @@ fn noop_fold_item_underscore(i: item_, fld: ast_fold) -> item_ {
} }
item_mod(m) { item_mod(fld.fold_mod(m)) } item_mod(m) { item_mod(fld.fold_mod(m)) }
item_native_mod(nm) { item_native_mod(fld.fold_native_mod(nm)) } item_native_mod(nm) { item_native_mod(fld.fold_native_mod(nm)) }
item_ty(t, typms) { item_ty(fld.fold_ty(t), item_ty(t, typms, rp) { item_ty(fld.fold_ty(t),
fold_ty_params(typms, fld)) } fold_ty_params(typms, fld),
item_enum(variants, typms) { rp) }
item_enum(variants, typms, r) {
item_enum(vec::map(variants, fld.fold_variant), item_enum(vec::map(variants, fld.fold_variant),
fold_ty_params(typms, fld)) fold_ty_params(typms, fld),
r)
} }
item_class(typms, ifaces, items, ctor) { item_class(typms, ifaces, items, ctor, rp) {
let ctor_body = fld.fold_block(ctor.node.body); let ctor_body = fld.fold_block(ctor.node.body);
let ctor_decl = fold_fn_decl(ctor.node.dec, fld); let ctor_decl = fold_fn_decl(ctor.node.dec, fld);
let ctor_id = fld.new_id(ctor.node.id); let ctor_id = fld.new_id(ctor.node.id);
item_class(typms, vec::map(ifaces, {|p| item_class(
{path: fld.fold_path(p.path), typms,
id: fld.new_id(p.id)}}), vec::map(ifaces, {|p|
vec::map(items, fld.fold_class_item), {path: fld.fold_path(p.path),
{node: {body: ctor_body, id: fld.new_id(p.id)}}),
dec: ctor_decl, vec::map(items, fld.fold_class_item),
id: ctor_id with ctor.node} {node: {body: ctor_body,
with ctor}) dec: ctor_decl,
id: ctor_id with ctor.node}
with ctor},
rp)
} }
item_impl(tps, ifce, ty, methods) { item_impl(tps, ifce, ty, methods) {
item_impl(tps, option::map(ifce, fld.fold_ty), fld.fold_ty(ty), item_impl(tps, option::map(ifce, fld.fold_ty), fld.fold_ty(ty),
vec::map(methods, fld.fold_method)) vec::map(methods, fld.fold_method))
} }
item_iface(tps, methods) { item_iface(tps, methods) } item_iface(tps, methods) { item_iface(tps, methods) }
item_res(decl, typms, body, did, cid) { item_res(decl, typms, body, did, cid, rp) {
item_res(fold_fn_decl(decl, fld), item_res(fold_fn_decl(decl, fld),
fold_ty_params(typms, fld), fold_ty_params(typms, fld),
fld.fold_block(body), fld.fold_block(body),
fld.new_id(did), fld.new_id(did),
fld.new_id(cid)) fld.new_id(cid),
rp)
} }
}; };
} }

View file

@ -1992,6 +1992,7 @@ fn parse_item_impl(p: parser, attrs: [ast::attribute]) -> @ast::item {
fn parse_item_res(p: parser, attrs: [ast::attribute]) -> @ast::item { fn parse_item_res(p: parser, attrs: [ast::attribute]) -> @ast::item {
let lo = p.last_span.lo; let lo = p.last_span.lo;
let ident = parse_value_ident(p); let ident = parse_value_ident(p);
let rp = parse_region_param(p);
let ty_params = parse_ty_params(p); let ty_params = parse_ty_params(p);
expect(p, token::LPAREN); expect(p, token::LPAREN);
let arg_ident = parse_value_ident(p); let arg_ident = parse_value_ident(p);
@ -2010,7 +2011,8 @@ fn parse_item_res(p: parser, attrs: [ast::attribute]) -> @ast::item {
cf: ast::return_val, cf: ast::return_val,
constraints: []}; constraints: []};
ret mk_item(p, lo, dtor.span.hi, ident, ret mk_item(p, lo, dtor.span.hi, ident,
ast::item_res(decl, ty_params, dtor, p.get_id(), p.get_id()), ast::item_res(decl, ty_params, dtor,
p.get_id(), p.get_id(), rp),
attrs); attrs);
} }
@ -2035,6 +2037,7 @@ fn parse_iface_ref_list(p:parser) -> [ast::iface_ref] {
fn parse_item_class(p: parser, attrs: [ast::attribute]) -> @ast::item { fn parse_item_class(p: parser, attrs: [ast::attribute]) -> @ast::item {
let lo = p.last_span.lo; let lo = p.last_span.lo;
let class_name = parse_value_ident(p); let class_name = parse_value_ident(p);
let rp = parse_region_param(p);
let ty_params = parse_ty_params(p); let ty_params = parse_ty_params(p);
let class_path = ident_to_path_tys(p, class_name, ty_params); let class_path = ident_to_path_tys(p, class_name, ty_params);
let ifaces : [ast::iface_ref] = if eat_word(p, "implements") let ifaces : [ast::iface_ref] = if eat_word(p, "implements")
@ -2057,11 +2060,11 @@ fn parse_item_class(p: parser, attrs: [ast::attribute]) -> @ast::item {
some((ct_d, ct_b, ct_s)) { some((ct_d, ct_b, ct_s)) {
ret mk_item(p, lo, p.last_span.hi, class_name, ret mk_item(p, lo, p.last_span.hi, class_name,
ast::item_class(ty_params, ifaces, ms, ast::item_class(ty_params, ifaces, ms,
{node: {id: ctor_id, {node: {id: ctor_id,
self_id: p.get_id(), self_id: p.get_id(),
dec: ct_d, dec: ct_d,
body: ct_b}, body: ct_b},
span: ct_s}), attrs); } span: ct_s}, rp), attrs); }
/* /*
Is it strange for the parser to check this? Is it strange for the parser to check this?
*/ */
@ -2236,17 +2239,23 @@ fn parse_type_decl(p: parser) -> {lo: uint, ident: ast::ident} {
fn parse_item_type(p: parser, attrs: [ast::attribute]) -> @ast::item { fn parse_item_type(p: parser, attrs: [ast::attribute]) -> @ast::item {
let t = parse_type_decl(p); let t = parse_type_decl(p);
let rp = parse_region_param(p);
let tps = parse_ty_params(p); let tps = parse_ty_params(p);
expect(p, token::EQ); expect(p, token::EQ);
let ty = parse_ty(p, false); let ty = parse_ty(p, false);
let mut hi = p.span.hi; let mut hi = p.span.hi;
expect(p, token::SEMI); expect(p, token::SEMI);
ret mk_item(p, t.lo, hi, t.ident, ast::item_ty(ty, tps), attrs); ret mk_item(p, t.lo, hi, t.ident, ast::item_ty(ty, tps, rp), attrs);
}
fn parse_region_param(p: parser) -> ast::region_param {
if eat(p, token::BINOP(token::AND)) {ast::rp_self} else {ast::rp_none}
} }
fn parse_item_enum(p: parser, attrs: [ast::attribute]) -> @ast::item { fn parse_item_enum(p: parser, attrs: [ast::attribute]) -> @ast::item {
let lo = p.last_span.lo; let lo = p.last_span.lo;
let id = parse_ident(p); let id = parse_ident(p);
let rp = parse_region_param(p);
let ty_params = parse_ty_params(p); let ty_params = parse_ty_params(p);
let mut variants: [ast::variant] = []; let mut variants: [ast::variant] = [];
// Newtype syntax // Newtype syntax
@ -2265,7 +2274,7 @@ fn parse_item_enum(p: parser, attrs: [ast::attribute]) -> @ast::item {
id: p.get_id(), id: p.get_id(),
disr_expr: none}); disr_expr: none});
ret mk_item(p, lo, ty.span.hi, id, ret mk_item(p, lo, ty.span.hi, id,
ast::item_enum([variant], ty_params), attrs); ast::item_enum([variant], ty_params, rp), attrs);
} }
expect(p, token::LBRACE); expect(p, token::LBRACE);
@ -2301,7 +2310,7 @@ fn parse_item_enum(p: parser, attrs: [ast::attribute]) -> @ast::item {
p.fatal("discriminator values can only be used with a c-like enum"); p.fatal("discriminator values can only be used with a c-like enum");
} }
ret mk_item(p, lo, p.last_span.hi, id, ret mk_item(p, lo, p.last_span.hi, id,
ast::item_enum(variants, ty_params), attrs); ast::item_enum(variants, ty_params, rp), attrs);
} }
fn parse_fn_ty_proto(p: parser) -> ast::proto { fn parse_fn_ty_proto(p: parser) -> ast::proto {

View file

@ -125,10 +125,10 @@ fn test_fun_to_str() {
} }
fn res_to_str(decl: ast::fn_decl, name: ast::ident, fn res_to_str(decl: ast::fn_decl, name: ast::ident,
params: [ast::ty_param]) -> str { params: [ast::ty_param], rp: ast::region_param) -> str {
let buffer = io::mem_buffer(); let buffer = io::mem_buffer();
let s = rust_printer(io::mem_buffer_writer(buffer)); let s = rust_printer(io::mem_buffer_writer(buffer));
print_res(s, decl, name, params); print_res(s, decl, name, params, rp);
end(s); // Close the head box end(s); // Close the head box
end(s); // Close the outer box end(s); // Close the outer box
eof(s.s); eof(s.s);
@ -454,11 +454,12 @@ fn print_item(s: ps, &&item: @ast::item) {
print_native_mod(s, nmod, item.attrs); print_native_mod(s, nmod, item.attrs);
bclose(s, item.span); bclose(s, item.span);
} }
ast::item_ty(ty, params) { ast::item_ty(ty, params, rp) {
ibox(s, indent_unit); ibox(s, indent_unit);
ibox(s, 0u); ibox(s, 0u);
word_nbsp(s, "type"); word_nbsp(s, "type");
word(s.s, item.ident); word(s.s, item.ident);
print_region_param(s, rp);
print_type_params(s, params); print_type_params(s, params);
end(s); // end the inner ibox end(s); // end the inner ibox
@ -468,7 +469,7 @@ fn print_item(s: ps, &&item: @ast::item) {
word(s.s, ";"); word(s.s, ";");
end(s); // end the outer ibox end(s); // end the outer ibox
} }
ast::item_enum(variants, params) { ast::item_enum(variants, params, rp) {
let newtype = let newtype =
vec::len(variants) == 1u && vec::len(variants) == 1u &&
str::eq(item.ident, variants[0].node.name) && str::eq(item.ident, variants[0].node.name) &&
@ -478,6 +479,7 @@ fn print_item(s: ps, &&item: @ast::item) {
word_space(s, "enum"); word_space(s, "enum");
} else { head(s, "enum"); } } else { head(s, "enum"); }
word(s.s, item.ident); word(s.s, item.ident);
print_region_param(s, rp);
print_type_params(s, params); print_type_params(s, params);
space(s.s); space(s.s);
if newtype { if newtype {
@ -500,9 +502,10 @@ fn print_item(s: ps, &&item: @ast::item) {
bclose(s, item.span); bclose(s, item.span);
} }
} }
ast::item_class(tps,ifaces,items,ctor) { ast::item_class(tps,ifaces,items,ctor, rp) {
head(s, "class"); head(s, "class");
word_nbsp(s, item.ident); word_nbsp(s, item.ident);
print_region_param(s, rp);
print_type_params(s, tps); print_type_params(s, tps);
word_space(s, "implements"); word_space(s, "implements");
commasep(s, inconsistent, ifaces, {|s, p| commasep(s, inconsistent, ifaces, {|s, p|
@ -584,8 +587,8 @@ fn print_item(s: ps, &&item: @ast::item) {
for methods.each {|meth| print_ty_method(s, meth); } for methods.each {|meth| print_ty_method(s, meth); }
bclose(s, item.span); bclose(s, item.span);
} }
ast::item_res(decl, tps, body, dt_id, ct_id) { ast::item_res(decl, tps, body, dt_id, ct_id, rp) {
print_res(s, decl, item.ident, tps); print_res(s, decl, item.ident, tps, rp);
print_block(s, body); print_block(s, body);
} }
} }
@ -593,9 +596,10 @@ fn print_item(s: ps, &&item: @ast::item) {
} }
fn print_res(s: ps, decl: ast::fn_decl, name: ast::ident, fn print_res(s: ps, decl: ast::fn_decl, name: ast::ident,
typarams: [ast::ty_param]) { typarams: [ast::ty_param], rp: ast::region_param) {
head(s, "resource"); head(s, "resource");
word(s.s, name); word(s.s, name);
print_region_param(s, rp);
print_type_params(s, typarams); print_type_params(s, typarams);
popen(s); popen(s);
word_space(s, decl.inputs[0].ident + ":"); word_space(s, decl.inputs[0].ident + ":");
@ -1401,6 +1405,13 @@ fn print_bounds(s: ps, bounds: @[ast::ty_param_bound]) {
} }
} }
fn print_region_param(s: ps, rp: ast::region_param) {
alt rp {
ast::rp_self { word(s.s, "&") }
ast::rp_none { }
}
}
fn print_type_params(s: ps, &&params: [ast::ty_param]) { fn print_type_params(s: ps, &&params: [ast::ty_param]) {
if vec::len(params) > 0u { if vec::len(params) > 0u {
word(s.s, "<"); word(s.s, "<");

View file

@ -15,7 +15,7 @@ enum vt<E> { mk_vt(visitor<E>), }
enum fn_kind { enum fn_kind {
fk_item_fn(ident, [ty_param]), //< an item declared with fn() fk_item_fn(ident, [ty_param]), //< an item declared with fn()
fk_method(ident, [ty_param], @method), fk_method(ident, [ty_param], @method),
fk_res(ident, [ty_param]), fk_res(ident, [ty_param], region_param),
fk_anon(proto), //< an anonymous function like fn@(...) fk_anon(proto), //< an anonymous function like fn@(...)
fk_fn_block, //< a block {||...} fk_fn_block, //< a block {||...}
fk_ctor(ident, [ty_param], node_id /* self id */, fk_ctor(ident, [ty_param], node_id /* self id */,
@ -24,7 +24,7 @@ enum fn_kind {
fn name_of_fn(fk: fn_kind) -> ident { fn name_of_fn(fk: fn_kind) -> ident {
alt fk { alt fk {
fk_item_fn(name, _) | fk_method(name, _, _) | fk_res(name, _) fk_item_fn(name, _) | fk_method(name, _, _) | fk_res(name, _, _)
| fk_ctor(name, _, _, _) { name } | fk_ctor(name, _, _, _) { name }
fk_anon(_) | fk_fn_block { "anon" } fk_anon(_) | fk_fn_block { "anon" }
} }
@ -32,7 +32,7 @@ fn name_of_fn(fk: fn_kind) -> ident {
fn tps_of_fn(fk: fn_kind) -> [ty_param] { fn tps_of_fn(fk: fn_kind) -> [ty_param] {
alt fk { alt fk {
fk_item_fn(_, tps) | fk_method(_, tps, _) | fk_res(_, tps) fk_item_fn(_, tps) | fk_method(_, tps, _) | fk_res(_, tps, _)
| fk_ctor(_, tps, _, _) { tps } | fk_ctor(_, tps, _, _) { tps }
fk_anon(_) | fk_fn_block { [] } fk_anon(_) | fk_fn_block { [] }
} }
@ -118,12 +118,15 @@ fn visit_item<E>(i: @item, e: E, v: vt<E>) {
for nm.view_items.each {|vi| v.visit_view_item(vi, e, v); } for nm.view_items.each {|vi| v.visit_view_item(vi, e, v); }
for nm.items.each {|ni| v.visit_native_item(ni, e, v); } for nm.items.each {|ni| v.visit_native_item(ni, e, v); }
} }
item_ty(t, tps) { v.visit_ty(t, e, v); v.visit_ty_params(tps, e, v); } item_ty(t, tps, rp) {
item_res(decl, tps, body, dtor_id, _) { v.visit_ty(t, e, v);
v.visit_fn(fk_res(i.ident, tps), decl, body, i.span, v.visit_ty_params(tps, e, v);
}
item_res(decl, tps, body, dtor_id, _, rp) {
v.visit_fn(fk_res(i.ident, tps, rp), decl, body, i.span,
dtor_id, e, v); dtor_id, e, v);
} }
item_enum(variants, tps) { item_enum(variants, tps, _) {
v.visit_ty_params(tps, e, v); v.visit_ty_params(tps, e, v);
for variants.each {|vr| for variants.each {|vr|
for vr.node.args.each {|va| v.visit_ty(va.ty, e, v); } for vr.node.args.each {|va| v.visit_ty(va.ty, e, v); }
@ -137,7 +140,7 @@ fn visit_item<E>(i: @item, e: E, v: vt<E>) {
visit_method_helper(m, e, v) visit_method_helper(m, e, v)
} }
} }
item_class(tps, ifaces, members, ctor) { item_class(tps, ifaces, members, ctor, _) {
v.visit_ty_params(tps, e, v); v.visit_ty_params(tps, e, v);
for members.each {|m| for members.each {|m|
v.visit_class_item(m, e, v); v.visit_class_item(m, e, v);

View file

@ -143,8 +143,8 @@ fn visit_ids(item: ast::inlined_item, vfn: fn@(ast::node_id)) {
visit_item: fn@(i: @ast::item) { visit_item: fn@(i: @ast::item) {
vfn(i.id); vfn(i.id);
alt i.node { alt i.node {
ast::item_res(_, _, _, d_id, c_id) { vfn(d_id); vfn(c_id); } ast::item_res(_, _, _, d_id, c_id, _) { vfn(d_id); vfn(c_id); }
ast::item_enum(vs, _) { for vs.each {|v| vfn(v.node.id); } } ast::item_enum(vs, _, _) { for vs.each {|v| vfn(v.node.id); } }
_ {} _ {}
} }
}, },
@ -209,7 +209,7 @@ fn visit_ids(item: ast::inlined_item, vfn: fn@(ast::node_id)) {
vfn(parent_id.node); vfn(parent_id.node);
} }
visit::fk_item_fn(_, tps) | visit::fk_item_fn(_, tps) |
visit::fk_res(_, tps) { visit::fk_res(_, tps, _) {
vec::iter(tps) {|tp| vfn(tp.id)} vec::iter(tps) {|tp| vfn(tp.id)}
} }
visit::fk_method(_, tps, m) { visit::fk_method(_, tps, m) {
@ -679,7 +679,10 @@ impl helpers for ebml::writer {
self.emit_bounds(ecx, bs) self.emit_bounds(ecx, bs)
} }
} }
self.emit_rec_field("ty", 0u) {|| self.emit_rec_field("rp", 1u) {||
ast::serialize_region_param(self, tpbt.rp)
}
self.emit_rec_field("ty", 2u) {||
self.emit_ty(ecx, tpbt.ty); self.emit_ty(ecx, tpbt.ty);
} }
} }
@ -848,6 +851,11 @@ impl decoder for ebml::doc {
impl decoder for ebml::ebml_deserializer { impl decoder for ebml::ebml_deserializer {
fn read_ty(xcx: extended_decode_ctxt) -> ty::t { fn read_ty(xcx: extended_decode_ctxt) -> ty::t {
// Note: regions types embed local node ids. In principle, we
// should translate these node ids into the new decode
// context. However, we do not bother, because region types
// are not used during trans.
tydecode::parse_ty_data( tydecode::parse_ty_data(
self.parent.data, xcx.dcx.cdata.cnum, self.pos, xcx.dcx.tcx, self.parent.data, xcx.dcx.cdata.cnum, self.pos, xcx.dcx.tcx,
xcx.tr_def_id(_)) xcx.tr_def_id(_))
@ -870,7 +878,10 @@ impl decoder for ebml::ebml_deserializer {
bounds: self.read_rec_field("bounds", 0u) {|| bounds: self.read_rec_field("bounds", 0u) {||
@self.read_to_vec {|| self.read_bounds(xcx) } @self.read_to_vec {|| self.read_bounds(xcx) }
}, },
ty: self.read_rec_field("ty", 1u) {|| rp: self.read_rec_field("rp", 1u) {||
ast::deserialize_region_param(self)
},
ty: self.read_rec_field("ty", 2u) {||
self.read_ty(xcx) self.read_ty(xcx)
} }
} }

View file

@ -84,6 +84,8 @@ const tag_path_elt_name: uint = 0x43u;
const tag_item_field: uint = 0x44u; const tag_item_field: uint = 0x44u;
const tag_class_mut: uint = 0x45u; const tag_class_mut: uint = 0x45u;
const tag_region_param: uint = 0x46u;
// used to encode crate_ctxt side tables // used to encode crate_ctxt side tables
enum astencode_tag { // Reserves 0x50 -- 0x6f enum astencode_tag { // Reserves 0x50 -- 0x6f
tag_ast = 0x50, tag_ast = 0x50,

View file

@ -157,7 +157,7 @@ fn get_field_type(tcx: ty::ctxt, class_id: ast::def_id,
class_id, def)}); class_id, def)});
#debug("got field data %?", the_field); #debug("got field data %?", the_field);
let ty = decoder::item_type(def, the_field, tcx, cdata); let ty = decoder::item_type(def, the_field, tcx, cdata);
ret {bounds: @[], ty: ty}; ret {bounds: @[], rp: ast::rp_none, ty: ty};
} }
fn get_impl_iface(tcx: ty::ctxt, def: ast::def_id) fn get_impl_iface(tcx: ty::ctxt, def: ast::def_id)

View file

@ -15,6 +15,7 @@ import syntax::print::pprust;
import cmd=cstore::crate_metadata; import cmd=cstore::crate_metadata;
import middle::trans::common::maps; import middle::trans::common::maps;
import util::ppaux::ty_to_str; import util::ppaux::ty_to_str;
import ebml::deserializer;
export get_class_fields; export get_class_fields;
export get_symbol; export get_symbol;
@ -176,6 +177,18 @@ fn item_ty_param_bounds(item: ebml::doc, tcx: ty::ctxt, cdata: cmd)
@bounds @bounds
} }
fn item_ty_region_param(item: ebml::doc) -> ast::region_param {
alt ebml::maybe_get_doc(item, tag_region_param) {
some(rp_doc) {
let dsr = ebml::ebml_deserializer(rp_doc);
ast::deserialize_region_param(dsr)
}
none { // not all families of items have region params
ast::rp_none
}
}
}
fn item_ty_param_count(item: ebml::doc) -> uint { fn item_ty_param_count(item: ebml::doc) -> uint {
let mut n = 0u; let mut n = 0u;
ebml::tagged_docs(item, tag_items_data_item_ty_param_bounds, ebml::tagged_docs(item, tag_items_data_item_ty_param_bounds,
@ -272,12 +285,14 @@ fn lookup_def(cnum: ast::crate_num, data: @[u8], did_: ast::def_id) ->
fn get_type(cdata: cmd, id: ast::node_id, tcx: ty::ctxt) fn get_type(cdata: cmd, id: ast::node_id, tcx: ty::ctxt)
-> ty::ty_param_bounds_and_ty { -> ty::ty_param_bounds_and_ty {
let item = lookup_item(id, cdata.data); let item = lookup_item(id, cdata.data);
let t = item_type({crate: cdata.cnum, node: id}, item, tcx, cdata); let t = item_type({crate: cdata.cnum, node: id}, item, tcx, cdata);
let tp_bounds = if family_has_type_params(item_family(item)) { let tp_bounds = if family_has_type_params(item_family(item)) {
item_ty_param_bounds(item, tcx, cdata) item_ty_param_bounds(item, tcx, cdata)
} else { @[] }; } else { @[] };
ret {bounds: tp_bounds, ty: t}; let rp = item_ty_region_param(item);
ret {bounds: tp_bounds, rp: rp, ty: t};
} }
fn get_type_param_count(data: @[u8], id: ast::node_id) -> uint { fn get_type_param_count(data: @[u8], id: ast::node_id) -> uint {

View file

@ -16,6 +16,7 @@ import middle::ast_map;
import syntax::attr; import syntax::attr;
import driver::session::session; import driver::session::session;
import std::serialization::serializer; import std::serialization::serializer;
import std::ebml::serializer;
export encode_metadata; export encode_metadata;
export encoded_ty; export encoded_ty;
@ -40,6 +41,12 @@ fn encode_def_id(ebml_w: ebml::writer, id: def_id) {
ebml_w.wr_tagged_str(tag_def_id, def_to_str(id)); ebml_w.wr_tagged_str(tag_def_id, def_to_str(id));
} }
fn encode_region_param(ebml_w: ebml::writer, rp: region_param) {
ebml_w.wr_tag(tag_region_param) {||
serialize_region_param(ebml_w, rp)
}
}
fn encode_named_def_id(ebml_w: ebml::writer, name: str, id: def_id) { fn encode_named_def_id(ebml_w: ebml::writer, name: str, id: def_id) {
ebml_w.wr_tag(tag_paths_data_item) {|| ebml_w.wr_tag(tag_paths_data_item) {||
encode_name(ebml_w, name); encode_name(ebml_w, name);
@ -132,14 +139,14 @@ fn encode_module_item_paths(ebml_w: ebml::writer, ecx: @encode_ctxt,
index); index);
ebml_w.end_tag(); ebml_w.end_tag();
} }
item_ty(_, tps) { item_ty(_, tps, _) {
add_to_index(ebml_w, path, index, it.ident); add_to_index(ebml_w, path, index, it.ident);
ebml_w.start_tag(tag_paths_data_item); ebml_w.start_tag(tag_paths_data_item);
encode_name(ebml_w, it.ident); encode_name(ebml_w, it.ident);
encode_def_id(ebml_w, local_def(it.id)); encode_def_id(ebml_w, local_def(it.id));
ebml_w.end_tag(); ebml_w.end_tag();
} }
item_res(_, tps, _, _, ctor_id) { item_res(_, tps, _, _, ctor_id, _) {
add_to_index(ebml_w, path, index, it.ident); add_to_index(ebml_w, path, index, it.ident);
ebml_w.start_tag(tag_paths_data_item); ebml_w.start_tag(tag_paths_data_item);
encode_name(ebml_w, it.ident); encode_name(ebml_w, it.ident);
@ -151,7 +158,7 @@ fn encode_module_item_paths(ebml_w: ebml::writer, ecx: @encode_ctxt,
encode_def_id(ebml_w, local_def(it.id)); encode_def_id(ebml_w, local_def(it.id));
ebml_w.end_tag(); ebml_w.end_tag();
} }
item_class(_, _, items, ctor) { item_class(_, _, items, ctor, _) {
add_to_index(ebml_w, path, index, it.ident); add_to_index(ebml_w, path, index, it.ident);
ebml_w.start_tag(tag_paths_data_item); ebml_w.start_tag(tag_paths_data_item);
encode_name(ebml_w, it.ident); encode_name(ebml_w, it.ident);
@ -165,7 +172,7 @@ fn encode_module_item_paths(ebml_w: ebml::writer, ecx: @encode_ctxt,
index); index);
ebml_w.end_tag(); ebml_w.end_tag();
} }
item_enum(variants, tps) { item_enum(variants, _, _) {
add_to_index(ebml_w, path, index, it.ident); add_to_index(ebml_w, path, index, it.ident);
ebml_w.start_tag(tag_paths_data_item); ebml_w.start_tag(tag_paths_data_item);
encode_name(ebml_w, it.ident); encode_name(ebml_w, it.ident);
@ -480,7 +487,8 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
index: @mut [entry<int>], path: ast_map::path) { index: @mut [entry<int>], path: ast_map::path) {
let tcx = ecx.ccx.tcx; let tcx = ecx.ccx.tcx;
let must_write = alt item.node { item_enum(_, _) { true } _ { false } }; let must_write =
alt item.node { item_enum(_, _, _) { true } _ { false } };
if !must_write && !ecx.ccx.reachable.contains_key(item.id) { ret; } if !must_write && !ecx.ccx.reachable.contains_key(item.id) { ret; }
fn add_to_index_(item: @item, ebml_w: ebml::writer, fn add_to_index_(item: @item, ebml_w: ebml::writer,
@ -528,7 +536,7 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
encode_path(ebml_w, path, ast_map::path_name(item.ident)); encode_path(ebml_w, path, ast_map::path_name(item.ident));
ebml_w.end_tag(); ebml_w.end_tag();
} }
item_ty(_, tps) { item_ty(_, tps, rp) {
add_to_index(); add_to_index();
ebml_w.start_tag(tag_items_data_item); ebml_w.start_tag(tag_items_data_item);
encode_def_id(ebml_w, local_def(item.id)); encode_def_id(ebml_w, local_def(item.id));
@ -537,26 +545,28 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id)); encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id));
encode_name(ebml_w, item.ident); encode_name(ebml_w, item.ident);
encode_path(ebml_w, path, ast_map::path_name(item.ident)); encode_path(ebml_w, path, ast_map::path_name(item.ident));
encode_region_param(ebml_w, rp);
ebml_w.end_tag(); ebml_w.end_tag();
} }
item_enum(variants, tps) { item_enum(variants, tps, rp) {
add_to_index(); add_to_index();
ebml_w.start_tag(tag_items_data_item); ebml_w.wr_tag(tag_items_data_item) {||
encode_def_id(ebml_w, local_def(item.id)); encode_def_id(ebml_w, local_def(item.id));
encode_family(ebml_w, 't'); encode_family(ebml_w, 't');
encode_type_param_bounds(ebml_w, ecx, tps); encode_type_param_bounds(ebml_w, ecx, tps);
encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id)); encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id));
encode_name(ebml_w, item.ident); encode_name(ebml_w, item.ident);
for variants.each {|v| for variants.each {|v|
encode_variant_id(ebml_w, local_def(v.node.id)); encode_variant_id(ebml_w, local_def(v.node.id));
}
astencode::encode_inlined_item(ecx, ebml_w, path, ii_item(item));
encode_path(ebml_w, path, ast_map::path_name(item.ident));
encode_region_param(ebml_w, rp);
} }
astencode::encode_inlined_item(ecx, ebml_w, path, ii_item(item));
encode_path(ebml_w, path, ast_map::path_name(item.ident));
ebml_w.end_tag();
encode_enum_variant_info(ecx, ebml_w, item.id, variants, encode_enum_variant_info(ecx, ebml_w, item.id, variants,
path, index, tps); path, index, tps);
} }
item_class(tps, _ifaces, items,ctor) { item_class(tps, _ifaces, items, ctor, rp) {
/* First, encode the fields and methods /* First, encode the fields and methods
These come first because we need to write them to make These come first because we need to write them to make
the index, and the index needs to be in the item for the the index, and the index needs to be in the item for the
@ -573,6 +583,7 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id)); encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id));
encode_name(ebml_w, item.ident); encode_name(ebml_w, item.ident);
encode_path(ebml_w, path, ast_map::path_name(item.ident)); encode_path(ebml_w, path, ast_map::path_name(item.ident));
encode_region_param(ebml_w, rp);
/* FIXME: encode ifaces */ /* FIXME: encode ifaces */
/* Encode def_ids for each field and method /* Encode def_ids for each field and method
for methods, write all the stuff get_iface_method for methods, write all the stuff get_iface_method
@ -605,7 +616,7 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
encode_index(ebml_w, bkts, write_int); encode_index(ebml_w, bkts, write_int);
ebml_w.end_tag(); ebml_w.end_tag();
} }
item_res(_, tps, _, _, ctor_id) { item_res(_, tps, _, _, ctor_id, rp) {
add_to_index(); add_to_index();
let fn_ty = node_id_to_type(tcx, ctor_id); let fn_ty = node_id_to_type(tcx, ctor_id);
@ -620,6 +631,7 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
encode_symbol(ecx, ebml_w, item.id); encode_symbol(ecx, ebml_w, item.id);
} }
encode_path(ebml_w, path, ast_map::path_name(item.ident)); encode_path(ebml_w, path, ast_map::path_name(item.ident));
encode_region_param(ebml_w, rp);
ebml_w.end_tag(); ebml_w.end_tag();
*index += [{val: ctor_id, pos: ebml_w.writer.tell()}]; *index += [{val: ctor_id, pos: ebml_w.writer.tell()}];
@ -732,7 +744,7 @@ fn encode_info_for_items(ecx: @encode_ctxt, ebml_w: ebml::writer,
encode_info_for_item(ecx, ebml_w, i, index, *pt); encode_info_for_item(ecx, ebml_w, i, index, *pt);
/* encode ctor, then encode items */ /* encode ctor, then encode items */
alt i.node { alt i.node {
item_class(tps,_,_,ctor) { item_class(tps, _, _, ctor, _) {
/* this is assuming that ctors aren't inlined... /* this is assuming that ctors aren't inlined...
probably shouldn't assume that */ probably shouldn't assume that */
#debug("encoding info for ctor %s %d", i.ident, #debug("encoding info for ctor %s %d", i.ident,

View file

@ -182,6 +182,65 @@ fn parse_vstore(st: @pstate) -> ty::vstore {
st.tcx.sess.unimpl("tydecode::parse_vstore"); st.tcx.sess.unimpl("tydecode::parse_vstore");
} }
fn parse_substs(st: @pstate, conv: conv_did) -> ty::substs {
let self_r = parse_opt(st) {|| parse_region(st) };
assert next(st) == '[';
let mut params: [ty::t] = [];
while peek(st) != ']' { params += [parse_ty(st, conv)]; }
st.pos = st.pos + 1u;
ret {self_r: self_r, tps: params};
}
fn parse_bound_region(st: @pstate) -> ty::bound_region {
alt check next(st) {
's' { ty::br_self }
'a' { ty::br_anon }
'[' { ty::br_named(parse_str(st, ']')) }
}
}
fn parse_region(st: @pstate) -> ty::region {
alt check next(st) {
'b' {
ty::re_bound(parse_bound_region(st))
}
'f' {
assert next(st) == '[';
let id = parse_int(st);
assert next(st) == '|';
let br = parse_bound_region(st);
assert next(st) == ']';
ty::re_free(id, br)
}
's' {
let id = parse_int(st);
assert next(st) == '|';
ty::re_scope(id)
}
't' {
ty::re_static
}
}
}
fn parse_opt<T>(st: @pstate, f: fn() -> T) -> option<T> {
alt check next(st) {
'n' { none }
's' { some(f()) }
}
}
fn parse_str(st: @pstate, term: char) -> str {
let mut result = "";
while peek(st) != term {
result += str::from_byte(next_byte(st));
}
next(st);
ret result;
}
fn parse_ty(st: @pstate, conv: conv_did) -> ty::t { fn parse_ty(st: @pstate, conv: conv_did) -> ty::t {
alt check next(st) { alt check next(st) {
'n' { ret ty::mk_nil(st.tcx); } 'n' { ret ty::mk_nil(st.tcx); }
@ -209,10 +268,9 @@ fn parse_ty(st: @pstate, conv: conv_did) -> ty::t {
't' { 't' {
assert (next(st) == '['); assert (next(st) == '[');
let def = parse_def(st, conv); let def = parse_def(st, conv);
let mut params: [ty::t] = []; let substs = parse_substs(st, conv);
while peek(st) != ']' { params += [parse_ty(st, conv)]; } assert next(st) == ']';
st.pos = st.pos + 1u; ret ty::mk_enum(st.tcx, def, substs);
ret ty::mk_enum(st.tcx, def, params);
} }
'x' { 'x' {
assert (next(st) == '['); assert (next(st) == '[');
@ -250,11 +308,7 @@ fn parse_ty(st: @pstate, conv: conv_did) -> ty::t {
assert (next(st) == '['); assert (next(st) == '[');
let mut fields: [ty::field] = []; let mut fields: [ty::field] = [];
while peek(st) != ']' { while peek(st) != ']' {
let mut name = ""; let name = parse_str(st, '=');
while peek(st) != '=' {
name += str::from_byte(next_byte(st));
}
st.pos = st.pos + 1u;
fields += [{ident: name, mt: parse_mt(st, conv)}]; fields += [{ident: name, mt: parse_mt(st, conv)}];
} }
st.pos = st.pos + 1u; st.pos = st.pos + 1u;
@ -275,10 +329,9 @@ fn parse_ty(st: @pstate, conv: conv_did) -> ty::t {
assert (next(st) == '['); assert (next(st) == '[');
let def = parse_def(st, conv); let def = parse_def(st, conv);
let inner = parse_ty(st, conv); let inner = parse_ty(st, conv);
let mut params: [ty::t] = []; let substs = parse_substs(st, conv);
while peek(st) != ']' { params += [parse_ty(st, conv)]; } assert next(st) == ']';
st.pos = st.pos + 1u; ret ty::mk_res(st.tcx, def, inner, substs);
ret ty::mk_res(st.tcx, def, inner, params);
} }
'X' { 'X' {
ret ty::mk_var(st.tcx, ty::ty_vid(parse_int(st) as uint)); ret ty::mk_var(st.tcx, ty::ty_vid(parse_int(st) as uint));
@ -326,10 +379,9 @@ fn parse_ty(st: @pstate, conv: conv_did) -> ty::t {
#debug("saw a ["); #debug("saw a [");
let did = parse_def(st, conv); let did = parse_def(st, conv);
#debug("parsed a def_id %?", did); #debug("parsed a def_id %?", did);
let mut params: [ty::t] = []; let substs = parse_substs(st, conv);
while peek(st) != ']' { params += [parse_ty(st, conv)]; }
assert (next(st) == ']'); assert (next(st) == ']');
ret ty::mk_class(st.tcx, did, params); ret ty::mk_class(st.tcx, did, substs);
} }
c { #error("unexpected char in type string: %c", c); fail;} c { #error("unexpected char in type string: %c", c); fail;}
} }

View file

@ -100,18 +100,25 @@ fn enc_mt(w: io::writer, cx: @ctxt, mt: ty::mt) {
} }
enc_ty(w, cx, mt.ty); enc_ty(w, cx, mt.ty);
} }
fn enc_bound_region(w: io::writer, br: ty::bound_region) {
alt br { fn enc_opt<T>(w: io::writer, t: option<T>, enc_f: fn(T)) {
ty::br_self { w.write_char('s') } alt t {
ty::br_anon { w.write_char('a') } none { w.write_char('n') }
ty::br_named(s) { some(v) {
w.write_char('['); w.write_char('s');
w.write_str(s); enc_f(v);
w.write_char(']')
} }
} }
} }
fn enc_region(w: io::writer, r: ty::region) {
fn enc_substs(w: io::writer, cx: @ctxt, substs: ty::substs) {
enc_opt(w, substs.self_r) { |r| enc_region(w, cx, r) }
w.write_char('[');
for substs.tps.each { |t| enc_ty(w, cx, t); }
w.write_char(']');
}
fn enc_region(w: io::writer, cx: @ctxt, r: ty::region) {
alt r { alt r {
ty::re_bound(br) { ty::re_bound(br) {
w.write_char('b'); w.write_char('b');
@ -130,18 +137,29 @@ fn enc_region(w: io::writer, r: ty::region) {
w.write_int(nid); w.write_int(nid);
w.write_char('|'); w.write_char('|');
} }
ty::re_var(id) {
w.write_char('v');
w.write_uint(id.to_uint());
w.write_char('|');
}
ty::re_static { ty::re_static {
w.write_char('t'); w.write_char('t');
} }
ty::re_var(_) {
// these should not crop up after typeck
cx.tcx.sess.bug("Cannot encode region variables");
}
} }
} }
fn enc_vstore(w: io::writer, v: ty::vstore) { fn enc_bound_region(w: io::writer, br: ty::bound_region) {
alt br {
ty::br_self { w.write_char('s') }
ty::br_anon { w.write_char('a') }
ty::br_named(s) {
w.write_char('[');
w.write_str(s);
w.write_char(']')
}
}
}
fn enc_vstore(w: io::writer, cx: @ctxt, v: ty::vstore) {
w.write_char('/'); w.write_char('/');
alt v { alt v {
ty::vstore_fixed(u) { ty::vstore_fixed(u) {
@ -156,7 +174,7 @@ fn enc_vstore(w: io::writer, v: ty::vstore) {
} }
ty::vstore_slice(r) { ty::vstore_slice(r) {
w.write_char('&'); w.write_char('&');
enc_region(w, r); enc_region(w, cx, r);
} }
} }
} }
@ -193,11 +211,11 @@ fn enc_sty(w: io::writer, cx: @ctxt, st: ty::sty) {
} }
} }
ty::ty_str { w.write_char('S'); } ty::ty_str { w.write_char('S'); }
ty::ty_enum(def, tys) { ty::ty_enum(def, substs) {
w.write_str("t["); w.write_str("t[");
w.write_str(cx.ds(def)); w.write_str(cx.ds(def));
w.write_char('|'); w.write_char('|');
for tys.each {|t| enc_ty(w, cx, t); } enc_substs(w, cx, substs);
w.write_char(']'); w.write_char(']');
} }
ty::ty_iface(def, tys) { ty::ty_iface(def, tys) {
@ -217,17 +235,17 @@ fn enc_sty(w: io::writer, cx: @ctxt, st: ty::sty) {
ty::ty_ptr(mt) { w.write_char('*'); enc_mt(w, cx, mt); } ty::ty_ptr(mt) { w.write_char('*'); enc_mt(w, cx, mt); }
ty::ty_rptr(r, mt) { ty::ty_rptr(r, mt) {
w.write_char('&'); w.write_char('&');
enc_region(w, r); enc_region(w, cx, r);
enc_mt(w, cx, mt); enc_mt(w, cx, mt);
} }
ty::ty_evec(mt, v) { ty::ty_evec(mt, v) {
w.write_char('V'); w.write_char('V');
enc_mt(w, cx, mt); enc_mt(w, cx, mt);
enc_vstore(w, v); enc_vstore(w, cx, v);
} }
ty::ty_estr(v) { ty::ty_estr(v) {
w.write_char('v'); w.write_char('v');
enc_vstore(w, v); enc_vstore(w, cx, v);
} }
ty::ty_vec(mt) { w.write_char('I'); enc_mt(w, cx, mt); } ty::ty_vec(mt) { w.write_char('I'); enc_mt(w, cx, mt); }
ty::ty_rec(fields) { ty::ty_rec(fields) {
@ -243,12 +261,12 @@ fn enc_sty(w: io::writer, cx: @ctxt, st: ty::sty) {
enc_proto(w, f.proto); enc_proto(w, f.proto);
enc_ty_fn(w, cx, f); enc_ty_fn(w, cx, f);
} }
ty::ty_res(def, ty, tps) { ty::ty_res(def, ty, substs) {
w.write_str("r["); w.write_str("r[");
w.write_str(cx.ds(def)); w.write_str(cx.ds(def));
w.write_char('|'); w.write_char('|');
enc_ty(w, cx, ty); enc_ty(w, cx, ty);
for tps.each {|t| enc_ty(w, cx, t); } enc_substs(w, cx, substs);
w.write_char(']'); w.write_char(']');
} }
ty::ty_var(id) { ty::ty_var(id) {
@ -277,7 +295,7 @@ fn enc_sty(w: io::writer, cx: @ctxt, st: ty::sty) {
w.write_char(']'); w.write_char(']');
} }
ty::ty_opaque_box { w.write_char('B'); } ty::ty_opaque_box { w.write_char('B'); }
ty::ty_class(def, tys) { ty::ty_class(def, substs) {
#debug("~~~~ %s", "a["); #debug("~~~~ %s", "a[");
w.write_str("a["); w.write_str("a[");
let s = cx.ds(def); let s = cx.ds(def);
@ -285,7 +303,7 @@ fn enc_sty(w: io::writer, cx: @ctxt, st: ty::sty) {
w.write_str(s); w.write_str(s);
#debug("~~~~ %s", "|"); #debug("~~~~ %s", "|");
w.write_str("|"); w.write_str("|");
for tys.each {|t| enc_ty(w, cx, t); } enc_substs(w, cx, substs);
#debug("~~~~ %s", "]"); #debug("~~~~ %s", "]");
w.write_char(']'); w.write_char(']');
} }

View file

@ -503,7 +503,7 @@ fn ty_can_unsafely_include(cx: ctx, needle: unsafe_ty, haystack: ty::t,
} { ret true; } } { ret true; }
alt ty::get(haystack).struct { alt ty::get(haystack).struct {
ty::ty_enum(_, ts) { ty::ty_enum(_, ts) {
for ts.each {|t| for ts.tps.each {|t|
if helper(tcx, needle, t, mutbl) { ret true; } if helper(tcx, needle, t, mutbl) { ret true; }
} }
ret false; ret false;
@ -565,10 +565,11 @@ fn copy_is_expensive(tcx: ty::ctxt, ty: ty::t) -> bool {
ty::ty_fn(_) { 4u } ty::ty_fn(_) { 4u }
ty::ty_str | ty::ty_vec(_) | ty::ty_param(_, _) { 50u } ty::ty_str | ty::ty_vec(_) | ty::ty_param(_, _) { 50u }
ty::ty_uniq(mt) { 1u + score_ty(tcx, mt.ty) } ty::ty_uniq(mt) { 1u + score_ty(tcx, mt.ty) }
ty::ty_enum(_, ts) | ty::ty_tup(ts) { ty::ty_enum(_, substs) {
let mut sum = 0u; substs.tps.foldl(0u) { |sum, t| sum + score_ty(tcx, t) }
for ts.each {|t| sum += score_ty(tcx, t); } }
sum ty::ty_tup(ts) {
ts.foldl(0u) { |sum, t| sum + score_ty(tcx, t) }
} }
ty::ty_rec(fs) { ty::ty_rec(fs) {
let mut sum = 0u; let mut sum = 0u;

View file

@ -183,13 +183,13 @@ fn map_item(i: @item, cx: ctx, v: vt) {
map_method(impl_did, extend(cx, i.ident), m, cx); map_method(impl_did, extend(cx, i.ident), m, cx);
} }
} }
item_res(decl, tps, _, dtor_id, ctor_id) { item_res(decl, tps, _, dtor_id, ctor_id, _) {
cx.map.insert(ctor_id, node_ctor(i.ident, tps, cx.map.insert(ctor_id, node_ctor(i.ident, tps,
res_ctor(decl, ctor_id, i.span), res_ctor(decl, ctor_id, i.span),
item_path)); item_path));
cx.map.insert(dtor_id, node_item(i, item_path)); cx.map.insert(dtor_id, node_item(i, item_path));
} }
item_enum(vs, _) { item_enum(vs, _, _) {
for vs.each {|v| for vs.each {|v|
cx.map.insert(v.node.id, node_variant( cx.map.insert(v.node.id, node_variant(
v, i, extend(cx, i.ident))); v, i, extend(cx, i.ident)));
@ -204,7 +204,7 @@ fn map_item(i: @item, cx: ctx, v: vt) {
cx.map.insert(nitem.id, node_native_item(nitem, abi, @cx.path)); cx.map.insert(nitem.id, node_native_item(nitem, abi, @cx.path));
} }
} }
item_class(_, _, items, ctor) { item_class(_, _, items, ctor, _) {
let d_id = ast_util::local_def(i.id); let d_id = ast_util::local_def(i.id);
let p = extend(cx, i.ident); let p = extend(cx, i.ident);
for items.each {|ci| for items.each {|ci|

View file

@ -22,7 +22,7 @@ fn check_item(sess: session, ast_map: ast_map::map, def_map: resolve::def_map,
v.visit_expr(ex, true, v); v.visit_expr(ex, true, v);
check_item_recursion(sess, ast_map, def_map, it); check_item_recursion(sess, ast_map, def_map, it);
} }
item_enum(vs, _) { item_enum(vs, _, _) {
for vs.each {|var| for vs.each {|var|
option::iter(var.node.disr_expr) {|ex| option::iter(var.node.disr_expr) {|ex|
v.visit_expr(ex, true, v); v.visit_expr(ex, true, v);

View file

@ -538,11 +538,21 @@ impl unify_methods for infer_ctxt {
sub(self).tys(a, b).chain {|_t| ok(()) } sub(self).tys(a, b).chain {|_t| ok(()) }
} }
fn sub_regions(a: ty::region, b: ty::region) -> ures {
sub(self).regions(a, b).chain {|_t| ok(()) }
}
fn eq_tys(a: ty::t, b: ty::t) -> ures { fn eq_tys(a: ty::t, b: ty::t) -> ures {
self.sub_tys(a, b).then {|| self.sub_tys(a, b).then {||
self.sub_tys(b, a) self.sub_tys(b, a)
} }
} }
fn eq_regions(a: ty::region, b: ty::region) -> ures {
self.sub_regions(a, b).then {||
self.sub_regions(b, a)
}
}
} }
impl resolve_methods for infer_ctxt { impl resolve_methods for infer_ctxt {
@ -905,6 +915,7 @@ iface combine {
fn contratys(a: ty::t, b: ty::t) -> cres<ty::t>; fn contratys(a: ty::t, b: ty::t) -> cres<ty::t>;
fn tys(a: ty::t, b: ty::t) -> cres<ty::t>; fn tys(a: ty::t, b: ty::t) -> cres<ty::t>;
fn tps(as: [ty::t], bs: [ty::t]) -> cres<[ty::t]>; fn tps(as: [ty::t], bs: [ty::t]) -> cres<[ty::t]>;
fn substs(as: ty::substs, bs: ty::substs) -> cres<ty::substs>;
fn fns(a: ty::fn_ty, b: ty::fn_ty) -> cres<ty::fn_ty>; fn fns(a: ty::fn_ty, b: ty::fn_ty) -> cres<ty::fn_ty>;
fn flds(a: ty::field, b: ty::field) -> cres<ty::field>; fn flds(a: ty::field, b: ty::field) -> cres<ty::field>;
fn modes(a: ast::mode, b: ast::mode) -> cres<ast::mode>; fn modes(a: ast::mode, b: ast::mode) -> cres<ast::mode>;
@ -921,6 +932,41 @@ enum sub = infer_ctxt; // "subtype", "subregion" etc
enum lub = infer_ctxt; // "least upper bound" (common supertype) enum lub = infer_ctxt; // "least upper bound" (common supertype)
enum glb = infer_ctxt; // "greatest lower bound" (common subtype) enum glb = infer_ctxt; // "greatest lower bound" (common subtype)
fn super_substs<C:combine>(
self: C, a: ty::substs, b: ty::substs) -> cres<ty::substs> {
fn eq_opt_regions(infcx: infer_ctxt,
a: option<ty::region>,
b: option<ty::region>) -> cres<option<ty::region>> {
alt (a, b) {
(none, none) {
ok(none)
}
(some(a), some(b)) {
infcx.eq_regions(a, b);
ok(some(a))
}
(_, _) {
// If these two substitutions are for the same type (and
// they should be), then the type should either
// consistenly have a region parameter or not have a
// region parameter.
infcx.tcx.sess.bug(
#fmt["substitution a had opt_region %s and \
b had opt_region %s",
a.to_str(infcx),
b.to_str(infcx)]);
}
}
}
self.tps(a.tps, b.tps).chain { |tps|
eq_opt_regions(self.infcx(), a.self_r, b.self_r).chain { |self_r|
ok({self_r: self_r, tps: tps})
}
}
}
fn super_tps<C:combine>( fn super_tps<C:combine>(
self: C, as: [ty::t], bs: [ty::t]) -> cres<[ty::t]> { self: C, as: [ty::t], bs: [ty::t]) -> cres<[ty::t]> {
@ -1057,9 +1103,9 @@ fn super_tys<C:combine>(
ok(a) ok(a)
} }
(ty::ty_enum(a_id, a_tps), ty::ty_enum(b_id, b_tps)) (ty::ty_enum(a_id, a_substs), ty::ty_enum(b_id, b_substs))
if a_id == b_id { if a_id == b_id {
self.tps(a_tps, b_tps).chain {|tps| self.substs(a_substs, b_substs).chain {|tps|
ok(ty::mk_enum(tcx, a_id, tps)) ok(ty::mk_enum(tcx, a_id, tps))
} }
} }
@ -1071,10 +1117,10 @@ fn super_tys<C:combine>(
} }
} }
(ty::ty_class(a_id, a_tps), ty::ty_class(b_id, b_tps)) (ty::ty_class(a_id, a_substs), ty::ty_class(b_id, b_substs))
if a_id == b_id { if a_id == b_id {
self.tps(a_tps, b_tps).chain {|tps| self.substs(a_substs, b_substs).chain {|substs|
ok(ty::mk_class(tcx, a_id, tps)) ok(ty::mk_class(tcx, a_id, substs))
} }
} }
@ -1124,11 +1170,12 @@ fn super_tys<C:combine>(
} }
} }
(ty::ty_res(a_id, a_t, a_tps), ty::ty_res(b_id, b_t, b_tps)) (ty::ty_res(a_id, a_t, a_substs),
ty::ty_res(b_id, b_t, b_substs))
if a_id == b_id { if a_id == b_id {
self.tys(a_t, b_t).chain {|t| self.tys(a_t, b_t).chain {|t|
self.tps(a_tps, b_tps).chain {|tps| self.substs(a_substs, b_substs).chain {|substs|
ok(ty::mk_res(tcx, a_id, t, tps)) ok(ty::mk_res(tcx, a_id, t, substs))
} }
} }
} }
@ -1299,6 +1346,10 @@ impl of combine for sub {
super_fns(self, a, b) super_fns(self, a, b)
} }
fn substs(as: ty::substs, bs: ty::substs) -> cres<ty::substs> {
super_substs(self, as, bs)
}
fn tps(as: [ty::t], bs: [ty::t]) -> cres<[ty::t]> { fn tps(as: [ty::t], bs: [ty::t]) -> cres<[ty::t]> {
super_tps(self, as, bs) super_tps(self, as, bs)
} }
@ -1470,6 +1521,10 @@ impl of combine for lub {
super_fns(self, a, b) super_fns(self, a, b)
} }
fn substs(as: ty::substs, bs: ty::substs) -> cres<ty::substs> {
super_substs(self, as, bs)
}
fn tps(as: [ty::t], bs: [ty::t]) -> cres<[ty::t]> { fn tps(as: [ty::t], bs: [ty::t]) -> cres<[ty::t]> {
super_tps(self, as, bs) super_tps(self, as, bs)
} }
@ -1656,6 +1711,10 @@ impl of combine for glb {
super_fns(self, a, b) super_fns(self, a, b)
} }
fn substs(as: ty::substs, bs: ty::substs) -> cres<ty::substs> {
super_substs(self, as, bs)
}
fn tps(as: [ty::t], bs: [ty::t]) -> cres<[ty::t]> { fn tps(as: [ty::t], bs: [ty::t]) -> cres<[ty::t]> {
super_tps(self, as, bs) super_tps(self, as, bs)
} }

View file

@ -30,18 +30,18 @@ fn expr_root_(tcx: ty::ctxt, ctor_self: option<node_id>,
outer_t: t}]; outer_t: t}];
t = mt.ty; t = mt.ty;
} }
ty::ty_res(_, inner, tps) { ty::ty_res(_, inner, substs) {
ds += [@{mutbl: false, kind: unbox(false), outer_t: t}]; ds += [@{mutbl: false, kind: unbox(false), outer_t: t}];
t = ty::substitute_type_params(tcx, tps, inner); t = ty::subst(tcx, substs, inner);
} }
ty::ty_enum(did, tps) { ty::ty_enum(did, substs) {
let variants = ty::enum_variants(tcx, did); let variants = ty::enum_variants(tcx, did);
if vec::len(*variants) != 1u || if vec::len(*variants) != 1u ||
vec::len(variants[0].args) != 1u { vec::len(variants[0].args) != 1u {
break; break;
} }
ds += [@{mutbl: false, kind: unbox(false), outer_t: t}]; ds += [@{mutbl: false, kind: unbox(false), outer_t: t}];
t = ty::substitute_type_params(tcx, tps, variants[0].args[0]); t = ty::subst(tcx, substs, variants[0].args[0]);
} }
_ { break; } _ { break; }
} }
@ -216,7 +216,7 @@ fn visit_expr(ex: @expr, &&cx: @ctx, v: visit::vt<@ctx>) {
fn visit_item(item: @item, &&cx: @ctx, v: visit::vt<@ctx>) { fn visit_item(item: @item, &&cx: @ctx, v: visit::vt<@ctx>) {
alt item.node { alt item.node {
item_class(tps, _, items, ctor) { item_class(tps, _, items, ctor, _) {
v.visit_ty_params(tps, cx, v); v.visit_ty_params(tps, cx, v);
vec::map::<@class_member, ()>(items, vec::map::<@class_member, ()>(items,
{|i| v.visit_class_item(i, cx, v); }); {|i| v.visit_class_item(i, cx, v); });

View file

@ -143,16 +143,7 @@ import std::list::list;
import std::map; import std::map;
import std::map::hashmap; import std::map::hashmap;
/* Represents the type of the most immediate parent node. */ type parent = option<ast::node_id>;
enum parent {
pa_fn_item(ast::node_id),
pa_block(ast::node_id),
pa_nested_fn(ast::node_id),
pa_item(ast::node_id),
pa_call(ast::node_id),
pa_alt(ast::node_id),
pa_crate
}
/* Records the parameter ID of a region name. */ /* Records the parameter ID of a region name. */
type binding = {node_id: ast::node_id, type binding = {node_id: ast::node_id,
@ -167,43 +158,11 @@ type region_map = {
local_blocks: hashmap<ast::node_id,ast::node_id> local_blocks: hashmap<ast::node_id,ast::node_id>
}; };
type region_scope = @{
node_id: ast::node_id,
kind: region_scope_kind
};
enum region_scope_kind {
rsk_root,
rsk_body(region_scope),
rsk_self(region_scope),
rsk_binding(region_scope, @mut [binding])
}
fn root_scope(node_id: ast::node_id) -> region_scope {
@{node_id: node_id, kind: rsk_root}
}
impl methods for region_scope {
fn body_subscope(node_id: ast::node_id) -> region_scope {
@{node_id: node_id, kind: rsk_body(self)}
}
fn binding_subscope(node_id: ast::node_id) -> region_scope {
@{node_id: node_id, kind: rsk_binding(self, @mut [])}
}
fn self_subscope(node_id: ast::node_id) -> region_scope {
@{node_id: node_id, kind: rsk_self(self)}
}
}
type ctxt = { type ctxt = {
sess: session, sess: session,
def_map: resolve::def_map, def_map: resolve::def_map,
region_map: @region_map, region_map: @region_map,
scope: region_scope,
parent: parent parent: parent
}; };
@ -269,40 +228,8 @@ fn nearest_common_ancestor(region_map: @region_map, scope_a: ast::node_id,
} }
} }
fn get_inferred_region(cx: ctxt, sp: syntax::codemap::span) -> ty::region {
// We infer to the caller region if we're at item scope
// and to the block region if we're at block scope.
//
// TODO: What do we do if we're in an alt?
ret alt cx.parent {
pa_fn_item(_) | pa_nested_fn(_) { ty::re_bound(ty::br_anon) }
pa_block(node_id) | pa_call(node_id) | pa_alt(node_id) {
ty::re_scope(node_id)
}
pa_item(_) { ty::re_bound(ty::br_anon) }
pa_crate { cx.sess.span_bug(sp, "inferred region at crate level?!"); }
}
}
fn opt_parent_id(cx: ctxt) -> option<ast::node_id> {
alt cx.parent {
pa_fn_item(parent_id) |
pa_item(parent_id) |
pa_block(parent_id) |
pa_alt(parent_id) |
pa_call(parent_id) |
pa_nested_fn(parent_id) {
some(parent_id)
}
pa_crate {
none
}
}
}
fn parent_id(cx: ctxt, span: span) -> ast::node_id { fn parent_id(cx: ctxt, span: span) -> ast::node_id {
alt opt_parent_id(cx) { alt cx.parent {
none { none {
cx.sess.span_bug(span, "crate should not be parent here"); cx.sess.span_bug(span, "crate should not be parent here");
} }
@ -313,7 +240,7 @@ fn parent_id(cx: ctxt, span: span) -> ast::node_id {
} }
fn record_parent(cx: ctxt, child_id: ast::node_id) { fn record_parent(cx: ctxt, child_id: ast::node_id) {
alt opt_parent_id(cx) { alt cx.parent {
none { /* no-op */ } none { /* no-op */ }
some(parent_id) { some(parent_id) {
cx.region_map.parents.insert(child_id, parent_id); cx.region_map.parents.insert(child_id, parent_id);
@ -326,8 +253,7 @@ fn resolve_block(blk: ast::blk, cx: ctxt, visitor: visit::vt<ctxt>) {
record_parent(cx, blk.node.id); record_parent(cx, blk.node.id);
// Descend. // Descend.
let new_cx: ctxt = {parent: pa_block(blk.node.id), let new_cx: ctxt = {parent: some(blk.node.id)
scope: cx.scope.body_subscope(blk.node.id)
with cx}; with cx};
visit::visit_block(blk, new_cx, visitor); visit::visit_block(blk, new_cx, visitor);
} }
@ -361,21 +287,15 @@ fn resolve_expr(expr: @ast::expr, cx: ctxt, visitor: visit::vt<ctxt>) {
record_parent(cx, expr.id); record_parent(cx, expr.id);
alt expr.node { alt expr.node {
ast::expr_fn(_, _, _, _) | ast::expr_fn_block(_, _) { ast::expr_fn(_, _, _, _) | ast::expr_fn_block(_, _) {
let new_cx = {parent: pa_nested_fn(expr.id), let new_cx = {parent: some(expr.id) with cx};
scope: cx.scope.binding_subscope(expr.id)
with cx};
visit::visit_expr(expr, new_cx, visitor); visit::visit_expr(expr, new_cx, visitor);
} }
ast::expr_call(_, _, _) { ast::expr_call(_, _, _) {
let new_cx = {parent: pa_call(expr.id), let new_cx = {parent: some(expr.id) with cx};
scope: cx.scope.binding_subscope(expr.id)
with cx};
visit::visit_expr(expr, new_cx, visitor); visit::visit_expr(expr, new_cx, visitor);
} }
ast::expr_alt(subexpr, _, _) { ast::expr_alt(subexpr, _, _) {
let new_cx = {parent: pa_alt(expr.id), let new_cx = {parent: some(expr.id) with cx};
scope: cx.scope.binding_subscope(expr.id)
with cx};
visit::visit_expr(expr, new_cx, visitor); visit::visit_expr(expr, new_cx, visitor);
} }
_ { _ {
@ -392,27 +312,7 @@ fn resolve_local(local: @ast::local, cx: ctxt, visitor: visit::vt<ctxt>) {
fn resolve_item(item: @ast::item, cx: ctxt, visitor: visit::vt<ctxt>) { fn resolve_item(item: @ast::item, cx: ctxt, visitor: visit::vt<ctxt>) {
// Items create a new outer block scope as far as we're concerned. // Items create a new outer block scope as far as we're concerned.
let {parent, scope} = { let new_cx: ctxt = {parent: some(item.id) with cx};
alt item.node {
ast::item_fn(_, _, _) | ast::item_enum(_, _) {
{parent: pa_fn_item(item.id),
scope: cx.scope.binding_subscope(item.id)}
}
ast::item_impl(_, _, _, _) | ast::item_class(_, _, _, _) {
{parent: pa_item(item.id),
scope: cx.scope.self_subscope(item.id)}
}
_ {
{parent: pa_item(item.id),
scope: root_scope(item.id)}
}
}
};
let new_cx: ctxt = {parent: parent,
scope: scope
with cx};
visit::visit_item(item, new_cx, visitor); visit::visit_item(item, new_cx, visitor);
} }
@ -422,8 +322,7 @@ fn resolve_crate(sess: session, def_map: resolve::def_map, crate: @ast::crate)
def_map: def_map, def_map: def_map,
region_map: @{parents: map::int_hash(), region_map: @{parents: map::int_hash(),
local_blocks: map::int_hash()}, local_blocks: map::int_hash()},
scope: root_scope(0), parent: none};
parent: pa_crate};
let visitor = visit::mk_vt(@{ let visitor = visit::mk_vt(@{
visit_block: resolve_block, visit_block: resolve_block,
visit_item: resolve_item, visit_item: resolve_item,

View file

@ -434,7 +434,7 @@ fn resolve_names(e: @env, c: @ast::crate) {
non-class items non-class items
*/ */
alt i.node { alt i.node {
ast::item_class(_, ifaces, _, _) { ast::item_class(_, ifaces, _, _, _) {
/* visit the iface paths... */ /* visit the iface paths... */
for ifaces.each {|p| for ifaces.each {|p|
maybe_insert(e, p.id, maybe_insert(e, p.id,
@ -559,7 +559,7 @@ fn visit_item_with_scope(e: @env, i: @ast::item, sc: scopes, v: vt<scopes>) {
v.visit_ty(m.decl.output, msc, v); v.visit_ty(m.decl.output, msc, v);
} }
} }
ast::item_class(tps, ifaces, members, ctor) { ast::item_class(tps, ifaces, members, ctor, _) {
visit::visit_ty_params(tps, sc, v); visit::visit_ty_params(tps, sc, v);
// Can maybe skip this now that we require self on class fields // Can maybe skip this now that we require self on class fields
let class_scope = cons(scope_item(i), @sc); let class_scope = cons(scope_item(i), @sc);
@ -613,7 +613,7 @@ fn visit_fn_with_scope(e: @env, fk: visit::fn_kind, decl: ast::fn_decl,
// for f's constrs in the table. // for f's constrs in the table.
for decl.constraints.each {|c| resolve_constr(e, c, sc, v); } for decl.constraints.each {|c| resolve_constr(e, c, sc, v); }
let scope = alt fk { let scope = alt fk {
visit::fk_item_fn(_, tps) | visit::fk_res(_, tps) | 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) } { scope_bare_fn(decl, id, tps) }
visit::fk_anon(ast::proto_bare) { scope_bare_fn(decl, id, []) } visit::fk_anon(ast::proto_bare) { scope_bare_fn(decl, id, []) }
@ -1019,7 +1019,7 @@ fn lookup_in_scope(e: env, sc: scopes, sp: span, name: ident, ns: namespace,
ast::item_impl(tps, _, _, _) { ast::item_impl(tps, _, _, _) {
if ns == ns_type { ret lookup_in_ty_params(e, name, tps); } if ns == ns_type { ret lookup_in_ty_params(e, name, tps); }
} }
ast::item_enum(_, tps) | ast::item_ty(_, tps) { ast::item_enum(_, tps, _) | ast::item_ty(_, tps, _) {
if ns == ns_type { ret lookup_in_ty_params(e, name, tps); } if ns == ns_type { ret lookup_in_ty_params(e, name, tps); }
} }
ast::item_iface(tps, _) { ast::item_iface(tps, _) {
@ -1036,7 +1036,7 @@ fn lookup_in_scope(e: env, sc: scopes, sp: span, name: ident, ns: namespace,
ast::item_native_mod(m) { ast::item_native_mod(m) {
ret lookup_in_local_native_mod(e, it.id, sp, name, ns); ret lookup_in_local_native_mod(e, it.id, sp, name, ns);
} }
ast::item_class(tps, _, members, ctor) { ast::item_class(tps, _, members, ctor, _) {
if ns == ns_type { if ns == ns_type {
ret lookup_in_ty_params(e, name, tps); ret lookup_in_ty_params(e, name, tps);
} }
@ -1210,7 +1210,7 @@ fn lookup_in_block(e: env, name: ident, sp: span, b: ast::blk_, pos: uint,
} }
ast::decl_item(it) { ast::decl_item(it) {
alt it.node { alt it.node {
ast::item_enum(variants, _) { ast::item_enum(variants, _, _) {
if ns == ns_type { if ns == ns_type {
if str::eq(it.ident, name) { if str::eq(it.ident, name) {
ret some(ast::def_ty(local_def(it.id))); ret some(ast::def_ty(local_def(it.id)));
@ -1309,10 +1309,10 @@ fn found_def_item(i: @ast::item, ns: namespace) -> option<def> {
ast::item_native_mod(_) { ast::item_native_mod(_) {
if ns == ns_module { ret some(ast::def_native_mod(local_def(i.id))); } if ns == ns_module { ret some(ast::def_native_mod(local_def(i.id))); }
} }
ast::item_ty(_, _) | item_iface(_, _) | item_enum(_, _) { ast::item_ty(_, _, _) | item_iface(_, _) | item_enum(_, _, _) {
if ns == ns_type { ret some(ast::def_ty(local_def(i.id))); } if ns == ns_type { ret some(ast::def_ty(local_def(i.id))); }
} }
ast::item_res(_, _, _, _, ctor_id) { ast::item_res(_, _, _, _, ctor_id, _) {
alt ns { alt ns {
ns_val { ns_val {
ret some(ast::def_fn(local_def(ctor_id), ast::impure_fn)); ret some(ast::def_fn(local_def(ctor_id), ast::impure_fn));
@ -1321,7 +1321,7 @@ fn found_def_item(i: @ast::item, ns: namespace) -> option<def> {
_ { } _ { }
} }
} }
ast::item_class(_, _, _, _) { ast::item_class(_, _, _, _, _) {
if ns == ns_type { if ns == ns_type {
ret some(ast::def_class(local_def(i.id))); ret some(ast::def_class(local_def(i.id)));
} }
@ -1614,12 +1614,12 @@ fn index_mod(md: ast::_mod) -> mod_index {
for md.items.each {|it| for md.items.each {|it|
alt it.node { alt it.node {
ast::item_const(_, _) | ast::item_fn(_, _, _) | ast::item_mod(_) | ast::item_const(_, _) | ast::item_fn(_, _, _) | ast::item_mod(_) |
ast::item_native_mod(_) | ast::item_ty(_, _) | ast::item_native_mod(_) | ast::item_ty(_, _, _) |
ast::item_res(_, _, _, _, _) | ast::item_res(_, _, _, _, _, _) |
ast::item_impl(_, _, _, _) | ast::item_iface(_, _) { ast::item_impl(_, _, _, _) | ast::item_iface(_, _) {
add_to_index(index, it.ident, mie_item(it)); add_to_index(index, it.ident, mie_item(it));
} }
ast::item_enum(variants, _) { ast::item_enum(variants, _, _) {
add_to_index(index, it.ident, mie_item(it)); add_to_index(index, it.ident, mie_item(it));
let mut variant_idx: uint = 0u; let mut variant_idx: uint = 0u;
for variants.each {|v| for variants.each {|v|
@ -1629,7 +1629,7 @@ fn index_mod(md: ast::_mod) -> mod_index {
variant_idx += 1u; variant_idx += 1u;
} }
} }
ast::item_class(tps, _, items, ctor) { ast::item_class(tps, _, items, ctor, _) {
// add the class name itself // add the class name itself
add_to_index(index, it.ident, mie_item(it)); add_to_index(index, it.ident, mie_item(it));
// add the constructor decl // add the constructor decl
@ -1763,7 +1763,7 @@ fn check_item(e: @env, i: @ast::item, &&x: (), v: vt<()>) {
ensure_unique(*e, i.span, ty_params, {|tp| tp.ident}, ensure_unique(*e, i.span, ty_params, {|tp| tp.ident},
"type parameter"); "type parameter");
} }
ast::item_enum(_, ty_params) { ast::item_enum(_, ty_params, _) {
ensure_unique(*e, i.span, ty_params, {|tp| tp.ident}, ensure_unique(*e, i.span, ty_params, {|tp| tp.ident},
"type parameter"); "type parameter");
} }
@ -1837,7 +1837,7 @@ fn check_block(e: @env, b: ast::blk, &&x: (), v: vt<()>) {
} }
ast::decl_item(it) { ast::decl_item(it) {
alt it.node { alt it.node {
ast::item_enum(variants, _) { ast::item_enum(variants, _, _) {
add_name(types, it.span, it.ident); add_name(types, it.span, it.ident);
for variants.each {|v| for variants.each {|v|
add_name(values, v.span, v.node.name); add_name(values, v.span, v.node.name);
@ -1849,10 +1849,10 @@ fn check_block(e: @env, b: ast::blk, &&x: (), v: vt<()>) {
ast::item_const(_, _) | ast::item_fn(_, _, _) { ast::item_const(_, _) | ast::item_fn(_, _, _) {
add_name(values, it.span, it.ident); add_name(values, it.span, it.ident);
} }
ast::item_ty(_, _) | ast::item_iface(_, _) { ast::item_ty(_, _, _) | ast::item_iface(_, _) {
add_name(types, it.span, it.ident); add_name(types, it.span, it.ident);
} }
ast::item_res(_, _, _, _, _) { ast::item_res(_, _, _, _, _, _) {
add_name(types, it.span, it.ident); add_name(types, it.span, it.ident);
add_name(values, it.span, it.ident); add_name(values, it.span, it.ident);
} }
@ -2030,7 +2030,7 @@ fn check_exports(e: @env) {
some(ms) { some(ms) {
let maybe_id = list_search(ms) {|m| let maybe_id = list_search(ms) {|m|
alt m { alt m {
mie_item(@{node: item_enum(_, _), id, _}) { some(id) } mie_item(@{node: item_enum(_, _, _), id, _}) { some(id) }
_ { none } _ { none }
} }
}; };

View file

@ -263,11 +263,10 @@ fn extract_variant_args(bcx: block, pat_id: ast::node_id,
let _icx = bcx.insn_ctxt("alt::extract_variant_args"); let _icx = bcx.insn_ctxt("alt::extract_variant_args");
let ccx = bcx.fcx.ccx; let ccx = bcx.fcx.ccx;
let enum_ty_substs = alt check ty::get(node_id_type(bcx, pat_id)).struct { let enum_ty_substs = alt check ty::get(node_id_type(bcx, pat_id)).struct {
ty::ty_enum(id, tps) { assert id == vdefs.enm; tps } ty::ty_enum(id, substs) { assert id == vdefs.enm; substs.tps }
}; };
let mut blobptr = val; let mut blobptr = val;
let variants = ty::enum_variants(ccx.tcx, vdefs.enm); let variants = ty::enum_variants(ccx.tcx, vdefs.enm);
let mut args = [];
let size = ty::enum_variant_with_id(ccx.tcx, vdefs.enm, let size = ty::enum_variant_with_id(ccx.tcx, vdefs.enm,
vdefs.var).args.len(); vdefs.var).args.len();
if size > 0u && (*variants).len() != 1u { if size > 0u && (*variants).len() != 1u {
@ -275,14 +274,12 @@ fn extract_variant_args(bcx: block, pat_id: ast::node_id,
PointerCast(bcx, val, T_opaque_enum_ptr(ccx)); PointerCast(bcx, val, T_opaque_enum_ptr(ccx));
blobptr = GEPi(bcx, enumptr, [0, 1]); blobptr = GEPi(bcx, enumptr, [0, 1]);
} }
let mut i = 0u;
let vdefs_tg = vdefs.enm; let vdefs_tg = vdefs.enm;
let vdefs_var = vdefs.var; let vdefs_var = vdefs.var;
while i < size { let args = vec::from_fn(size) { |i|
args += [GEP_enum(bcx, blobptr, vdefs_tg, vdefs_var, GEP_enum(bcx, blobptr, vdefs_tg, vdefs_var,
enum_ty_substs, i)]; enum_ty_substs, i)
i += 1u; };
}
ret {vals: args, bcx: bcx}; ret {vals: args, bcx: bcx};
} }

View file

@ -297,7 +297,7 @@ fn GEP_enum(bcx: block, llblobptr: ValueRef, enum_id: ast::def_id,
assert ix < variant.args.len(); assert ix < variant.args.len();
let arg_lltys = vec::map(variant.args, {|aty| let arg_lltys = vec::map(variant.args, {|aty|
type_of(ccx, ty::substitute_type_params(ccx.tcx, ty_substs, aty)) type_of(ccx, ty::subst_tps(ccx.tcx, ty_substs, aty))
}); });
let typed_blobptr = PointerCast(bcx, llblobptr, let typed_blobptr = PointerCast(bcx, llblobptr,
T_ptr(T_struct(arg_lltys))); T_ptr(T_struct(arg_lltys)));
@ -686,8 +686,8 @@ fn make_drop_glue(bcx: block, v0: ValueRef, t: ty::t) {
ty::ty_evec(_, ty::vstore_uniq) | ty::ty_estr(ty::vstore_uniq) { ty::ty_evec(_, ty::vstore_uniq) | ty::ty_estr(ty::vstore_uniq) {
free_ty(bcx, Load(bcx, v0), t) free_ty(bcx, Load(bcx, v0), t)
} }
ty::ty_res(did, inner, tps) { ty::ty_res(did, inner, substs) {
trans_res_drop(bcx, v0, did, inner, tps) trans_res_drop(bcx, v0, did, inner, substs.tps)
} }
ty::ty_fn(_) { ty::ty_fn(_) {
closure::make_fn_glue(bcx, v0, t, drop_ty) closure::make_fn_glue(bcx, v0, t, drop_ty)
@ -735,7 +735,7 @@ fn trans_res_drop(bcx: block, rs: ValueRef, did: ast::def_id,
inner_t: ty::t, tps: [ty::t]) -> block { inner_t: ty::t, tps: [ty::t]) -> block {
let _icx = bcx.insn_ctxt("trans_res_drop"); let _icx = bcx.insn_ctxt("trans_res_drop");
let ccx = bcx.ccx(); let ccx = bcx.ccx();
let inner_t_s = ty::substitute_type_params(ccx.tcx, tps, inner_t); let inner_t_s = ty::subst_tps(ccx.tcx, tps, inner_t);
let drop_flag = GEPi(bcx, rs, [0, 0]); let drop_flag = GEPi(bcx, rs, [0, 0]);
with_cond(bcx, IsNotNull(bcx, Load(bcx, drop_flag))) {|bcx| with_cond(bcx, IsNotNull(bcx, Load(bcx, drop_flag))) {|bcx|
@ -911,7 +911,7 @@ fn iter_structural_ty(cx: block, av: ValueRef, t: ty::t,
let v_id = variant.id; let v_id = variant.id;
for vec::each(args) {|a| for vec::each(args) {|a|
let llfldp_a = GEP_enum(cx, a_tup, tid, v_id, tps, j); let llfldp_a = GEP_enum(cx, a_tup, tid, v_id, tps, j);
let ty_subst = ty::substitute_type_params(ccx.tcx, tps, a.ty); let ty_subst = ty::subst_tps(ccx.tcx, tps, a.ty);
cx = f(cx, llfldp_a, ty_subst); cx = f(cx, llfldp_a, ty_subst);
j += 1u; j += 1u;
} }
@ -943,19 +943,20 @@ fn iter_structural_ty(cx: block, av: ValueRef, t: ty::t,
cx = f(cx, llfld_a, arg); cx = f(cx, llfld_a, arg);
} }
} }
ty::ty_res(_, inner, tps) { ty::ty_res(_, inner, substs) {
let tcx = cx.tcx(); let tcx = cx.tcx();
let inner1 = ty::substitute_type_params(tcx, tps, inner); let inner1 = ty::subst(tcx, substs, inner);
let llfld_a = GEPi(cx, av, [0, 1]); let llfld_a = GEPi(cx, av, [0, 1]);
ret f(cx, llfld_a, inner1); ret f(cx, llfld_a, inner1);
} }
ty::ty_enum(tid, tps) { ty::ty_enum(tid, substs) {
let variants = ty::enum_variants(cx.tcx(), tid); let variants = ty::enum_variants(cx.tcx(), tid);
let n_variants = (*variants).len(); let n_variants = (*variants).len();
// Cast the enums to types we can GEP into. // Cast the enums to types we can GEP into.
if n_variants == 1u { if n_variants == 1u {
ret iter_variant(cx, av, variants[0], tps, tid, f); ret iter_variant(cx, av, variants[0],
substs.tps, tid, f);
} }
let ccx = cx.ccx(); let ccx = cx.ccx();
@ -979,15 +980,16 @@ fn iter_structural_ty(cx: block, av: ValueRef, t: ty::t,
int::to_str(variant.disr_val, 10u)); int::to_str(variant.disr_val, 10u));
AddCase(llswitch, C_int(ccx, variant.disr_val), variant_cx.llbb); AddCase(llswitch, C_int(ccx, variant.disr_val), variant_cx.llbb);
let variant_cx = let variant_cx =
iter_variant(variant_cx, llunion_a_ptr, variant, tps, tid, f); iter_variant(variant_cx, llunion_a_ptr, variant,
substs.tps, tid, f);
Br(variant_cx, next_cx.llbb); Br(variant_cx, next_cx.llbb);
} }
ret next_cx; ret next_cx;
} }
ty::ty_class(did, tps) { ty::ty_class(did, substs) {
// a class is like a record type // a class is like a record type
let mut i: int = 0; let mut i: int = 0;
for vec::each(ty::class_items_as_fields(cx.tcx(), did, tps)) {|fld| for vec::each(ty::class_items_as_fields(cx.tcx(), did, substs)) {|fld|
let llfld_a = GEPi(cx, av, [0, i]); let llfld_a = GEPi(cx, av, [0, i]);
cx = f(cx, llfld_a, fld.mt.ty); cx = f(cx, llfld_a, fld.mt.ty);
i += 1; i += 1;
@ -1617,17 +1619,17 @@ fn autoderef(cx: block, v: ValueRef, t: ty::t) -> result_t {
t1 = mt.ty; t1 = mt.ty;
v1 = v; v1 = v;
} }
ty::ty_res(did, inner, tps) { ty::ty_res(did, inner, substs) {
t1 = ty::substitute_type_params(ccx.tcx, tps, inner); t1 = ty::subst(ccx.tcx, substs, inner);
v1 = GEPi(cx, v1, [0, 1]); v1 = GEPi(cx, v1, [0, 1]);
} }
ty::ty_enum(did, tps) { ty::ty_enum(did, substs) {
let variants = ty::enum_variants(ccx.tcx, did); let variants = ty::enum_variants(ccx.tcx, did);
if (*variants).len() != 1u || variants[0].args.len() != 1u { if (*variants).len() != 1u || variants[0].args.len() != 1u {
break; break;
} }
t1 = t1 =
ty::substitute_type_params(ccx.tcx, tps, variants[0].args[0]); ty::subst(ccx.tcx, substs, variants[0].args[0]);
v1 = PointerCast(cx, v1, T_ptr(type_of(ccx, t1))); v1 = PointerCast(cx, v1, T_ptr(type_of(ccx, t1)));
} }
_ { break; } _ { break; }
@ -1939,7 +1941,7 @@ fn monomorphic_fn(ccx: @crate_ctxt, fn_id: ast::def_id, real_substs: [ty::t],
let (pt, name) = alt map_node { let (pt, name) = alt map_node {
ast_map::node_item(i, pt) { ast_map::node_item(i, pt) {
alt i.node { alt i.node {
ast::item_res(_, _, _, dtor_id, _) { ast::item_res(_, _, _, dtor_id, _, _) {
item_ty = ty::node_id_to_type(ccx.tcx, dtor_id); item_ty = ty::node_id_to_type(ccx.tcx, dtor_id);
} }
_ {} _ {}
@ -1958,7 +1960,7 @@ fn monomorphic_fn(ccx: @crate_ctxt, fn_id: ast::def_id, real_substs: [ty::t],
ast_map::node_ctor(nm, _, _, pt) { (pt, nm) } ast_map::node_ctor(nm, _, _, pt) { (pt, nm) }
_ { fail "unexpected node type"; } _ { fail "unexpected node type"; }
}; };
let mono_ty = ty::substitute_type_params(ccx.tcx, substs, item_ty); let mono_ty = ty::subst_tps(ccx.tcx, substs, item_ty);
let llfty = type_of_fn_from_ty(ccx, mono_ty); let llfty = type_of_fn_from_ty(ccx, mono_ty);
let pt = *pt + [path_name(ccx.names(name))]; let pt = *pt + [path_name(ccx.names(name))];
@ -1972,7 +1974,8 @@ fn monomorphic_fn(ccx: @crate_ctxt, fn_id: ast::def_id, real_substs: [ty::t],
set_inline_hint_if_appr(i.attrs, lldecl); set_inline_hint_if_appr(i.attrs, lldecl);
trans_fn(ccx, pt, decl, body, lldecl, no_self, psubsts, fn_id.node); trans_fn(ccx, pt, decl, body, lldecl, no_self, psubsts, fn_id.node);
} }
ast_map::node_item(@{node: ast::item_res(d, _, body, d_id, _), _}, _) { ast_map::node_item(
@{node: ast::item_res(d, _, body, d_id, _, _), _}, _) {
trans_fn(ccx, pt, d, body, lldecl, no_self, psubsts, d_id); trans_fn(ccx, pt, d, body, lldecl, no_self, psubsts, d_id);
} }
ast_map::node_native_item(i, _, _) { ast_map::node_native_item(i, _, _) {
@ -1990,7 +1993,7 @@ fn monomorphic_fn(ccx: @crate_ctxt, fn_id: ast::def_id, real_substs: [ty::t],
ast_map::node_method(mth, impl_def_id, _) { ast_map::node_method(mth, impl_def_id, _) {
set_inline_hint_if_appr(mth.attrs, lldecl); set_inline_hint_if_appr(mth.attrs, lldecl);
let selfty = ty::node_id_to_type(ccx.tcx, mth.self_id); let selfty = ty::node_id_to_type(ccx.tcx, mth.self_id);
let selfty = ty::substitute_type_params(ccx.tcx, substs, selfty); let selfty = ty::subst_tps(ccx.tcx, substs, selfty);
trans_fn(ccx, pt, mth.decl, mth.body, lldecl, trans_fn(ccx, pt, mth.decl, mth.body, lldecl,
impl_self(selfty), psubsts, fn_id.node); impl_self(selfty), psubsts, fn_id.node);
} }
@ -2048,7 +2051,7 @@ fn maybe_instantiate_inline(ccx: @crate_ctxt, fn_id: ast::def_id)
ccx.external.insert(parent_id, some(item.id)); ccx.external.insert(parent_id, some(item.id));
let mut my_id = 0; let mut my_id = 0;
alt check item.node { alt check item.node {
ast::item_enum(_, _) { ast::item_enum(_, _, _) {
let vs_here = ty::enum_variants(ccx.tcx, local_def(item.id)); let vs_here = ty::enum_variants(ccx.tcx, local_def(item.id));
let vs_there = ty::enum_variants(ccx.tcx, parent_id); let vs_there = ty::enum_variants(ccx.tcx, parent_id);
vec::iter2(*vs_here, *vs_there) {|here, there| vec::iter2(*vs_here, *vs_there) {|here, there|
@ -2056,14 +2059,16 @@ fn maybe_instantiate_inline(ccx: @crate_ctxt, fn_id: ast::def_id)
ccx.external.insert(there.id, some(here.id.node)); ccx.external.insert(there.id, some(here.id.node));
} }
} }
ast::item_res(_, _, _, _, ctor_id) { my_id = ctor_id; } ast::item_res(_, _, _, _, ctor_id, _) {
my_id = ctor_id;
}
} }
trans_item(ccx, *item); trans_item(ccx, *item);
local_def(my_id) local_def(my_id)
} }
csearch::found(ast::ii_method(impl_did, mth)) { csearch::found(ast::ii_method(impl_did, mth)) {
ccx.external.insert(fn_id, some(mth.id)); ccx.external.insert(fn_id, some(mth.id));
let {bounds: impl_bnds, ty: impl_ty} = let {bounds: impl_bnds, rp: _, ty: impl_ty} =
ty::lookup_item_type(ccx.tcx, impl_did); ty::lookup_item_type(ccx.tcx, impl_did);
if (*impl_bnds).len() + mth.tps.len() == 0u { if (*impl_bnds).len() + mth.tps.len() == 0u {
let llfn = get_item_val(ccx, mth.id); let llfn = get_item_val(ccx, mth.id);
@ -2264,8 +2269,8 @@ fn trans_rec_field_inner(bcx: block, val: ValueRef, ty: ty::t,
field: ast::ident, sp: span) -> lval_result { field: ast::ident, sp: span) -> lval_result {
let fields = alt ty::get(ty).struct { let fields = alt ty::get(ty).struct {
ty::ty_rec(fs) { fs } ty::ty_rec(fs) { fs }
ty::ty_class(did,ts) { ty::ty_class(did, substs) {
ty::class_items_as_fields(bcx.tcx(), did, ts) } ty::class_items_as_fields(bcx.tcx(), did, substs) }
// Constraint? // Constraint?
_ { bcx.tcx().sess.span_bug(sp, "trans_rec_field:\ _ { bcx.tcx().sess.span_bug(sp, "trans_rec_field:\
base expr has non-record type"); } base expr has non-record type"); }
@ -4379,7 +4384,9 @@ fn trans_class_ctor(ccx: @crate_ctxt, path: path, decl: ast::fn_decl,
// kludgy -- this wouldn't be necessary if the typechecker // kludgy -- this wouldn't be necessary if the typechecker
// special-cased constructors, then we could just look up // special-cased constructors, then we could just look up
// the ctor's return type. // the ctor's return type.
let rslt_ty = ty::mk_class(ccx.tcx, parent_id, psubsts.tys); let rslt_ty = ty::mk_class(ccx.tcx, parent_id,
dummy_substs(psubsts.tys));
// Make the fn context // Make the fn context
let fcx = new_fn_ctxt_w_id(ccx, path, llctor_decl, ctor_id, let fcx = new_fn_ctxt_w_id(ccx, path, llctor_decl, ctor_id,
some(psubsts), some(sp)); some(psubsts), some(sp));
@ -4397,7 +4404,7 @@ fn trans_class_ctor(ccx: @crate_ctxt, path: path, decl: ast::fn_decl,
let selfptr = alloc_ty(bcx_top, rslt_ty); let selfptr = alloc_ty(bcx_top, rslt_ty);
// initialize fields to zero // initialize fields to zero
let fields = ty::class_items_as_fields(bcx_top.tcx(), parent_id, let fields = ty::class_items_as_fields(bcx_top.tcx(), parent_id,
psubsts.tys); dummy_substs(psubsts.tys));
let mut bcx = bcx_top; let mut bcx = bcx_top;
// Initialize fields to zero so init assignments can validly // Initialize fields to zero so init assignments can validly
// drop their LHS // drop their LHS
@ -4450,7 +4457,7 @@ fn trans_item(ccx: @crate_ctxt, item: ast::item) {
ast::item_impl(tps, _, _, ms) { ast::item_impl(tps, _, _, ms) {
impl::trans_impl(ccx, *path, item.ident, ms, tps); impl::trans_impl(ccx, *path, item.ident, ms, tps);
} }
ast::item_res(decl, tps, body, dtor_id, ctor_id) { ast::item_res(decl, tps, body, dtor_id, ctor_id, _) {
if tps.len() == 0u { if tps.len() == 0u {
let llctor_decl = get_item_val(ccx, ctor_id); let llctor_decl = get_item_val(ccx, ctor_id);
trans_res_ctor(ccx, *path, decl, ctor_id, none, llctor_decl); trans_res_ctor(ccx, *path, decl, ctor_id, none, llctor_decl);
@ -4463,7 +4470,7 @@ fn trans_item(ccx: @crate_ctxt, item: ast::item) {
ast::item_mod(m) { ast::item_mod(m) {
trans_mod(ccx, m); trans_mod(ccx, m);
} }
ast::item_enum(variants, tps) { ast::item_enum(variants, tps, _) {
if tps.len() == 0u { if tps.len() == 0u {
let degen = variants.len() == 1u; let degen = variants.len() == 1u;
let vi = ty::enum_variants(ccx.tcx, local_def(item.id)); let vi = ty::enum_variants(ccx.tcx, local_def(item.id));
@ -4487,7 +4494,7 @@ fn trans_item(ccx: @crate_ctxt, item: ast::item) {
}; };
native::trans_native_mod(ccx, native_mod, abi); native::trans_native_mod(ccx, native_mod, abi);
} }
ast::item_class(tps, _ifaces, items, ctor) { ast::item_class(tps, _ifaces, items, ctor, _) {
if tps.len() == 0u { if tps.len() == 0u {
let psubsts = {tys: ty::ty_params_to_tys(ccx.tcx, tps), let psubsts = {tys: ty::ty_params_to_tys(ccx.tcx, tps),
// FIXME: vtables have to get filled in depending // FIXME: vtables have to get filled in depending
@ -4495,7 +4502,7 @@ fn trans_item(ccx: @crate_ctxt, item: ast::item) {
vtables: none, vtables: none,
bounds: @[]}; bounds: @[]};
trans_class_ctor(ccx, *path, ctor.node.dec, ctor.node.body, trans_class_ctor(ccx, *path, ctor.node.dec, ctor.node.body,
get_item_val(ccx, ctor.node.id), psubsts, get_item_val(ccx, ctor.node.id), psubsts,
ctor.node.id, local_def(item.id), ctor.span); ctor.node.id, local_def(item.id), ctor.span);
} }
// If there are ty params, the ctor will get monomorphized // If there are ty params, the ctor will get monomorphized
@ -4684,7 +4691,7 @@ fn get_item_val(ccx: @crate_ctxt, id: ast::node_id) -> ValueRef {
set_inline_hint_if_appr(i.attrs, llfn); set_inline_hint_if_appr(i.attrs, llfn);
llfn llfn
} }
ast::item_res(_, _, _, dtor_id, _) { ast::item_res(_, _, _, dtor_id, _, _) {
// Note that the destructor is associated with the item's id, // Note that the destructor is associated with the item's id,
// not the dtor_id. This is a bit counter-intuitive, but // not the dtor_id. This is a bit counter-intuitive, but
// simplifies ty_res, which would have to carry around two // simplifies ty_res, which would have to carry around two
@ -4726,7 +4733,7 @@ fn get_item_val(ccx: @crate_ctxt, id: ast::node_id) -> ValueRef {
assert v.node.args.len() != 0u; assert v.node.args.len() != 0u;
let pth = *pth + [path_name(enm.ident), path_name(v.node.name)]; let pth = *pth + [path_name(enm.ident), path_name(v.node.name)];
let llfn = alt check enm.node { let llfn = alt check enm.node {
ast::item_enum(_, _) { ast::item_enum(_, _, _) {
register_fn(ccx, v.span, pth, id) register_fn(ccx, v.span, pth, id)
} }
}; };
@ -4747,7 +4754,7 @@ fn get_item_val(ccx: @crate_ctxt, id: ast::node_id) -> ValueRef {
fn trans_constant(ccx: @crate_ctxt, it: @ast::item) { fn trans_constant(ccx: @crate_ctxt, it: @ast::item) {
let _icx = ccx.insn_ctxt("trans_constant"); let _icx = ccx.insn_ctxt("trans_constant");
alt it.node { alt it.node {
ast::item_enum(variants, _) { ast::item_enum(variants, _, _) {
let vi = ty::enum_variants(ccx.tcx, {crate: ast::local_crate, let vi = ty::enum_variants(ccx.tcx, {crate: ast::local_crate,
node: it.id}); node: it.id});
let mut i = 0; let mut i = 0;

View file

@ -882,7 +882,7 @@ fn node_id_type(bcx: block, id: ast::node_id) -> ty::t {
let tcx = bcx.tcx(); let tcx = bcx.tcx();
let t = ty::node_id_to_type(tcx, id); let t = ty::node_id_to_type(tcx, id);
alt bcx.fcx.param_substs { alt bcx.fcx.param_substs {
some(substs) { ty::substitute_type_params(tcx, substs.tys, t) } some(substs) { ty::subst_tps(tcx, substs.tys, t) }
_ { assert !ty::type_has_params(t); t } _ { assert !ty::type_has_params(t); t }
} }
} }
@ -894,7 +894,7 @@ fn node_id_type_params(bcx: block, id: ast::node_id) -> [ty::t] {
let params = ty::node_id_to_type_params(tcx, id); let params = ty::node_id_to_type_params(tcx, id);
alt bcx.fcx.param_substs { alt bcx.fcx.param_substs {
some(substs) { some(substs) {
vec::map(params) {|t| ty::substitute_type_params(tcx, substs.tys, t) } vec::map(params) {|t| ty::subst_tps(tcx, substs.tys, t) }
} }
_ { params } _ { params }
} }
@ -910,6 +910,10 @@ fn field_idx_strict(cx: ty::ctxt, sp: span, ident: ast::ident,
} }
} }
fn dummy_substs(tps: [ty::t]) -> ty::substs {
{self_r: some(ty::re_bound(ty::br_self)), tps: tps}
}
// //
// Local Variables: // Local Variables:
// mode: rust // mode: rust

View file

@ -747,7 +747,7 @@ fn create_function(fcx: fn_ctxt) -> @metadata<subprogram_md> {
let (ident, ret_ty, id) = alt cx.tcx.items.get(fcx.id) { let (ident, ret_ty, id) = alt cx.tcx.items.get(fcx.id) {
ast_map::node_item(item, _) { ast_map::node_item(item, _) {
alt item.node { alt item.node {
ast::item_fn(decl, _, _) | ast::item_res(decl, _, _, _, _) { ast::item_fn(decl, _, _) | ast::item_res(decl, _, _, _, _, _) {
(item.ident, decl.output, item.id) (item.ident, decl.output, item.id)
} }
_ { fcx.ccx.sess.span_bug(item.span, "create_function: item \ _ { fcx.ccx.sess.span_bug(item.span, "create_function: item \

View file

@ -178,7 +178,7 @@ fn resolve_vtable_in_fn_ctxt(fcx: fn_ctxt, vt: typeck::vtable_origin)
let tys = alt fcx.param_substs { let tys = alt fcx.param_substs {
some(substs) { some(substs) {
vec::map(tys, {|t| vec::map(tys, {|t|
ty::substitute_type_params(fcx.ccx.tcx, substs.tys, t) ty::subst_tps(fcx.ccx.tcx, substs.tys, t)
}) })
} }
_ { tys } _ { tys }
@ -244,7 +244,7 @@ fn make_impl_vtable(ccx: @crate_ctxt, impl_id: ast::def_id, substs: [ty::t],
let ifce_id = ty::ty_to_def_id(option::get(ty::impl_iface(tcx, impl_id))); let ifce_id = ty::ty_to_def_id(option::get(ty::impl_iface(tcx, impl_id)));
let has_tps = (*ty::lookup_item_type(ccx.tcx, impl_id).bounds).len() > 0u; let has_tps = (*ty::lookup_item_type(ccx.tcx, impl_id).bounds).len() > 0u;
make_vtable(ccx, vec::map(*ty::iface_methods(tcx, ifce_id), {|im| make_vtable(ccx, vec::map(*ty::iface_methods(tcx, ifce_id), {|im|
let fty = ty::substitute_type_params(tcx, substs, let fty = ty::subst_tps(tcx, substs,
ty::mk_fn(tcx, im.fty)); ty::mk_fn(tcx, im.fty));
if (*im.tps).len() > 0u || ty::type_has_vars(fty) { if (*im.tps).len() > 0u || ty::type_has_vars(fty) {
C_null(T_ptr(T_nil())) C_null(T_ptr(T_nil()))

View file

@ -84,7 +84,7 @@ fn traverse_public_item(cx: ctx, item: @item) {
for vec::each(nm.items) {|item| cx.rmap.insert(item.id, ()); } for vec::each(nm.items) {|item| cx.rmap.insert(item.id, ()); }
} }
} }
item_res(_, tps, blk, _, _) { item_res(_, tps, blk, _, _, _) {
// resources seem to be unconditionally inlined // resources seem to be unconditionally inlined
traverse_inline_body(cx, blk); traverse_inline_body(cx, blk);
} }
@ -102,7 +102,7 @@ fn traverse_public_item(cx: ctx, item: @item) {
} }
} }
} }
item_class(tps, _ifaces, items, ctor) { item_class(tps, _ifaces, items, ctor, _) {
cx.rmap.insert(ctor.node.id, ()); cx.rmap.insert(ctor.node.id, ());
for vec::each(items) {|item| for vec::each(items) {|item|
alt item.node { alt item.node {
@ -117,7 +117,8 @@ fn traverse_public_item(cx: ctx, item: @item) {
} }
} }
} }
item_const(_, _) | item_ty(_, _) | item_enum(_, _) | item_iface(_, _) {} item_const(_, _) | item_ty(_, _, _) |
item_enum(_, _, _) | item_iface(_, _) {}
} }
} }
@ -152,7 +153,9 @@ fn traverse_all_resources(cx: ctx, crate_mod: _mod) {
visit_item: {|i, cx, v| visit_item: {|i, cx, v|
visit::visit_item(i, cx, v); visit::visit_item(i, cx, v);
alt i.node { alt i.node {
item_res(_, _, _, _, _) { traverse_public_item(cx, i); } item_res(_, _, _, _, _, _) {
traverse_public_item(cx, i);
}
_ {} _ {}
} }
} }

View file

@ -315,7 +315,9 @@ fn shape_of(ccx: @crate_ctxt, t: ty::t, ty_param_map: [uint]) -> [u8] {
add_substr(s, shape_of(ccx, unit_ty, ty_param_map)); add_substr(s, shape_of(ccx, unit_ty, ty_param_map));
s s
} }
ty::ty_enum(did, tps) { ty::ty_enum(did, substs) {
let tps = substs.tps;
alt enum_kind(ccx, did) { alt enum_kind(ccx, did) {
// FIXME: For now we do this. // FIXME: For now we do this.
tk_unit { [s_variant_enum_t(ccx.tcx)] } tk_unit { [s_variant_enum_t(ccx.tcx)] }
@ -437,8 +439,9 @@ fn shape_of(ccx: @crate_ctxt, t: ty::t, ty_param_map: [uint]) -> [u8] {
add_substr(s, shape_of(ccx, tm.ty, ty_param_map)); add_substr(s, shape_of(ccx, tm.ty, ty_param_map));
s s
} }
ty::ty_res(did, raw_subt, tps) { ty::ty_res(did, raw_subt, substs) {
let subt = ty::substitute_type_params(ccx.tcx, tps, raw_subt); let subt = ty::subst(ccx.tcx, substs, raw_subt);
let tps = substs.tps;
let ri = {did: did, tps: tps}; let ri = {did: did, tps: tps};
let id = interner::intern(ccx.shape_cx.resources, ri); let id = interner::intern(ccx.shape_cx.resources, ri);
@ -651,7 +654,7 @@ fn llalign_of(cx: @crate_ctxt, t: TypeRef) -> ValueRef {
fn static_size_of_enum(cx: @crate_ctxt, t: ty::t) -> uint { fn static_size_of_enum(cx: @crate_ctxt, t: ty::t) -> uint {
if cx.enum_sizes.contains_key(t) { ret cx.enum_sizes.get(t); } if cx.enum_sizes.contains_key(t) { ret cx.enum_sizes.get(t); }
alt ty::get(t).struct { alt ty::get(t).struct {
ty::ty_enum(tid, subtys) { ty::ty_enum(tid, substs) {
// Compute max(variant sizes). // Compute max(variant sizes).
let mut max_size = 0u; let mut max_size = 0u;
let variants = ty::enum_variants(cx.tcx, tid); let variants = ty::enum_variants(cx.tcx, tid);
@ -659,7 +662,7 @@ fn static_size_of_enum(cx: @crate_ctxt, t: ty::t) -> uint {
let tup_ty = simplify_type(cx.tcx, let tup_ty = simplify_type(cx.tcx,
ty::mk_tup(cx.tcx, variant.args)); ty::mk_tup(cx.tcx, variant.args));
// Perform any type parameter substitutions. // Perform any type parameter substitutions.
let tup_ty = ty::substitute_type_params(cx.tcx, subtys, tup_ty); let tup_ty = ty::subst(cx.tcx, substs, tup_ty);
// Here we possibly do a recursive call. // Here we possibly do a recursive call.
let this_size = let this_size =
llsize_of_real(cx, type_of::type_of(cx, tup_ty)); llsize_of_real(cx, type_of::type_of(cx, tup_ty));
@ -690,8 +693,8 @@ 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_estr(ty::vstore_uniq) | ty::ty_estr(ty::vstore_box) |
ty::ty_ptr(_) | ty::ty_rptr(_,_) { nilptr(tcx) } ty::ty_ptr(_) | ty::ty_rptr(_,_) { nilptr(tcx) }
ty::ty_fn(_) { ty::mk_tup(tcx, [nilptr(tcx), nilptr(tcx)]) } ty::ty_fn(_) { ty::mk_tup(tcx, [nilptr(tcx), nilptr(tcx)]) }
ty::ty_res(_, sub, tps) { ty::ty_res(_, sub, substs) {
let sub1 = ty::substitute_type_params(tcx, tps, sub); let sub1 = ty::subst(tcx, substs, sub);
ty::mk_tup(tcx, [ty::mk_int(tcx), simplify_type(tcx, sub1)]) ty::mk_tup(tcx, [ty::mk_int(tcx), simplify_type(tcx, sub1)])
} }
ty::ty_evec(_, ty::vstore_slice(_)) | ty::ty_evec(_, ty::vstore_slice(_)) |

View file

@ -89,8 +89,8 @@ 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_fn(_) { T_fn_pair(cx, type_of_fn_from_ty(cx, t)) }
ty::ty_iface(_, _) { T_opaque_iface(cx) } ty::ty_iface(_, _) { T_opaque_iface(cx) }
ty::ty_res(_, sub, tps) { ty::ty_res(_, sub, substs) {
let sub1 = ty::substitute_type_params(cx.tcx, tps, sub); let sub1 = ty::subst(cx.tcx, substs, sub);
ret T_struct([T_i8(), type_of(cx, sub1)]); ret T_struct([T_i8(), type_of(cx, sub1)]);
} }
ty::ty_param(_, _) { T_typaram(cx.tn) } ty::ty_param(_, _) { T_typaram(cx.tn) }

View file

@ -65,7 +65,7 @@ fn type_uses_for(ccx: @crate_ctxt, fn_id: def_id, n_tps: uint)
}; };
alt check map_node { alt check map_node {
ast_map::node_item(@{node: item_fn(_, _, body), _}, _) | ast_map::node_item(@{node: item_fn(_, _, body), _}, _) |
ast_map::node_item(@{node: item_res(_, _, body, _, _), _}, _) | ast_map::node_item(@{node: item_res(_, _, body, _, _, _), _}, _) |
ast_map::node_method(@{body, _}, _, _) { ast_map::node_method(@{body, _}, _, _) {
handle_body(cx, body); handle_body(cx, body);
} }
@ -107,13 +107,12 @@ fn type_needs_inner(cx: ctx, use: uint, ty: ty::t,
alt ty::get(ty).struct { alt ty::get(ty).struct {
ty::ty_fn(_) | ty::ty_ptr(_) | ty::ty_rptr(_, _) | ty::ty_fn(_) | ty::ty_ptr(_) | ty::ty_rptr(_, _) |
ty::ty_box(_) | ty::ty_iface(_, _) { false } ty::ty_box(_) | ty::ty_iface(_, _) { false }
ty::ty_enum(did, tps) { ty::ty_enum(did, substs) {
if option::is_none(list::find(enums_seen, {|id| id == did})) { if option::is_none(list::find(enums_seen, {|id| id == did})) {
let seen = list::cons(did, @enums_seen); let seen = list::cons(did, @enums_seen);
for vec::each(*ty::enum_variants(cx.ccx.tcx, did)) {|v| for vec::each(*ty::enum_variants(cx.ccx.tcx, did)) {|v|
for vec::each(v.args) {|aty| for vec::each(v.args) {|aty|
let t = ty::substitute_type_params(cx.ccx.tcx, let t = ty::subst(cx.ccx.tcx, substs, aty);
tps, aty);
type_needs_inner(cx, use, t, seen); type_needs_inner(cx, use, t, seen);
} }
} }
@ -153,7 +152,7 @@ fn mark_for_expr(cx: ctx, e: @expr) {
} }
} }
expr_path(_) { expr_path(_) {
option::iter(cx.ccx.tcx.node_type_substs.find(e.id)) {|ts| cx.ccx.tcx.node_type_substs.find(e.id).iter {|ts|
let id = ast_util::def_id_of_def(cx.ccx.tcx.def_map.get(e.id)); let id = ast_util::def_id_of_def(cx.ccx.tcx.def_map.get(e.id));
vec::iter2(type_uses_for(cx.ccx, id, ts.len()), ts) {|uses, subst| vec::iter2(type_uses_for(cx.ccx, id, ts.len()), ts) {|uses, subst|
type_needs(cx, uses, subst) type_needs(cx, uses, subst)

View file

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

View file

@ -61,7 +61,7 @@ export sequence_element_type;
export sort_methods; export sort_methods;
export stmt_node_id; export stmt_node_id;
export sty; export sty;
export substitute_type_params; export subst, subst_tps, substs_is_noop, substs;
export t; export t;
export new_ty_hash; export new_ty_hash;
export enum_variants, substd_enum_variants; export enum_variants, substd_enum_variants;
@ -281,6 +281,23 @@ enum bound_region {
br_named(str) // A named region parameter. br_named(str) // A named region parameter.
} }
type opt_region = option<region>;
// The type substs represents the kinds of things that can be substituted into
// a type. There may be at most one region parameter (self_r), along with
// some number of type parameters (tps).
//
// The region parameter is present on nominative types (enums, resources,
// classes) that are declared as having a region parameter. If the type is
// declared as `enum foo&`, then self_r should always be non-none. If the
// type is declared as `enum foo`, then self_r will always be none. In the
// latter case, typeck::ast_ty_to_ty() will reject any references to `&T` or
// `&self.T` within the type and report an error.
type substs = {
self_r: opt_region,
tps: [t]
};
// NB: If you change this, you'll probably want to change the corresponding // NB: If you change this, you'll probably want to change the corresponding
// AST structure in front/ast::rs as well. // AST structure in front/ast::rs as well.
enum sty { enum sty {
@ -292,7 +309,7 @@ enum sty {
ty_float(ast::float_ty), ty_float(ast::float_ty),
ty_str, ty_str,
ty_estr(vstore), ty_estr(vstore),
ty_enum(def_id, [t]), ty_enum(def_id, substs),
ty_box(mt), ty_box(mt),
ty_uniq(mt), ty_uniq(mt),
ty_vec(mt), ty_vec(mt),
@ -302,8 +319,8 @@ enum sty {
ty_rec([field]), ty_rec([field]),
ty_fn(fn_ty), ty_fn(fn_ty),
ty_iface(def_id, [t]), ty_iface(def_id, [t]),
ty_class(def_id, [t]), ty_class(def_id, substs),
ty_res(def_id, t, [t]), ty_res(def_id, t, substs),
ty_tup([t]), ty_tup([t]),
ty_var(ty_vid), // type variable during typechecking ty_var(ty_vid), // type variable during typechecking
@ -389,7 +406,9 @@ fn param_bounds_to_kind(bounds: param_bounds) -> kind {
kind kind
} }
type ty_param_bounds_and_ty = {bounds: @[param_bounds], ty: t}; type ty_param_bounds_and_ty = {bounds: @[param_bounds],
rp: ast::region_param,
ty: t};
type type_cache = hashmap<ast::def_id, ty_param_bounds_and_ty>; type type_cache = hashmap<ast::def_id, ty_param_bounds_and_ty>;
@ -475,7 +494,13 @@ fn mk_t_with_id(cx: ctxt, st: sty, o_def_id: option<ast::def_id>) -> t {
ty_opaque_box {} ty_opaque_box {}
ty_param(_, _) { has_params = true; } ty_param(_, _) { has_params = true; }
ty_var(_) | ty_self(_) { has_vars = true; } ty_var(_) | ty_self(_) { has_vars = true; }
ty_enum(_, tys) | ty_iface(_, tys) | ty_class(_, tys) { ty_enum(_, substs) | ty_class(_, substs) {
for substs.tps.each {|tt|
derive_flags(has_params, has_vars, has_regions, tt);
}
substs.self_r.iter { |_i| has_regions = true; }
}
ty_iface(_, tys) {
for tys.each {|tt| for tys.each {|tt|
derive_flags(has_params, has_vars, has_regions, tt); derive_flags(has_params, has_vars, has_regions, tt);
} }
@ -506,9 +531,9 @@ fn mk_t_with_id(cx: ctxt, st: sty, o_def_id: option<ast::def_id>) -> t {
} }
derive_flags(has_params, has_vars, has_regions, f.output); derive_flags(has_params, has_vars, has_regions, f.output);
} }
ty_res(_, tt, tps) { ty_res(_, tt, substs) {
derive_flags(has_params, has_vars, has_regions, tt); derive_flags(has_params, has_vars, has_regions, tt);
for tps.each {|tt| for substs.tps.each {|tt|
derive_flags(has_params, has_vars, has_regions, tt); derive_flags(has_params, has_vars, has_regions, tt);
} }
} }
@ -553,8 +578,8 @@ fn mk_estr(cx: ctxt, t: vstore) -> t {
mk_t(cx, ty_estr(t)) mk_t(cx, ty_estr(t))
} }
fn mk_enum(cx: ctxt, did: ast::def_id, tys: [t]) -> t { fn mk_enum(cx: ctxt, did: ast::def_id, substs: substs) -> t {
mk_t(cx, ty_enum(did, tys)) mk_t(cx, ty_enum(did, substs))
} }
fn mk_box(cx: ctxt, tm: mt) -> t { mk_t(cx, ty_box(tm)) } fn mk_box(cx: ctxt, tm: mt) -> t { mk_t(cx, ty_box(tm)) }
@ -602,12 +627,13 @@ fn mk_iface(cx: ctxt, did: ast::def_id, tys: [t]) -> t {
mk_t(cx, ty_iface(did, tys)) mk_t(cx, ty_iface(did, tys))
} }
fn mk_class(cx: ctxt, class_id: ast::def_id, tys: [t]) -> t { fn mk_class(cx: ctxt, class_id: ast::def_id, substs: substs) -> t {
mk_t(cx, ty_class(class_id, tys)) mk_t(cx, ty_class(class_id, substs))
} }
fn mk_res(cx: ctxt, did: ast::def_id, inner: t, tps: [t]) -> t { fn mk_res(cx: ctxt, did: ast::def_id,
mk_t(cx, ty_res(did, inner, tps)) inner: t, substs: substs) -> t {
mk_t(cx, ty_res(did, inner, substs))
} }
fn mk_var(cx: ctxt, v: ty_vid) -> t { mk_t(cx, ty_var(v)) } fn mk_var(cx: ctxt, v: ty_vid) -> t { mk_t(cx, ty_var(v)) }
@ -657,8 +683,10 @@ fn maybe_walk_ty(ty: t, f: fn(t) -> bool) {
ty_ptr(tm) | ty_rptr(_, tm) { ty_ptr(tm) | ty_rptr(_, tm) {
maybe_walk_ty(tm.ty, f); maybe_walk_ty(tm.ty, f);
} }
ty_enum(_, subtys) | ty_iface(_, subtys) | ty_class(_, subtys) ty_enum(_, substs) | ty_class(_, substs) {
| ty_self(subtys) { for substs.tps.each {|subty| maybe_walk_ty(subty, f); }
}
ty_iface(_, subtys) |ty_self(subtys) {
for subtys.each {|subty| maybe_walk_ty(subty, f); } for subtys.each {|subty| maybe_walk_ty(subty, f); }
} }
ty_rec(fields) { ty_rec(fields) {
@ -669,9 +697,9 @@ fn maybe_walk_ty(ty: t, f: fn(t) -> bool) {
for ft.inputs.each {|a| maybe_walk_ty(a.ty, f); } for ft.inputs.each {|a| maybe_walk_ty(a.ty, f); }
maybe_walk_ty(ft.output, f); maybe_walk_ty(ft.output, f);
} }
ty_res(_, sub, tps) { ty_res(_, sub, substs) {
maybe_walk_ty(sub, f); maybe_walk_ty(sub, f);
for tps.each {|tp| maybe_walk_ty(tp, f); } for substs.tps.each {|tp| maybe_walk_ty(tp, f); }
} }
ty_constr(sub, _) { maybe_walk_ty(sub, f); } ty_constr(sub, _) { maybe_walk_ty(sub, f); }
ty_uniq(tm) { maybe_walk_ty(tm.ty, f); } ty_uniq(tm) { maybe_walk_ty(tm.ty, f); }
@ -683,6 +711,11 @@ fn fold_sty_to_ty(tcx: ty::ctxt, sty: sty, foldop: fn(t) -> t) -> t {
} }
fn fold_sty(sty: sty, fldop: fn(t) -> t) -> sty { fn fold_sty(sty: sty, fldop: fn(t) -> t) -> sty {
fn fold_substs(substs: substs, fldop: fn(t) -> t) -> substs {
{self_r: substs.self_r,
tps: substs.tps.map { |t| fldop(t) }}
}
alt sty { alt sty {
ty_box(tm) { ty_box(tm) {
ty_box({ty: fldop(tm.ty), mutbl: tm.mutbl}) ty_box({ty: fldop(tm.ty), mutbl: tm.mutbl})
@ -699,8 +732,8 @@ fn fold_sty(sty: sty, fldop: fn(t) -> t) -> sty {
ty_evec(tm, vst) { ty_evec(tm, vst) {
ty_evec({ty: fldop(tm.ty), mutbl: tm.mutbl}, vst) ty_evec({ty: fldop(tm.ty), mutbl: tm.mutbl}, vst)
} }
ty_enum(tid, subtys) { ty_enum(tid, substs) {
ty_enum(tid, vec::map(subtys) {|t| fldop(t) }) ty_enum(tid, fold_substs(substs, fldop))
} }
ty_iface(did, subtys) { ty_iface(did, subtys) {
ty_iface(did, vec::map(subtys) {|t| fldop(t) }) ty_iface(did, vec::map(subtys) {|t| fldop(t) })
@ -728,9 +761,9 @@ fn fold_sty(sty: sty, fldop: fn(t) -> t) -> sty {
let new_output = fldop(f.output); let new_output = fldop(f.output);
ty_fn({inputs: new_args, output: new_output with f}) ty_fn({inputs: new_args, output: new_output with f})
} }
ty_res(did, subty, tps) { ty_res(did, subty, substs) {
let new_tps = vec::map(tps) {|ty| fldop(ty) }; ty_res(did, fldop(subty),
ty_res(did, fldop(subty), new_tps) fold_substs(substs, fldop))
} }
ty_rptr(r, tm) { ty_rptr(r, tm) {
ty_rptr(r, {ty: fldop(tm.ty), mutbl: tm.mutbl}) ty_rptr(r, {ty: fldop(tm.ty), mutbl: tm.mutbl})
@ -738,9 +771,8 @@ fn fold_sty(sty: sty, fldop: fn(t) -> t) -> sty {
ty_constr(subty, cs) { ty_constr(subty, cs) {
ty_constr(fldop(subty), cs) ty_constr(fldop(subty), cs)
} }
ty_class(did, tps) { ty_class(did, substs) {
let new_tps = vec::map(tps) {|ty| fldop(ty) }; ty_class(did, fold_substs(substs, fldop))
ty_class(did, new_tps)
} }
ty_nil | ty_bot | ty_bool | ty_int(_) | ty_uint(_) | ty_float(_) | ty_nil | ty_bot | ty_bool | ty_int(_) | ty_uint(_) | ty_float(_) |
ty_str | ty_estr(_) | ty_type | ty_opaque_closure_ptr(_) | ty_str | ty_estr(_) | ty_type | ty_opaque_closure_ptr(_) |
@ -765,6 +797,61 @@ fn fold_ty_var(cx: ctxt, t0: t, fldop: fn(ty_vid) -> t) -> t {
} }
} }
fn fold_regions_and_ty(
cx: ctxt,
ty: t,
fldr: fn(r: region) -> region,
fldfnt: fn(t: t) -> t,
fldt: fn(t: t) -> t) -> t {
fn fold_substs(
substs: substs,
fldr: fn(r: region) -> region,
fldt: fn(t: t) -> t) -> substs {
{self_r: substs.self_r.map { |r| fldr(r) },
tps: substs.tps.map { |t| fldt(t) }}
}
let tb = ty::get(ty);
alt tb.struct {
ty::ty_rptr(r, mt) {
let m_r = fldr(r);
let m_t = fldt(mt.ty);
ty::mk_rptr(cx, m_r, {ty: m_t, mutbl: mt.mutbl})
}
ty_estr(vstore_slice(r)) {
let m_r = fldr(r);
ty::mk_estr(cx, vstore_slice(m_r))
}
ty_evec(mt, vstore_slice(r)) {
let m_r = fldr(r);
let m_t = fldt(mt.ty);
ty::mk_evec(cx, {ty: m_t, mutbl: mt.mutbl}, vstore_slice(m_r))
}
ty_enum(def_id, substs) {
ty::mk_enum(cx, def_id, fold_substs(substs, fldr, fldt))
}
ty_class(def_id, substs) {
ty::mk_class(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)
}
}
sty {
fold_sty_to_ty(cx, sty) {|t|
fldt(t)
}
}
}
}
// n.b. this function is intended to eventually replace fold_region() below, // n.b. this function is intended to eventually replace fold_region() below,
// that is why its name is so similar. // that is why its name is so similar.
fn fold_regions( fn fold_regions(
@ -774,36 +861,13 @@ fn fold_regions(
fn do_fold(cx: ctxt, ty: t, in_fn: bool, fn do_fold(cx: ctxt, ty: t, in_fn: bool,
fldr: fn(region, bool) -> region) -> t { fldr: fn(region, bool) -> region) -> t {
let tb = ty::get(ty); if !type_has_regions(ty) { ret ty; }
if !tb.has_regions { ret ty; } fold_regions_and_ty(
alt tb.struct { cx, ty,
ty::ty_rptr(r, mt) { { |r| fldr(r, in_fn) },
let m_r = fldr(r, in_fn); { |t| do_fold(cx, t, true, fldr) },
let m_t = do_fold(cx, mt.ty, in_fn, fldr); { |t| do_fold(cx, t, in_fn, fldr) })
ty::mk_rptr(cx, m_r, {ty: m_t, mutbl: mt.mutbl})
}
ty_estr(vstore_slice(r)) {
let m_r = fldr(r, in_fn);
ty::mk_estr(cx, vstore_slice(m_r))
}
ty_evec(mt, vstore_slice(r)) {
let m_r = fldr(r, in_fn);
let m_t = do_fold(cx, mt.ty, in_fn, fldr);
ty::mk_evec(cx, {ty: m_t, mutbl: mt.mutbl}, vstore_slice(m_r))
}
sty @ ty_fn(_) {
fold_sty_to_ty(cx, sty) {|t|
do_fold(cx, t, true, fldr)
}
}
sty {
fold_sty_to_ty(cx, sty) {|t|
do_fold(cx, t, in_fn, fldr)
}
}
}
} }
do_fold(cx, ty, false, fldr) do_fold(cx, ty, false, fldr)
} }
@ -842,13 +906,63 @@ fn fold_region(cx: ctxt, t0: t, fldop: fn(region, bool) -> region) -> t {
do_fold(cx, t0, false, fldop) do_fold(cx, t0, false, fldop)
} }
fn substitute_type_params(cx: ctxt, substs: [ty::t], typ: t) -> t { // Substitute *only* type parameters. Used in trans where regions are erased.
if substs.len() == 0u { ret typ; } fn subst_tps(cx: ctxt, tps: [t], typ: t) -> t {
let tb = get(typ); if tps.len() == 0u { ret typ; }
let tb = ty::get(typ);
if !tb.has_params { ret typ; } if !tb.has_params { ret typ; }
alt tb.struct { alt tb.struct {
ty_param(idx, _) { substs[idx] } ty_param(idx, _) { tps[idx] }
s { mk_t(cx, fold_sty(s) {|t| substitute_type_params(cx, substs, t)}) } sty { fold_sty_to_ty(cx, sty) {|t| subst_tps(cx, tps, t) } }
}
}
fn substs_is_noop(substs: substs) -> bool {
substs.tps.len() == 0u && substs.self_r.is_none()
}
fn substs_to_str(cx: ctxt, substs: substs) -> str {
#fmt["substs(self_r=%s, tps=%?)",
substs.self_r.map_default("none", { |r| region_to_str(cx, r) }),
substs.tps.map { |t| ty_to_str(cx, t) }]
}
fn subst(cx: ctxt,
substs: substs,
typ: t) -> t {
if substs_is_noop(substs) { ret typ; }
#debug["subst(substs=%s, typ=%s)",
substs_to_str(cx, substs),
ty_to_str(cx, typ)];
let r = do_subst(cx, substs, typ);
#debug[" r = %s", ty_to_str(cx, r)];
ret r;
fn do_subst(cx: ctxt,
substs: substs,
typ: t) -> t {
let tb = get(typ);
if !tb.has_params && !tb.has_regions { ret typ; }
alt tb.struct {
ty_param(idx, _) { substs.tps[idx] }
_ {
fold_regions_and_ty(
cx, typ,
{ |r|
alt r {
re_bound(br_self) {
option::get(substs.self_r)
}
_ {
r
}
}
},
{ |t| do_subst(cx, substs, t) },
{ |t| do_subst(cx, substs, t) })
}
}
} }
} }
@ -862,7 +976,7 @@ fn type_is_bool(ty: t) -> bool { get(ty).struct == ty_bool }
fn type_is_structural(ty: t) -> bool { fn type_is_structural(ty: t) -> bool {
alt get(ty).struct { alt get(ty).struct {
ty_rec(_) | ty_class(_,_) | ty_tup(_) | ty_enum(_, _) | ty_fn(_) | ty_rec(_) | ty_class(_, _) | ty_tup(_) | ty_enum(_, _) | ty_fn(_) |
ty_iface(_, _) | ty_res(_, _, _) | ty_evec(_, vstore_fixed(_)) ty_iface(_, _) | ty_res(_, _, _) | ty_evec(_, vstore_fixed(_))
| ty_estr(vstore_fixed(_)) { true } | ty_estr(vstore_fixed(_)) { true }
_ { false } _ { false }
@ -994,8 +1108,8 @@ fn type_needs_drop(cx: ctxt, ty: t) -> bool {
for flds.each {|f| if type_needs_drop(cx, f.mt.ty) { accum = true; } } for flds.each {|f| if type_needs_drop(cx, f.mt.ty) { accum = true; } }
accum accum
} }
ty_class(did, ts) { ty_class(did, substs) {
for vec::each(ty::class_items_as_fields(cx, did, ts)) {|f| for vec::each(ty::class_items_as_fields(cx, did, substs)) {|f|
if type_needs_drop(cx, f.mt.ty) { accum = true; } if type_needs_drop(cx, f.mt.ty) { accum = true; }
} }
accum accum
@ -1005,12 +1119,12 @@ fn type_needs_drop(cx: ctxt, ty: t) -> bool {
for elts.each {|m| if type_needs_drop(cx, m) { accum = true; } } for elts.each {|m| if type_needs_drop(cx, m) { accum = true; } }
accum accum
} }
ty_enum(did, tps) { ty_enum(did, substs) {
let variants = enum_variants(cx, did); let variants = enum_variants(cx, did);
for vec::each(*variants) {|variant| for vec::each(*variants) {|variant|
for variant.args.each {|aty| for variant.args.each {|aty|
// Perform any type parameter substitutions. // Perform any type parameter substitutions.
let arg_ty = substitute_type_params(cx, tps, aty); let arg_ty = subst(cx, substs, aty);
if type_needs_drop(cx, arg_ty) { accum = true; } if type_needs_drop(cx, arg_ty) { accum = true; }
} }
if accum { break; } if accum { break; }
@ -1064,10 +1178,10 @@ fn type_needs_unwind_cleanup_(cx: ctxt, ty: t,
ty_rec(_) | ty_tup(_) | ty_ptr(_) { ty_rec(_) | ty_tup(_) | ty_ptr(_) {
true true
} }
ty_enum(did, tps) { ty_enum(did, substs) {
for vec::each(*enum_variants(cx, did)) {|v| for vec::each(*enum_variants(cx, did)) {|v|
for v.args.each {|aty| for v.args.each {|aty|
let t = substitute_type_params(cx, tps, aty); let t = subst(cx, substs, aty);
needs_unwind_cleanup |= needs_unwind_cleanup |=
type_needs_unwind_cleanup_(cx, t, tycache, type_needs_unwind_cleanup_(cx, t, tycache,
encountered_box); encountered_box);
@ -1211,7 +1325,7 @@ fn type_kind(cx: ctxt, ty: t) -> kind {
lowest lowest
} }
// Enums lower to the lowest of their variants. // Enums lower to the lowest of their variants.
ty_enum(did, tps) { ty_enum(did, substs) {
let mut lowest = kind_sendable; let mut lowest = kind_sendable;
let variants = enum_variants(cx, did); let variants = enum_variants(cx, did);
if vec::len(*variants) == 0u { if vec::len(*variants) == 0u {
@ -1220,7 +1334,7 @@ fn type_kind(cx: ctxt, ty: t) -> kind {
for vec::each(*variants) {|variant| for vec::each(*variants) {|variant|
for variant.args.each {|aty| for variant.args.each {|aty|
// Perform any type parameter substitutions. // Perform any type parameter substitutions.
let arg_ty = substitute_type_params(cx, tps, aty); let arg_ty = subst(cx, substs, aty);
lowest = lower_kind(lowest, type_kind(cx, arg_ty)); lowest = lower_kind(lowest, type_kind(cx, arg_ty));
if lowest == kind_noncopyable { break; } if lowest == kind_noncopyable { break; }
} }
@ -1316,11 +1430,11 @@ fn is_instantiable(cx: ctxt, r_ty: t) -> bool {
false false
} }
ty_class(did, tps) { ty_class(did, substs) {
vec::push(*seen, did); vec::push(*seen, did);
let r = vec::any(lookup_class_fields(cx, did)) {|f| let r = vec::any(lookup_class_fields(cx, did)) {|f|
let fty = ty::lookup_item_type(cx, f.id); let fty = ty::lookup_item_type(cx, f.id);
let sty = substitute_type_params(cx, tps, fty.ty); let sty = subst(cx, substs, fty.ty);
type_requires(cx, seen, r_ty, sty) type_requires(cx, seen, r_ty, sty)
}; };
vec::pop(*seen); vec::pop(*seen);
@ -1331,9 +1445,9 @@ fn is_instantiable(cx: ctxt, r_ty: t) -> bool {
false false
} }
ty_res(did, sub, tps) { ty_res(did, sub, substs) {
vec::push(*seen, did); vec::push(*seen, did);
let sty = substitute_type_params(cx, tps, sub); let sty = subst(cx, substs, sub);
let r = type_requires(cx, seen, r_ty, sty); let r = type_requires(cx, seen, r_ty, sty);
vec::pop(*seen); vec::pop(*seen);
r r
@ -1349,12 +1463,12 @@ fn is_instantiable(cx: ctxt, r_ty: t) -> bool {
false false
} }
ty_enum(did, tps) { ty_enum(did, substs) {
vec::push(*seen, did); vec::push(*seen, did);
let vs = enum_variants(cx, did); let vs = enum_variants(cx, did);
let r = vec::len(*vs) > 0u && vec::all(*vs) {|variant| let r = vec::len(*vs) > 0u && vec::all(*vs) {|variant|
vec::any(variant.args) {|aty| vec::any(variant.args) {|aty|
let sty = substitute_type_params(cx, tps, aty); let sty = subst(cx, substs, aty);
type_requires(cx, seen, r_ty, sty) type_requires(cx, seen, r_ty, sty)
} }
}; };
@ -1380,10 +1494,10 @@ fn type_structurally_contains(cx: ctxt, ty: t, test: fn(sty) -> bool) ->
let sty = get(ty).struct; let sty = get(ty).struct;
if test(sty) { ret true; } if test(sty) { ret true; }
alt sty { alt sty {
ty_enum(did, tps) { ty_enum(did, substs) {
for vec::each(*enum_variants(cx, did)) {|variant| for vec::each(*enum_variants(cx, did)) {|variant|
for variant.args.each {|aty| for variant.args.each {|aty|
let sty = substitute_type_params(cx, tps, aty); let sty = subst(cx, substs, aty);
if type_structurally_contains(cx, sty, test) { ret true; } if type_structurally_contains(cx, sty, test) { ret true; }
} }
} }
@ -1401,8 +1515,8 @@ fn type_structurally_contains(cx: ctxt, ty: t, test: fn(sty) -> bool) ->
} }
ret false; ret false;
} }
ty_res(_, sub, tps) { ty_res(_, sub, substs) {
let sty = substitute_type_params(cx, tps, sub); let sty = subst(cx, substs, sub);
ret type_structurally_contains(cx, sty, test); ret type_structurally_contains(cx, sty, test);
} }
ty_evec(mt, vstore_fixed(_)) { ty_evec(mt, vstore_fixed(_)) {
@ -1485,13 +1599,13 @@ fn type_is_pod(cx: ctxt, ty: t) -> bool {
ty_str | ty_box(_) | ty_uniq(_) | ty_vec(_) | ty_fn(_) | ty_str | ty_box(_) | ty_uniq(_) | ty_vec(_) | ty_fn(_) |
ty_iface(_, _) | ty_rptr(_,_) | ty_opaque_box { result = false; } ty_iface(_, _) | ty_rptr(_,_) | ty_opaque_box { result = false; }
// Structural types // Structural types
ty_enum(did, tps) { ty_enum(did, substs) {
let variants = enum_variants(cx, did); let variants = enum_variants(cx, did);
for vec::each(*variants) {|variant| for vec::each(*variants) {|variant|
let tup_ty = mk_tup(cx, variant.args); let tup_ty = mk_tup(cx, variant.args);
// Perform any type parameter substitutions. // Perform any type parameter substitutions.
let tup_ty = substitute_type_params(cx, tps, tup_ty); let tup_ty = subst(cx, substs, tup_ty);
if !type_is_pod(cx, tup_ty) { result = false; } if !type_is_pod(cx, tup_ty) { result = false; }
} }
} }
@ -1507,8 +1621,8 @@ fn type_is_pod(cx: ctxt, ty: t) -> bool {
ty_evec(mt, vstore_fixed(_)) { ty_evec(mt, vstore_fixed(_)) {
result = type_is_pod(cx, mt.ty); result = type_is_pod(cx, mt.ty);
} }
ty_res(_, inner, tps) { ty_res(_, inner, substs) {
result = type_is_pod(cx, substitute_type_params(cx, tps, inner)); result = type_is_pod(cx, subst(cx, substs, inner));
} }
ty_constr(subt, _) { result = type_is_pod(cx, subt); } ty_constr(subt, _) { result = type_is_pod(cx, subt); }
ty_param(_, _) { result = false; } ty_param(_, _) { result = false; }
@ -1530,7 +1644,7 @@ fn type_is_enum(ty: t) -> bool {
// constructors // constructors
fn type_is_c_like_enum(cx: ctxt, ty: t) -> bool { fn type_is_c_like_enum(cx: ctxt, ty: t) -> bool {
alt get(ty).struct { alt get(ty).struct {
ty_enum(did, tps) { ty_enum(did, substs) {
let variants = enum_variants(cx, did); let variants = enum_variants(cx, did);
let some_n_ary = vec::any(*variants, {|v| vec::len(v.args) > 0u}); let some_n_ary = vec::any(*variants, {|v| vec::len(v.args) > 0u});
ret !some_n_ary; ret !some_n_ary;
@ -1562,15 +1676,15 @@ fn type_autoderef(cx: ctxt, t: t) -> t {
loop { loop {
alt get(t1).struct { alt get(t1).struct {
ty_box(mt) | ty_uniq(mt) | ty::ty_rptr(_, mt) { t1 = mt.ty; } ty_box(mt) | ty_uniq(mt) | ty::ty_rptr(_, mt) { t1 = mt.ty; }
ty_res(_, inner, tps) { ty_res(_, inner, substs) {
t1 = substitute_type_params(cx, tps, inner); t1 = subst(cx, substs, inner);
} }
ty_enum(did, tps) { ty_enum(did, substs) {
let variants = enum_variants(cx, did); let variants = enum_variants(cx, did);
if vec::len(*variants) != 1u || vec::len(variants[0].args) != 1u { if vec::len(*variants) != 1u || vec::len(variants[0].args) != 1u {
break; break;
} }
t1 = substitute_type_params(cx, tps, variants[0].args[0]); t1 = subst(cx, substs, variants[0].args[0]);
} }
_ { break; } _ { break; }
} }
@ -1627,6 +1741,10 @@ fn hash_type_structure(st: sty) -> uint {
re_bot { 4u } re_bot { 4u }
} }
} }
fn hash_substs(h: uint, substs: substs) -> uint {
let h = hash_subtys(h, substs.tps);
h + substs.self_r.map_default(0u, hash_region)
}
alt st { alt st {
ty_nil { 0u } ty_bool { 1u } ty_nil { 0u } ty_bool { 1u }
ty_int(t) { ty_int(t) {
@ -1646,10 +1764,9 @@ fn hash_type_structure(st: sty) -> uint {
} }
ty_estr(_) { 16u } ty_estr(_) { 16u }
ty_str { 17u } ty_str { 17u }
ty_enum(did, tys) { ty_enum(did, substs) {
let mut h = hash_def(18u, did); let mut h = hash_def(18u, did);
for tys.each {|typ| h = hash_subty(h, typ); } hash_substs(h, substs)
h
} }
ty_box(mt) { hash_subty(19u, mt.ty) } ty_box(mt) { hash_subty(19u, mt.ty) }
ty_evec(mt, _) { hash_subty(20u, mt.ty) } ty_evec(mt, _) { hash_subty(20u, mt.ty) }
@ -1679,9 +1796,9 @@ fn hash_type_structure(st: sty) -> uint {
let mut h = (46u << 2u) + hash_region(region); let mut h = (46u << 2u) + hash_region(region);
hash_subty(h, mt.ty) hash_subty(h, mt.ty)
} }
ty_res(did, sub, tps) { ty_res(did, sub, substs) {
let mut h = hash_subty(hash_def(18u, did), sub); let mut h = hash_subty(hash_def(18u, did), sub);
hash_subtys(h, tps) hash_substs(h, substs)
} }
ty_constr(t, cs) { ty_constr(t, cs) {
let mut h = hash_subty(36u, t); let mut h = hash_subty(36u, t);
@ -1698,10 +1815,9 @@ fn hash_type_structure(st: sty) -> uint {
ty_opaque_closure_ptr(ck_box) { 42u } ty_opaque_closure_ptr(ck_box) { 42u }
ty_opaque_closure_ptr(ck_uniq) { 43u } ty_opaque_closure_ptr(ck_uniq) { 43u }
ty_opaque_box { 44u } ty_opaque_box { 44u }
ty_class(did, tys) { ty_class(did, substs) {
let mut h = hash_def(45u, did); let mut h = hash_def(45u, did);
for tys.each {|typ| h = hash_subty(h, typ); } hash_substs(h, substs)
h
} }
} }
} }
@ -1997,7 +2113,7 @@ fn ty_sort_str(cx: ctxt, t: t) -> str {
ty_to_str(cx, t) ty_to_str(cx, t)
} }
ty_enum(_, _) { "enum" } ty_enum(id, _) { #fmt["enum %s", item_path_str(cx, id)] }
ty_box(_) { "@-ptr" } ty_box(_) { "@-ptr" }
ty_uniq(_) { "~-ptr" } ty_uniq(_) { "~-ptr" }
ty_evec(_, _) | ty_vec(_) { "vector" } ty_evec(_, _) | ty_vec(_) { "vector" }
@ -2005,9 +2121,9 @@ fn ty_sort_str(cx: ctxt, t: t) -> str {
ty_rptr(_, _) { "&-ptr" } ty_rptr(_, _) { "&-ptr" }
ty_rec(_) { "record" } ty_rec(_) { "record" }
ty_fn(_) { "fn" } ty_fn(_) { "fn" }
ty_iface(_, _) { "iface" } ty_iface(id, _) { #fmt["iface %s", item_path_str(cx, id)] }
ty_class(_, _) { "class" } ty_class(id, _) { #fmt["class %s", item_path_str(cx, id)] }
ty_res(_, _, _) { "resource" } ty_res(id, _, _) { #fmt["resource %s", item_path_str(cx, id)] }
ty_tup(_) { "tuple" } ty_tup(_) { "tuple" }
ty_var(_) { "variable" } ty_var(_) { "variable" }
ty_param(_, _) { "type parameter" } ty_param(_, _) { "type parameter" }
@ -2148,15 +2264,15 @@ fn ty_to_def_id(ty: t) -> ast::def_id {
type variant_info = @{args: [t], ctor_ty: t, name: str, type variant_info = @{args: [t], ctor_ty: t, name: str,
id: ast::def_id, disr_val: int}; id: ast::def_id, disr_val: int};
fn substd_enum_variants(cx: ctxt, id: ast::def_id, tps: [ty::t]) fn substd_enum_variants(cx: ctxt,
-> [variant_info] { id: ast::def_id,
substs: substs) -> [variant_info] {
vec::map(*enum_variants(cx, id)) { |variant_info| vec::map(*enum_variants(cx, id)) { |variant_info|
let substd_args = vec::map(variant_info.args) {|aty| let substd_args = vec::map(variant_info.args) {|aty|
substitute_type_params(cx, tps, aty) subst(cx, substs, aty)
}; };
let substd_ctor_ty = let substd_ctor_ty = subst(cx, substs, variant_info.ctor_ty);
substitute_type_params(cx, tps, variant_info.ctor_ty);
@{args: substd_args, ctor_ty: substd_ctor_ty with *variant_info} @{args: substd_args, ctor_ty: substd_ctor_ty with *variant_info}
} }
@ -2214,6 +2330,7 @@ fn enum_variants(cx: ctxt, id: ast::def_id) -> @[variant_info] {
some(variants) { ret variants; } some(variants) { ret variants; }
_ { /* fallthrough */ } _ { /* fallthrough */ }
} }
let result = if ast::local_crate != id.crate { let result = if ast::local_crate != id.crate {
@csearch::get_enum_variants(cx, id) @csearch::get_enum_variants(cx, id)
} else { } else {
@ -2221,13 +2338,15 @@ fn enum_variants(cx: ctxt, id: ast::def_id) -> @[variant_info] {
// check the disr_expr if it exists), this code should likely be // check the disr_expr if it exists), this code should likely be
// moved there to avoid having to call eval_const_expr twice. // moved there to avoid having to call eval_const_expr twice.
alt cx.items.get(id.node) { alt cx.items.get(id.node) {
ast_map::node_item(@{node: ast::item_enum(variants, _), _}, _) { ast_map::node_item(@{node: ast::item_enum(variants, _, _), _}, _) {
let mut disr_val = -1; let mut disr_val = -1;
@vec::map(variants, {|variant| @vec::map(variants, {|variant|
let ctor_ty = node_id_to_type(cx, variant.node.id); let ctor_ty = node_id_to_type(cx, variant.node.id);
let arg_tys = if vec::len(variant.node.args) > 0u { let arg_tys = {
vec::map(ty_fn_args(ctor_ty), {|a| a.ty}) if vec::len(variant.node.args) > 0u {
} else { [] }; ty_fn_args(ctor_ty).map { |a| a.ty }
} else { [] }
};
alt variant.node.disr_expr { alt variant.node.disr_expr {
some (ex) { some (ex) {
// FIXME: issue #1417 // FIXME: issue #1417
@ -2287,7 +2406,8 @@ fn lookup_item_type(cx: ctxt, did: ast::def_id) -> ty_param_bounds_and_ty {
// Look up a field ID, whether or not it's local // Look up a field ID, whether or not it's local
// Takes a list of type substs in case the class is generic // Takes a list of type substs in case the class is generic
fn lookup_field_type(tcx: ctxt, class_id: def_id, id: def_id, fn lookup_field_type(tcx: ctxt, class_id: def_id, id: def_id,
substs: [ty::t]) -> ty::t { substs: substs) -> ty::t {
let t = if id.crate == ast::local_crate { let t = if id.crate == ast::local_crate {
node_id_to_type(tcx, id.node) node_id_to_type(tcx, id.node)
} }
@ -2304,7 +2424,7 @@ fn lookup_field_type(tcx: ctxt, class_id: def_id, id: def_id,
} }
} }
}; };
substitute_type_params(tcx, substs, t) subst(tcx, substs, t)
} }
// Look up the list of field names and IDs for a given class // Look up the list of field names and IDs for a given class
@ -2314,7 +2434,7 @@ fn lookup_class_fields(cx: ctxt, did: ast::def_id) -> [field_ty] {
alt cx.items.find(did.node) { alt cx.items.find(did.node) {
some(ast_map::node_item(i,_)) { some(ast_map::node_item(i,_)) {
alt i.node { alt i.node {
ast::item_class(_, _, items, _) { ast::item_class(_, _, items, _, _) {
class_field_tys(items) class_field_tys(items)
} }
_ { cx.sess.bug("class ID bound to non-class"); } _ { cx.sess.bug("class ID bound to non-class"); }
@ -2356,7 +2476,7 @@ pure fn is_public(f: field_ty) -> bool {
fn lookup_class_method_ids(cx: ctxt, did: ast::def_id) fn lookup_class_method_ids(cx: ctxt, did: ast::def_id)
: is_local(did) -> [{name: ident, id: node_id, privacy: privacy}] { : is_local(did) -> [{name: ident, id: node_id, privacy: privacy}] {
alt cx.items.find(did.node) { alt cx.items.find(did.node) {
some(ast_map::node_item(@{node: item_class(_,_,items,_), _}, _)) { some(ast_map::node_item(@{node: item_class(_,_,items,_,_), _}, _)) {
let (_,ms) = split_class_items(items); let (_,ms) = split_class_items(items);
vec::map(ms, {|m| {name: m.ident, id: m.id, vec::map(ms, {|m| {name: m.ident, id: m.id,
privacy: m.privacy}}) privacy: m.privacy}})
@ -2406,8 +2526,8 @@ fn class_field_tys(items: [@class_member]) -> [field_ty] {
// Return a list of fields corresponding to the class's items // Return a list of fields corresponding to the class's items
// (as if the class was a record). trans uses this // (as if the class was a record). trans uses this
// Takes a list of substs with which to instantiate field types // Takes a list of substs with which to instantiate field types
fn class_items_as_fields(cx:ctxt, did: ast::def_id, substs: [ty::t]) fn class_items_as_fields(cx:ctxt, did: ast::def_id,
-> [field] { substs: substs) -> [field] {
let mut rslt = []; let mut rslt = [];
for lookup_class_fields(cx, did).each {|f| for lookup_class_fields(cx, did).each {|f|
// consider all instance vars mut, because the // consider all instance vars mut, because the

File diff suppressed because it is too large Load diff

View file

@ -10,11 +10,12 @@ import syntax::{ast, ast_util};
import middle::ast_map; import middle::ast_map;
import driver::session::session; import driver::session::session;
fn bound_region_to_str(_cx: ctxt, br: bound_region) -> str { fn bound_region_to_str(cx: ctxt, br: bound_region) -> str {
alt br { alt br {
br_anon { "&" } br_anon { "&" }
br_named(str) { #fmt["&%s", str] } br_named(str) { #fmt["&%s", str] }
br_self { "&self" } br_self if cx.sess.opts.debug_rustc { "&<self>" }
br_self { "&self" }
} }
} }
@ -127,12 +128,23 @@ fn ty_to_str(cx: ctxt, typ: t) -> str {
fn field_to_str(cx: ctxt, f: field) -> str { fn field_to_str(cx: ctxt, f: field) -> str {
ret f.ident + ": " + mt_to_str(cx, f.mt); ret f.ident + ": " + mt_to_str(cx, f.mt);
} }
fn parameterized(cx: ctxt, base: str, tps: [ty::t]) -> str { fn parameterized(cx: ctxt,
base: str,
self_r: option<ty::region>,
tps: [ty::t]) -> str {
let r_str = alt self_r {
none { "" }
some(r) {
#fmt["/%s", region_to_str(cx, r)]
}
};
if vec::len(tps) > 0u { if vec::len(tps) > 0u {
let strs = vec::map(tps, {|t| ty_to_str(cx, t)}); let strs = vec::map(tps, {|t| ty_to_str(cx, t)});
#fmt["%s<%s>", base, str::connect(strs, ",")] #fmt["%s%s<%s>", base, r_str, str::connect(strs, ",")]
} else { } else {
base #fmt["%s%s", base, r_str]
} }
} }
@ -141,9 +153,11 @@ fn ty_to_str(cx: ctxt, typ: t) -> str {
some(def_id) { some(def_id) {
let cs = ast_map::path_to_str(ty::item_path(cx, def_id)); let cs = ast_map::path_to_str(ty::item_path(cx, def_id));
ret alt ty::get(typ).struct { ret alt ty::get(typ).struct {
ty_enum(_, tps) | ty_res(_, _, tps) | ty_iface(_, tps) | ty_enum(_, substs) | ty_res(_, _, substs) | ty_class(_, substs) {
ty_class(_, tps) { parameterized(cx, cs, substs.self_r, substs.tps)
parameterized(cx, cs, tps) }
ty_iface(_, tps) {
parameterized(cx, cs, none, tps)
} }
_ { cs } _ { cs }
}; };
@ -164,7 +178,7 @@ fn ty_to_str(cx: ctxt, typ: t) -> str {
ty_float(ast::ty_f) { "float" } ty_float(ast::ty_f) { "float" }
ty_float(t) { ast_util::float_ty_to_str(t) } ty_float(t) { ast_util::float_ty_to_str(t) }
ty_str { "str" } ty_str { "str" }
ty_self(ts) { parameterized(cx, "self", ts) } ty_self(ts) { parameterized(cx, "self", none, ts) }
ty_box(tm) { "@" + mt_to_str(cx, tm) } ty_box(tm) { "@" + mt_to_str(cx, tm) }
ty_uniq(tm) { "~" + mt_to_str(cx, tm) } ty_uniq(tm) { "~" + mt_to_str(cx, tm) }
ty_ptr(tm) { "*" + mt_to_str(cx, tm) } ty_ptr(tm) { "*" + mt_to_str(cx, tm) }
@ -196,11 +210,15 @@ fn ty_to_str(cx: ctxt, typ: t) -> str {
ty_param(id, _) { ty_param(id, _) {
"'" + str::from_bytes([('a' as u8) + (id as u8)]) "'" + str::from_bytes([('a' as u8) + (id as u8)])
} }
ty_enum(did, tps) | ty_res(did, _, tps) | ty_iface(did, tps) | ty_enum(did, substs) | ty_res(did, _, substs) | ty_class(did, substs) {
ty_class(did, tps) {
let path = ty::item_path(cx, did); let path = ty::item_path(cx, did);
let base = ast_map::path_to_str(path); let base = ast_map::path_to_str(path);
parameterized(cx, base, tps) parameterized(cx, base, substs.self_r, substs.tps)
}
ty_iface(did, tps) {
let path = ty::item_path(cx, did);
let base = ast_map::path_to_str(path);
parameterized(cx, base, none, tps)
} }
ty_evec(mt, vs) { ty_evec(mt, vs) {
#fmt["[%s]/%s", mt_to_str(cx, mt), #fmt["[%s]/%s", mt_to_str(cx, mt),

View file

@ -147,7 +147,7 @@ fn fold_enum(
let desc = astsrv::exec(srv) {|ctxt| let desc = astsrv::exec(srv) {|ctxt|
alt check ctxt.ast_map.get(doc_id) { alt check ctxt.ast_map.get(doc_id) {
ast_map::node_item(@{ ast_map::node_item(@{
node: ast::item_enum(ast_variants, _), _ node: ast::item_enum(ast_variants, _, _), _
}, _) { }, _) {
let ast_variant = option::get( let ast_variant = option::get(
vec::find(ast_variants) {|v| vec::find(ast_variants) {|v|

View file

@ -78,12 +78,12 @@ fn moddoc_from_mod(
constdoc_from_const(itemdoc) constdoc_from_const(itemdoc)
)) ))
} }
ast::item_enum(variants, _) { ast::item_enum(variants, _, _) {
some(doc::enumtag( some(doc::enumtag(
enumdoc_from_enum(itemdoc, variants) enumdoc_from_enum(itemdoc, variants)
)) ))
} }
ast::item_res(_, _, _, _, _) { ast::item_res(_, _, _, _, _, _) {
some(doc::restag( some(doc::restag(
resdoc_from_resource(itemdoc) resdoc_from_resource(itemdoc)
)) ))
@ -98,7 +98,7 @@ fn moddoc_from_mod(
impldoc_from_impl(itemdoc, methods) impldoc_from_impl(itemdoc, methods)
)) ))
} }
ast::item_ty(_, _) { ast::item_ty(_, _, _) {
some(doc::tytag( some(doc::tytag(
tydoc_from_ty(itemdoc) tydoc_from_ty(itemdoc)
)) ))

View file

@ -112,7 +112,7 @@ fn fold_enum(
let sig = astsrv::exec(srv) {|ctxt| let sig = astsrv::exec(srv) {|ctxt|
alt check ctxt.ast_map.get(doc_id) { alt check ctxt.ast_map.get(doc_id) {
ast_map::node_item(@{ ast_map::node_item(@{
node: ast::item_enum(ast_variants, _), _ node: ast::item_enum(ast_variants, _, _), _
}, _) { }, _) {
let ast_variant = option::get( let ast_variant = option::get(
vec::find(ast_variants) {|v| vec::find(ast_variants) {|v|
@ -149,9 +149,9 @@ fn fold_res(
sig: some(astsrv::exec(srv) {|ctxt| sig: some(astsrv::exec(srv) {|ctxt|
alt check ctxt.ast_map.get(doc.id()) { alt check ctxt.ast_map.get(doc.id()) {
ast_map::node_item(@{ ast_map::node_item(@{
node: ast::item_res(decl, tys, _, _, _), _ node: ast::item_res(decl, tys, _, _, _, rp), _
}, _) { }, _) {
pprust::res_to_str(decl, doc.name(), tys) pprust::res_to_str(decl, doc.name(), tys, rp)
} }
} }
}) })
@ -303,7 +303,7 @@ fn fold_type(
alt ctxt.ast_map.get(doc.id()) { alt ctxt.ast_map.get(doc.id()) {
ast_map::node_item(@{ ast_map::node_item(@{
ident: ident, ident: ident,
node: ast::item_ty(ty, params), _ node: ast::item_ty(ty, params, ast::rp_none), _
}, _) { }, _) {
some(#fmt( some(#fmt(
"type %s%s = %s", "type %s%s = %s",

View file

@ -2,7 +2,7 @@ use std;
import std::arena; import std::arena;
import std::arena::arena; import std::arena::arena;
enum tree { nil, node(&tree, &tree, int), } enum tree& { nil, node(&tree, &tree, int), }
fn item_check(t: &tree) -> int { fn item_check(t: &tree) -> int {
alt *t { alt *t {

View file

@ -0,0 +1,33 @@
enum ast& {
num(uint),
add(&ast, &ast)
}
fn build() {
let x = num(3u);
let y = num(4u);
let z = add(&x, &y);
compute(&z);
}
fn compute(x: &ast) -> uint {
alt *x {
num(x) { x }
add(x, y) { compute(x) + compute(y) }
}
}
fn map_nums(x: &ast, f: fn(uint) -> uint) -> &ast {
alt *x {
num(x) {
ret &num(f(x)); //! ERROR mismatched types: expected `&ast/&` but found
}
add(x, y) {
let m_x = map_nums(x, f);
let m_y = map_nums(y, f);
ret &add(m_x, m_y); //! ERROR mismatched types: expected `&ast/&` but found
}
}
}
fn main() {}

View file

@ -0,0 +1,25 @@
enum no0 {
x0(&uint) //! ERROR to use region types here, the containing type must be declared with a region bound
}
enum no1 {
x1(&self.uint) //! ERROR to use region types here, the containing type must be declared with a region bound
}
enum no2 {
x2(&foo.uint) //! ERROR named regions other than `self` are not allowed as part of a type declaration
}
enum yes0& {
x3(&uint)
}
enum yes1& {
x4(&self.uint)
}
enum yes2& {
x5(&foo.uint) //! ERROR named regions other than `self` are not allowed as part of a type declaration
}
fn main() {}

View file

@ -0,0 +1,19 @@
resource no0(x: &uint) { //! ERROR to use region types here, the containing type must be declared with a region bound
}
resource no1(x: &self.uint) { //! ERROR to use region types here, the containing type must be declared with a region bound
}
resource no2(x: &foo.uint) { //! ERROR named regions other than `self` are not allowed as part of a type declaration
}
resource yes0&(x: &uint) {
}
resource yes1&(x: &self.uint) {
}
resource yes2&(x: &foo.uint) { //! ERROR named regions other than `self` are not allowed as part of a type declaration
}
fn main() {}

View file

@ -0,0 +1,25 @@
type item_ty_no0 = {
x: &uint //! ERROR to use region types here, the containing type must be declared with a region bound
};
type item_ty_no1 = {
x: &self.uint //! ERROR to use region types here, the containing type must be declared with a region bound
};
type item_ty_no2 = {
x: &foo.uint //! ERROR named regions other than `self` are not allowed as part of a type declaration
};
type item_ty_yes0& = {
x: &uint
};
type item_ty_yes1& = {
x: &self.uint
};
type item_ty_yes2& = {
x: &foo.uint //! ERROR named regions other than `self` are not allowed as part of a type declaration
};
fn main() {}

View file

@ -2,8 +2,7 @@ use std;
fn main() { fn main() {
iface seq { } iface seq { }
impl <T> of seq<T> for [T] { impl <T> of seq<T> for [T] { //! ERROR wrong number of type arguments
//!^ ERROR wrong number of type arguments for a polymorphic type
/* ... */ /* ... */
} }
impl of seq<bool> for u32 { impl of seq<bool> for u32 {

View file

@ -2,11 +2,11 @@ import libc, sys, unsafe;
enum arena = (); enum arena = ();
type bcx = { type bcx& = {
fcx: &fcx fcx: &fcx
}; };
type fcx = { type fcx& = {
arena: &arena, arena: &arena,
ccx: &ccx ccx: &ccx
}; };

View file

@ -2,11 +2,11 @@ import libc, sys, unsafe;
enum arena = (); enum arena = ();
type bcx = { type bcx& = {
fcx: &fcx fcx: &fcx
}; };
type fcx = { type fcx& = {
arena: &arena, arena: &arena,
ccx: &ccx ccx: &ccx
}; };