提交 1ed6a275 编写于 作者: M Marijn Haverbeke

Change representation of type params to handle interface bounds

Issue #1227
上级 5930463f
......@@ -22,7 +22,7 @@
const tag_items_data_item_family: uint = 0x0au;
const tag_items_data_item_ty_param_kinds: uint = 0x0bu;
const tag_items_data_item_ty_param_bounds: uint = 0x0bu;
const tag_items_data_item_type: uint = 0x0cu;
......
......@@ -86,7 +86,7 @@ fn get_impl_methods(cstore: cstore::cstore, def: ast::def_id)
decoder::lookup_impl_methods(cdata, def.node, def.crate)
}
fn get_type(tcx: ty::ctxt, def: ast::def_id) -> ty::ty_param_kinds_and_ty {
fn get_type(tcx: ty::ctxt, def: ast::def_id) -> ty::ty_param_bounds_and_ty {
let cstore = tcx.sess.get_cstore();
let cnum = def.crate;
let cdata = cstore::get_crate_data(cstore, cnum).data;
......
......@@ -14,7 +14,6 @@
export get_tag_variants;
export get_type;
export get_type_param_count;
export get_type_param_kinds;
export lookup_def;
export lookup_item_name;
export resolve_path;
......@@ -90,21 +89,22 @@ fn variant_tag_id(d: ebml::doc) -> ast::def_id {
ret parse_def_id(ebml::doc_data(tagdoc));
}
fn parse_external_def_id(this_cnum: ast::crate_num,
extres: external_resolver, s: str) ->
ast::def_id {
let buf = str::bytes(s);
let external_def_id = parse_def_id(buf);
// This item was defined in the crate we're searching if it's has the
// local crate number, otherwise we need to search a different crate
if external_def_id.crate == ast::local_crate {
ret {crate: this_cnum, node: external_def_id.node};
} else { ret extres(external_def_id); }
}
fn item_type(item: ebml::doc, this_cnum: ast::crate_num, tcx: ty::ctxt,
extres: external_resolver) -> ty::t {
fn parse_external_def_id(this_cnum: ast::crate_num,
extres: external_resolver, s: str) ->
ast::def_id {
let buf = str::bytes(s);
let external_def_id = parse_def_id(buf);
// This item was defined in the crate we're searching if it's has the
// local crate number, otherwise we need to search a different crate
if external_def_id.crate == ast::local_crate {
ret {crate: this_cnum, node: external_def_id.node};
} else { ret extres(external_def_id); }
}
let tp = ebml::get_doc(item, tag_items_data_item_type);
let def_parser = bind parse_external_def_id(this_cnum, extres, _);
let t = parse_ty_data(item.data, this_cnum, tp.start, tp.end - tp.start,
......@@ -115,32 +115,24 @@ fn parse_external_def_id(this_cnum: ast::crate_num,
t
}
fn item_ty_param_kinds(item: ebml::doc) -> [ast::kind] {
let ks: [ast::kind] = [];
let tp = tag_items_data_item_ty_param_kinds;
ebml::tagged_docs(item, tp) {|p|
let dat: [u8] = ebml::doc_data(p);
let vi = ebml::vint_at(dat, 0u);
let i = 0u;
while i < vi.val {
let k =
alt dat[vi.next + i] as char {
's' { ast::kind_sendable }
'c' { ast::kind_copyable }
'a' { ast::kind_noncopyable }
};
ks += [k];
i += 1u;
}
};
ret ks;
fn item_ty_param_bounds(item: ebml::doc, this_cnum: ast::crate_num,
tcx: ty::ctxt, extres: external_resolver)
-> [@[ty::param_bound]] {
let bounds = [];
let def_parser = bind parse_external_def_id(this_cnum, extres, _);
ebml::tagged_docs(item, tag_items_data_item_ty_param_bounds) {|p|
bounds += [tydecode::parse_bounds_data(@ebml::doc_data(p), this_cnum,
def_parser, tcx)];
}
bounds
}
fn item_ty_param_count(item: ebml::doc) -> uint {
let n = 0u;
let tp = tag_items_data_item_ty_param_kinds;
ebml::tagged_docs(item, tp) {|p|
n += ebml::vint_at(ebml::doc_data(p), 0u).val;
ebml::tagged_docs(item, tag_items_data_item_ty_param_bounds) {|p|
for byte in ebml::doc_data(p) {
if byte as char == '.' { n += 1u; }
}
}
n
}
......@@ -213,28 +205,21 @@ fn lookup_def(cnum: ast::crate_num, data: @[u8], did_: ast::def_id) ->
}
fn get_type(data: @[u8], def: ast::def_id, tcx: ty::ctxt,
extres: external_resolver) -> ty::ty_param_kinds_and_ty {
extres: external_resolver) -> ty::ty_param_bounds_and_ty {
let this_cnum = def.crate;
let node_id = def.node;
let item = lookup_item(node_id, data);
let t = item_type(item, this_cnum, tcx, extres);
let tp_kinds: [ast::kind];
let fam_ch = item_family(item);
let has_ty_params = family_has_type_params(fam_ch);
if has_ty_params {
tp_kinds = item_ty_param_kinds(item);
} else { tp_kinds = []; }
ret {kinds: tp_kinds, ty: t};
let tp_bounds = if family_has_type_params(item_family(item)) {
item_ty_param_bounds(item, this_cnum, tcx, extres)
} else { [] };
ret {bounds: tp_bounds, ty: t};
}
fn get_type_param_count(data: @[u8], id: ast::node_id) -> uint {
item_ty_param_count(lookup_item(id, data))
}
fn get_type_param_kinds(data: @[u8], id: ast::node_id) -> [ast::kind] {
ret item_ty_param_kinds(lookup_item(id, data));
}
fn get_symbol(data: @[u8], id: ast::node_id) -> str {
ret item_symbol(lookup_item(id, data));
}
......
......@@ -183,18 +183,17 @@ fn encode_family(ebml_w: ebml::writer, c: u8) {
fn def_to_str(did: def_id) -> str { ret #fmt["%d:%d", did.crate, did.node]; }
fn encode_type_param_kinds(ebml_w: ebml::writer, tps: [ty_param]) {
ebml::start_tag(ebml_w, tag_items_data_item_ty_param_kinds);
ebml::write_vint(ebml_w.writer, vec::len::<ty_param>(tps));
for tp: ty_param in tps {
let c = alt ast_util::ty_param_kind(tp) {
kind_sendable. { 's' }
kind_copyable. { 'c' }
kind_noncopyable. { 'a' }
};
ebml_w.writer.write([c as u8]);
fn encode_type_param_bounds(ebml_w: ebml::writer, ecx: @encode_ctxt,
params: [ty_param]) {
let ty_str_ctxt = @{ds: def_to_str,
tcx: ecx.ccx.tcx,
abbrevs: tyencode::ac_use_abbrevs(ecx.type_abbrevs)};
for param in params {
ebml::start_tag(ebml_w, tag_items_data_item_ty_param_bounds);
let bs = ecx.ccx.tcx.ty_param_bounds.get(local_def(param.id));
tyencode::enc_bounds(io::new_writer(ebml_w.writer), ty_str_ctxt, bs);
ebml::end_tag(ebml_w);
}
ebml::end_tag(ebml_w);
}
fn encode_variant_id(ebml_w: ebml::writer, vid: def_id) {
......@@ -205,9 +204,8 @@ fn encode_variant_id(ebml_w: ebml::writer, vid: def_id) {
fn encode_type(ecx: @encode_ctxt, ebml_w: ebml::writer, typ: ty::t) {
ebml::start_tag(ebml_w, tag_items_data_item_type);
let f = def_to_str;
let ty_str_ctxt =
@{ds: f,
@{ds: def_to_str,
tcx: ecx.ccx.tcx,
abbrevs: tyencode::ac_use_abbrevs(ecx.type_abbrevs)};
tyencode::enc_ty(io::new_writer(ebml_w.writer), ty_str_ctxt, typ);
......@@ -247,7 +245,7 @@ fn encode_tag_variant_info(ecx: @encode_ctxt, ebml_w: ebml::writer,
encode_symbol(ecx, ebml_w, variant.node.id);
}
encode_discriminant(ecx, ebml_w, variant.node.id);
encode_type_param_kinds(ebml_w, ty_params);
encode_type_param_bounds(ebml_w, ecx, ty_params);
ebml::end_tag(ebml_w);
}
}
......@@ -293,7 +291,7 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
pure_fn. { 'p' }
impure_fn. { 'f' }
} as u8);
encode_type_param_kinds(ebml_w, tps);
encode_type_param_bounds(ebml_w, ecx, tps);
encode_type(ecx, ebml_w, node_id_to_monotype(ecx.ccx.tcx, item.id));
encode_symbol(ecx, ebml_w, item.id);
ebml::end_tag(ebml_w);
......@@ -312,7 +310,7 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
ebml::start_tag(ebml_w, tag_items_data_item);
encode_def_id(ebml_w, local_def(item.id));
encode_family(ebml_w, 'y' as u8);
encode_type_param_kinds(ebml_w, tps);
encode_type_param_bounds(ebml_w, ecx, tps);
encode_type(ecx, ebml_w, node_id_to_monotype(ecx.ccx.tcx, item.id));
encode_name(ebml_w, item.ident);
ebml::end_tag(ebml_w);
......@@ -321,7 +319,7 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
ebml::start_tag(ebml_w, tag_items_data_item);
encode_def_id(ebml_w, local_def(item.id));
encode_family(ebml_w, 't' as u8);
encode_type_param_kinds(ebml_w, tps);
encode_type_param_bounds(ebml_w, ecx, tps);
encode_type(ecx, ebml_w, node_id_to_monotype(ecx.ccx.tcx, item.id));
encode_name(ebml_w, item.ident);
for v: variant in variants {
......@@ -336,7 +334,7 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
ebml::start_tag(ebml_w, tag_items_data_item);
encode_def_id(ebml_w, local_def(ctor_id));
encode_family(ebml_w, 'y' as u8);
encode_type_param_kinds(ebml_w, tps);
encode_type_param_bounds(ebml_w, ecx, tps);
encode_type(ecx, ebml_w, ty::ty_fn_ret(ecx.ccx.tcx, fn_ty));
encode_name(ebml_w, item.ident);
encode_symbol(ecx, ebml_w, item.id);
......@@ -346,7 +344,7 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
ebml::start_tag(ebml_w, tag_items_data_item);
encode_def_id(ebml_w, local_def(ctor_id));
encode_family(ebml_w, 'f' as u8);
encode_type_param_kinds(ebml_w, tps);
encode_type_param_bounds(ebml_w, ecx, tps);
encode_type(ecx, ebml_w, fn_ty);
encode_symbol(ecx, ebml_w, ctor_id);
ebml::end_tag(ebml_w);
......@@ -357,7 +355,7 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
ebml::start_tag(ebml_w, tag_items_data_item);
encode_def_id(ebml_w, local_def(item.id));
encode_family(ebml_w, 'y' as u8);
encode_type_param_kinds(ebml_w, tps);
encode_type_param_bounds(ebml_w, ecx, tps);
encode_type(ecx, ebml_w, ty::ty_fn_ret(ecx.ccx.tcx, fn_ty));
encode_name(ebml_w, item.ident);
ebml::end_tag(ebml_w);
......@@ -366,7 +364,7 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
ebml::start_tag(ebml_w, tag_items_data_item);
encode_def_id(ebml_w, local_def(ctor_id));
encode_family(ebml_w, 'f' as u8);
encode_type_param_kinds(ebml_w, tps);
encode_type_param_bounds(ebml_w, ecx, tps);
encode_type(ecx, ebml_w, fn_ty);
encode_symbol(ecx, ebml_w, ctor_id);
ebml::end_tag(ebml_w);
......@@ -375,7 +373,7 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
ebml::start_tag(ebml_w, tag_items_data_item);
encode_def_id(ebml_w, local_def(item.id));
encode_family(ebml_w, 'i' as u8);
encode_type_param_kinds(ebml_w, tps);
encode_type_param_bounds(ebml_w, ecx, tps);
encode_type(ecx, ebml_w, node_id_to_monotype(ecx.ccx.tcx, item.id));
encode_name(ebml_w, item.ident);
for m in methods {
......@@ -390,7 +388,7 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
ebml::start_tag(ebml_w, tag_items_data_item);
encode_def_id(ebml_w, local_def(m.id));
encode_family(ebml_w, 'f' as u8);
encode_type_param_kinds(ebml_w, tps + m.tps);
encode_type_param_bounds(ebml_w, ecx, tps + m.tps);
encode_type(ecx, ebml_w,
node_id_to_monotype(ecx.ccx.tcx, m.id));
encode_name(ebml_w, m.ident);
......@@ -421,7 +419,7 @@ fn encode_info_for_native_item(ecx: @encode_ctxt, ebml_w: ebml::writer,
} as u8;
encode_def_id(ebml_w, local_def(nitem.id));
encode_family(ebml_w, letter);
encode_type_param_kinds(ebml_w, tps);
encode_type_param_bounds(ebml_w, ecx, tps);
encode_type(ecx, ebml_w, node_id_to_monotype(ecx.ccx.tcx, nitem.id));
encode_symbol(ecx, ebml_w, nitem.id);
}
......
......@@ -10,6 +10,7 @@
export parse_def_id;
export parse_ty_data;
export parse_bounds_data;
// Compact string representation for ty::t values. API ty_str &
// parse_from_str. Extra parameters are for converting to/from def_ids in the
......@@ -21,7 +22,9 @@
type pstate =
{data: @[u8], crate: int, mutable pos: uint, len: uint, tcx: ty::ctxt};
fn peek(st: @pstate) -> u8 { ret st.data[st.pos]; }
fn peek(st: @pstate) -> u8 {
if st.pos < vec::len(*st.data) { st.data[st.pos] } else { 0u8 }
}
fn next(st: @pstate) -> u8 {
let ch = st.data[st.pos];
......@@ -48,8 +51,7 @@ fn parse_ty_data(data: @[u8], crate_num: int, pos: uint, len: uint,
sd: str_def, tcx: ty::ctxt) -> ty::t {
let st =
@{data: data, crate: crate_num, mutable pos: pos, len: len, tcx: tcx};
let result = parse_ty(st, sd);
ret result;
parse_ty(st, sd)
}
fn parse_ret_ty(st: @pstate, sd: str_def) -> (ast::ret_style, ty::t) {
......@@ -201,18 +203,8 @@ fn parse_ty(st: @pstate, sd: str_def) -> ty::t {
ret ty::mk_tag(st.tcx, def, params);
}
'p' {
let k =
alt next(st) as char {
's' { kind_sendable }
'c' { kind_copyable }
'a' { kind_noncopyable }
c {
#error("unexpected char in encoded type param: ");
log(error, c);
fail
}
};
ret ty::mk_param(st.tcx, parse_int(st) as uint, k);
let bounds = parse_bounds(st, sd);
ret ty::mk_param(st.tcx, parse_int(st) as uint, bounds);
}
'@' { ret ty::mk_box(st.tcx, parse_mt(st, sd)); }
'~' { ret ty::mk_uniq(st.tcx, parse_mt(st, sd)); }
......@@ -400,6 +392,26 @@ fn parse_def_id(buf: [u8]) -> ast::def_id {
ret {crate: crate_num, node: def_num};
}
fn parse_bounds_data(data: @[u8], crate_num: int, sd: str_def, tcx: ty::ctxt)
-> @[ty::param_bound] {
let st = @{data: data, crate: crate_num, mutable pos: 0u,
len: vec::len(*data), tcx: tcx};
parse_bounds(st, sd)
}
fn parse_bounds(st: @pstate, sd: str_def) -> @[ty::param_bound] {
let bounds = [];
while peek(st) as char == '.' {
next(st);
bounds += [alt next(st) as char {
'S' { ty::bound_send }
'C' { ty::bound_copy }
'I' { ty::bound_iface(parse_ty(st, sd)) }
}];
}
@bounds
}
//
// Local Variables:
// mode: rust
......
......@@ -13,6 +13,7 @@
export ac_no_abbrevs;
export ac_use_abbrevs;
export enc_ty;
export enc_bounds;
type ctxt =
// Def -> str Callback:
......@@ -175,12 +176,9 @@ fn enc_sty(w: io::writer, cx: @ctxt, st: ty::sty) {
w.write_str(cx.ds(def));
w.write_char('|');
}
ty::ty_param(id, k) {
alt k {
kind_sendable. { w.write_str("ps"); }
kind_copyable. { w.write_str("pc"); }
kind_noncopyable. { w.write_str("pa"); }
}
ty::ty_param(id, bounds) {
w.write_char('p');
enc_bounds(w, cx, bounds);
w.write_str(uint::str(id));
}
ty::ty_type. { w.write_char('Y'); }
......@@ -265,6 +263,19 @@ fn enc_ty_constr(w: io::writer, cx: @ctxt, c: @ty::type_constr) {
w.write_char(')');
}
fn enc_bounds(w: io::writer, cx: @ctxt, bs: @[ty::param_bound]) {
for bound in *bs {
w.write_char('.');
alt bound {
ty::bound_send. { w.write_char('S'); }
ty::bound_copy. { w.write_char('C'); }
ty::bound_iface(tp) {
w.write_char('I');
enc_ty(w, cx, tp);
}
}
}
}
//
// Local Variables:
......
......@@ -162,7 +162,9 @@ fn check_expr(e: @expr, cx: ctx, v: visit::vt<ctx>) {
alt substs.substs {
some(ts) {
let did = ast_util::def_id_of_def(cx.tcx.def_map.get(e.id));
let kinds = ty::lookup_item_type(cx.tcx, did).kinds, i = 0u;
let kinds = vec::map(ty::lookup_item_type(cx.tcx, did).bounds,
{|bs| ty::param_bounds_to_kind(bs)});
let i = 0u;
for ty in ts {
let kind = ty::type_kind(cx.tcx, ty);
if !ty::kind_lteq(kinds[i], kind) {
......
......@@ -399,6 +399,7 @@ fn visit_item_with_scope(i: @ast::item, sc: scopes, v: vt<scopes>) {
let sc = cons(scope_item(i), @sc);
alt i.node {
ast::item_impl(tps, ifce, sty, methods) {
visit::visit_ty_params(tps, sc, v);
alt ifce { some(ty) { v.visit_ty(ty, sc, v); } _ {} }
v.visit_ty(sty, sc, v);
for m in methods {
......@@ -901,12 +902,12 @@ fn in_scope(e: env, sp: span, name: ident, s: scope, ns: namespace) ->
fn lookup_in_ty_params(name: ident, ty_params: [ast::ty_param]) ->
option::t<def> {
let i = 0u;
let n = 0u;
for tp: ast::ty_param in ty_params {
if str::eq(tp.ident, name) {
ret some(ast::def_ty_param(i, ast_util::ty_param_kind(tp)));
ret some(ast::def_ty_param(local_def(tp.id), n));
}
i += 1u;
n += 1u;
}
ret none::<def>;
}
......
......@@ -450,7 +450,7 @@ fn gen_tag_shapes(ccx: @crate_ctxt) -> ValueRef {
let did = ccx.shape_cx.tag_order[i];
let variants = ty::tag_variants(ccx.tcx, did);
let item_tyt = ty::lookup_item_type(ccx.tcx, did);
let ty_param_count = vec::len(item_tyt.kinds);
let ty_param_count = vec::len(item_tyt.bounds);
for v: ty::variant_info in *variants {
offsets += [vec::len(data) as u16];
......
......@@ -227,14 +227,14 @@ fn type_of_tag(cx: @crate_ctxt, sp: span, did: ast::def_id, t: ty::t)
}
}
fn type_of_ty_param_kinds_and_ty(lcx: @local_ctxt, sp: span,
tpt: ty::ty_param_kinds_and_ty) -> TypeRef {
fn type_of_ty_param_bounds_and_ty(lcx: @local_ctxt, sp: span,
tpt: ty::ty_param_bounds_and_ty) -> TypeRef {
let cx = lcx.ccx;
let t = tpt.ty;
alt ty::struct(cx.tcx, t) {
ty::ty_fn(_) | ty::ty_native_fn(_, _) {
check returns_non_ty_var(cx, t);
ret type_of_fn_from_ty(cx, sp, t, vec::len(tpt.kinds));
ret type_of_fn_from_ty(cx, sp, t, vec::len(tpt.bounds));
}
_ {
// fall through
......@@ -2599,11 +2599,11 @@ fn lval_no_env(bcx: @block_ctxt, val: ValueRef, kind: lval_kind)
}
fn trans_external_path(cx: @block_ctxt, did: ast::def_id,
tpt: ty::ty_param_kinds_and_ty) -> ValueRef {
tpt: ty::ty_param_bounds_and_ty) -> ValueRef {
let lcx = cx.fcx.lcx;
let name = csearch::get_symbol(lcx.ccx.sess.get_cstore(), did);
ret get_extern_const(lcx.ccx.externs, lcx.ccx.llmod, name,
type_of_ty_param_kinds_and_ty(lcx, cx.sp, tpt));
type_of_ty_param_bounds_and_ty(lcx, cx.sp, tpt));
}
fn lval_static_fn(bcx: @block_ctxt, fn_id: ast::def_id, id: ast::node_id)
......@@ -2731,8 +2731,7 @@ fn trans_var(cx: @block_ctxt, sp: span, def: ast::def, id: ast::node_id)
ret lval_no_env(cx, ccx.consts.get(did.node), owned);
} else {
let tp = ty::node_id_to_monotype(ccx.tcx, id);
let k: [ast::kind] = [];
let val = trans_external_path(cx, did, {kinds: k, ty: tp});
let val = trans_external_path(cx, did, {bounds: [], ty: tp});
ret lval_no_env(cx, load_if_immediate(cx, val, tp), owned_imm);
}
}
......@@ -4657,8 +4656,7 @@ fn trans_tag_variant(cx: @local_ctxt, tag_id: ast::node_id,
let ty_param_substs: [ty::t] = [];
i = 0u;
for tp: ast::ty_param in ty_params {
ty_param_substs += [ty::mk_param(ccx.tcx, i,
ast_util::ty_param_kind(tp))];
ty_param_substs += [ty::mk_param(ccx.tcx, i, @[])];
i += 1u;
}
let arg_tys = arg_tys_of_fn(ccx, variant.node.id);
......
......@@ -106,7 +106,7 @@
export iface_methods, store_iface_methods;
export tag_variant_with_id;
export ty_param_substs_opt_and_ty;
export ty_param_kinds_and_ty;
export ty_param_bounds_and_ty;
export ty_native_fn;
export ty_bool;
export ty_bot;
......@@ -185,6 +185,8 @@
export closure_block;
export closure_shared;
export closure_send;
export param_bound, bound_copy, bound_send, bound_iface;
export param_bounds_to_kind;
// Data types
......@@ -192,7 +194,7 @@
type field = {ident: ast::ident, mt: mt};
type method = {ident: ast::ident, tps: [ast::kind], fty: fn_ty};
type method = {ident: ast::ident, tps: [@[param_bound]], fty: fn_ty};
type constr_table = hashmap<ast::node_id, [constr]>;
......@@ -217,7 +219,8 @@
kind_cache: hashmap<t, ast::kind>,
ast_ty_to_ty_cache: hashmap<@ast::ty, option::t<t>>,
tag_var_cache: hashmap<ast::def_id, @[variant_info]>,
iface_method_cache: hashmap<def_id, @[method]>};
iface_method_cache: hashmap<def_id, @[method]>,
ty_param_bounds: hashmap<def_id, @[param_bound]>};
type ty_ctxt = ctxt;
......@@ -265,7 +268,7 @@
ty_tup([t]);
ty_var(int); // type variable
ty_param(uint, ast::kind); // fn/tag type param
ty_param(uint, @[param_bound]); // fn/tag type param
ty_type; // type_desc*
ty_send_type; // type_desc* that has been cloned into exchange heap
......@@ -299,9 +302,29 @@
terr_constr_mismatch(@type_constr, @type_constr);
}
type ty_param_kinds_and_ty = {kinds: [ast::kind], ty: t};
tag param_bound {
bound_copy;
bound_send;
bound_iface(t);
}
fn param_bounds_to_kind(bounds: @[param_bound]) -> ast::kind {
let kind = ast::kind_noncopyable;
for bound in *bounds {
alt bound {
bound_copy. {
if kind != ast::kind_sendable { kind = ast::kind_copyable; }
}
bound_send. { kind = ast::kind_sendable; }
_ {}
}
}
kind
}
type ty_param_bounds_and_ty = {bounds: [@[param_bound]], ty: t};
type type_cache = hashmap<ast::def_id, ty_param_kinds_and_ty>;
type type_cache = hashmap<ast::def_id, ty_param_bounds_and_ty>;
const idx_nil: uint = 0u;
......@@ -415,7 +438,8 @@ fn eq_raw_ty(&&a: @raw_t, &&b: @raw_t) -> bool {
ast_ty_to_ty_cache:
map::mk_hashmap(ast_util::hash_ty, ast_util::eq_ty),
tag_var_cache: new_def_hash(),
iface_method_cache: new_def_hash()};
iface_method_cache: new_def_hash(),
ty_param_bounds: new_def_hash()};
populate_type_store(cx);
ret cx;
}
......@@ -600,7 +624,7 @@ fn mk_res(cx: ctxt, did: ast::def_id, inner: t, tps: [t]) -> t {
fn mk_var(cx: ctxt, v: int) -> t { ret gen_ty(cx, ty_var(v)); }
fn mk_param(cx: ctxt, n: uint, k: ast::kind) -> t {
fn mk_param(cx: ctxt, n: uint, k: @[param_bound]) -> t {
ret gen_ty(cx, ty_param(n, k));
}
......@@ -698,7 +722,7 @@ fn walk_ty(cx: ctxt, walker: ty_walk, ty: t) {
tag fold_mode {
fm_var(fn@(int) -> t);
fm_param(fn@(uint, ast::kind) -> t);
fm_param(fn@(uint, @[param_bound]) -> t);
fm_general(fn@(t) -> t);
}
......@@ -1029,7 +1053,7 @@ fn type_kind(cx: ctxt, ty: t) -> ast::kind {
}
// Resources are always noncopyable.
ty_res(did, inner, tps) { ast::kind_noncopyable }
ty_param(_, k) { k }
ty_param(_, bounds) { param_bounds_to_kind(bounds) }
ty_constr(t, _) { type_kind(cx, t) }
};
......@@ -2574,7 +2598,7 @@ fn bind_params_in_type(sp: span, cx: ctxt, next_ty_var: fn@() -> int, typ: t,
while i < ty_param_count { *param_var_ids += [next_ty_var()]; i += 1u; }
fn binder(sp: span, cx: ctxt, param_var_ids: @mutable [int],
_next_ty_var: fn@() -> int, index: uint,
_kind: ast::kind) -> t {
_bounds: @[param_bound]) -> t {
if index < vec::len(*param_var_ids) {
ret mk_var(cx, param_var_ids[index]);
} else {
......@@ -2593,7 +2617,8 @@ fn binder(sp: span, cx: ctxt, param_var_ids: @mutable [int],
// substitions.
fn substitute_type_params(cx: ctxt, substs: [ty::t], typ: t) -> t {
if !type_contains_params(cx, typ) { ret typ; }
fn substituter(_cx: ctxt, substs: @[ty::t], idx: uint, _kind: ast::kind)
fn substituter(_cx: ctxt, substs: @[ty::t], idx: uint,
_bounds: @[param_bound])
-> t {
// FIXME: bounds check can fail
ret substs[idx];
......@@ -2674,7 +2699,7 @@ fn tag_variant_with_id(cx: ctxt, tag_id: ast::def_id, variant_id: ast::def_id)
// If the given item is in an external crate, looks up its type and adds it to
// the type cache. Returns the type parameters and type.
fn lookup_item_type(cx: ctxt, did: ast::def_id) -> ty_param_kinds_and_ty {
fn lookup_item_type(cx: ctxt, did: ast::def_id) -> ty_param_bounds_and_ty {
if did.crate == ast::local_crate {
// The item is in this crate. The caller should have added it to the
// type cache already; we simply return it.
......
import syntax::{ast, ast_util};
import ast::spanned;
import syntax::ast_util::{local_def, respan, ty_param_kind};
import syntax::ast_util::{local_def, respan};
import syntax::visit;
import metadata::csearch;
import driver::session;
......@@ -9,7 +9,7 @@
import middle::ty;
import middle::ty::{node_id_to_type, arg, bind_params_in_type, block_ty,
expr_ty, field, node_type_table, mk_nil,
ty_param_substs_opt_and_ty, ty_param_kinds_and_ty};
ty_param_substs_opt_and_ty, ty_param_bounds_and_ty};
import util::ppaux::ty_to_str;
import middle::ty::unify::{ures_ok, ures_err, fix_ok, fix_err};
import core::{int, vec, str, option};
......@@ -70,28 +70,28 @@ fn lookup_def(fcx: @fn_ctxt, sp: span, id: ast::node_id) -> ast::def {
}
// Returns the type parameter count and the type for the given definition.
fn ty_param_kinds_and_ty_for_def(fcx: @fn_ctxt, sp: span, defn: ast::def) ->
ty_param_kinds_and_ty {
fn ty_param_bounds_and_ty_for_def(fcx: @fn_ctxt, sp: span, defn: ast::def) ->
ty_param_bounds_and_ty {
alt defn {
ast::def_arg(id, _) {
assert (fcx.locals.contains_key(id.node));
let typ = ty::mk_var(fcx.ccx.tcx, lookup_local(fcx, sp, id.node));
ret {kinds: [], ty: typ};
ret {bounds: [], ty: typ};
}
ast::def_local(id, _) {
assert (fcx.locals.contains_key(id.node));
let typ = ty::mk_var(fcx.ccx.tcx, lookup_local(fcx, sp, id.node));
ret {kinds: [], ty: typ};
ret {bounds: [], ty: typ};
}
ast::def_obj_field(id, _) {
assert (fcx.locals.contains_key(id.node));
let typ = ty::mk_var(fcx.ccx.tcx, lookup_local(fcx, sp, id.node));
ret {kinds: [], ty: typ};
ret {bounds: [], ty: typ};
}
ast::def_self(id) {
alt get_self_info(fcx.ccx) {
some(self_obj(_, obj_t)) | some(self_impl(obj_t)) {
ret {kinds: [], ty: obj_t};
ret {bounds: [], ty: obj_t};
}
}
}
......@@ -102,18 +102,18 @@ fn ty_param_kinds_and_ty_for_def(fcx: @fn_ctxt, sp: span, defn: ast::def) ->
ast::def_binding(id) {
assert (fcx.locals.contains_key(id.node));
let typ = ty::mk_var(fcx.ccx.tcx, lookup_local(fcx, sp, id.node));
ret {kinds: [], ty: typ};
ret {bounds: [], ty: typ};
}
ast::def_mod(_) {
// Hopefully part of a path.
// TODO: return a type that's more poisonous, perhaps?
ret {kinds: [], ty: ty::mk_nil(fcx.ccx.tcx)};
ret {bounds: [], ty: ty::mk_nil(fcx.ccx.tcx)};
}
ast::def_ty(_) {
fcx.ccx.tcx.sess.span_fatal(sp, "expected value but found type");
}
ast::def_upvar(_, inner, _) {
ret ty_param_kinds_and_ty_for_def(fcx, sp, *inner);
ret ty_param_bounds_and_ty_for_def(fcx, sp, *inner);
}
_ {
// FIXME: handle other names.
......@@ -126,9 +126,9 @@ fn ty_param_kinds_and_ty_for_def(fcx: @fn_ctxt, sp: span, defn: ast::def) ->
// Instantiates the given path, which must refer to an item with the given
// number of type parameters and type.
fn instantiate_path(fcx: @fn_ctxt, pth: @ast::path,
tpt: ty_param_kinds_and_ty, sp: span)
tpt: ty_param_bounds_and_ty, sp: span)
-> ty_param_substs_opt_and_ty {
let ty_param_count = vec::len(tpt.kinds);
let ty_param_count = vec::len(tpt.bounds);
let bind_result =
bind_params_in_type(sp, fcx.ccx.tcx, bind next_ty_var_id(fcx), tpt.ty,
ty_param_count);
......@@ -238,7 +238,7 @@ fn default_arg_mode_for_ty(tcx: ty::ctxt, m: ast::mode,
fn ast_ty_to_ty(tcx: ty::ctxt, mode: mode, &&ast_ty: @ast::ty) -> ty::t {
fn getter(tcx: ty::ctxt, mode: mode, id: ast::def_id)
-> ty::ty_param_kinds_and_ty {
-> ty::ty_param_bounds_and_ty {
alt mode {
m_check. | m_check_tyvar(_) { ty::lookup_item_type(tcx, id) }
m_collect. {
......@@ -281,14 +281,14 @@ fn instantiate(tcx: ty::ctxt, sp: span, mode: mode,
// TODO: maybe record cname chains so we can do
// "foo = int" like OCaml?
let ty_param_kinds_and_ty = getter(tcx, mode, id);
if vec::len(ty_param_kinds_and_ty.kinds) == 0u {
ret ty_param_kinds_and_ty.ty;
let ty_param_bounds_and_ty = getter(tcx, mode, id);
if vec::len(ty_param_bounds_and_ty.bounds) == 0u {
ret ty_param_bounds_and_ty.ty;
}
// The typedef is type-parametric. Do the type substitution.
let param_bindings: [ty::t] = [];
if vec::len(args) != vec::len(ty_param_kinds_and_ty.kinds) {
if vec::len(args) != vec::len(ty_param_bounds_and_ty.bounds) {
tcx.sess.span_fatal(sp, "Wrong number of type arguments for a \
polymorphic type");
}
......@@ -297,7 +297,7 @@ fn instantiate(tcx: ty::ctxt, sp: span, mode: mode,
}
let typ =
ty::substitute_type_params(tcx, param_bindings,
ty_param_kinds_and_ty.ty);
ty_param_bounds_and_ty.ty);
ret typ;
}
let typ;
......@@ -342,7 +342,9 @@ fn instantiate(tcx: ty::ctxt, sp: span, mode: mode,
typ = instantiate(tcx, ast_ty.span, mode, id, path.node.types);
}
some(ast::def_native_ty(id)) { typ = getter(tcx, mode, id).ty; }
some(ast::def_ty_param(id, k)) { typ = ty::mk_param(tcx, id, k); }
some(ast::def_ty_param(id, n)) {
typ = ty::mk_param(tcx, n, tcx.ty_param_bounds.get(id));
}
some(_) {
tcx.sess.span_fatal(ast_ty.span,
"found type name used as a variable");
......@@ -376,11 +378,11 @@ fn instantiate(tcx: ty::ctxt, sp: span, mode: mode,
}
fn ty_of_item(tcx: ty::ctxt, mode: mode, it: @ast::item)
-> ty::ty_param_kinds_and_ty {
-> ty::ty_param_bounds_and_ty {
alt it.node {
ast::item_const(t, _) {
let typ = ast_ty_to_ty(tcx, mode, t);
let tpt = {kinds: [], ty: typ};
let tpt = {bounds: [], ty: typ};
tcx.tcache.insert(local_def(it.id), tpt);
ret tpt;
}
......@@ -399,34 +401,37 @@ fn ty_of_item(tcx: ty::ctxt, mode: mode, it: @ast::item)
}
// Tell ast_ty_to_ty() that we want to perform a recursive
// call to resolve any named types.
let typ = ty::mk_named(tcx, ast_ty_to_ty(tcx, mode, t), @it.ident);
let tpt = {kinds: ty_param_kinds(tps), ty: typ};
let tpt = {bounds: ty_param_bounds(tcx, mode, tps),
ty: ty::mk_named(tcx, ast_ty_to_ty(tcx, mode, t),
@it.ident)};
tcx.tcache.insert(local_def(it.id), tpt);
ret tpt;
}
ast::item_res(decl, tps, _, _, _) {
let {bounds, params} = mk_ty_params(tcx, tps);
let t_arg = ty_of_arg(tcx, mode, decl.inputs[0]);
let t = ty::mk_named(tcx, ty::mk_res(tcx, local_def(it.id), t_arg.ty,
mk_ty_params(tcx, tps)),
params),
@it.ident);
let t_res = {kinds: ty_param_kinds(tps), ty: t};
let t_res = {bounds: bounds, ty: t};
tcx.tcache.insert(local_def(it.id), t_res);
ret t_res;
}
ast::item_tag(_, tps) {
// Create a new generic polytype.
let subtys: [ty::t] = mk_ty_params(tcx, tps);
let t = ty::mk_named(tcx, ty::mk_tag(tcx, local_def(it.id), subtys),
let {bounds, params} = mk_ty_params(tcx, tps);
let t = ty::mk_named(tcx, ty::mk_tag(tcx, local_def(it.id), params),
@it.ident);
let tpt = {kinds: ty_param_kinds(tps), ty: t};
let tpt = {bounds: bounds, ty: t};
tcx.tcache.insert(local_def(it.id), tpt);
ret tpt;
}
ast::item_iface(tps, ms) {
let {bounds, params} = mk_ty_params(tcx, tps);
let t = ty::mk_named(tcx, ty::mk_iface(tcx, local_def(it.id),
mk_ty_params(tcx, tps)),
params),
@it.ident);
let tpt = {kinds: ty_param_kinds(tps), ty: t};
let tpt = {bounds: bounds, ty: t};
tcx.tcache.insert(local_def(it.id), tpt);
ty::store_iface_methods(tcx, it.id, @vec::map(ms, {|m|
ty_of_ty_method(tcx, m_collect, m)
......@@ -438,7 +443,7 @@ fn ty_of_item(tcx: ty::ctxt, mode: mode, it: @ast::item)
}
}
fn ty_of_native_item(tcx: ty::ctxt, mode: mode, it: @ast::native_item)
-> ty::ty_param_kinds_and_ty {
-> ty::ty_param_bounds_and_ty {
alt it.node {
ast::native_item_fn(fn_decl, params) {
ret ty_of_native_fn_decl(tcx, mode, fn_decl, params,
......@@ -450,7 +455,7 @@ fn ty_of_native_item(tcx: ty::ctxt, mode: mode, it: @ast::native_item)
none. { }
}
let t = ty::mk_native(tcx, ast_util::local_def(it.id));
let tpt = {kinds: [], ty: t};
let tpt = {bounds: [], ty: t};
tcx.tcache.insert(local_def(it.id), tpt);
ret tpt;
}
......@@ -474,43 +479,69 @@ fn ty_of_fn_decl(tcx: ty::ctxt, mode: mode, decl: ast::fn_decl) -> ty::fn_ty {
}
fn ty_of_fn(tcx: ty::ctxt, mode: mode, decl: ast::fn_decl,
ty_params: [ast::ty_param], def_id: ast::def_id)
-> ty::ty_param_kinds_and_ty {
let tpt = {kinds: ty_param_kinds(ty_params),
-> ty::ty_param_bounds_and_ty {
let tpt = {bounds: ty_param_bounds(tcx, mode, ty_params),
ty: ty::mk_fn(tcx, ty_of_fn_decl(tcx, mode, decl))};
tcx.tcache.insert(def_id, tpt);
ret tpt;
}
fn ty_of_native_fn_decl(tcx: ty::ctxt, mode: mode, decl: ast::fn_decl,
ty_params: [ast::ty_param], def_id: ast::def_id)
-> ty::ty_param_kinds_and_ty {
let input_tys = [];
-> ty::ty_param_bounds_and_ty {
let input_tys = [], bounds = ty_param_bounds(tcx, mode, ty_params);
for a: ast::arg in decl.inputs { input_tys += [ty_of_arg(tcx, mode, a)]; }
let output_ty = ast_ty_to_ty(tcx, mode, decl.output);
let t_fn = ty::mk_native_fn(tcx, input_tys, output_ty);
let tpt = {kinds: ty_param_kinds(ty_params), ty: t_fn};
let tpt = {bounds: bounds, ty: t_fn};
tcx.tcache.insert(def_id, tpt);
ret tpt;
}
fn ty_param_bounds(tcx: ty::ctxt, mode: mode, params: [ast::ty_param])
-> [@[ty::param_bound]] {
let result = [];
for param in params {
result += [alt tcx.ty_param_bounds.find(local_def(param.id)) {
some(bs) { bs }
none. {
let bounds = [];
for b in *param.bounds {
bounds += [alt b {
ast::bound_send. { ty::bound_send }
ast::bound_copy. { ty::bound_copy }
ast::bound_iface(ifc) {
ty::bound_iface(ast_ty_to_ty(tcx, mode, ifc))
}
}];
}
let boxed = @bounds;
tcx.ty_param_bounds.insert(local_def(param.id), boxed);
boxed
}
}];
}
result
}
fn ty_of_method(tcx: ty::ctxt, mode: mode, m: @ast::method) -> ty::method {
{ident: m.ident, tps: vec::map(m.tps, {|tp| tp.kind}),
{ident: m.ident, tps: ty_param_bounds(tcx, mode, m.tps),
fty: ty_of_fn_decl(tcx, mode, m.decl)}
}
fn ty_of_ty_method(tcx: ty::ctxt, mode: mode, m: ast::ty_method)
-> ty::method {
{ident: m.ident, tps: vec::map(m.tps, {|tp| tp.kind}),
{ident: m.ident, tps: ty_param_bounds(tcx, mode, m.tps),
fty: ty_of_fn_decl(tcx, mode, m.decl)}
}
fn ty_of_obj(tcx: ty::ctxt, mode: mode, id: ast::ident, ob: ast::_obj,
ty_params: [ast::ty_param]) -> ty::ty_param_kinds_and_ty {
ty_params: [ast::ty_param]) -> ty::ty_param_bounds_and_ty {
let bounds = ty_param_bounds(tcx, mode, ty_params);
let methods = vec::map(ob.methods, {|m| ty_of_method(tcx, mode, m)});
let t_obj = ty::mk_named(tcx, ty::mk_obj(tcx, ty::sort_methods(methods)),
@id);
ret {kinds: ty_param_kinds(ty_params), ty: t_obj};
ret {bounds: bounds, ty: t_obj};
}
fn ty_of_obj_ctor(tcx: ty::ctxt, mode: mode, id: ast::ident, ob: ast::_obj,
ctor_id: ast::node_id, ty_params: [ast::ty_param])
-> ty::ty_param_kinds_and_ty {
-> ty::ty_param_bounds_and_ty {
let t_obj = ty_of_obj(tcx, mode, id, ob, ty_params);
let t_inputs: [arg] = [];
for f: ast::obj_field in ob.fields {
......@@ -520,7 +551,7 @@ fn ty_of_obj_ctor(tcx: ty::ctxt, mode: mode, id: ast::ident, ob: ast::_obj,
let t_fn = ty::mk_fn(tcx, {proto: ast::proto_shared(ast::sugar_normal),
inputs: t_inputs, output: t_obj.ty,
ret_style: ast::return_val, constraints: []});
let tpt = {kinds: ty_param_kinds(ty_params), ty: t_fn};
let tpt = {bounds: ty_param_bounds(tcx, mode, ty_params), ty: t_fn};
tcx.tcache.insert(local_def(ctor_id), tpt);
ret tpt;
}
......@@ -588,20 +619,15 @@ fn bot_ty(tcx: ty::ctxt, node_id: ast::node_id) {
}
}
fn mk_ty_params(tcx: ty::ctxt, atps: [ast::ty_param]) -> [ty::t] {
let tps = [];
let i = 0u;
for atp: ast::ty_param in atps {
tps += [ty::mk_param(tcx, i, ty_param_kind(atp))];
i += 1u;
}
ret tps;
}
fn ty_param_kinds(tps: [ast::ty_param]) -> [ast::kind] {
let k: [ast::kind] = [];
for p: ast::ty_param in tps { k += [ty_param_kind(p)]; }
ret k;
fn mk_ty_params(tcx: ty::ctxt, atps: [ast::ty_param])
-> {bounds: [@[ty::param_bound]], params: [ty::t]} {
let i = 0u, bounds = ty_param_bounds(tcx, m_collect, atps);
{bounds: bounds,
params: vec::map(atps, {|_atp|
let t = ty::mk_param(tcx, i, bounds[i]);
i += 1u;
t
})}
}
// Item collection - a pair of bootstrap passes:
......@@ -646,7 +672,8 @@ fn get_tag_variant_types(cx: @ctxt, tag_ty: ty::t,
inputs: args, output: tag_ty,
ret_style: ast::return_val, constraints: []})
};
let tpt = {kinds: ty_param_kinds(ty_params), ty: result_ty};
let tpt = {bounds: ty_param_bounds(cx.tcx, m_collect, ty_params),
ty: result_ty};
cx.tcx.tcache.insert(local_def(variant.node.id), tpt);
write::ty_only(cx.tcx, variant.node.id, result_ty);
}
......@@ -660,13 +687,14 @@ fn convert(cx: @ctxt, it: @ast::item) {
write::ty_only(cx.tcx, it.id, tpt.ty);
get_tag_variant_types(cx, tpt.ty, variants, ty_params);
}
ast::item_impl(_, _, selfty, ms) {
ast::item_impl(tps, _, selfty, ms) {
ty_param_bounds(cx.tcx, m_collect, tps);
for m in ms {
let bounds = ty_param_bounds(cx.tcx, m_collect, m.tps);
let ty = ty::mk_fn(cx.tcx, ty_of_fn_decl(cx.tcx, m_collect,
m.decl));
cx.tcx.tcache.insert(local_def(m.id),
{kinds: ty_param_kinds(m.tps),
ty: ty});
cx.tcx.tcache.insert(local_def(m.id), {bounds: bounds,
ty: ty});
write::ty_only(cx.tcx, m.id, ty);
}
write::ty_only(cx.tcx, it.id, ast_ty_to_ty(cx.tcx, m_collect,
......@@ -705,10 +733,10 @@ fn convert(cx: @ctxt, it: @ast::item) {
}
}
ast::item_res(decl, tps, _, dtor_id, ctor_id) {
let {bounds, params} = mk_ty_params(cx.tcx, tps);
let t_arg = ty_of_arg(cx.tcx, m_collect, decl.inputs[0]);
let t_res =
ty::mk_res(cx.tcx, local_def(it.id), t_arg.ty,
mk_ty_params(cx.tcx, tps));
let t_res = ty::mk_res(cx.tcx, local_def(it.id), t_arg.ty,
params);
let t_ctor = ty::mk_fn(cx.tcx, {
proto: ast::proto_shared(ast::sugar_normal),
inputs: [{mode: ast::by_copy with t_arg}],
......@@ -723,7 +751,8 @@ fn convert(cx: @ctxt, it: @ast::item) {
write::ty_only(cx.tcx, it.id, t_res);
write::ty_only(cx.tcx, ctor_id, t_ctor);
cx.tcx.tcache.insert(local_def(ctor_id),
{kinds: ty_param_kinds(tps), ty: t_ctor});
{bounds: bounds,
ty: t_ctor});
write::ty_only(cx.tcx, dtor_id, t_dtor);
}
_ {
......@@ -1449,7 +1478,7 @@ fn lookup_method(fcx: @fn_ctxt, isc: resolve::iscopes,
}
} else {
let tpt = csearch::get_type(fcx.ccx.tcx, did);
(vec::len(tpt.kinds), tpt.ty)
(vec::len(tpt.bounds), tpt.ty)
};
let {ids, ty: self_ty} = if n_tps > 0u {
bind_params_in_type(ast_util::dummy_sp(), fcx.ccx.tcx,
......@@ -1782,7 +1811,7 @@ fn check_binop_type_compat(fcx: @fn_ctxt, span: span, ty: ty::t,
ast::expr_path(pth) {
let defn = lookup_def(fcx, pth.span, id);
let tpt = ty_param_kinds_and_ty_for_def(fcx, expr.span, defn);
let tpt = ty_param_bounds_and_ty_for_def(fcx, expr.span, defn);
if ty::def_has_ty_params(defn) {
let path_tpot = instantiate_path(fcx, pth, tpt, expr.span);
write::ty_fixup(fcx, id, path_tpot);
......
......@@ -24,7 +24,13 @@
const local_crate: crate_num = 0;
const crate_node_id: node_id = 0;
type ty_param = {ident: ident, kind: kind};
tag ty_param_bound {
bound_copy;
bound_send;
bound_iface(@ty);
}
type ty_param = {ident: ident, id: node_id, bounds: @[ty_param_bound]};
tag def {
def_fn(def_id, purity);
......@@ -37,7 +43,7 @@
def_local(def_id, let_style);
def_variant(def_id /* tag */, def_id /* variant */);
def_ty(def_id);
def_ty_param(uint, kind);
def_ty_param(def_id, uint);
def_binding(def_id);
def_use(def_id);
def_native_ty(def_id);
......
......@@ -25,22 +25,11 @@ fn variant_def_ids(d: def) -> {tg: def_id, var: def_id} {
fn def_id_of_def(d: def) -> def_id {
alt d {
def_fn(id, _) { ret id; }
def_obj_field(id, _) { ret id; }
def_self(id) { ret id; }
def_mod(id) { ret id; }
def_native_mod(id) { ret id; }
def_const(id) { ret id; }
def_arg(id, _) { ret id; }
def_local(id, _) { ret id; }
def_variant(_, id) { ret id; }
def_ty(id) { ret id; }
def_ty_param(_, _) { fail; }
def_binding(id) { ret id; }
def_use(id) { ret id; }
def_native_ty(id) { ret id; }
def_native_fn(id, _) { ret id; }
def_upvar(id, _, _) { ret id; }
def_fn(id, _) | def_obj_field(id, _) | def_self(id) | def_mod(id) |
def_native_mod(id) | def_const(id) | def_arg(id, _) | def_local(id, _) |
def_variant(_, id) | def_ty(id) | def_ty_param(id, _) |
def_binding(id) | def_use(id) | def_native_ty(id) |
def_native_fn(id, _) | def_upvar(id, _, _) { id }
}
}
......@@ -247,8 +236,6 @@ fn ternary_to_if(e: @expr) -> @expr {
}
}
fn ty_param_kind(tp: ty_param) -> kind { tp.kind }
// FIXME this doesn't handle big integer/float literals correctly (nor does
// the rest of our literal handling)
tag const_val {
......
......@@ -1718,10 +1718,18 @@ fn parse_block_tail(p: parser, lo: uint, s: ast::blk_check_mode) -> ast::blk {
}
fn parse_ty_param(p: parser) -> ast::ty_param {
let k = if eat_word(p, "send") { ast::kind_sendable }
else if eat_word(p, "copy") { ast::kind_copyable }
else { ast::kind_noncopyable };
ret {ident: parse_ident(p), kind: k};
let bounds = [];
if eat_word(p, "send") { bounds += [ast::bound_send]; }
else if eat_word(p, "copy") { bounds += [ast::bound_copy]; }
let ident = parse_ident(p);
if eat(p, token::COLON) {
while p.peek() != token::COMMA && p.peek() != token::GT {
if eat_word(p, "send") { bounds += [ast::bound_send]; }
else if eat_word(p, "copy") { bounds += [ast::bound_copy]; }
else { bounds += [ast::bound_iface(parse_ty(p, false))]; }
}
}
ret {ident: ident, id: p.get_id(), bounds: @bounds};
}
fn parse_ty_params(p: parser) -> [ast::ty_param] {
......@@ -1856,7 +1864,8 @@ fn wrap_path(p: parser, pt: @ast::path) -> @ast::ty {
ast::ty_path(pt, _) {
if vec::len(pt.node.idents) == 1u &&
vec::len(pt.node.types) == 0u {
ret {ident: pt.node.idents[0], kind: ast::kind_sendable};
ret {ident: pt.node.idents[0], id: p.get_id(),
bounds: @[]};
}
}
_ {}
......
......@@ -1204,11 +1204,17 @@ fn print_arg_mode(s: ps, m: ast::mode) {
}
}
fn print_kind(s: ps, kind: ast::kind) {
alt kind {
ast::kind_sendable. { word_nbsp(s, "send"); }
ast::kind_copyable. { word_nbsp(s, "copy"); }
ast::kind_noncopyable. {}
fn print_bounds(s: ps, bounds: @[ast::ty_param_bound]) {
if vec::len(*bounds) > 0u {
word(s.s, ":");
for bound in *bounds {
nbsp(s);
alt bound {
ast::bound_copy. { word(s.s, "copy"); }
ast::bound_send. { word(s.s, "send"); }
ast::bound_iface(t) { print_type(s, t); }
}
}
}
}
......@@ -1216,8 +1222,8 @@ fn print_type_params(s: ps, params: [ast::ty_param]) {
if vec::len(params) > 0u {
word(s.s, "<");
fn printParam(s: ps, param: ast::ty_param) {
print_kind(s, param.kind);
word(s.s, param.ident);
print_bounds(s, param.bounds);
}
commasep(s, inconsistent, params, printParam);
word(s.s, ">");
......
......@@ -92,24 +92,27 @@ fn visit_item<E>(i: @item, e: E, v: vt<E>) {
for vi: @view_item in nm.view_items { v.visit_view_item(vi, e, v); }
for ni: @native_item in nm.items { v.visit_native_item(ni, e, v); }
}
item_ty(t, _) { v.visit_ty(t, e, v); }
item_ty(t, tps) { v.visit_ty(t, e, v); visit_ty_params(tps, e, v); }
item_res(decl, tps, body, dtor_id, _) {
v.visit_fn(decl, tps, body, i.span, some(i.ident), dtor_id,
e, v);
}
item_tag(variants, _) {
item_tag(variants, tps) {
visit_ty_params(tps, e, v);
for vr: variant in variants {
for va: variant_arg in vr.node.args { v.visit_ty(va.ty, e, v); }
}
}
item_obj(ob, _, _) {
item_obj(ob, tps, _) {
visit_ty_params(tps, e, v);
for f: obj_field in ob.fields { v.visit_ty(f.ty, e, v); }
for m: @method in ob.methods {
v.visit_fn(m.decl, m.tps, m.body, m.span,
some(m.ident), m.id, e, v);
}
}
item_impl(_, ifce, ty, methods) {
item_impl(tps, ifce, ty, methods) {
visit_ty_params(tps, e, v);
alt ifce { some(ty) { v.visit_ty(ty, e, v); } _ {} }
v.visit_ty(ty, e, v);
for m in methods {
......@@ -117,7 +120,8 @@ fn visit_item<E>(i: @item, e: E, v: vt<E>) {
some(m.ident), m.id, e, v);
}
}
item_iface(_, methods) {
item_iface(tps, methods) {
visit_ty_params(tps, e, v);
for m in methods {
for a in m.decl.inputs { v.visit_ty(a.ty, e, v); }
v.visit_ty(m.decl.output, e, v);
......@@ -191,11 +195,25 @@ fn visit_pat<E>(p: @pat, e: E, v: vt<E>) {
fn visit_native_item<E>(ni: @native_item, e: E, v: vt<E>) {
alt ni.node {
native_item_fn(fd, _) { visit_fn_decl(fd, e, v); }
native_item_fn(fd, tps) {
visit_ty_params(tps, e, v);
visit_fn_decl(fd, e, v);
}
native_item_ty. { }
}
}
fn visit_ty_params<E>(tps: [ty_param], e: E, v: vt<E>) {
for tp in tps {
for bound in *tp.bounds {
alt bound {
bound_iface(t) { v.visit_ty(t, e, v); }
_ {}
}
}
}
}
fn visit_fn_decl<E>(fd: fn_decl, e: E, v: vt<E>) {
for a: arg in fd.inputs { v.visit_ty(a.ty, e, v); }
for c: @constr in fd.constraints {
......@@ -204,9 +222,10 @@ fn visit_fn_decl<E>(fd: fn_decl, e: E, v: vt<E>) {
v.visit_ty(fd.output, e, v);
}
fn visit_fn<E>(decl: fn_decl, _tp: [ty_param], body: blk, _sp: span,
fn visit_fn<E>(decl: fn_decl, tp: [ty_param], body: blk, _sp: span,
_i: fn_ident, _id: node_id, e: E, v: vt<E>) {
visit_fn_decl(decl, e, v);
visit_ty_params(tp, e, v);
v.visit_block(body, e, v);
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册