parent
7ea175f23f
commit
40d5f288c3
@ -129,11 +129,8 @@ fn item_ty_param_bounds(item: ebml::doc, this_cnum: ast::crate_num,
|
||||
|
||||
fn item_ty_param_count(item: ebml::doc) -> uint {
|
||||
let n = 0u;
|
||||
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; }
|
||||
}
|
||||
}
|
||||
ebml::tagged_docs(item, tag_items_data_item_ty_param_bounds,
|
||||
{|_p| n += 1u; });
|
||||
n
|
||||
}
|
||||
|
||||
|
@ -202,9 +202,17 @@ fn parse_ty(st: @pstate, sd: str_def) -> ty::t {
|
||||
st.pos = st.pos + 1u;
|
||||
ret ty::mk_tag(st.tcx, def, params);
|
||||
}
|
||||
'x' {
|
||||
assert (next(st) as char == '[');
|
||||
let def = parse_def(st, sd);
|
||||
let params: [ty::t] = [];
|
||||
while peek(st) as char != ']' { params += [parse_ty(st, sd)]; }
|
||||
st.pos = st.pos + 1u;
|
||||
ret ty::mk_iface(st.tcx, def, params);
|
||||
}
|
||||
'p' {
|
||||
let bounds = parse_bounds(st, sd);
|
||||
ret ty::mk_param(st.tcx, parse_int(st) as uint, bounds);
|
||||
let did = parse_def(st, sd);
|
||||
ret ty::mk_param(st.tcx, parse_int(st) as uint, did);
|
||||
}
|
||||
'@' { ret ty::mk_box(st.tcx, parse_mt(st, sd)); }
|
||||
'~' { ret ty::mk_uniq(st.tcx, parse_mt(st, sd)); }
|
||||
@ -401,8 +409,7 @@ fn parse_bounds_data(data: @[u8], crate_num: int, sd: str_def, tcx: ty::ctxt)
|
||||
|
||||
fn parse_bounds(st: @pstate, sd: str_def) -> @[ty::param_bound] {
|
||||
let bounds = [];
|
||||
while peek(st) as char == '.' {
|
||||
next(st);
|
||||
while peek(st) != 0u8 {
|
||||
bounds += [alt next(st) as char {
|
||||
'S' { ty::bound_send }
|
||||
'C' { ty::bound_copy }
|
||||
|
@ -126,6 +126,13 @@ fn enc_sty(w: io::writer, cx: @ctxt, st: ty::sty) {
|
||||
for t: ty::t in tys { enc_ty(w, cx, t); }
|
||||
w.write_char(']');
|
||||
}
|
||||
ty::ty_iface(def, tys) {
|
||||
w.write_str("x[");
|
||||
w.write_str(cx.ds(def));
|
||||
w.write_char('|');
|
||||
for t: ty::t in tys { enc_ty(w, cx, t); }
|
||||
w.write_char(']');
|
||||
}
|
||||
ty::ty_tup(ts) {
|
||||
w.write_str("T[");
|
||||
for t in ts { enc_ty(w, cx, t); }
|
||||
@ -176,9 +183,10 @@ fn enc_sty(w: io::writer, cx: @ctxt, st: ty::sty) {
|
||||
w.write_str(cx.ds(def));
|
||||
w.write_char('|');
|
||||
}
|
||||
ty::ty_param(id, bounds) {
|
||||
ty::ty_param(id, did) {
|
||||
w.write_char('p');
|
||||
enc_bounds(w, cx, bounds);
|
||||
w.write_str(cx.ds(did));
|
||||
w.write_char('|');
|
||||
w.write_str(uint::str(id));
|
||||
}
|
||||
ty::ty_type. { w.write_char('Y'); }
|
||||
@ -265,7 +273,6 @@ fn enc_ty_constr(w: io::writer, cx: @ctxt, c: @ty::type_constr) {
|
||||
|
||||
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'); }
|
||||
|
@ -4658,7 +4658,8 @@ 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, @[])];
|
||||
ty_param_substs += [ty::mk_param(ccx.tcx, i,
|
||||
ast_util::local_def(tp.id))];
|
||||
i += 1u;
|
||||
}
|
||||
let arg_tys = arg_tys_of_fn(ccx, variant.node.id);
|
||||
|
@ -218,7 +218,7 @@ type ctxt =
|
||||
needs_drop_cache: hashmap<t, bool>,
|
||||
kind_cache: hashmap<t, kind>,
|
||||
ast_ty_to_ty_cache: hashmap<@ast::ty, option::t<t>>,
|
||||
tag_var_cache: hashmap<ast::def_id, @[variant_info]>,
|
||||
tag_var_cache: hashmap<def_id, @[variant_info]>,
|
||||
iface_method_cache: hashmap<def_id, @[method]>,
|
||||
ty_param_bounds: hashmap<def_id, @[param_bound]>};
|
||||
|
||||
@ -268,7 +268,7 @@ tag sty {
|
||||
ty_tup([t]);
|
||||
ty_var(int); // type variable
|
||||
|
||||
ty_param(uint, @[param_bound]); // fn/tag type param
|
||||
ty_param(uint, def_id); // fn/tag type param
|
||||
|
||||
ty_type; // type_desc*
|
||||
ty_send_type; // type_desc* that has been cloned into exchange heap
|
||||
@ -624,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: @[param_bound]) -> t {
|
||||
fn mk_param(cx: ctxt, n: uint, k: def_id) -> t {
|
||||
ret gen_ty(cx, ty_param(n, k));
|
||||
}
|
||||
|
||||
@ -722,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, @[param_bound]) -> t);
|
||||
fm_param(fn@(uint, def_id) -> t);
|
||||
fm_general(fn@(t) -> t);
|
||||
}
|
||||
|
||||
@ -813,8 +813,8 @@ fn fold_ty(cx: ctxt, fld: fold_mode, ty_0: t) -> t {
|
||||
ty_var(id) {
|
||||
alt fld { fm_var(folder) { ty = folder(id); } _ {/* no-op */ } }
|
||||
}
|
||||
ty_param(id, k) {
|
||||
alt fld { fm_param(folder) { ty = folder(id, k); } _ {/* no-op */ } }
|
||||
ty_param(id, did) {
|
||||
alt fld { fm_param(folder) { ty = folder(id, did); } _ {/* no-op */ } }
|
||||
}
|
||||
}
|
||||
|
||||
@ -1083,7 +1083,7 @@ fn type_kind(cx: ctxt, ty: t) -> kind {
|
||||
}
|
||||
// Resources are always noncopyable.
|
||||
ty_res(did, inner, tps) { kind_noncopyable }
|
||||
ty_param(_, bounds) { param_bounds_to_kind(bounds) }
|
||||
ty_param(_, did) { param_bounds_to_kind(cx.ty_param_bounds.get(did)) }
|
||||
ty_constr(t, _) { type_kind(cx, t) }
|
||||
};
|
||||
|
||||
@ -1131,7 +1131,7 @@ fn type_structurally_contains(cx: ctxt, ty: t, test: fn(sty) -> bool) ->
|
||||
}
|
||||
}
|
||||
|
||||
pure fn type_has_dynamic_size(cx: ctxt, ty: t) -> bool {
|
||||
pure fn type_has_dynamic_size(cx: ctxt, ty: t) -> bool unchecked {
|
||||
|
||||
/* type_structurally_contains can't be declared pure
|
||||
because it takes a function argument. But it should be
|
||||
@ -1141,15 +1141,9 @@ pure fn type_has_dynamic_size(cx: ctxt, ty: t) -> bool {
|
||||
actually checkable. It seems to me like a lot of properties
|
||||
that the type context tracks about types should be immutable.)
|
||||
*/
|
||||
unchecked{
|
||||
type_structurally_contains(cx, ty,
|
||||
fn (sty: sty) -> bool {
|
||||
ret alt sty {
|
||||
ty_param(_, _) { true }
|
||||
_ { false }
|
||||
};
|
||||
})
|
||||
}
|
||||
type_structurally_contains(cx, ty, fn (sty: sty) -> bool {
|
||||
alt sty { ty_param(_, _) { true } _ { false }}
|
||||
})
|
||||
}
|
||||
|
||||
// Returns true for noncopyable types and types where a copy of a value can be
|
||||
@ -2205,7 +2199,14 @@ mod unify {
|
||||
_ { ret ures_err(terr_mismatch); }
|
||||
}
|
||||
}
|
||||
ty::ty_param(_, _) { ret struct_cmp(cx, expected, actual); }
|
||||
ty::ty_param(expected_n, _) {
|
||||
alt struct(cx.tcx, actual) {
|
||||
ty::ty_param(actual_n, _) when expected_n == actual_n {
|
||||
ret ures_ok(expected);
|
||||
}
|
||||
_ { ret ures_err(terr_mismatch); }
|
||||
}
|
||||
}
|
||||
ty::ty_tag(expected_id, expected_tps) {
|
||||
alt struct(cx.tcx, actual) {
|
||||
ty::ty_tag(actual_id, actual_tps) {
|
||||
@ -2627,8 +2628,7 @@ fn bind_params_in_type(sp: span, cx: ctxt, next_ty_var: fn@() -> int, typ: t,
|
||||
let i = 0u;
|
||||
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,
|
||||
_bounds: @[param_bound]) -> t {
|
||||
_next_ty_var: fn@() -> int, index: uint, _did: def_id) -> t {
|
||||
if index < vec::len(*param_var_ids) {
|
||||
ret mk_var(cx, param_var_ids[index]);
|
||||
} else {
|
||||
@ -2647,9 +2647,8 @@ fn bind_params_in_type(sp: span, cx: ctxt, next_ty_var: fn@() -> int, typ: t,
|
||||
// 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,
|
||||
_bounds: @[param_bound])
|
||||
-> t {
|
||||
fn substituter(_cx: ctxt, substs: @[ty::t], idx: uint, _did: def_id)
|
||||
-> t {
|
||||
// FIXME: bounds check can fail
|
||||
ret substs[idx];
|
||||
}
|
||||
|
@ -343,7 +343,7 @@ fn ast_ty_to_ty(tcx: ty::ctxt, mode: mode, &&ast_ty: @ast::ty) -> ty::t {
|
||||
}
|
||||
some(ast::def_native_ty(id)) { typ = getter(tcx, mode, id).ty; }
|
||||
some(ast::def_ty_param(id, n)) {
|
||||
typ = ty::mk_param(tcx, n, tcx.ty_param_bounds.get(id));
|
||||
typ = ty::mk_param(tcx, n, id);
|
||||
}
|
||||
some(_) {
|
||||
tcx.sess.span_fatal(ast_ty.span,
|
||||
@ -625,8 +625,8 @@ 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]);
|
||||
params: vec::map(atps, {|atp|
|
||||
let t = ty::mk_param(tcx, i, local_def(atp.id));
|
||||
i += 1u;
|
||||
t
|
||||
})}
|
||||
@ -2666,13 +2666,16 @@ fn check_method(ccx: @crate_ctxt, method: @ast::method) {
|
||||
fn check_item(ccx: @crate_ctxt, it: @ast::item) {
|
||||
alt it.node {
|
||||
ast::item_const(_, e) { check_const(ccx, it.span, e, it.id); }
|
||||
ast::item_fn(decl, _, body) {
|
||||
ast::item_fn(decl, tps, body) {
|
||||
check_ty_params(ccx, tps);
|
||||
check_fn(ccx, ast::proto_bare, decl, body, it.id, none);
|
||||
}
|
||||
ast::item_res(decl, _, body, dtor_id, _) {
|
||||
ast::item_res(decl, tps, body, dtor_id, _) {
|
||||
check_ty_params(ccx, tps);
|
||||
check_fn(ccx, ast::proto_bare, decl, body, dtor_id, none);
|
||||
}
|
||||
ast::item_obj(ob, _, _) {
|
||||
ast::item_obj(ob, tps, _) {
|
||||
check_ty_params(ccx, tps);
|
||||
// We're entering an object, so gather up the info we need.
|
||||
ccx.self_infos += [self_obj(ob.fields,
|
||||
ccx.tcx.tcache.get(local_def(it.id)).ty)];
|
||||
@ -2681,9 +2684,11 @@ fn check_item(ccx: @crate_ctxt, it: @ast::item) {
|
||||
// Now remove the info from the stack.
|
||||
vec::pop(ccx.self_infos);
|
||||
}
|
||||
ast::item_impl(_, ifce, ty, ms) {
|
||||
ast::item_impl(tps, ifce, ty, ms) {
|
||||
check_ty_params(ccx, tps);
|
||||
ccx.self_infos += [self_impl(ast_ty_to_ty(ccx.tcx, m_check, ty))];
|
||||
let my_methods = vec::map(ms, {|m|
|
||||
check_ty_params(ccx, m.tps);
|
||||
check_method(ccx, m);
|
||||
ty_of_method(ccx.tcx, m_check, m)
|
||||
});
|
||||
@ -2717,10 +2722,43 @@ fn check_item(ccx: @crate_ctxt, it: @ast::item) {
|
||||
_ {}
|
||||
}
|
||||
}
|
||||
ast::item_iface(tps, _) | ast::item_ty(_, tps) | ast::item_tag(_, tps) {
|
||||
check_ty_params(ccx, tps);
|
||||
}
|
||||
_ {/* nothing to do */ }
|
||||
}
|
||||
}
|
||||
|
||||
fn check_native_item(ccx: @crate_ctxt, it: @ast::native_item) {
|
||||
alt it.node {
|
||||
ast::native_item_fn(_, tps) { check_ty_params(ccx, tps); }
|
||||
_ {}
|
||||
}
|
||||
}
|
||||
|
||||
fn check_ty_params(ccx: @crate_ctxt, tps: [ast::ty_param]) {
|
||||
for tp in tps {
|
||||
let i = 0u;
|
||||
for bound in *tp.bounds {
|
||||
alt bound {
|
||||
ast::bound_iface(at) {
|
||||
let tbound = ccx.tcx.ty_param_bounds.get(local_def(tp.id))[i];
|
||||
let bound_ty = alt tbound { ty::bound_iface(t) { t } };
|
||||
alt ty::struct(ccx.tcx, bound_ty) {
|
||||
ty::ty_iface(_, _) {}
|
||||
_ {
|
||||
ccx.tcx.sess.span_err(at.span, "type parameter bounds \
|
||||
must be interface types");
|
||||
}
|
||||
}
|
||||
}
|
||||
_ {}
|
||||
}
|
||||
i += 1u;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn arg_is_argv_ty(tcx: ty::ctxt, a: ty::arg) -> bool {
|
||||
alt ty::struct(tcx, a.ty) {
|
||||
ty::ty_vec(mt) {
|
||||
@ -2778,8 +2816,10 @@ fn check_crate(tcx: ty::ctxt, impl_map: resolve::impl_map,
|
||||
method_map: std::map::new_int_hash(),
|
||||
tcx: tcx};
|
||||
let visit =
|
||||
visit::mk_simple_visitor(@{visit_item: bind check_item(ccx, _)
|
||||
with *visit::default_simple_visitor()});
|
||||
visit::mk_simple_visitor(@{visit_item: bind check_item(ccx, _),
|
||||
visit_native_item:
|
||||
bind check_native_item(ccx, _)
|
||||
with *visit::default_simple_visitor()});
|
||||
visit::visit_crate(*crate, (), visit);
|
||||
check_for_main_fn(tcx, crate);
|
||||
tcx.sess.abort_if_errors();
|
||||
|
Loading…
Reference in New Issue
Block a user