2011-06-15 13:19:50 -05:00
|
|
|
|
2011-05-19 18:06:23 -05:00
|
|
|
import std::int;
|
2011-05-17 13:41:41 -05:00
|
|
|
import std::str;
|
|
|
|
import std::uint;
|
|
|
|
import std::vec;
|
2011-05-12 10:24:54 -05:00
|
|
|
import std::box;
|
|
|
|
import std::ufind;
|
|
|
|
import std::map;
|
|
|
|
import std::map::hashmap;
|
|
|
|
import std::option;
|
|
|
|
import std::option::none;
|
|
|
|
import std::option::some;
|
2011-05-20 20:36:35 -05:00
|
|
|
import std::smallintmap;
|
2011-05-12 10:24:54 -05:00
|
|
|
import driver::session;
|
|
|
|
import front::ast;
|
2011-06-15 17:14:30 -05:00
|
|
|
import front::ast::def_id;
|
|
|
|
import front::ast::constr_arg_general;
|
2011-05-12 10:24:54 -05:00
|
|
|
import front::ast::mutability;
|
2011-05-20 16:15:39 -05:00
|
|
|
import front::ast::controlflow;
|
2011-05-12 10:24:54 -05:00
|
|
|
import front::creader;
|
|
|
|
import middle::metadata;
|
2011-06-15 17:14:30 -05:00
|
|
|
import util::common::*;
|
2011-05-20 15:57:09 -05:00
|
|
|
import util::data::interner;
|
2011-05-16 15:58:13 -05:00
|
|
|
|
2010-12-21 14:13:51 -06:00
|
|
|
|
2011-06-15 13:19:50 -05:00
|
|
|
// Data types
|
|
|
|
tag mode { mo_val; mo_alias(bool); }
|
2011-05-09 14:27:03 -05:00
|
|
|
|
|
|
|
type arg = rec(mode mode, t ty);
|
2011-06-15 13:19:50 -05:00
|
|
|
|
2011-05-12 10:24:54 -05:00
|
|
|
type field = rec(ast::ident ident, mt mt);
|
2011-06-15 13:19:50 -05:00
|
|
|
|
|
|
|
type method =
|
|
|
|
rec(ast::proto proto,
|
|
|
|
ast::ident ident,
|
|
|
|
vec[arg] inputs,
|
|
|
|
t output,
|
|
|
|
controlflow cf,
|
2011-06-15 17:14:30 -05:00
|
|
|
vec[@constr_def] constrs);
|
2010-12-21 14:13:51 -06:00
|
|
|
|
2011-05-19 19:21:21 -05:00
|
|
|
tag any_item {
|
|
|
|
any_item_rust(@ast::item);
|
|
|
|
any_item_native(@ast::native_item, ast::native_abi);
|
|
|
|
}
|
|
|
|
|
2011-06-15 13:19:50 -05:00
|
|
|
type item_table = hashmap[ast::def_id, any_item];
|
2011-06-16 18:55:46 -05:00
|
|
|
|
|
|
|
type constr_table = hashmap[ast::def_id, vec[constr_def]];
|
2011-05-19 19:21:21 -05:00
|
|
|
|
2011-05-12 10:24:54 -05:00
|
|
|
type mt = rec(t ty, ast::mutability mut);
|
2011-03-17 19:39:47 -05:00
|
|
|
|
2011-06-15 13:19:50 -05:00
|
|
|
|
2011-04-25 14:15:55 -05:00
|
|
|
// Contains information needed to resolve types and (in the future) look up
|
|
|
|
// the types of AST nodes.
|
2011-06-15 13:19:50 -05:00
|
|
|
type creader_cache = hashmap[tup(int, uint, uint), ty::t];
|
|
|
|
|
|
|
|
type ctxt =
|
|
|
|
rec(@type_store ts,
|
|
|
|
session::session sess,
|
|
|
|
resolve::def_map def_map,
|
|
|
|
node_type_table node_types,
|
|
|
|
item_table items, // Only contains type items
|
2011-06-16 18:55:46 -05:00
|
|
|
|
2011-06-15 17:14:30 -05:00
|
|
|
constr_table fn_constrs,
|
2011-06-15 13:19:50 -05:00
|
|
|
type_cache tcache,
|
|
|
|
creader_cache rcache,
|
|
|
|
hashmap[t, str] short_names_cache,
|
|
|
|
hashmap[@ast::ty, option::t[t]] ast_ty_to_ty_cache);
|
|
|
|
|
|
|
|
type ty_ctxt = ctxt;
|
|
|
|
|
2011-06-16 18:55:46 -05:00
|
|
|
|
|
|
|
// Needed for disambiguation from unify::ctxt.
|
|
|
|
// Convert from method type to function type. Pretty easy; we just drop
|
|
|
|
// 'ident'.
|
|
|
|
fn method_ty_to_fn_ty(&ctxt cx, method m) -> t {
|
|
|
|
ret mk_fn(cx, m.proto, m.inputs, m.output, m.cf, m.constrs);
|
|
|
|
}
|
|
|
|
|
2011-06-15 13:19:50 -05:00
|
|
|
|
2011-05-11 19:05:39 -05:00
|
|
|
// Never construct these manually. These are interned.
|
2011-04-20 12:51:41 -05:00
|
|
|
//
|
|
|
|
// TODO: It'd be really nice to be able to hide this definition from the
|
2011-04-22 14:08:23 -05:00
|
|
|
// outside world, to enforce the above invariants.
|
2011-06-15 13:19:50 -05:00
|
|
|
type raw_t =
|
|
|
|
rec(sty struct,
|
|
|
|
option::t[str] cname,
|
|
|
|
uint hash,
|
|
|
|
bool has_params,
|
|
|
|
bool has_vars);
|
2011-05-11 19:05:39 -05:00
|
|
|
|
|
|
|
type t = uint;
|
2011-04-20 12:51:41 -05:00
|
|
|
|
2011-06-15 13:19:50 -05:00
|
|
|
|
2010-12-21 14:13:51 -06:00
|
|
|
// NB: If you change this, you'll probably want to change the corresponding
|
2011-05-12 10:24:54 -05:00
|
|
|
// AST structure in front/ast::rs as well.
|
2010-12-21 14:13:51 -06:00
|
|
|
tag sty {
|
|
|
|
ty_nil;
|
2011-05-14 21:02:30 -05:00
|
|
|
ty_bot;
|
2010-12-21 14:13:51 -06:00
|
|
|
ty_bool;
|
|
|
|
ty_int;
|
2011-03-21 19:12:05 -05:00
|
|
|
ty_float;
|
2010-12-21 14:13:51 -06:00
|
|
|
ty_uint;
|
2011-06-15 17:14:30 -05:00
|
|
|
ty_machine(ty_mach);
|
2010-12-21 14:13:51 -06:00
|
|
|
ty_char;
|
|
|
|
ty_str;
|
2011-06-09 18:23:19 -05:00
|
|
|
ty_istr;
|
2011-06-15 17:14:30 -05:00
|
|
|
ty_tag(def_id, vec[t]);
|
2011-03-17 19:39:47 -05:00
|
|
|
ty_box(mt);
|
|
|
|
ty_vec(mt);
|
2011-06-09 18:23:19 -05:00
|
|
|
ty_ivec(mt);
|
2011-06-03 14:02:58 -05:00
|
|
|
ty_ptr(mt);
|
2011-04-22 14:27:28 -05:00
|
|
|
ty_port(t);
|
|
|
|
ty_chan(t);
|
2011-03-25 23:53:57 -05:00
|
|
|
ty_task;
|
2011-03-17 19:39:47 -05:00
|
|
|
ty_tup(vec[mt]);
|
2010-12-21 14:13:51 -06:00
|
|
|
ty_rec(vec[field]);
|
2011-06-15 17:14:30 -05:00
|
|
|
ty_fn(ast::proto, vec[arg], t, controlflow, vec[@constr_def]);
|
2011-05-12 10:24:54 -05:00
|
|
|
ty_native_fn(ast::native_abi, vec[arg], t);
|
2010-12-21 14:13:51 -06:00
|
|
|
ty_obj(vec[method]);
|
2011-06-15 13:19:50 -05:00
|
|
|
ty_var(int); // type variable
|
|
|
|
|
|
|
|
ty_param(uint); // fn/tag type param
|
|
|
|
|
2011-02-01 16:56:21 -06:00
|
|
|
ty_type;
|
2011-02-10 17:39:55 -06:00
|
|
|
ty_native;
|
2011-04-22 14:27:28 -05:00
|
|
|
// TODO: ty_fn_arg(t), for a possibly-aliased function argument
|
2011-06-15 13:19:50 -05:00
|
|
|
|
2010-12-21 14:13:51 -06:00
|
|
|
}
|
|
|
|
|
2011-06-15 17:14:30 -05:00
|
|
|
type constr_def = spanned[constr_general[uint]];
|
2011-06-16 18:55:46 -05:00
|
|
|
|
|
|
|
type constr_general[T] =
|
|
|
|
rec(path path, vec[@constr_arg_general[T]] args, def_id id);
|
|
|
|
|
2010-12-21 19:47:13 -06:00
|
|
|
|
2011-06-15 13:19:50 -05:00
|
|
|
// Data structures used in type unification
|
2010-12-21 19:47:13 -06:00
|
|
|
tag type_err {
|
|
|
|
terr_mismatch;
|
2011-05-20 16:15:39 -05:00
|
|
|
terr_controlflow_mismatch;
|
2011-03-17 19:39:47 -05:00
|
|
|
terr_box_mutability;
|
|
|
|
terr_vec_mutability;
|
2010-12-21 19:47:13 -06:00
|
|
|
terr_tuple_size(uint, uint);
|
|
|
|
terr_tuple_mutability;
|
|
|
|
terr_record_size(uint, uint);
|
|
|
|
terr_record_mutability;
|
2011-06-15 13:19:50 -05:00
|
|
|
terr_record_fields(ast::ident, ast::ident);
|
2010-12-31 12:26:29 -06:00
|
|
|
terr_meth_count;
|
2011-06-15 13:19:50 -05:00
|
|
|
terr_obj_meths(ast::ident, ast::ident);
|
2010-12-21 19:47:13 -06:00
|
|
|
terr_arg_count;
|
|
|
|
}
|
|
|
|
|
2011-04-22 14:27:28 -05:00
|
|
|
type ty_param_count_and_ty = tup(uint, t);
|
2011-06-15 13:19:50 -05:00
|
|
|
|
|
|
|
type type_cache = hashmap[ast::def_id, ty_param_count_and_ty];
|
|
|
|
|
|
|
|
const uint idx_nil = 0u;
|
|
|
|
|
|
|
|
const uint idx_bool = 1u;
|
|
|
|
|
|
|
|
const uint idx_int = 2u;
|
|
|
|
|
|
|
|
const uint idx_float = 3u;
|
|
|
|
|
|
|
|
const uint idx_uint = 4u;
|
|
|
|
|
|
|
|
const uint idx_i8 = 5u;
|
|
|
|
|
|
|
|
const uint idx_i16 = 6u;
|
|
|
|
|
|
|
|
const uint idx_i32 = 7u;
|
|
|
|
|
|
|
|
const uint idx_i64 = 8u;
|
|
|
|
|
|
|
|
const uint idx_u8 = 9u;
|
|
|
|
|
|
|
|
const uint idx_u16 = 10u;
|
|
|
|
|
|
|
|
const uint idx_u32 = 11u;
|
|
|
|
|
|
|
|
const uint idx_u64 = 12u;
|
|
|
|
|
|
|
|
const uint idx_f32 = 13u;
|
|
|
|
|
|
|
|
const uint idx_f64 = 14u;
|
|
|
|
|
|
|
|
const uint idx_char = 15u;
|
|
|
|
|
|
|
|
const uint idx_str = 16u;
|
|
|
|
|
|
|
|
const uint idx_istr = 17u;
|
|
|
|
|
|
|
|
const uint idx_task = 18u;
|
|
|
|
|
|
|
|
const uint idx_native = 19u;
|
|
|
|
|
|
|
|
const uint idx_type = 20u;
|
|
|
|
|
|
|
|
const uint idx_bot = 21u;
|
|
|
|
|
2011-06-09 18:23:19 -05:00
|
|
|
const uint idx_first_others = 22u;
|
2011-05-11 19:05:39 -05:00
|
|
|
|
2011-05-16 15:58:13 -05:00
|
|
|
type type_store = interner::interner[raw_t];
|
2011-04-20 20:52:04 -05:00
|
|
|
|
2011-05-13 14:12:54 -05:00
|
|
|
type ty_param_substs_opt_and_ty = tup(option::t[vec[ty::t]], ty::t);
|
2011-06-15 13:19:50 -05:00
|
|
|
|
2011-05-13 15:05:55 -05:00
|
|
|
type node_type_table =
|
|
|
|
@mutable vec[mutable option::t[ty::ty_param_substs_opt_and_ty]];
|
2011-05-12 18:36:47 -05:00
|
|
|
|
2011-05-19 19:21:21 -05:00
|
|
|
fn populate_type_store(&ctxt cx) {
|
|
|
|
intern(cx, ty_nil, none[str]);
|
|
|
|
intern(cx, ty_bool, none[str]);
|
|
|
|
intern(cx, ty_int, none[str]);
|
|
|
|
intern(cx, ty_float, none[str]);
|
|
|
|
intern(cx, ty_uint, none[str]);
|
|
|
|
intern(cx, ty_machine(ty_i8), none[str]);
|
|
|
|
intern(cx, ty_machine(ty_i16), none[str]);
|
|
|
|
intern(cx, ty_machine(ty_i32), none[str]);
|
|
|
|
intern(cx, ty_machine(ty_i64), none[str]);
|
|
|
|
intern(cx, ty_machine(ty_u8), none[str]);
|
|
|
|
intern(cx, ty_machine(ty_u16), none[str]);
|
|
|
|
intern(cx, ty_machine(ty_u32), none[str]);
|
|
|
|
intern(cx, ty_machine(ty_u64), none[str]);
|
|
|
|
intern(cx, ty_machine(ty_f32), none[str]);
|
|
|
|
intern(cx, ty_machine(ty_f64), none[str]);
|
|
|
|
intern(cx, ty_char, none[str]);
|
|
|
|
intern(cx, ty_str, none[str]);
|
2011-06-09 18:23:19 -05:00
|
|
|
intern(cx, ty_istr, none[str]);
|
2011-05-19 19:21:21 -05:00
|
|
|
intern(cx, ty_task, none[str]);
|
|
|
|
intern(cx, ty_native, none[str]);
|
|
|
|
intern(cx, ty_type, none[str]);
|
|
|
|
intern(cx, ty_bot, none[str]);
|
2011-06-15 13:19:50 -05:00
|
|
|
assert (vec::len(cx.ts.vect) == idx_first_others);
|
2011-04-20 20:52:04 -05:00
|
|
|
}
|
|
|
|
|
2011-04-29 10:26:28 -05:00
|
|
|
fn mk_rcache() -> creader_cache {
|
2011-06-15 13:19:50 -05:00
|
|
|
fn hash_cache_entry(&tup(int, uint, uint) k) -> uint {
|
2011-04-29 10:26:28 -05:00
|
|
|
ret (k._0 as uint) + k._1 + k._2;
|
|
|
|
}
|
2011-06-15 13:19:50 -05:00
|
|
|
fn eq_cache_entries(&tup(int, uint, uint) a, &tup(int, uint, uint) b) ->
|
|
|
|
bool {
|
|
|
|
ret a._0 == b._0 && a._1 == b._1 && a._2 == b._2;
|
2011-04-29 10:26:28 -05:00
|
|
|
}
|
|
|
|
auto h = hash_cache_entry;
|
|
|
|
auto e = eq_cache_entries;
|
2011-06-15 13:19:50 -05:00
|
|
|
ret map::mk_hashmap[tup(int, uint, uint), t](h, e);
|
2011-04-29 10:26:28 -05:00
|
|
|
}
|
2011-04-25 14:15:55 -05:00
|
|
|
|
2011-06-15 17:14:30 -05:00
|
|
|
fn mk_ctxt(session::session s, resolve::def_map dm, constr_table cs) -> ctxt {
|
2011-05-19 17:47:15 -05:00
|
|
|
let vec[mutable option::t[ty::ty_param_substs_opt_and_ty]] ntt_sub =
|
2011-06-15 13:19:50 -05:00
|
|
|
[mutable ];
|
2011-05-19 17:47:15 -05:00
|
|
|
let node_type_table ntt = @mutable ntt_sub;
|
2011-06-15 17:14:30 -05:00
|
|
|
auto tcache = new_def_hash[ty::ty_param_count_and_ty]();
|
|
|
|
auto items = new_def_hash[any_item]();
|
2011-05-20 15:57:09 -05:00
|
|
|
auto ts = @interner::mk[raw_t](hash_raw_ty, eq_raw_ty);
|
2011-05-19 19:21:21 -05:00
|
|
|
auto cx =
|
2011-06-15 13:19:50 -05:00
|
|
|
rec(ts=ts,
|
|
|
|
sess=s,
|
|
|
|
def_map=dm,
|
|
|
|
node_types=ntt,
|
|
|
|
items=items,
|
2011-06-16 18:55:46 -05:00
|
|
|
fn_constrs=cs,
|
2011-06-15 13:19:50 -05:00
|
|
|
tcache=tcache,
|
|
|
|
rcache=mk_rcache(),
|
|
|
|
short_names_cache=map::mk_hashmap[ty::t,
|
|
|
|
str](ty::hash_ty, ty::eq_ty),
|
|
|
|
ast_ty_to_ty_cache=map::mk_hashmap[@ast::ty,
|
|
|
|
option::t[t]](ast::hash_ty,
|
|
|
|
ast::eq_ty));
|
2011-05-19 19:21:21 -05:00
|
|
|
populate_type_store(cx);
|
|
|
|
ret cx;
|
2011-04-29 10:26:28 -05:00
|
|
|
}
|
2011-05-11 19:05:39 -05:00
|
|
|
|
|
|
|
|
2011-04-20 12:51:41 -05:00
|
|
|
// Type constructors
|
2011-05-19 19:21:21 -05:00
|
|
|
fn mk_raw_ty(&ctxt cx, &sty st, &option::t[str] cname) -> raw_t {
|
2011-04-22 21:26:00 -05:00
|
|
|
auto h = hash_type_info(st, cname);
|
2011-04-25 18:17:14 -05:00
|
|
|
let bool has_params = false;
|
|
|
|
let bool has_vars = false;
|
2011-06-15 13:19:50 -05:00
|
|
|
fn derive_flags_t(&ctxt cx, &mutable bool has_params,
|
|
|
|
&mutable bool has_vars, &t tt) {
|
2011-05-19 19:21:21 -05:00
|
|
|
auto rt = interner::get[raw_t](*cx.ts, tt);
|
2011-05-11 19:05:39 -05:00
|
|
|
has_params = has_params || rt.has_params;
|
|
|
|
has_vars = has_vars || rt.has_vars;
|
2011-04-25 18:17:14 -05:00
|
|
|
}
|
2011-06-15 13:19:50 -05:00
|
|
|
fn derive_flags_mt(&ctxt cx, &mutable bool has_params,
|
|
|
|
&mutable bool has_vars, &mt m) {
|
2011-05-20 20:36:35 -05:00
|
|
|
derive_flags_t(cx, has_params, has_vars, m.ty);
|
2011-04-25 18:17:14 -05:00
|
|
|
}
|
2011-06-15 13:19:50 -05:00
|
|
|
fn derive_flags_arg(&ctxt cx, &mutable bool has_params,
|
|
|
|
&mutable bool has_vars, &arg a) {
|
2011-05-20 20:36:35 -05:00
|
|
|
derive_flags_t(cx, has_params, has_vars, a.ty);
|
2011-04-25 18:17:14 -05:00
|
|
|
}
|
2011-06-15 13:19:50 -05:00
|
|
|
fn derive_flags_sig(&ctxt cx, &mutable bool has_params,
|
|
|
|
&mutable bool has_vars, &vec[arg] args, &t tt) {
|
|
|
|
for (arg a in args) { derive_flags_arg(cx, has_params, has_vars, a); }
|
2011-05-20 20:36:35 -05:00
|
|
|
derive_flags_t(cx, has_params, has_vars, tt);
|
2011-04-25 18:17:14 -05:00
|
|
|
}
|
|
|
|
alt (st) {
|
2011-06-15 13:19:50 -05:00
|
|
|
case (ty_nil) {/* no-op */ }
|
|
|
|
case (ty_bot) {/* no-op */ }
|
|
|
|
case (ty_bool) {/* no-op */ }
|
|
|
|
case (ty_int) {/* no-op */ }
|
|
|
|
case (ty_float) {/* no-op */ }
|
|
|
|
case (ty_uint) {/* no-op */ }
|
|
|
|
case (ty_machine(_)) {/* no-op */ }
|
|
|
|
case (ty_char) {/* no-op */ }
|
|
|
|
case (ty_str) {/* no-op */ }
|
|
|
|
case (ty_istr) {/* no-op */ }
|
|
|
|
case (ty_task) {/* no-op */ }
|
|
|
|
case (ty_type) {/* no-op */ }
|
|
|
|
case (ty_native) {/* no-op */ }
|
|
|
|
case (ty_param(_)) { has_params = true; }
|
2011-04-25 18:17:14 -05:00
|
|
|
case (ty_var(_)) { has_vars = true; }
|
2011-05-19 20:28:09 -05:00
|
|
|
case (ty_tag(_, ?tys)) {
|
2011-04-25 18:17:14 -05:00
|
|
|
for (t tt in tys) {
|
2011-05-20 20:36:35 -05:00
|
|
|
derive_flags_t(cx, has_params, has_vars, tt);
|
2011-04-25 18:17:14 -05:00
|
|
|
}
|
|
|
|
}
|
2011-06-15 13:19:50 -05:00
|
|
|
case (ty_box(?m)) { derive_flags_mt(cx, has_params, has_vars, m); }
|
|
|
|
case (ty_vec(?m)) { derive_flags_mt(cx, has_params, has_vars, m); }
|
|
|
|
case (ty_ivec(?m)) { derive_flags_mt(cx, has_params, has_vars, m); }
|
|
|
|
case (ty_ptr(?m)) { derive_flags_mt(cx, has_params, has_vars, m); }
|
|
|
|
case (ty_port(?tt)) { derive_flags_t(cx, has_params, has_vars, tt); }
|
|
|
|
case (ty_chan(?tt)) { derive_flags_t(cx, has_params, has_vars, tt); }
|
2011-04-25 18:17:14 -05:00
|
|
|
case (ty_tup(?mts)) {
|
|
|
|
for (mt m in mts) {
|
2011-05-20 20:36:35 -05:00
|
|
|
derive_flags_mt(cx, has_params, has_vars, m);
|
2011-04-25 18:17:14 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
case (ty_rec(?flds)) {
|
|
|
|
for (field f in flds) {
|
2011-05-20 20:36:35 -05:00
|
|
|
derive_flags_mt(cx, has_params, has_vars, f.mt);
|
2011-04-25 18:17:14 -05:00
|
|
|
}
|
|
|
|
}
|
2011-06-09 11:48:16 -05:00
|
|
|
case (ty_fn(_, ?args, ?tt, _, _)) {
|
2011-05-20 20:36:35 -05:00
|
|
|
derive_flags_sig(cx, has_params, has_vars, args, tt);
|
2011-04-25 18:17:14 -05:00
|
|
|
}
|
|
|
|
case (ty_native_fn(_, ?args, ?tt)) {
|
2011-05-20 20:36:35 -05:00
|
|
|
derive_flags_sig(cx, has_params, has_vars, args, tt);
|
2011-04-25 18:17:14 -05:00
|
|
|
}
|
|
|
|
case (ty_obj(?meths)) {
|
|
|
|
for (method m in meths) {
|
2011-05-20 20:36:35 -05:00
|
|
|
derive_flags_sig(cx, has_params, has_vars, m.inputs,
|
|
|
|
m.output);
|
2011-04-25 18:17:14 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2011-06-15 13:19:50 -05:00
|
|
|
ret rec(struct=st,
|
|
|
|
cname=cname,
|
|
|
|
hash=h,
|
2011-05-20 20:36:35 -05:00
|
|
|
has_params=has_params,
|
|
|
|
has_vars=has_vars);
|
2011-05-11 19:05:39 -05:00
|
|
|
}
|
|
|
|
|
2011-05-19 19:21:21 -05:00
|
|
|
fn intern(&ctxt cx, &sty st, &option::t[str] cname) {
|
|
|
|
interner::intern[raw_t](*cx.ts, mk_raw_ty(cx, st, cname));
|
2011-04-25 11:49:08 -05:00
|
|
|
}
|
2011-04-21 21:30:53 -05:00
|
|
|
|
2011-05-12 10:24:54 -05:00
|
|
|
fn gen_ty_full(&ctxt cx, &sty st, &option::t[str] cname) -> t {
|
2011-05-19 19:21:21 -05:00
|
|
|
auto raw_type = mk_raw_ty(cx, st, cname);
|
2011-05-19 20:28:09 -05:00
|
|
|
ret interner::intern[raw_t](*cx.ts, raw_type);
|
2011-04-20 14:22:28 -05:00
|
|
|
}
|
|
|
|
|
2011-06-15 13:19:50 -05:00
|
|
|
|
2011-04-25 18:17:14 -05:00
|
|
|
// These are private constructors to this module. External users should always
|
|
|
|
// use the mk_foo() functions below.
|
2011-06-15 13:19:50 -05:00
|
|
|
fn gen_ty(&ctxt cx, &sty st) -> t { ret gen_ty_full(cx, st, none[str]); }
|
|
|
|
|
|
|
|
fn mk_nil(&ctxt cx) -> t { ret idx_nil; }
|
|
|
|
|
|
|
|
fn mk_bot(&ctxt cx) -> t { ret idx_bot; }
|
2011-04-25 18:17:14 -05:00
|
|
|
|
2011-06-15 13:19:50 -05:00
|
|
|
fn mk_bool(&ctxt cx) -> t { ret idx_bool; }
|
|
|
|
|
|
|
|
fn mk_int(&ctxt cx) -> t { ret idx_int; }
|
|
|
|
|
|
|
|
fn mk_float(&ctxt cx) -> t { ret idx_float; }
|
|
|
|
|
|
|
|
fn mk_uint(&ctxt cx) -> t { ret idx_uint; }
|
2011-04-20 12:51:41 -05:00
|
|
|
|
2011-06-15 17:14:30 -05:00
|
|
|
fn mk_mach(&ctxt cx, &ty_mach tm) -> t {
|
2011-04-25 11:49:08 -05:00
|
|
|
alt (tm) {
|
2011-06-15 13:19:50 -05:00
|
|
|
case (ty_u8) { ret idx_u8; }
|
2011-05-11 19:05:39 -05:00
|
|
|
case (ty_u16) { ret idx_u16; }
|
|
|
|
case (ty_u32) { ret idx_u32; }
|
|
|
|
case (ty_u64) { ret idx_u64; }
|
2011-06-15 13:19:50 -05:00
|
|
|
case (ty_i8) { ret idx_i8; }
|
2011-05-11 19:05:39 -05:00
|
|
|
case (ty_i16) { ret idx_i16; }
|
|
|
|
case (ty_i32) { ret idx_i32; }
|
|
|
|
case (ty_i64) { ret idx_i64; }
|
|
|
|
case (ty_f32) { ret idx_f32; }
|
|
|
|
case (ty_f64) { ret idx_f64; }
|
2011-04-25 11:49:08 -05:00
|
|
|
}
|
2011-04-20 12:51:41 -05:00
|
|
|
}
|
|
|
|
|
2011-06-15 13:19:50 -05:00
|
|
|
fn mk_char(&ctxt cx) -> t { ret idx_char; }
|
|
|
|
|
|
|
|
fn mk_str(&ctxt cx) -> t { ret idx_str; }
|
|
|
|
|
|
|
|
fn mk_istr(&ctxt cx) -> t { ret idx_istr; }
|
2011-04-20 13:23:36 -05:00
|
|
|
|
2011-05-12 10:24:54 -05:00
|
|
|
fn mk_tag(&ctxt cx, &ast::def_id did, &vec[t] tys) -> t {
|
2011-04-25 14:15:55 -05:00
|
|
|
ret gen_ty(cx, ty_tag(did, tys));
|
2011-04-20 20:52:04 -05:00
|
|
|
}
|
2011-04-20 13:23:36 -05:00
|
|
|
|
2011-06-15 13:19:50 -05:00
|
|
|
fn mk_box(&ctxt cx, &mt tm) -> t { ret gen_ty(cx, ty_box(tm)); }
|
2011-04-20 20:52:04 -05:00
|
|
|
|
2011-06-15 13:19:50 -05:00
|
|
|
fn mk_ptr(&ctxt cx, &mt tm) -> t { ret gen_ty(cx, ty_ptr(tm)); }
|
2011-06-03 14:02:58 -05:00
|
|
|
|
2011-05-09 15:09:20 -05:00
|
|
|
fn mk_imm_box(&ctxt cx, &t ty) -> t {
|
2011-05-12 10:24:54 -05:00
|
|
|
ret mk_box(cx, rec(ty=ty, mut=ast::imm));
|
2011-04-20 20:52:04 -05:00
|
|
|
}
|
|
|
|
|
2011-06-15 13:19:50 -05:00
|
|
|
fn mk_vec(&ctxt cx, &mt tm) -> t { ret gen_ty(cx, ty_vec(tm)); }
|
2011-05-12 20:37:28 -05:00
|
|
|
|
2011-06-09 18:23:19 -05:00
|
|
|
fn mk_ivec(&ctxt cx, &mt tm) -> t { ret gen_ty(cx, ty_ivec(tm)); }
|
|
|
|
|
2011-05-12 20:37:28 -05:00
|
|
|
fn mk_imm_vec(&ctxt cx, &t typ) -> t {
|
|
|
|
ret gen_ty(cx, ty_vec(rec(ty=typ, mut=ast::imm)));
|
|
|
|
}
|
|
|
|
|
2011-06-15 13:19:50 -05:00
|
|
|
fn mk_port(&ctxt cx, &t ty) -> t { ret gen_ty(cx, ty_port(ty)); }
|
|
|
|
|
|
|
|
fn mk_chan(&ctxt cx, &t ty) -> t { ret gen_ty(cx, ty_chan(ty)); }
|
|
|
|
|
|
|
|
fn mk_task(&ctxt cx) -> t { ret gen_ty(cx, ty_task); }
|
2011-04-20 20:52:04 -05:00
|
|
|
|
2011-05-09 15:09:20 -05:00
|
|
|
fn mk_tup(&ctxt cx, &vec[mt] tms) -> t { ret gen_ty(cx, ty_tup(tms)); }
|
2011-04-20 20:52:04 -05:00
|
|
|
|
2011-05-09 15:09:20 -05:00
|
|
|
fn mk_imm_tup(&ctxt cx, &vec[t] tys) -> t {
|
2011-04-20 13:23:36 -05:00
|
|
|
// TODO: map
|
2011-06-15 13:19:50 -05:00
|
|
|
|
2011-05-16 20:21:22 -05:00
|
|
|
let vec[ty::mt] mts = [];
|
2011-06-15 13:19:50 -05:00
|
|
|
for (t typ in tys) { mts += [rec(ty=typ, mut=ast::imm)]; }
|
2011-04-25 14:15:55 -05:00
|
|
|
ret mk_tup(cx, mts);
|
2011-04-20 20:52:04 -05:00
|
|
|
}
|
|
|
|
|
2011-05-09 15:09:20 -05:00
|
|
|
fn mk_rec(&ctxt cx, &vec[field] fs) -> t { ret gen_ty(cx, ty_rec(fs)); }
|
2011-04-20 13:23:36 -05:00
|
|
|
|
2011-06-15 13:19:50 -05:00
|
|
|
fn mk_fn(&ctxt cx, &ast::proto proto, &vec[arg] args, &t ty, &controlflow cf,
|
2011-06-15 17:14:30 -05:00
|
|
|
&vec[@constr_def] constrs) -> t {
|
2011-06-09 11:48:16 -05:00
|
|
|
ret gen_ty(cx, ty_fn(proto, args, ty, cf, constrs));
|
2011-04-20 20:52:04 -05:00
|
|
|
}
|
|
|
|
|
2011-05-12 10:24:54 -05:00
|
|
|
fn mk_native_fn(&ctxt cx, &ast::native_abi abi, &vec[arg] args, &t ty) -> t {
|
2011-04-25 14:15:55 -05:00
|
|
|
ret gen_ty(cx, ty_native_fn(abi, args, ty));
|
2011-04-20 20:52:04 -05:00
|
|
|
}
|
2011-04-20 12:51:41 -05:00
|
|
|
|
2011-05-09 15:09:20 -05:00
|
|
|
fn mk_obj(&ctxt cx, &vec[method] meths) -> t {
|
2011-04-25 14:15:55 -05:00
|
|
|
ret gen_ty(cx, ty_obj(meths));
|
2011-04-20 12:51:41 -05:00
|
|
|
}
|
|
|
|
|
2011-06-15 13:19:50 -05:00
|
|
|
fn mk_var(&ctxt cx, int v) -> t { ret gen_ty(cx, ty_var(v)); }
|
2011-04-20 20:52:04 -05:00
|
|
|
|
2011-06-15 13:19:50 -05:00
|
|
|
fn mk_param(&ctxt cx, uint n) -> t { ret gen_ty(cx, ty_param(n)); }
|
|
|
|
|
|
|
|
fn mk_type(&ctxt cx) -> t { ret idx_type; }
|
2011-04-20 20:52:04 -05:00
|
|
|
|
2011-06-15 13:19:50 -05:00
|
|
|
fn mk_native(&ctxt cx) -> t { ret idx_native; }
|
2011-04-20 12:51:41 -05:00
|
|
|
|
|
|
|
|
2011-04-22 14:08:23 -05:00
|
|
|
// Returns the one-level-deep type structure of the given type.
|
2011-05-16 15:58:13 -05:00
|
|
|
fn struct(&ctxt cx, &t typ) -> sty {
|
|
|
|
ret interner::get[raw_t](*cx.ts, typ).struct;
|
|
|
|
}
|
2011-04-22 14:08:23 -05:00
|
|
|
|
2011-06-15 13:19:50 -05:00
|
|
|
|
2011-04-22 15:45:21 -05:00
|
|
|
// Returns the canonical name of the given type.
|
2011-05-16 15:58:13 -05:00
|
|
|
fn cname(&ctxt cx, &t typ) -> option::t[str] {
|
|
|
|
ret interner::get[raw_t](*cx.ts, typ).cname;
|
|
|
|
}
|
2011-04-22 15:45:21 -05:00
|
|
|
|
2011-04-22 14:08:23 -05:00
|
|
|
|
2010-12-21 14:13:51 -06:00
|
|
|
// Stringification
|
2011-05-12 10:24:54 -05:00
|
|
|
fn path_to_str(&ast::path pth) -> str {
|
2011-06-15 13:19:50 -05:00
|
|
|
auto result = str::connect(pth.node.idents, "::");
|
2011-05-17 13:41:41 -05:00
|
|
|
if (vec::len[@ast::ty](pth.node.types) > 0u) {
|
2011-06-15 13:19:50 -05:00
|
|
|
fn f(&@ast::ty t) -> str { ret pretty::pprust::ty_to_str(*t); }
|
2010-12-21 14:13:51 -06:00
|
|
|
result += "[";
|
2011-05-17 13:41:41 -05:00
|
|
|
result += str::connect(vec::map(f, pth.node.types), ",");
|
2010-12-21 14:13:51 -06:00
|
|
|
result += "]";
|
|
|
|
}
|
|
|
|
ret result;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-06-15 13:19:50 -05:00
|
|
|
// Type folds
|
|
|
|
type ty_walk = fn(t) ;
|
2011-04-15 14:23:00 -05:00
|
|
|
|
2011-05-19 17:47:15 -05:00
|
|
|
fn walk_ty(&ctxt cx, ty_walk walker, t ty) {
|
2011-04-25 14:15:55 -05:00
|
|
|
alt (struct(cx, ty)) {
|
2011-06-15 13:19:50 -05:00
|
|
|
case (ty_nil) {/* no-op */ }
|
|
|
|
case (ty_bot) {/* no-op */ }
|
|
|
|
case (ty_bool) {/* no-op */ }
|
|
|
|
case (ty_int) {/* no-op */ }
|
|
|
|
case (ty_uint) {/* no-op */ }
|
|
|
|
case (ty_float) {/* no-op */ }
|
|
|
|
case (ty_machine(_)) {/* no-op */ }
|
|
|
|
case (ty_char) {/* no-op */ }
|
|
|
|
case (ty_str) {/* no-op */ }
|
|
|
|
case (ty_istr) {/* no-op */ }
|
|
|
|
case (ty_type) {/* no-op */ }
|
|
|
|
case (ty_native) {/* no-op */ }
|
|
|
|
case (ty_box(?tm)) { walk_ty(cx, walker, tm.ty); }
|
|
|
|
case (ty_vec(?tm)) { walk_ty(cx, walker, tm.ty); }
|
|
|
|
case (ty_ivec(?tm)) { walk_ty(cx, walker, tm.ty); }
|
2011-06-16 19:05:59 -05:00
|
|
|
case (ty_ptr(?tm)) { walk_ty(cx, walker, tm.ty); }
|
2011-06-15 13:19:50 -05:00
|
|
|
case (ty_port(?subty)) { walk_ty(cx, walker, subty); }
|
|
|
|
case (ty_chan(?subty)) { walk_ty(cx, walker, subty); }
|
2011-04-15 14:23:00 -05:00
|
|
|
case (ty_tag(?tid, ?subtys)) {
|
2011-06-15 13:19:50 -05:00
|
|
|
for (t subty in subtys) { walk_ty(cx, walker, subty); }
|
2011-04-15 14:23:00 -05:00
|
|
|
}
|
|
|
|
case (ty_tup(?mts)) {
|
2011-06-15 13:19:50 -05:00
|
|
|
for (mt tm in mts) { walk_ty(cx, walker, tm.ty); }
|
2011-04-15 14:23:00 -05:00
|
|
|
}
|
|
|
|
case (ty_rec(?fields)) {
|
2011-06-15 13:19:50 -05:00
|
|
|
for (field fl in fields) { walk_ty(cx, walker, fl.mt.ty); }
|
2011-04-15 14:23:00 -05:00
|
|
|
}
|
2011-06-09 11:48:16 -05:00
|
|
|
case (ty_fn(?proto, ?args, ?ret_ty, _, _)) {
|
2011-06-15 13:19:50 -05:00
|
|
|
for (arg a in args) { walk_ty(cx, walker, a.ty); }
|
2011-04-25 14:15:55 -05:00
|
|
|
walk_ty(cx, walker, ret_ty);
|
2011-04-15 14:23:00 -05:00
|
|
|
}
|
|
|
|
case (ty_native_fn(?abi, ?args, ?ret_ty)) {
|
2011-06-15 13:19:50 -05:00
|
|
|
for (arg a in args) { walk_ty(cx, walker, a.ty); }
|
2011-04-25 14:15:55 -05:00
|
|
|
walk_ty(cx, walker, ret_ty);
|
2011-04-15 14:23:00 -05:00
|
|
|
}
|
|
|
|
case (ty_obj(?methods)) {
|
2011-05-16 20:21:22 -05:00
|
|
|
let vec[method] new_methods = [];
|
2011-04-15 14:23:00 -05:00
|
|
|
for (method m in methods) {
|
2011-06-15 13:19:50 -05:00
|
|
|
for (arg a in m.inputs) { walk_ty(cx, walker, a.ty); }
|
2011-04-25 14:15:55 -05:00
|
|
|
walk_ty(cx, walker, m.output);
|
2011-04-15 14:23:00 -05:00
|
|
|
}
|
|
|
|
}
|
2011-06-15 13:19:50 -05:00
|
|
|
case (ty_var(_)) {/* no-op */ }
|
|
|
|
case (ty_param(_)) {/* no-op */ }
|
2011-04-15 14:23:00 -05:00
|
|
|
}
|
|
|
|
walker(ty);
|
|
|
|
}
|
|
|
|
|
2011-06-09 13:20:47 -05:00
|
|
|
tag fold_mode {
|
2011-06-15 13:19:50 -05:00
|
|
|
fm_var(fn(int) -> t );
|
|
|
|
fm_param(fn(uint) -> t );
|
|
|
|
fm_general(fn(t) -> t );
|
2011-06-09 13:20:47 -05:00
|
|
|
}
|
2011-04-15 14:23:00 -05:00
|
|
|
|
2011-06-09 13:20:47 -05:00
|
|
|
fn fold_ty(&ctxt cx, fold_mode fld, t ty_0) -> t {
|
2011-04-15 14:23:00 -05:00
|
|
|
auto ty = ty_0;
|
2011-06-09 13:20:47 -05:00
|
|
|
// Fast paths.
|
2011-06-15 13:19:50 -05:00
|
|
|
|
2011-06-09 13:20:47 -05:00
|
|
|
alt (fld) {
|
|
|
|
case (fm_var(_)) { if (!type_contains_vars(cx, ty)) { ret ty; } }
|
|
|
|
case (fm_param(_)) { if (!type_contains_params(cx, ty)) { ret ty; } }
|
2011-06-15 13:19:50 -05:00
|
|
|
case (fm_general(_)) {/* no fast path */ }
|
2011-06-09 13:20:47 -05:00
|
|
|
}
|
2011-04-25 14:15:55 -05:00
|
|
|
alt (struct(cx, ty)) {
|
2011-06-15 13:19:50 -05:00
|
|
|
case (ty_nil) {/* no-op */ }
|
|
|
|
case (ty_bot) {/* no-op */ }
|
|
|
|
case (ty_bool) {/* no-op */ }
|
|
|
|
case (ty_int) {/* no-op */ }
|
|
|
|
case (ty_uint) {/* no-op */ }
|
|
|
|
case (ty_float) {/* no-op */ }
|
|
|
|
case (ty_machine(_)) {/* no-op */ }
|
|
|
|
case (ty_char) {/* no-op */ }
|
|
|
|
case (ty_str) {/* no-op */ }
|
|
|
|
case (ty_istr) {/* no-op */ }
|
|
|
|
case (ty_type) {/* no-op */ }
|
|
|
|
case (ty_native) {/* no-op */ }
|
|
|
|
case (ty_task) {/* no-op */ }
|
2011-03-17 19:39:47 -05:00
|
|
|
case (ty_box(?tm)) {
|
2011-06-15 13:19:50 -05:00
|
|
|
ty =
|
|
|
|
copy_cname(cx,
|
|
|
|
mk_box(cx,
|
|
|
|
rec(ty=fold_ty(cx, fld, tm.ty),
|
|
|
|
mut=tm.mut)), ty);
|
2010-12-21 14:13:51 -06:00
|
|
|
}
|
2011-06-06 15:33:42 -05:00
|
|
|
case (ty_ptr(?tm)) {
|
2011-06-15 13:19:50 -05:00
|
|
|
ty =
|
|
|
|
copy_cname(cx,
|
|
|
|
mk_ptr(cx,
|
|
|
|
rec(ty=fold_ty(cx, fld, tm.ty),
|
|
|
|
mut=tm.mut)), ty);
|
2011-06-06 15:33:42 -05:00
|
|
|
}
|
2011-03-17 19:39:47 -05:00
|
|
|
case (ty_vec(?tm)) {
|
2011-06-15 13:19:50 -05:00
|
|
|
ty =
|
|
|
|
copy_cname(cx,
|
|
|
|
mk_vec(cx,
|
|
|
|
rec(ty=fold_ty(cx, fld, tm.ty),
|
|
|
|
mut=tm.mut)), ty);
|
2010-12-21 14:13:51 -06:00
|
|
|
}
|
2011-06-10 14:07:38 -05:00
|
|
|
case (ty_ivec(?tm)) {
|
2011-06-15 13:19:50 -05:00
|
|
|
ty =
|
|
|
|
copy_cname(cx,
|
|
|
|
mk_ivec(cx,
|
|
|
|
rec(ty=fold_ty(cx, fld, tm.ty),
|
|
|
|
mut=tm.mut)), ty);
|
2011-06-10 14:07:38 -05:00
|
|
|
}
|
2011-03-10 21:58:55 -06:00
|
|
|
case (ty_port(?subty)) {
|
2011-04-25 14:15:55 -05:00
|
|
|
ty = copy_cname(cx, mk_port(cx, fold_ty(cx, fld, subty)), ty);
|
2011-03-10 21:58:55 -06:00
|
|
|
}
|
|
|
|
case (ty_chan(?subty)) {
|
2011-04-25 14:15:55 -05:00
|
|
|
ty = copy_cname(cx, mk_chan(cx, fold_ty(cx, fld, subty)), ty);
|
2011-03-10 21:58:55 -06:00
|
|
|
}
|
2011-02-17 18:23:31 -06:00
|
|
|
case (ty_tag(?tid, ?subtys)) {
|
2011-05-16 20:21:22 -05:00
|
|
|
let vec[t] new_subtys = [];
|
2011-04-22 14:27:28 -05:00
|
|
|
for (t subty in subtys) {
|
2011-05-16 20:21:22 -05:00
|
|
|
new_subtys += [fold_ty(cx, fld, subty)];
|
2011-02-17 18:23:31 -06:00
|
|
|
}
|
2011-04-25 14:15:55 -05:00
|
|
|
ty = copy_cname(cx, mk_tag(cx, tid, new_subtys), ty);
|
2011-02-17 18:23:31 -06:00
|
|
|
}
|
2011-03-17 19:39:47 -05:00
|
|
|
case (ty_tup(?mts)) {
|
2011-05-16 20:21:22 -05:00
|
|
|
let vec[mt] new_mts = [];
|
2011-03-17 19:39:47 -05:00
|
|
|
for (mt tm in mts) {
|
2011-04-25 14:15:55 -05:00
|
|
|
auto new_subty = fold_ty(cx, fld, tm.ty);
|
2011-05-16 20:21:22 -05:00
|
|
|
new_mts += [rec(ty=new_subty, mut=tm.mut)];
|
2010-12-21 14:13:51 -06:00
|
|
|
}
|
2011-04-25 14:15:55 -05:00
|
|
|
ty = copy_cname(cx, mk_tup(cx, new_mts), ty);
|
2010-12-21 14:13:51 -06:00
|
|
|
}
|
|
|
|
case (ty_rec(?fields)) {
|
2011-05-16 20:21:22 -05:00
|
|
|
let vec[field] new_fields = [];
|
2010-12-21 14:13:51 -06:00
|
|
|
for (field fl in fields) {
|
2011-04-25 14:15:55 -05:00
|
|
|
auto new_ty = fold_ty(cx, fld, fl.mt.ty);
|
2011-03-17 19:39:47 -05:00
|
|
|
auto new_mt = rec(ty=new_ty, mut=fl.mt.mut);
|
2011-05-16 20:21:22 -05:00
|
|
|
new_fields += [rec(ident=fl.ident, mt=new_mt)];
|
2010-12-21 14:13:51 -06:00
|
|
|
}
|
2011-04-25 14:15:55 -05:00
|
|
|
ty = copy_cname(cx, mk_rec(cx, new_fields), ty);
|
2010-12-21 14:13:51 -06:00
|
|
|
}
|
2011-06-09 11:48:16 -05:00
|
|
|
case (ty_fn(?proto, ?args, ?ret_ty, ?cf, ?constrs)) {
|
2011-05-16 20:21:22 -05:00
|
|
|
let vec[arg] new_args = [];
|
2010-12-21 14:13:51 -06:00
|
|
|
for (arg a in args) {
|
2011-04-25 14:15:55 -05:00
|
|
|
auto new_ty = fold_ty(cx, fld, a.ty);
|
2011-05-16 20:21:22 -05:00
|
|
|
new_args += [rec(mode=a.mode, ty=new_ty)];
|
2010-12-21 14:13:51 -06:00
|
|
|
}
|
2011-06-15 13:19:50 -05:00
|
|
|
ty =
|
|
|
|
copy_cname(cx,
|
|
|
|
mk_fn(cx, proto, new_args,
|
|
|
|
fold_ty(cx, fld, ret_ty), cf, constrs), ty);
|
2010-12-21 14:13:51 -06:00
|
|
|
}
|
2011-02-25 14:58:08 -06:00
|
|
|
case (ty_native_fn(?abi, ?args, ?ret_ty)) {
|
2011-05-16 20:21:22 -05:00
|
|
|
let vec[arg] new_args = [];
|
2011-02-23 10:59:07 -06:00
|
|
|
for (arg a in args) {
|
2011-04-25 14:15:55 -05:00
|
|
|
auto new_ty = fold_ty(cx, fld, a.ty);
|
2011-05-16 20:21:22 -05:00
|
|
|
new_args += [rec(mode=a.mode, ty=new_ty)];
|
2011-02-23 10:59:07 -06:00
|
|
|
}
|
2011-06-15 13:19:50 -05:00
|
|
|
ty =
|
|
|
|
copy_cname(cx,
|
|
|
|
mk_native_fn(cx, abi, new_args,
|
|
|
|
fold_ty(cx, fld, ret_ty)), ty);
|
2011-02-23 10:59:07 -06:00
|
|
|
}
|
2010-12-21 14:13:51 -06:00
|
|
|
case (ty_obj(?methods)) {
|
2011-05-16 20:21:22 -05:00
|
|
|
let vec[method] new_methods = [];
|
2010-12-21 14:13:51 -06:00
|
|
|
for (method m in methods) {
|
2011-05-16 20:21:22 -05:00
|
|
|
let vec[arg] new_args = [];
|
2010-12-21 14:13:51 -06:00
|
|
|
for (arg a in m.inputs) {
|
2011-06-15 13:19:50 -05:00
|
|
|
new_args += [rec(mode=a.mode, ty=fold_ty(cx, fld, a.ty))];
|
2010-12-21 14:13:51 -06:00
|
|
|
}
|
2011-06-15 13:19:50 -05:00
|
|
|
new_methods +=
|
|
|
|
[rec(proto=m.proto,
|
|
|
|
ident=m.ident,
|
|
|
|
inputs=new_args,
|
|
|
|
output=fold_ty(cx, fld, m.output),
|
|
|
|
cf=m.cf,
|
|
|
|
constrs=m.constrs)];
|
2010-12-21 14:13:51 -06:00
|
|
|
}
|
2011-04-25 14:15:55 -05:00
|
|
|
ty = copy_cname(cx, mk_obj(cx, new_methods), ty);
|
2010-12-21 14:13:51 -06:00
|
|
|
}
|
2011-06-09 13:20:47 -05:00
|
|
|
case (ty_var(?id)) {
|
|
|
|
alt (fld) {
|
|
|
|
case (fm_var(?folder)) { ty = folder(id); }
|
2011-06-15 13:19:50 -05:00
|
|
|
case (_) {/* no-op */ }
|
2011-06-09 13:20:47 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
case (ty_param(?id)) {
|
|
|
|
alt (fld) {
|
|
|
|
case (fm_param(?folder)) { ty = folder(id); }
|
2011-06-15 13:19:50 -05:00
|
|
|
case (_) {/* no-op */ }
|
2011-06-09 13:20:47 -05:00
|
|
|
}
|
|
|
|
}
|
2010-12-21 14:13:51 -06:00
|
|
|
}
|
|
|
|
|
2011-06-09 13:20:47 -05:00
|
|
|
// If this is a general type fold, then we need to run it now.
|
|
|
|
alt (fld) {
|
|
|
|
case (fm_general(?folder)) { ret folder(ty); }
|
|
|
|
case (_) { ret ty; }
|
|
|
|
}
|
2010-12-21 14:13:51 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-06-15 13:19:50 -05:00
|
|
|
// Type utilities
|
2011-05-19 17:47:15 -05:00
|
|
|
fn rename(&ctxt cx, t typ, str new_cname) -> t {
|
2011-04-25 14:15:55 -05:00
|
|
|
ret gen_ty_full(cx, struct(cx, typ), some[str](new_cname));
|
2011-04-20 13:59:10 -05:00
|
|
|
}
|
|
|
|
|
2011-06-15 13:19:50 -05:00
|
|
|
|
2011-04-20 13:59:10 -05:00
|
|
|
// Returns a type with the structural part taken from `struct_ty` and the
|
|
|
|
// canonical name from `cname_ty`.
|
2011-05-19 17:47:15 -05:00
|
|
|
fn copy_cname(&ctxt cx, t struct_ty, t cname_ty) -> t {
|
2011-05-11 19:05:39 -05:00
|
|
|
ret gen_ty_full(cx, struct(cx, struct_ty), cname(cx, cname_ty));
|
2011-04-20 13:59:10 -05:00
|
|
|
}
|
|
|
|
|
2011-05-09 15:09:20 -05:00
|
|
|
fn type_is_nil(&ctxt cx, &t ty) -> bool {
|
2011-04-25 14:15:55 -05:00
|
|
|
alt (struct(cx, ty)) {
|
2010-12-21 14:13:51 -06:00
|
|
|
case (ty_nil) { ret true; }
|
|
|
|
case (_) { ret false; }
|
|
|
|
}
|
2011-05-14 21:02:30 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
fn type_is_bot(&ctxt cx, &t ty) -> bool {
|
|
|
|
alt (struct(cx, ty)) {
|
|
|
|
case (ty_bot) { ret true; }
|
|
|
|
case (_) { ret false; }
|
|
|
|
}
|
2010-12-21 14:13:51 -06:00
|
|
|
}
|
|
|
|
|
2011-05-09 15:09:20 -05:00
|
|
|
fn type_is_bool(&ctxt cx, &t ty) -> bool {
|
2011-04-25 14:15:55 -05:00
|
|
|
alt (struct(cx, ty)) {
|
2011-04-19 17:22:57 -05:00
|
|
|
case (ty_bool) { ret true; }
|
|
|
|
case (_) { ret false; }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-06-17 16:32:43 -05:00
|
|
|
fn type_is_chan(&ctxt cx, &t ty) -> bool {
|
|
|
|
alt (struct(cx, ty)) {
|
|
|
|
case (ty_chan(_)) { ret true; }
|
|
|
|
case (_) { ret false; }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-05-09 15:09:20 -05:00
|
|
|
fn type_is_structural(&ctxt cx, &t ty) -> bool {
|
2011-04-25 14:15:55 -05:00
|
|
|
alt (struct(cx, ty)) {
|
2011-06-15 13:19:50 -05:00
|
|
|
case (ty_tup(_)) { ret true; }
|
|
|
|
case (ty_rec(_)) { ret true; }
|
|
|
|
case (ty_tag(_, _)) { ret true; }
|
|
|
|
case (ty_fn(_, _, _, _, _)) { ret true; }
|
|
|
|
case (ty_obj(_)) { ret true; }
|
|
|
|
case (ty_ivec(_)) { ret true; }
|
|
|
|
case (ty_istr) { ret true; }
|
|
|
|
case (_) { ret false; }
|
2010-12-21 14:13:51 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-05-09 15:09:20 -05:00
|
|
|
fn type_is_sequence(&ctxt cx, &t ty) -> bool {
|
2011-04-25 14:15:55 -05:00
|
|
|
alt (struct(cx, ty)) {
|
2011-06-15 13:19:50 -05:00
|
|
|
case (ty_str) { ret true; }
|
|
|
|
case (ty_istr) { ret true; }
|
|
|
|
case (ty_vec(_)) { ret true; }
|
|
|
|
case (ty_ivec(_)) { ret true; }
|
|
|
|
case (_) { ret false; }
|
2011-03-02 18:42:09 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-06-13 20:52:04 -05:00
|
|
|
fn sequence_is_interior(&ctxt cx, &t ty) -> bool {
|
|
|
|
alt (struct(cx, ty)) {
|
2011-06-15 13:19:50 -05:00
|
|
|
case (
|
|
|
|
// TODO: Or-patterns
|
|
|
|
ty::ty_vec(_)) {
|
|
|
|
ret false;
|
|
|
|
}
|
|
|
|
case (ty::ty_str) { ret false; }
|
|
|
|
case (ty::ty_ivec(_)) { ret true; }
|
|
|
|
case (ty::ty_istr) { ret true; }
|
2011-06-13 20:52:04 -05:00
|
|
|
case (_) {
|
|
|
|
cx.sess.bug("sequence_is_interior called on non-sequence type");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-05-09 15:09:20 -05:00
|
|
|
fn sequence_element_type(&ctxt cx, &t ty) -> t {
|
2011-04-25 14:15:55 -05:00
|
|
|
alt (struct(cx, ty)) {
|
2011-06-15 17:14:30 -05:00
|
|
|
case (ty_str) { ret mk_mach(cx, ty_u8); }
|
|
|
|
case (ty_istr) { ret mk_mach(cx, ty_u8); }
|
2011-06-15 13:19:50 -05:00
|
|
|
case (ty_vec(?mt)) { ret mt.ty; }
|
2011-06-10 21:35:59 -05:00
|
|
|
case (ty_ivec(?mt)) { ret mt.ty; }
|
|
|
|
case (_) {
|
|
|
|
cx.sess.bug("sequence_element_type called on non-sequence value");
|
|
|
|
}
|
2011-03-03 20:18:51 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-05-09 15:09:20 -05:00
|
|
|
fn type_is_tup_like(&ctxt cx, &t ty) -> bool {
|
2011-04-25 14:15:55 -05:00
|
|
|
alt (struct(cx, ty)) {
|
2011-06-15 13:19:50 -05:00
|
|
|
case (ty_box(_)) { ret true; }
|
|
|
|
case (ty_tup(_)) { ret true; }
|
|
|
|
case (ty_rec(_)) { ret true; }
|
|
|
|
case (ty_tag(_, _)) { ret true; }
|
|
|
|
case (_) { ret false; }
|
2011-01-19 18:29:14 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-05-09 15:09:20 -05:00
|
|
|
fn get_element_type(&ctxt cx, &t ty, uint i) -> t {
|
2011-05-02 19:47:24 -05:00
|
|
|
assert (type_is_tup_like(cx, ty));
|
2011-04-25 14:15:55 -05:00
|
|
|
alt (struct(cx, ty)) {
|
2011-06-15 13:19:50 -05:00
|
|
|
case (ty_tup(?mts)) { ret mts.(i).ty; }
|
|
|
|
case (ty_rec(?flds)) { ret flds.(i).mt.ty; }
|
2011-01-19 18:29:14 -06:00
|
|
|
}
|
2011-06-15 13:19:50 -05:00
|
|
|
// NB: This is not exhaustive -- struct(cx, ty) could be a box or a
|
|
|
|
// tag.
|
2011-06-02 20:10:18 -05:00
|
|
|
|
2011-06-15 13:19:50 -05:00
|
|
|
cx.sess.bug("get_element_type called on a value other than a " +
|
|
|
|
"tuple or record");
|
2011-01-19 18:29:14 -06:00
|
|
|
}
|
|
|
|
|
2011-05-09 15:09:20 -05:00
|
|
|
fn type_is_box(&ctxt cx, &t ty) -> bool {
|
2011-04-25 14:15:55 -05:00
|
|
|
alt (struct(cx, ty)) {
|
2011-03-09 22:14:19 -06:00
|
|
|
case (ty_box(_)) { ret true; }
|
|
|
|
case (_) { ret false; }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-05-09 15:09:20 -05:00
|
|
|
fn type_is_boxed(&ctxt cx, &t ty) -> bool {
|
2011-04-25 14:15:55 -05:00
|
|
|
alt (struct(cx, ty)) {
|
2010-12-21 14:13:51 -06:00
|
|
|
case (ty_str) { ret true; }
|
|
|
|
case (ty_vec(_)) { ret true; }
|
|
|
|
case (ty_box(_)) { ret true; }
|
2011-03-16 20:49:15 -05:00
|
|
|
case (ty_port(_)) { ret true; }
|
|
|
|
case (ty_chan(_)) { ret true; }
|
2011-05-24 14:18:42 -05:00
|
|
|
case (ty_task) { ret true; }
|
2010-12-21 14:13:51 -06:00
|
|
|
case (_) { ret false; }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-05-09 15:09:20 -05:00
|
|
|
fn type_is_scalar(&ctxt cx, &t ty) -> bool {
|
2011-04-25 14:15:55 -05:00
|
|
|
alt (struct(cx, ty)) {
|
2010-12-21 14:13:51 -06:00
|
|
|
case (ty_nil) { ret true; }
|
|
|
|
case (ty_bool) { ret true; }
|
|
|
|
case (ty_int) { ret true; }
|
2011-03-21 19:12:05 -05:00
|
|
|
case (ty_float) { ret true; }
|
2010-12-21 14:13:51 -06:00
|
|
|
case (ty_uint) { ret true; }
|
|
|
|
case (ty_machine(_)) { ret true; }
|
|
|
|
case (ty_char) { ret true; }
|
2011-02-01 16:56:21 -06:00
|
|
|
case (ty_type) { ret true; }
|
2011-03-17 13:46:21 -05:00
|
|
|
case (ty_native) { ret true; }
|
2011-06-06 15:33:42 -05:00
|
|
|
case (ty_ptr(_)) { ret true; }
|
2010-12-21 14:13:51 -06:00
|
|
|
case (_) { ret false; }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-05-19 20:28:09 -05:00
|
|
|
fn type_has_pointers(&ctxt cx, &t ty) -> bool {
|
|
|
|
alt (struct(cx, ty)) {
|
2011-06-15 13:19:50 -05:00
|
|
|
case (
|
|
|
|
// scalar types
|
|
|
|
ty_nil) {
|
|
|
|
ret false;
|
|
|
|
}
|
2011-06-02 19:48:40 -05:00
|
|
|
case (ty_bot) { ret false; }
|
2011-05-19 20:28:09 -05:00
|
|
|
case (ty_bool) { ret false; }
|
|
|
|
case (ty_int) { ret false; }
|
|
|
|
case (ty_float) { ret false; }
|
|
|
|
case (ty_uint) { ret false; }
|
|
|
|
case (ty_machine(_)) { ret false; }
|
|
|
|
case (ty_char) { ret false; }
|
|
|
|
case (ty_type) { ret false; }
|
|
|
|
case (ty_native) { ret false; }
|
2011-06-15 13:19:50 -05:00
|
|
|
case (ty_tup(?elts)) {
|
2011-05-19 20:28:09 -05:00
|
|
|
for (mt m in elts) {
|
|
|
|
if (type_has_pointers(cx, m.ty)) { ret true; }
|
|
|
|
}
|
|
|
|
ret false;
|
|
|
|
}
|
|
|
|
case (ty_rec(?flds)) {
|
|
|
|
for (field f in flds) {
|
|
|
|
if (type_has_pointers(cx, f.mt.ty)) { ret true; }
|
|
|
|
}
|
|
|
|
ret false;
|
|
|
|
}
|
2011-06-15 13:19:50 -05:00
|
|
|
case (ty_tag(?did, ?tps)) {
|
2011-05-19 20:28:09 -05:00
|
|
|
auto variants = tag_variants(cx, did);
|
|
|
|
for (variant_info variant in variants) {
|
|
|
|
auto tup_ty = mk_imm_tup(cx, variant.args);
|
|
|
|
// Perform any type parameter substitutions.
|
2011-06-15 13:19:50 -05:00
|
|
|
|
2011-05-19 20:28:09 -05:00
|
|
|
tup_ty = substitute_type_params(cx, tps, tup_ty);
|
|
|
|
if (type_has_pointers(cx, tup_ty)) { ret true; }
|
|
|
|
}
|
|
|
|
ret false;
|
|
|
|
}
|
|
|
|
case (_) { ret true; }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-03-03 15:43:47 -06:00
|
|
|
// FIXME: should we just return true for native types in
|
|
|
|
// type_is_scalar?
|
2011-05-09 15:09:20 -05:00
|
|
|
fn type_is_native(&ctxt cx, &t ty) -> bool {
|
2011-04-25 14:15:55 -05:00
|
|
|
alt (struct(cx, ty)) {
|
2011-03-03 15:43:47 -06:00
|
|
|
case (ty_native) { ret true; }
|
|
|
|
case (_) { ret false; }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-05-09 15:09:20 -05:00
|
|
|
fn type_has_dynamic_size(&ctxt cx, &t ty) -> bool {
|
2011-04-25 14:15:55 -05:00
|
|
|
alt (struct(cx, ty)) {
|
2011-06-17 14:03:40 -05:00
|
|
|
case (ty_nil) { ret false; }
|
|
|
|
case (ty_bot) { ret false; }
|
|
|
|
case (ty_bool) { ret false; }
|
|
|
|
case (ty_int) { ret false; }
|
|
|
|
case (ty_float) { ret false; }
|
|
|
|
case (ty_uint) { ret false; }
|
|
|
|
case (ty_machine(_)) { ret false; }
|
|
|
|
case (ty_char) { ret false; }
|
|
|
|
case (ty_str) { ret false; }
|
|
|
|
case (ty_istr) { ret false; }
|
|
|
|
case (ty_tag(_, ?subtys)) {
|
|
|
|
auto i = 0u;
|
|
|
|
while (i < vec::len[t](subtys)) {
|
|
|
|
if (type_has_dynamic_size(cx, subtys.(i))) { ret true; }
|
|
|
|
i += 1u;
|
|
|
|
}
|
|
|
|
ret false;
|
|
|
|
}
|
|
|
|
case (ty_box(_)) { ret false; }
|
|
|
|
case (ty_vec(_)) { ret false; }
|
|
|
|
case (ty_ivec(?mt)) { ret type_has_dynamic_size(cx, mt.ty); }
|
|
|
|
case (ty_ptr(_)) { ret false; }
|
|
|
|
case (ty_port(_)) { ret false; }
|
|
|
|
case (ty_chan(_)) { ret false; }
|
|
|
|
case (ty_task) { ret false; }
|
2011-03-17 19:39:47 -05:00
|
|
|
case (ty_tup(?mts)) {
|
2010-12-22 20:02:16 -06:00
|
|
|
auto i = 0u;
|
2011-05-17 13:41:41 -05:00
|
|
|
while (i < vec::len[mt](mts)) {
|
2011-04-25 14:15:55 -05:00
|
|
|
if (type_has_dynamic_size(cx, mts.(i).ty)) { ret true; }
|
2010-12-22 20:02:16 -06:00
|
|
|
i += 1u;
|
|
|
|
}
|
2011-06-17 14:03:40 -05:00
|
|
|
ret false;
|
2010-12-22 20:02:16 -06:00
|
|
|
}
|
|
|
|
case (ty_rec(?fields)) {
|
|
|
|
auto i = 0u;
|
2011-05-17 13:41:41 -05:00
|
|
|
while (i < vec::len[field](fields)) {
|
2011-06-15 13:19:50 -05:00
|
|
|
if (type_has_dynamic_size(cx, fields.(i).mt.ty)) { ret true; }
|
2010-12-22 20:02:16 -06:00
|
|
|
i += 1u;
|
|
|
|
}
|
2011-06-17 14:03:40 -05:00
|
|
|
ret false;
|
2010-12-22 20:02:16 -06:00
|
|
|
}
|
2011-06-17 14:03:40 -05:00
|
|
|
case (ty_fn(_,_,_,_,_)) { ret false; }
|
|
|
|
case (ty_native_fn(_,_,_)) { ret false; }
|
|
|
|
case (ty_obj(_)) { ret false; }
|
|
|
|
case (ty_var(_)) { fail "ty_var in type_has_dynamic_size()"; }
|
2010-12-22 20:02:16 -06:00
|
|
|
case (ty_param(_)) { ret true; }
|
2011-06-17 14:03:40 -05:00
|
|
|
case (ty_type) { ret false; }
|
|
|
|
case (ty_native) { ret false; }
|
2010-12-22 20:02:16 -06:00
|
|
|
}
|
|
|
|
}
|
2010-12-21 14:13:51 -06:00
|
|
|
|
2011-05-09 15:09:20 -05:00
|
|
|
fn type_is_integral(&ctxt cx, &t ty) -> bool {
|
2011-04-25 14:15:55 -05:00
|
|
|
alt (struct(cx, ty)) {
|
2010-12-21 14:13:51 -06:00
|
|
|
case (ty_int) { ret true; }
|
|
|
|
case (ty_uint) { ret true; }
|
|
|
|
case (ty_machine(?m)) {
|
|
|
|
alt (m) {
|
2011-06-15 17:14:30 -05:00
|
|
|
case (ty_i8) { ret true; }
|
|
|
|
case (ty_i16) { ret true; }
|
|
|
|
case (ty_i32) { ret true; }
|
|
|
|
case (ty_i64) { ret true; }
|
|
|
|
case (ty_u8) { ret true; }
|
|
|
|
case (ty_u16) { ret true; }
|
|
|
|
case (ty_u32) { ret true; }
|
|
|
|
case (ty_u64) { ret true; }
|
2010-12-21 14:13:51 -06:00
|
|
|
case (_) { ret false; }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
case (ty_char) { ret true; }
|
|
|
|
case (_) { ret false; }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-05-09 15:09:20 -05:00
|
|
|
fn type_is_fp(&ctxt cx, &t ty) -> bool {
|
2011-04-25 14:15:55 -05:00
|
|
|
alt (struct(cx, ty)) {
|
2010-12-21 14:13:51 -06:00
|
|
|
case (ty_machine(?tm)) {
|
|
|
|
alt (tm) {
|
2011-06-15 17:14:30 -05:00
|
|
|
case (ty_f32) { ret true; }
|
|
|
|
case (ty_f64) { ret true; }
|
2010-12-21 14:13:51 -06:00
|
|
|
case (_) { ret false; }
|
|
|
|
}
|
|
|
|
}
|
2011-06-15 13:19:50 -05:00
|
|
|
case (ty_float) { ret true; }
|
2010-12-21 14:13:51 -06:00
|
|
|
case (_) { ret false; }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-05-09 15:09:20 -05:00
|
|
|
fn type_is_signed(&ctxt cx, &t ty) -> bool {
|
2011-04-25 14:15:55 -05:00
|
|
|
alt (struct(cx, ty)) {
|
2010-12-21 14:13:51 -06:00
|
|
|
case (ty_int) { ret true; }
|
|
|
|
case (ty_machine(?tm)) {
|
|
|
|
alt (tm) {
|
2011-06-15 17:14:30 -05:00
|
|
|
case (ty_i8) { ret true; }
|
|
|
|
case (ty_i16) { ret true; }
|
|
|
|
case (ty_i32) { ret true; }
|
|
|
|
case (ty_i64) { ret true; }
|
2010-12-21 14:13:51 -06:00
|
|
|
case (_) { ret false; }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
case (_) { ret false; }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-06-17 14:32:07 -05:00
|
|
|
fn type_owns_heap_mem(&ctxt cx, &t ty) -> bool {
|
|
|
|
alt (struct(cx, ty)) {
|
|
|
|
case (ty_ivec(_)) { ret true; }
|
|
|
|
case (ty_istr) { ret true; }
|
|
|
|
|
|
|
|
case (ty_nil) { ret false; }
|
|
|
|
case (ty_bot) { ret false; }
|
|
|
|
case (ty_bool) { ret false; }
|
|
|
|
case (ty_int) { ret false; }
|
|
|
|
case (ty_float) { ret false; }
|
|
|
|
case (ty_uint) { ret false; }
|
|
|
|
case (ty_machine(_)) { ret false; }
|
|
|
|
case (ty_char) { ret false; }
|
|
|
|
case (ty_str) { ret false; }
|
|
|
|
case (ty_tag(_,_)) { ret false; }
|
|
|
|
case (ty_box(_)) { ret false; }
|
|
|
|
case (ty_vec(_)) { ret false; }
|
|
|
|
case (ty_ptr(_)) { ret false; }
|
|
|
|
case (ty_port(_)) { ret false; }
|
|
|
|
case (ty_chan(_)) { ret false; }
|
|
|
|
case (ty_task) { ret false; }
|
|
|
|
case (ty_tup(_)) { ret false; }
|
|
|
|
case (ty_rec(_)) { ret false; }
|
|
|
|
case (ty_fn(_,_,_,_,_)) { ret false; }
|
|
|
|
case (ty_native_fn(_,_,_)) { ret false; }
|
|
|
|
case (ty_obj(_)) { ret false; }
|
|
|
|
case (ty_var(_)) { fail "ty_var in type_owns_heap_mem"; }
|
|
|
|
case (ty_param(_)) { ret false; }
|
|
|
|
case (ty_type) { ret false; }
|
|
|
|
case (ty_native) { ret false; }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-05-12 10:24:54 -05:00
|
|
|
fn type_param(&ctxt cx, &t ty) -> option::t[uint] {
|
2011-04-25 14:15:55 -05:00
|
|
|
alt (struct(cx, ty)) {
|
2011-04-12 17:09:50 -05:00
|
|
|
case (ty_param(?id)) { ret some[uint](id); }
|
2011-06-15 13:19:50 -05:00
|
|
|
case (_) {/* fall through */ }
|
2010-12-21 14:13:51 -06:00
|
|
|
}
|
2011-04-12 17:09:50 -05:00
|
|
|
ret none[uint];
|
2010-12-21 14:13:51 -06:00
|
|
|
}
|
|
|
|
|
2011-06-15 13:19:50 -05:00
|
|
|
fn def_to_str(&ast::def_id did) -> str { ret #fmt("%d:%d", did._0, did._1); }
|
2011-04-19 18:40:18 -05:00
|
|
|
|
2011-04-22 21:52:30 -05:00
|
|
|
|
2011-04-20 14:22:28 -05:00
|
|
|
// Type hashing. This function is private to this module (and slow); external
|
|
|
|
// users should use `hash_ty()` instead.
|
|
|
|
fn hash_type_structure(&sty st) -> uint {
|
2011-04-20 16:34:17 -05:00
|
|
|
fn hash_uint(uint id, uint n) -> uint {
|
|
|
|
auto h = id;
|
|
|
|
h += h << 5u + n;
|
|
|
|
ret h;
|
|
|
|
}
|
2011-05-12 10:24:54 -05:00
|
|
|
fn hash_def(uint id, ast::def_id did) -> uint {
|
2011-04-20 16:34:17 -05:00
|
|
|
auto h = id;
|
|
|
|
h += h << 5u + (did._0 as uint);
|
|
|
|
h += h << 5u + (did._1 as uint);
|
|
|
|
ret h;
|
2011-04-19 20:46:22 -05:00
|
|
|
}
|
2011-05-09 15:09:20 -05:00
|
|
|
fn hash_subty(uint id, &t subty) -> uint {
|
2011-04-20 16:34:17 -05:00
|
|
|
auto h = id;
|
|
|
|
h += h << 5u + hash_ty(subty);
|
|
|
|
ret h;
|
|
|
|
}
|
2011-05-09 15:09:20 -05:00
|
|
|
fn hash_fn(uint id, &vec[arg] args, &t rty) -> uint {
|
2011-04-20 16:34:17 -05:00
|
|
|
auto h = id;
|
2011-06-15 13:19:50 -05:00
|
|
|
for (arg a in args) { h += h << 5u + hash_ty(a.ty); }
|
2011-04-20 16:34:17 -05:00
|
|
|
h += h << 5u + hash_ty(rty);
|
|
|
|
ret h;
|
|
|
|
}
|
|
|
|
alt (st) {
|
|
|
|
case (ty_nil) { ret 0u; }
|
|
|
|
case (ty_bool) { ret 1u; }
|
|
|
|
case (ty_int) { ret 2u; }
|
|
|
|
case (ty_float) { ret 3u; }
|
|
|
|
case (ty_uint) { ret 4u; }
|
|
|
|
case (ty_machine(?tm)) {
|
|
|
|
alt (tm) {
|
2011-06-15 17:14:30 -05:00
|
|
|
case (ty_i8) { ret 5u; }
|
|
|
|
case (ty_i16) { ret 6u; }
|
|
|
|
case (ty_i32) { ret 7u; }
|
|
|
|
case (ty_i64) { ret 8u; }
|
|
|
|
case (ty_u8) { ret 9u; }
|
|
|
|
case (ty_u16) { ret 10u; }
|
|
|
|
case (ty_u32) { ret 11u; }
|
|
|
|
case (ty_u64) { ret 12u; }
|
|
|
|
case (ty_f32) { ret 13u; }
|
|
|
|
case (ty_f64) { ret 14u; }
|
2011-04-20 16:34:17 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
case (ty_char) { ret 15u; }
|
|
|
|
case (ty_str) { ret 16u; }
|
2011-06-09 18:23:19 -05:00
|
|
|
case (ty_istr) { ret 17u; }
|
2011-04-20 16:34:17 -05:00
|
|
|
case (ty_tag(?did, ?tys)) {
|
2011-06-09 18:23:19 -05:00
|
|
|
auto h = hash_def(18u, did);
|
2011-06-15 13:19:50 -05:00
|
|
|
for (t typ in tys) { h += h << 5u + hash_ty(typ); }
|
2011-04-20 16:34:17 -05:00
|
|
|
ret h;
|
|
|
|
}
|
2011-06-09 18:23:19 -05:00
|
|
|
case (ty_box(?mt)) { ret hash_subty(19u, mt.ty); }
|
|
|
|
case (ty_vec(?mt)) { ret hash_subty(20u, mt.ty); }
|
|
|
|
case (ty_ivec(?mt)) { ret hash_subty(21u, mt.ty); }
|
|
|
|
case (ty_port(?typ)) { ret hash_subty(22u, typ); }
|
|
|
|
case (ty_chan(?typ)) { ret hash_subty(23u, typ); }
|
|
|
|
case (ty_task) { ret 24u; }
|
2011-04-20 16:34:17 -05:00
|
|
|
case (ty_tup(?mts)) {
|
2011-06-09 18:23:19 -05:00
|
|
|
auto h = 25u;
|
2011-06-15 13:19:50 -05:00
|
|
|
for (mt tm in mts) { h += h << 5u + hash_ty(tm.ty); }
|
2011-04-20 16:34:17 -05:00
|
|
|
ret h;
|
|
|
|
}
|
|
|
|
case (ty_rec(?fields)) {
|
2011-06-09 18:23:19 -05:00
|
|
|
auto h = 26u;
|
2011-06-15 13:19:50 -05:00
|
|
|
for (field f in fields) { h += h << 5u + hash_ty(f.mt.ty); }
|
2011-04-20 16:34:17 -05:00
|
|
|
ret h;
|
|
|
|
}
|
2011-06-15 13:19:50 -05:00
|
|
|
case (
|
|
|
|
// ???
|
|
|
|
ty_fn(_, ?args, ?rty, _, _)) {
|
|
|
|
ret hash_fn(27u, args, rty);
|
|
|
|
}
|
2011-06-09 18:23:19 -05:00
|
|
|
case (ty_native_fn(_, ?args, ?rty)) { ret hash_fn(28u, args, rty); }
|
2011-04-20 16:34:17 -05:00
|
|
|
case (ty_obj(?methods)) {
|
2011-06-09 18:23:19 -05:00
|
|
|
auto h = 29u;
|
2011-06-15 13:19:50 -05:00
|
|
|
for (method m in methods) { h += h << 5u + str::hash(m.ident); }
|
2011-04-20 16:34:17 -05:00
|
|
|
ret h;
|
|
|
|
}
|
2011-06-09 18:23:19 -05:00
|
|
|
case (ty_var(?v)) { ret hash_uint(30u, v as uint); }
|
|
|
|
case (ty_param(?pid)) { ret hash_uint(31u, pid); }
|
|
|
|
case (ty_type) { ret 32u; }
|
|
|
|
case (ty_native) { ret 33u; }
|
|
|
|
case (ty_bot) { ret 34u; }
|
|
|
|
case (ty_ptr(?mt)) { ret hash_subty(35u, mt.ty); }
|
2011-04-20 16:34:17 -05:00
|
|
|
}
|
2010-12-21 14:13:51 -06:00
|
|
|
}
|
|
|
|
|
2011-05-12 10:24:54 -05:00
|
|
|
fn hash_type_info(&sty st, &option::t[str] cname_opt) -> uint {
|
2011-04-22 21:26:00 -05:00
|
|
|
auto h = hash_type_structure(st);
|
|
|
|
alt (cname_opt) {
|
2011-06-15 13:19:50 -05:00
|
|
|
case (none) {/* no-op */ }
|
2011-05-30 23:39:19 -05:00
|
|
|
case (some(?s)) { h += h << 5u + str::hash(s); }
|
2011-04-22 21:26:00 -05:00
|
|
|
}
|
|
|
|
ret h;
|
|
|
|
}
|
|
|
|
|
2011-05-11 19:05:39 -05:00
|
|
|
fn hash_raw_ty(&raw_t rt) -> uint { ret rt.hash; }
|
|
|
|
|
|
|
|
fn hash_ty(&t typ) -> uint { ret typ; }
|
2011-04-20 14:22:28 -05:00
|
|
|
|
2011-04-21 00:30:48 -05:00
|
|
|
|
2011-04-21 19:06:01 -05:00
|
|
|
// Type equality. This function is private to this module (and slow); external
|
|
|
|
// users should use `eq_ty()` instead.
|
2011-06-10 21:12:42 -05:00
|
|
|
fn eq_int(&uint x, &uint y) -> bool { ret x == y; }
|
|
|
|
|
2011-06-15 13:19:50 -05:00
|
|
|
fn arg_eq[T](&fn(&T, &T) -> bool eq, @ast::constr_arg_general[T] a,
|
2011-06-10 21:12:42 -05:00
|
|
|
@ast::constr_arg_general[T] b) -> bool {
|
2011-06-09 11:48:16 -05:00
|
|
|
alt (a.node) {
|
|
|
|
case (ast::carg_base) {
|
|
|
|
alt (b.node) {
|
2011-06-15 13:19:50 -05:00
|
|
|
case (ast::carg_base) { ret true; }
|
|
|
|
case (_) { ret false; }
|
2011-06-09 11:48:16 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
case (ast::carg_ident(?s)) {
|
|
|
|
alt (b.node) {
|
2011-06-15 13:19:50 -05:00
|
|
|
case (ast::carg_ident(?t)) { ret eq(s, t); }
|
|
|
|
case (_) { ret false; }
|
2011-06-09 11:48:16 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
case (ast::carg_lit(?l)) {
|
|
|
|
alt (b.node) {
|
2011-06-15 17:14:30 -05:00
|
|
|
case (ast::carg_lit(?m)) { ret lit_eq(l, m); }
|
2011-06-15 13:19:50 -05:00
|
|
|
case (_) { ret false; }
|
2011-06-09 11:48:16 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2011-06-10 21:12:42 -05:00
|
|
|
|
2011-06-15 13:19:50 -05:00
|
|
|
fn args_eq[T](fn(&T, &T) -> bool eq, vec[@ast::constr_arg_general[T]] a,
|
|
|
|
vec[@ast::constr_arg_general[T]] b) -> bool {
|
2011-06-09 11:48:16 -05:00
|
|
|
let uint i = 0u;
|
2011-06-10 21:12:42 -05:00
|
|
|
for (@ast::constr_arg_general[T] arg in a) {
|
2011-06-15 13:19:50 -05:00
|
|
|
if (!arg_eq(eq, arg, b.(i))) { ret false; }
|
2011-06-09 11:48:16 -05:00
|
|
|
i += 1u;
|
|
|
|
}
|
|
|
|
ret true;
|
|
|
|
}
|
|
|
|
|
2011-06-15 17:14:30 -05:00
|
|
|
fn constr_eq(&@constr_def c, &@constr_def d) -> bool {
|
2011-06-15 13:19:50 -05:00
|
|
|
ret path_to_str(c.node.path) == path_to_str(d.node.path) &&
|
2011-06-16 18:55:46 -05:00
|
|
|
// FIXME: hack
|
2011-06-15 13:19:50 -05:00
|
|
|
args_eq(eq_int, c.node.args, d.node.args);
|
2011-06-09 11:48:16 -05:00
|
|
|
}
|
|
|
|
|
2011-06-15 17:14:30 -05:00
|
|
|
fn constrs_eq(&vec[@constr_def] cs, &vec[@constr_def] ds) -> bool {
|
2011-06-15 13:19:50 -05:00
|
|
|
if (vec::len(cs) != vec::len(ds)) { ret false; }
|
2011-06-15 17:14:30 -05:00
|
|
|
auto i = 0u;
|
|
|
|
for (@constr_def c in cs) {
|
2011-06-15 13:19:50 -05:00
|
|
|
if (!constr_eq(c, ds.(i))) { ret false; }
|
2011-06-15 17:14:30 -05:00
|
|
|
i += 1u;
|
2011-06-09 11:48:16 -05:00
|
|
|
}
|
|
|
|
ret true;
|
|
|
|
}
|
|
|
|
|
2011-04-21 19:06:01 -05:00
|
|
|
fn equal_type_structures(&sty a, &sty b) -> bool {
|
|
|
|
fn equal_mt(&mt a, &mt b) -> bool {
|
2011-05-11 18:18:02 -05:00
|
|
|
ret a.mut == b.mut && eq_ty(a.ty, b.ty);
|
2011-04-21 19:06:01 -05:00
|
|
|
}
|
2011-06-15 13:19:50 -05:00
|
|
|
fn equal_fn(&vec[arg] args_a, &t rty_a, &vec[arg] args_b, &t rty_b) ->
|
|
|
|
bool {
|
2011-04-25 18:17:14 -05:00
|
|
|
if (!eq_ty(rty_a, rty_b)) { ret false; }
|
2011-05-17 13:41:41 -05:00
|
|
|
auto len = vec::len[arg](args_a);
|
|
|
|
if (len != vec::len[arg](args_b)) { ret false; }
|
2011-04-21 19:06:01 -05:00
|
|
|
auto i = 0u;
|
|
|
|
while (i < len) {
|
2011-06-15 13:19:50 -05:00
|
|
|
auto arg_a = args_a.(i);
|
|
|
|
auto arg_b = args_b.(i);
|
2011-05-09 14:27:03 -05:00
|
|
|
if (arg_a.mode != arg_b.mode) { ret false; }
|
2011-04-25 18:17:14 -05:00
|
|
|
if (!eq_ty(arg_a.ty, arg_b.ty)) { ret false; }
|
2011-04-21 19:06:01 -05:00
|
|
|
i += 1u;
|
|
|
|
}
|
|
|
|
ret true;
|
|
|
|
}
|
2011-05-12 10:24:54 -05:00
|
|
|
fn equal_def(&ast::def_id did_a, &ast::def_id did_b) -> bool {
|
2011-04-21 19:06:01 -05:00
|
|
|
ret did_a._0 == did_b._0 && did_a._1 == did_b._1;
|
|
|
|
}
|
|
|
|
alt (a) {
|
|
|
|
case (ty_nil) {
|
2011-06-15 13:19:50 -05:00
|
|
|
alt (b) { case (ty_nil) { ret true; } case (_) { ret false; } }
|
2011-04-21 19:06:01 -05:00
|
|
|
}
|
2011-05-14 21:02:30 -05:00
|
|
|
case (ty_bot) {
|
2011-06-15 13:19:50 -05:00
|
|
|
alt (b) { case (ty_bot) { ret true; } case (_) { ret false; } }
|
2011-05-14 21:02:30 -05:00
|
|
|
}
|
2011-04-21 19:06:01 -05:00
|
|
|
case (ty_bool) {
|
2011-06-15 13:19:50 -05:00
|
|
|
alt (b) { case (ty_bool) { ret true; } case (_) { ret false; } }
|
2011-04-21 19:06:01 -05:00
|
|
|
}
|
|
|
|
case (ty_int) {
|
2011-06-15 13:19:50 -05:00
|
|
|
alt (b) { case (ty_int) { ret true; } case (_) { ret false; } }
|
2011-04-21 19:06:01 -05:00
|
|
|
}
|
|
|
|
case (ty_float) {
|
2011-06-15 13:19:50 -05:00
|
|
|
alt (b) { case (ty_float) { ret true; } case (_) { ret false; } }
|
2011-04-21 19:06:01 -05:00
|
|
|
}
|
|
|
|
case (ty_uint) {
|
2011-06-15 13:19:50 -05:00
|
|
|
alt (b) { case (ty_uint) { ret true; } case (_) { ret false; } }
|
2011-04-21 19:06:01 -05:00
|
|
|
}
|
|
|
|
case (ty_machine(?tm_a)) {
|
|
|
|
alt (b) {
|
|
|
|
case (ty_machine(?tm_b)) {
|
|
|
|
ret hash_type_structure(a) == hash_type_structure(b);
|
|
|
|
}
|
|
|
|
case (_) { ret false; }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
case (ty_char) {
|
2011-06-15 13:19:50 -05:00
|
|
|
alt (b) { case (ty_char) { ret true; } case (_) { ret false; } }
|
2011-04-21 19:06:01 -05:00
|
|
|
}
|
|
|
|
case (ty_str) {
|
2011-06-15 13:19:50 -05:00
|
|
|
alt (b) { case (ty_str) { ret true; } case (_) { ret false; } }
|
2011-04-21 19:06:01 -05:00
|
|
|
}
|
2011-06-10 13:00:37 -05:00
|
|
|
case (ty_istr) {
|
2011-06-15 13:19:50 -05:00
|
|
|
alt (b) { case (ty_istr) { ret true; } case (_) { ret false; } }
|
2011-06-10 13:00:37 -05:00
|
|
|
}
|
2011-04-21 19:06:01 -05:00
|
|
|
case (ty_tag(?id_a, ?tys_a)) {
|
|
|
|
alt (b) {
|
|
|
|
case (ty_tag(?id_b, ?tys_b)) {
|
2011-04-21 21:30:53 -05:00
|
|
|
if (!equal_def(id_a, id_b)) { ret false; }
|
2011-05-17 13:41:41 -05:00
|
|
|
auto len = vec::len[t](tys_a);
|
|
|
|
if (len != vec::len[t](tys_b)) { ret false; }
|
2011-04-21 19:06:01 -05:00
|
|
|
auto i = 0u;
|
|
|
|
while (i < len) {
|
2011-04-25 18:17:14 -05:00
|
|
|
if (!eq_ty(tys_a.(i), tys_b.(i))) { ret false; }
|
2011-04-21 19:06:01 -05:00
|
|
|
i += 1u;
|
|
|
|
}
|
|
|
|
ret true;
|
|
|
|
}
|
|
|
|
case (_) { ret false; }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
case (ty_box(?mt_a)) {
|
|
|
|
alt (b) {
|
|
|
|
case (ty_box(?mt_b)) { ret equal_mt(mt_a, mt_b); }
|
|
|
|
case (_) { ret false; }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
case (ty_vec(?mt_a)) {
|
|
|
|
alt (b) {
|
|
|
|
case (ty_vec(?mt_b)) { ret equal_mt(mt_a, mt_b); }
|
|
|
|
case (_) { ret false; }
|
|
|
|
}
|
|
|
|
}
|
2011-06-10 13:00:37 -05:00
|
|
|
case (ty_ivec(?mt_a)) {
|
|
|
|
alt (b) {
|
|
|
|
case (ty_ivec(?mt_b)) { ret equal_mt(mt_a, mt_b); }
|
|
|
|
case (_) { ret false; }
|
|
|
|
}
|
|
|
|
}
|
2011-06-03 14:02:58 -05:00
|
|
|
case (ty_ptr(?mt_a)) {
|
|
|
|
alt (b) {
|
|
|
|
case (ty_ptr(?mt_b)) { ret equal_mt(mt_a, mt_b); }
|
|
|
|
case (_) { ret false; }
|
|
|
|
}
|
|
|
|
}
|
2011-04-21 19:06:01 -05:00
|
|
|
case (ty_port(?t_a)) {
|
|
|
|
alt (b) {
|
2011-04-25 18:17:14 -05:00
|
|
|
case (ty_port(?t_b)) { ret eq_ty(t_a, t_b); }
|
2011-04-21 19:06:01 -05:00
|
|
|
case (_) { ret false; }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
case (ty_chan(?t_a)) {
|
|
|
|
alt (b) {
|
2011-04-25 18:17:14 -05:00
|
|
|
case (ty_chan(?t_b)) { ret eq_ty(t_a, t_b); }
|
2011-04-21 19:06:01 -05:00
|
|
|
case (_) { ret false; }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
case (ty_task) {
|
2011-06-15 13:19:50 -05:00
|
|
|
alt (b) { case (ty_task) { ret true; } case (_) { ret false; } }
|
2011-04-21 19:06:01 -05:00
|
|
|
}
|
|
|
|
case (ty_tup(?mts_a)) {
|
|
|
|
alt (b) {
|
|
|
|
case (ty_tup(?mts_b)) {
|
2011-05-17 13:41:41 -05:00
|
|
|
auto len = vec::len[mt](mts_a);
|
|
|
|
if (len != vec::len[mt](mts_b)) { ret false; }
|
2011-04-21 19:06:01 -05:00
|
|
|
auto i = 0u;
|
|
|
|
while (i < len) {
|
|
|
|
if (!equal_mt(mts_a.(i), mts_b.(i))) { ret false; }
|
|
|
|
i += 1u;
|
|
|
|
}
|
|
|
|
ret true;
|
|
|
|
}
|
|
|
|
case (_) { ret false; }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
case (ty_rec(?flds_a)) {
|
|
|
|
alt (b) {
|
|
|
|
case (ty_rec(?flds_b)) {
|
2011-05-17 13:41:41 -05:00
|
|
|
auto len = vec::len[field](flds_a);
|
|
|
|
if (len != vec::len[field](flds_b)) { ret false; }
|
2011-04-21 19:06:01 -05:00
|
|
|
auto i = 0u;
|
|
|
|
while (i < len) {
|
2011-06-15 13:19:50 -05:00
|
|
|
auto fld_a = flds_a.(i);
|
|
|
|
auto fld_b = flds_b.(i);
|
2011-05-17 13:41:41 -05:00
|
|
|
if (!str::eq(fld_a.ident, fld_b.ident) ||
|
2011-04-21 19:06:01 -05:00
|
|
|
!equal_mt(fld_a.mt, fld_b.mt)) {
|
|
|
|
ret false;
|
|
|
|
}
|
|
|
|
i += 1u;
|
|
|
|
}
|
|
|
|
ret true;
|
|
|
|
}
|
|
|
|
case (_) { ret false; }
|
|
|
|
}
|
|
|
|
}
|
2011-06-09 11:48:16 -05:00
|
|
|
case (ty_fn(?p_a, ?args_a, ?rty_a, ?cf_a, ?constrs_a)) {
|
2011-04-21 19:06:01 -05:00
|
|
|
alt (b) {
|
2011-06-09 11:48:16 -05:00
|
|
|
case (ty_fn(?p_b, ?args_b, ?rty_b, ?cf_b, ?constrs_b)) {
|
2011-06-15 13:19:50 -05:00
|
|
|
ret p_a == p_b && cf_a == cf_b &&
|
|
|
|
constrs_eq(constrs_a, constrs_b) &&
|
|
|
|
equal_fn(args_a, rty_a, args_b, rty_b);
|
2011-04-21 19:06:01 -05:00
|
|
|
}
|
|
|
|
case (_) { ret false; }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
case (ty_native_fn(?abi_a, ?args_a, ?rty_a)) {
|
|
|
|
alt (b) {
|
|
|
|
case (ty_native_fn(?abi_b, ?args_b, ?rty_b)) {
|
2011-05-11 18:18:02 -05:00
|
|
|
ret abi_a == abi_b &&
|
2011-06-15 13:19:50 -05:00
|
|
|
equal_fn(args_a, rty_a, args_b, rty_b);
|
2011-04-21 19:06:01 -05:00
|
|
|
}
|
|
|
|
case (_) { ret false; }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
case (ty_obj(?methods_a)) {
|
|
|
|
alt (b) {
|
|
|
|
case (ty_obj(?methods_b)) {
|
2011-05-17 13:41:41 -05:00
|
|
|
auto len = vec::len[method](methods_a);
|
|
|
|
if (len != vec::len[method](methods_b)) { ret false; }
|
2011-04-21 19:06:01 -05:00
|
|
|
auto i = 0u;
|
|
|
|
while (i < len) {
|
2011-06-15 13:19:50 -05:00
|
|
|
auto m_a = methods_a.(i);
|
|
|
|
auto m_b = methods_b.(i);
|
2011-05-11 18:18:02 -05:00
|
|
|
if (m_a.proto != m_b.proto ||
|
2011-05-17 13:41:41 -05:00
|
|
|
!str::eq(m_a.ident, m_b.ident) ||
|
2011-06-15 13:19:50 -05:00
|
|
|
!equal_fn(m_a.inputs, m_a.output, m_b.inputs,
|
|
|
|
m_b.output)) {
|
2011-04-21 19:06:01 -05:00
|
|
|
ret false;
|
|
|
|
}
|
2011-04-21 21:30:53 -05:00
|
|
|
i += 1u;
|
2011-04-21 19:06:01 -05:00
|
|
|
}
|
|
|
|
ret true;
|
|
|
|
}
|
|
|
|
case (_) { ret false; }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
case (ty_var(?v_a)) {
|
|
|
|
alt (b) {
|
|
|
|
case (ty_var(?v_b)) { ret v_a == v_b; }
|
|
|
|
case (_) { ret false; }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
case (ty_param(?pid_a)) {
|
|
|
|
alt (b) {
|
|
|
|
case (ty_param(?pid_b)) { ret pid_a == pid_b; }
|
|
|
|
case (_) { ret false; }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
case (ty_type) {
|
2011-06-15 13:19:50 -05:00
|
|
|
alt (b) { case (ty_type) { ret true; } case (_) { ret false; } }
|
2011-04-21 19:06:01 -05:00
|
|
|
}
|
|
|
|
case (ty_native) {
|
2011-06-15 13:19:50 -05:00
|
|
|
alt (b) { case (ty_native) { ret true; } case (_) { ret false; } }
|
2011-04-21 19:06:01 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-06-15 13:19:50 -05:00
|
|
|
|
2011-04-21 21:30:53 -05:00
|
|
|
// An expensive type equality function. This function is private to this
|
|
|
|
// module.
|
2011-05-11 18:10:17 -05:00
|
|
|
//
|
|
|
|
// FIXME: Use structural comparison, but this loops forever and segfaults.
|
2011-05-11 19:05:39 -05:00
|
|
|
fn eq_raw_ty(&raw_t a, &raw_t b) -> bool {
|
2011-04-21 21:30:53 -05:00
|
|
|
// Check hashes (fast path).
|
2011-04-21 00:30:48 -05:00
|
|
|
|
2011-06-15 13:19:50 -05:00
|
|
|
if (a.hash != b.hash) { ret false; }
|
2011-04-21 21:30:53 -05:00
|
|
|
// Check canonical names.
|
2011-06-15 13:19:50 -05:00
|
|
|
|
2011-04-22 19:00:46 -05:00
|
|
|
alt (a.cname) {
|
2011-05-30 23:39:19 -05:00
|
|
|
case (none) {
|
2011-04-22 19:00:46 -05:00
|
|
|
alt (b.cname) {
|
2011-06-15 13:19:50 -05:00
|
|
|
case (none[str]) {/* ok */ }
|
2011-04-21 00:30:48 -05:00
|
|
|
case (_) { ret false; }
|
|
|
|
}
|
|
|
|
}
|
2011-05-30 23:39:19 -05:00
|
|
|
case (some(?s_a)) {
|
2011-04-22 19:00:46 -05:00
|
|
|
alt (b.cname) {
|
2011-06-15 13:19:50 -05:00
|
|
|
case (some(?s_b)) { if (!str::eq(s_a, s_b)) { ret false; } }
|
2011-04-21 00:30:48 -05:00
|
|
|
case (_) { ret false; }
|
|
|
|
}
|
|
|
|
}
|
2011-04-21 21:30:53 -05:00
|
|
|
}
|
|
|
|
// Check structures.
|
2011-06-15 13:19:50 -05:00
|
|
|
|
2011-04-22 19:00:46 -05:00
|
|
|
ret equal_type_structures(a.struct, b.struct);
|
2011-04-21 21:30:53 -05:00
|
|
|
}
|
2011-04-21 00:30:48 -05:00
|
|
|
|
2011-06-15 13:19:50 -05:00
|
|
|
|
2011-04-21 21:30:53 -05:00
|
|
|
// This is the equality function the public should use. It works as long as
|
|
|
|
// the types are interned.
|
2011-05-11 19:05:39 -05:00
|
|
|
fn eq_ty(&t a, &t b) -> bool { ret a == b; }
|
2011-04-21 00:30:48 -05:00
|
|
|
|
2010-12-21 14:13:51 -06:00
|
|
|
|
2011-05-13 18:40:21 -05:00
|
|
|
// Type lookups
|
2011-06-15 13:19:50 -05:00
|
|
|
fn ann_to_ty_param_substs_opt_and_ty(&ctxt cx, &ast::ann ann) ->
|
|
|
|
ty_param_substs_opt_and_ty {
|
2011-06-07 15:50:30 -05:00
|
|
|
|
|
|
|
// Pull out the node type table.
|
2011-06-15 13:19:50 -05:00
|
|
|
alt ({ cx.node_types.(ann.id) }) {
|
2011-05-30 23:39:19 -05:00
|
|
|
case (none) {
|
2011-06-07 17:07:27 -05:00
|
|
|
cx.sess.bug("ann_to_ty_param_substs_opt_and_ty() called on an " +
|
2011-06-15 13:19:50 -05:00
|
|
|
"untyped node");
|
2011-05-13 15:05:55 -05:00
|
|
|
}
|
2011-05-30 23:39:19 -05:00
|
|
|
case (some(?tpot)) { ret tpot; }
|
2011-05-13 15:05:55 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-06-07 17:07:27 -05:00
|
|
|
fn ann_to_type(&ctxt cx, &ast::ann ann) -> t {
|
|
|
|
ret ann_to_ty_param_substs_opt_and_ty(cx, ann)._1;
|
2011-05-13 18:40:21 -05:00
|
|
|
}
|
|
|
|
|
2011-06-07 17:07:27 -05:00
|
|
|
fn ann_to_type_params(&ctxt cx, &ast::ann ann) -> vec[t] {
|
|
|
|
alt (ann_to_ty_param_substs_opt_and_ty(cx, ann)._0) {
|
2011-06-15 13:19:50 -05:00
|
|
|
case (none) { let vec[t] result = []; ret result; }
|
2011-05-30 23:39:19 -05:00
|
|
|
case (some(?tps)) { ret tps; }
|
2011-05-13 18:40:21 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-06-07 17:07:27 -05:00
|
|
|
fn ann_has_type_params(&ctxt cx, &ast::ann ann) -> bool {
|
|
|
|
auto tpt = ann_to_ty_param_substs_opt_and_ty(cx, ann);
|
2011-05-13 18:53:35 -05:00
|
|
|
ret !option::is_none[vec[t]](tpt._0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-05-20 20:36:35 -05:00
|
|
|
// Returns a type with type parameter substitutions performed if applicable.
|
|
|
|
fn ty_param_substs_opt_and_ty_to_monotype(&ctxt cx,
|
2011-06-15 13:19:50 -05:00
|
|
|
&ty_param_substs_opt_and_ty tpot) ->
|
|
|
|
t {
|
2011-05-20 20:36:35 -05:00
|
|
|
alt (tpot._0) {
|
|
|
|
case (none) { ret tpot._1; }
|
|
|
|
case (some(?tps)) { ret substitute_type_params(cx, tps, tpot._1); }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-06-15 13:19:50 -05:00
|
|
|
|
2011-04-08 23:27:54 -05:00
|
|
|
// Returns the type of an annotation, with type parameter substitutions
|
|
|
|
// performed if applicable.
|
2011-05-19 17:47:15 -05:00
|
|
|
fn ann_to_monotype(&ctxt cx, ast::ann a) -> t {
|
2011-06-07 15:50:30 -05:00
|
|
|
auto tpot = ann_to_ty_param_substs_opt_and_ty(cx, a);
|
2011-05-20 20:36:35 -05:00
|
|
|
ret ty_param_substs_opt_and_ty_to_monotype(cx, tpot);
|
2011-04-08 23:27:54 -05:00
|
|
|
}
|
|
|
|
|
2011-05-13 18:40:21 -05:00
|
|
|
|
2011-04-12 17:09:50 -05:00
|
|
|
// Returns the number of distinct type parameters in the given type.
|
2011-05-19 17:47:15 -05:00
|
|
|
fn count_ty_params(&ctxt cx, t ty) -> uint {
|
|
|
|
fn counter(&ctxt cx, @mutable vec[uint] param_indices, t ty) {
|
2011-04-25 14:15:55 -05:00
|
|
|
alt (struct(cx, ty)) {
|
2011-04-15 14:23:00 -05:00
|
|
|
case (ty_param(?param_idx)) {
|
|
|
|
auto seen = false;
|
|
|
|
for (uint other_param_idx in *param_indices) {
|
2011-06-15 13:19:50 -05:00
|
|
|
if (param_idx == other_param_idx) { seen = true; }
|
2011-04-15 14:23:00 -05:00
|
|
|
}
|
2011-06-15 13:19:50 -05:00
|
|
|
if (!seen) { *param_indices += [param_idx]; }
|
2010-12-21 14:13:51 -06:00
|
|
|
}
|
2011-06-15 13:19:50 -05:00
|
|
|
case (_) {/* fall through */ }
|
2010-12-21 14:13:51 -06:00
|
|
|
}
|
|
|
|
}
|
2011-06-15 13:19:50 -05:00
|
|
|
let vec[uint] v = []; // FIXME: typechecker botch
|
2010-12-21 14:13:51 -06:00
|
|
|
|
2011-04-12 17:09:50 -05:00
|
|
|
let @mutable vec[uint] param_indices = @mutable v;
|
2011-04-25 14:15:55 -05:00
|
|
|
auto f = bind counter(cx, param_indices, _);
|
|
|
|
walk_ty(cx, f, ty);
|
2011-05-17 13:41:41 -05:00
|
|
|
ret vec::len[uint](*param_indices);
|
2010-12-21 14:13:51 -06:00
|
|
|
}
|
|
|
|
|
2011-05-09 15:09:20 -05:00
|
|
|
fn type_contains_vars(&ctxt cx, &t typ) -> bool {
|
2011-05-16 15:58:13 -05:00
|
|
|
ret interner::get[raw_t](*cx.ts, typ).has_vars;
|
2011-04-08 23:27:54 -05:00
|
|
|
}
|
|
|
|
|
2011-05-09 15:09:20 -05:00
|
|
|
fn type_contains_params(&ctxt cx, &t typ) -> bool {
|
2011-05-16 15:58:13 -05:00
|
|
|
ret interner::get[raw_t](*cx.ts, typ).has_params;
|
2011-04-25 00:39:18 -05:00
|
|
|
}
|
|
|
|
|
2011-01-03 20:22:39 -06:00
|
|
|
|
2011-06-15 13:19:50 -05:00
|
|
|
// Type accessors for substructures of types
|
2011-05-09 15:09:20 -05:00
|
|
|
fn ty_fn_args(&ctxt cx, &t fty) -> vec[arg] {
|
2011-04-25 14:15:55 -05:00
|
|
|
alt (struct(cx, fty)) {
|
2011-06-09 11:48:16 -05:00
|
|
|
case (ty::ty_fn(_, ?a, _, _, _)) { ret a; }
|
2011-05-12 10:24:54 -05:00
|
|
|
case (ty::ty_native_fn(_, ?a, _)) { ret a; }
|
2011-02-18 19:30:57 -06:00
|
|
|
}
|
2011-06-07 15:50:30 -05:00
|
|
|
cx.sess.bug("ty_fn_args() called on non-fn type");
|
2011-02-18 19:30:57 -06:00
|
|
|
}
|
|
|
|
|
2011-05-12 10:24:54 -05:00
|
|
|
fn ty_fn_proto(&ctxt cx, &t fty) -> ast::proto {
|
2011-06-15 13:19:50 -05:00
|
|
|
alt (struct(cx, fty)) { case (ty::ty_fn(?p, _, _, _, _)) { ret p; } }
|
2011-06-07 15:50:30 -05:00
|
|
|
cx.sess.bug("ty_fn_proto() called on non-fn type");
|
2011-01-03 20:22:39 -06:00
|
|
|
}
|
|
|
|
|
2011-05-12 10:24:54 -05:00
|
|
|
fn ty_fn_abi(&ctxt cx, &t fty) -> ast::native_abi {
|
2011-06-15 13:19:50 -05:00
|
|
|
alt (struct(cx, fty)) { case (ty::ty_native_fn(?a, _, _)) { ret a; } }
|
2011-06-07 15:50:30 -05:00
|
|
|
cx.sess.bug("ty_fn_abi() called on non-native-fn type");
|
2011-03-07 14:37:40 -06:00
|
|
|
}
|
|
|
|
|
2011-05-09 15:09:20 -05:00
|
|
|
fn ty_fn_ret(&ctxt cx, &t fty) -> t {
|
2011-04-25 14:15:55 -05:00
|
|
|
alt (struct(cx, fty)) {
|
2011-06-09 11:48:16 -05:00
|
|
|
case (ty::ty_fn(_, _, ?r, _, _)) { ret r; }
|
2011-05-12 10:24:54 -05:00
|
|
|
case (ty::ty_native_fn(_, _, ?r)) { ret r; }
|
2011-02-18 19:30:57 -06:00
|
|
|
}
|
2011-06-07 15:50:30 -05:00
|
|
|
cx.sess.bug("ty_fn_ret() called on non-fn type");
|
2011-01-03 20:22:39 -06:00
|
|
|
}
|
|
|
|
|
2011-05-09 15:09:20 -05:00
|
|
|
fn is_fn_ty(&ctxt cx, &t fty) -> bool {
|
2011-04-25 14:15:55 -05:00
|
|
|
alt (struct(cx, fty)) {
|
2011-06-09 11:48:16 -05:00
|
|
|
case (ty::ty_fn(_, _, _, _, _)) { ret true; }
|
2011-05-12 10:24:54 -05:00
|
|
|
case (ty::ty_native_fn(_, _, _)) { ret true; }
|
2011-02-18 19:30:57 -06:00
|
|
|
case (_) { ret false; }
|
|
|
|
}
|
2011-01-03 20:22:39 -06:00
|
|
|
}
|
|
|
|
|
2011-05-20 20:36:35 -05:00
|
|
|
fn ty_var_id(&ctxt cx, t typ) -> int {
|
|
|
|
alt (struct(cx, typ)) {
|
|
|
|
case (ty::ty_var(?vid)) { ret vid; }
|
|
|
|
case (_) { log_err "ty_var_id called on non-var ty"; fail; }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-01-03 20:22:39 -06:00
|
|
|
|
2010-12-21 14:13:51 -06:00
|
|
|
// Type accessors for AST nodes
|
2011-06-15 13:19:50 -05:00
|
|
|
fn block_ty(&ctxt cx, &ast::block b) -> t { ret ann_to_type(cx, b.node.a); }
|
2010-12-21 14:13:51 -06:00
|
|
|
|
|
|
|
|
2011-04-08 23:27:54 -05:00
|
|
|
// Returns the type of a pattern as a monotype. Like @expr_ty, this function
|
|
|
|
// doesn't provide type parameter substitutions.
|
2011-05-19 17:47:15 -05:00
|
|
|
fn pat_ty(&ctxt cx, &@ast::pat pat) -> t {
|
|
|
|
ret ann_to_monotype(cx, pat_ann(pat));
|
2010-12-21 14:13:51 -06:00
|
|
|
}
|
|
|
|
|
2011-05-12 10:24:54 -05:00
|
|
|
fn expr_ann(&@ast::expr e) -> ast::ann {
|
2011-05-12 18:57:08 -05:00
|
|
|
alt (e.node) {
|
2011-06-15 13:19:50 -05:00
|
|
|
case (ast::expr_vec(_, _, _, ?a)) { ret a; }
|
|
|
|
case (ast::expr_tup(_, ?a)) { ret a; }
|
|
|
|
case (ast::expr_rec(_, _, ?a)) { ret a; }
|
|
|
|
case (ast::expr_call(_, _, ?a)) { ret a; }
|
|
|
|
case (ast::expr_bind(_, _, ?a)) { ret a; }
|
|
|
|
case (ast::expr_binary(_, _, _, ?a)) { ret a; }
|
|
|
|
case (ast::expr_unary(_, _, ?a)) { ret a; }
|
|
|
|
case (ast::expr_lit(_, ?a)) { ret a; }
|
|
|
|
case (ast::expr_cast(_, _, ?a)) { ret a; }
|
|
|
|
case (ast::expr_if(_, _, _, ?a)) { ret a; }
|
2011-06-16 13:56:34 -05:00
|
|
|
case (ast::expr_if_check(_, _, _, ?a)) { ret a; }
|
2011-06-15 13:19:50 -05:00
|
|
|
case (ast::expr_while(_, _, ?a)) { ret a; }
|
|
|
|
case (ast::expr_for(_, _, _, ?a)) { ret a; }
|
|
|
|
case (ast::expr_for_each(_, _, _, ?a)) { ret a; }
|
|
|
|
case (ast::expr_do_while(_, _, ?a)) { ret a; }
|
|
|
|
case (ast::expr_alt(_, _, ?a)) { ret a; }
|
|
|
|
case (ast::expr_fn(_, ?a)) { ret a; }
|
|
|
|
case (ast::expr_block(_, ?a)) { ret a; }
|
|
|
|
case (ast::expr_move(_, _, ?a)) { ret a; }
|
|
|
|
case (ast::expr_assign(_, _, ?a)) { ret a; }
|
2011-06-16 18:55:46 -05:00
|
|
|
case (ast::expr_swap(_, _, ?a)) { ret a; }
|
2011-06-15 13:19:50 -05:00
|
|
|
case (ast::expr_assign_op(_, _, _, ?a)) { ret a; }
|
|
|
|
case (ast::expr_send(_, _, ?a)) { ret a; }
|
|
|
|
case (ast::expr_recv(_, _, ?a)) { ret a; }
|
|
|
|
case (ast::expr_field(_, _, ?a)) { ret a; }
|
|
|
|
case (ast::expr_index(_, _, ?a)) { ret a; }
|
|
|
|
case (ast::expr_path(_, ?a)) { ret a; }
|
|
|
|
case (ast::expr_ext(_, _, _, _, ?a)) { ret a; }
|
|
|
|
case (ast::expr_fail(?a, _)) { ret a; }
|
|
|
|
case (ast::expr_ret(_, ?a)) { ret a; }
|
|
|
|
case (ast::expr_put(_, ?a)) { ret a; }
|
|
|
|
case (ast::expr_be(_, ?a)) { ret a; }
|
|
|
|
case (ast::expr_log(_, _, ?a)) { ret a; }
|
|
|
|
case (ast::expr_assert(_, ?a)) { ret a; }
|
|
|
|
case (ast::expr_check(_, ?a)) { ret a; }
|
2011-05-12 18:57:08 -05:00
|
|
|
case (ast::expr_port(?a)) { ret a; }
|
2011-06-15 13:19:50 -05:00
|
|
|
case (ast::expr_chan(_, ?a)) { ret a; }
|
|
|
|
case (ast::expr_anon_obj(_, _, _, ?a)) { ret a; }
|
2011-05-12 18:57:08 -05:00
|
|
|
case (ast::expr_break(?a)) { ret a; }
|
|
|
|
case (ast::expr_cont(?a)) { ret a; }
|
|
|
|
case (ast::expr_self_method(_, ?a)) { ret a; }
|
2011-05-17 13:49:50 -05:00
|
|
|
case (ast::expr_spawn(_, _, _, _, ?a)) { ret a; }
|
2010-12-21 14:13:51 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-06-15 13:19:50 -05:00
|
|
|
|
2011-04-08 23:27:54 -05:00
|
|
|
// Returns the type of an expression as a monotype.
|
|
|
|
//
|
|
|
|
// NB: This type doesn't provide type parameter substitutions; e.g. if you
|
|
|
|
// ask for the type of "id" in "id(3)", it will return "fn(&int) -> int"
|
|
|
|
// instead of "fn(&T) -> T with T = int". If this isn't what you want, see
|
|
|
|
// expr_ty_params_and_ty() below.
|
2011-05-19 17:47:15 -05:00
|
|
|
fn expr_ty(&ctxt cx, &@ast::expr expr) -> t {
|
|
|
|
ret ann_to_monotype(cx, expr_ann(expr));
|
2011-04-08 23:27:54 -05:00
|
|
|
}
|
|
|
|
|
2011-06-15 13:19:50 -05:00
|
|
|
fn expr_ty_params_and_ty(&ctxt cx, &@ast::expr expr) -> tup(vec[t], t) {
|
2011-05-02 19:47:24 -05:00
|
|
|
auto a = expr_ann(expr);
|
2011-06-15 13:19:50 -05:00
|
|
|
ret tup(ann_to_type_params(cx, a), ann_to_type(cx, a));
|
2011-04-08 23:27:54 -05:00
|
|
|
}
|
|
|
|
|
2011-06-07 17:07:27 -05:00
|
|
|
fn expr_has_ty_params(&ctxt cx, &@ast::expr expr) -> bool {
|
|
|
|
ret ann_has_type_params(cx, expr_ann(expr));
|
2011-04-08 23:27:54 -05:00
|
|
|
}
|
|
|
|
|
2011-06-16 17:58:25 -05:00
|
|
|
fn decl_local_ty(&ctxt cx, &@ast::local l) -> t {
|
|
|
|
ret ann_to_type(cx, l.node.ann);
|
2011-05-27 19:00:21 -05:00
|
|
|
}
|
|
|
|
|
2011-05-17 21:00:29 -05:00
|
|
|
fn stmt_ann(&@ast::stmt s) -> ast::ann {
|
|
|
|
alt (s.node) {
|
|
|
|
case (ast::stmt_decl(_, ?a)) { ret a; }
|
|
|
|
case (ast::stmt_expr(_, ?a)) { ret a; }
|
|
|
|
case (ast::stmt_crate_directive(_)) {
|
|
|
|
log_err "ty::stmt_ann(): crate directive found";
|
|
|
|
fail;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn pat_ann(&@ast::pat p) -> ast::ann {
|
|
|
|
alt (p.node) {
|
2011-06-15 13:19:50 -05:00
|
|
|
case (ast::pat_wild(?a)) { ret a; }
|
|
|
|
case (ast::pat_bind(_, _, ?a)) { ret a; }
|
|
|
|
case (ast::pat_lit(_, ?a)) { ret a; }
|
|
|
|
case (ast::pat_tag(_, _, ?a)) { ret a; }
|
2011-05-17 21:00:29 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-04-11 17:03:14 -05:00
|
|
|
|
2010-12-21 14:13:51 -06:00
|
|
|
// Expression utilities
|
2011-06-15 13:19:50 -05:00
|
|
|
fn field_num(&session::session sess, &span sp, &ast::ident id) -> uint {
|
2010-12-21 14:13:51 -06:00
|
|
|
let uint accum = 0u;
|
|
|
|
let uint i = 0u;
|
|
|
|
for (u8 c in id) {
|
|
|
|
if (i == 0u) {
|
2011-06-15 13:19:50 -05:00
|
|
|
if (c != '_' as u8) {
|
2010-12-21 14:13:51 -06:00
|
|
|
sess.span_err(sp,
|
2011-06-15 13:19:50 -05:00
|
|
|
"bad numeric field on tuple: " +
|
|
|
|
"missing leading underscore");
|
2010-12-21 14:13:51 -06:00
|
|
|
}
|
|
|
|
} else {
|
2011-06-15 13:19:50 -05:00
|
|
|
if ('0' as u8 <= c && c <= '9' as u8) {
|
2010-12-21 14:13:51 -06:00
|
|
|
accum *= 10u;
|
|
|
|
accum += (c as uint) - ('0' as uint);
|
|
|
|
} else {
|
|
|
|
auto s = "";
|
2011-05-17 13:41:41 -05:00
|
|
|
s += str::unsafe_from_byte(c);
|
2010-12-21 14:13:51 -06:00
|
|
|
sess.span_err(sp,
|
2011-06-15 13:19:50 -05:00
|
|
|
"bad numeric field on tuple: " +
|
|
|
|
" non-digit character: " + s);
|
2010-12-21 14:13:51 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
i += 1u;
|
|
|
|
}
|
|
|
|
ret accum;
|
|
|
|
}
|
|
|
|
|
2011-06-15 13:19:50 -05:00
|
|
|
fn field_idx(&session::session sess, &span sp, &ast::ident id,
|
|
|
|
&vec[field] fields) -> uint {
|
2010-12-21 14:13:51 -06:00
|
|
|
let uint i = 0u;
|
2011-06-15 13:19:50 -05:00
|
|
|
for (field f in fields) { if (str::eq(f.ident, id)) { ret i; } i += 1u; }
|
2010-12-21 14:13:51 -06:00
|
|
|
sess.span_err(sp, "unknown field '" + id + "' of record");
|
|
|
|
}
|
|
|
|
|
2011-06-15 13:19:50 -05:00
|
|
|
fn method_idx(&session::session sess, &span sp, &ast::ident id,
|
|
|
|
&vec[method] meths) -> uint {
|
2010-12-21 14:13:51 -06:00
|
|
|
let uint i = 0u;
|
2011-06-15 13:19:50 -05:00
|
|
|
for (method m in meths) { if (str::eq(m.ident, id)) { ret i; } i += 1u; }
|
2010-12-21 14:13:51 -06:00
|
|
|
sess.span_err(sp, "unknown method '" + id + "' of obj");
|
|
|
|
}
|
|
|
|
|
2011-05-09 15:09:20 -05:00
|
|
|
fn sort_methods(&vec[method] meths) -> vec[method] {
|
2011-03-17 13:40:05 -05:00
|
|
|
fn method_lteq(&method a, &method b) -> bool {
|
2011-05-17 13:41:41 -05:00
|
|
|
ret str::lteq(a.ident, b.ident);
|
2011-03-17 13:40:05 -05:00
|
|
|
}
|
2011-06-15 13:19:50 -05:00
|
|
|
ret std::sort::merge_sort[method](bind method_lteq(_, _), meths);
|
2011-03-17 13:40:05 -05:00
|
|
|
}
|
|
|
|
|
2011-05-12 10:24:54 -05:00
|
|
|
fn is_lval(&@ast::expr expr) -> bool {
|
2010-12-21 14:13:51 -06:00
|
|
|
alt (expr.node) {
|
2011-06-15 13:19:50 -05:00
|
|
|
case (ast::expr_field(_, _, _)) { ret true; }
|
|
|
|
case (ast::expr_index(_, _, _)) { ret true; }
|
|
|
|
case (ast::expr_path(_, _)) { ret true; }
|
|
|
|
case (ast::expr_unary(ast::deref, _, _)) { ret true; }
|
|
|
|
case (_) { ret false; }
|
2010-12-21 14:13:51 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-06-15 13:19:50 -05:00
|
|
|
|
2011-02-18 16:52:33 -06:00
|
|
|
// Type unification via Robinson's algorithm (Robinson 1965). Implemented as
|
|
|
|
// described in Hoder and Voronkov:
|
|
|
|
//
|
|
|
|
// http://www.cs.man.ac.uk/~hoderk/ubench/unification_full.pdf
|
2011-05-14 20:13:47 -05:00
|
|
|
mod unify {
|
2011-06-15 13:19:50 -05:00
|
|
|
tag result { ures_ok(t); ures_err(type_err); }
|
|
|
|
tag union_result { unres_ok; unres_err(type_err); }
|
|
|
|
tag fixup_result {
|
|
|
|
fix_ok(t); // fixup succeeded
|
2011-05-20 20:36:35 -05:00
|
|
|
|
2011-06-15 13:19:50 -05:00
|
|
|
fix_err(int); // fixup failed because a type variable was unresolved
|
2011-04-21 13:46:31 -05:00
|
|
|
|
2011-05-19 18:06:23 -05:00
|
|
|
}
|
2011-06-15 13:19:50 -05:00
|
|
|
type var_bindings =
|
|
|
|
rec(ufind::ufind sets, smallintmap::smallintmap[t] types);
|
2011-05-20 20:36:35 -05:00
|
|
|
|
|
|
|
type ctxt = rec(@var_bindings vb, ty_ctxt tcx);
|
2011-05-18 13:53:26 -05:00
|
|
|
|
2011-05-20 20:36:35 -05:00
|
|
|
fn mk_var_bindings() -> @var_bindings {
|
|
|
|
ret @rec(sets=ufind::make(), types=smallintmap::mk[t]());
|
2011-05-18 13:53:26 -05:00
|
|
|
}
|
|
|
|
|
2011-05-20 20:36:35 -05:00
|
|
|
// Unifies two sets.
|
|
|
|
fn union(&@ctxt cx, uint set_a, uint set_b) -> union_result {
|
|
|
|
ufind::grow(cx.vb.sets, uint::max(set_a, set_b) + 1u);
|
|
|
|
auto root_a = ufind::find(cx.vb.sets, set_a);
|
|
|
|
auto root_b = ufind::find(cx.vb.sets, set_b);
|
|
|
|
ufind::union(cx.vb.sets, set_a, set_b);
|
|
|
|
auto root_c = ufind::find(cx.vb.sets, set_a);
|
|
|
|
alt (smallintmap::find[t](cx.vb.types, root_a)) {
|
|
|
|
case (none[t]) {
|
|
|
|
alt (smallintmap::find[t](cx.vb.types, root_b)) {
|
|
|
|
case (none[t]) { ret unres_ok; }
|
|
|
|
case (some[t](?t_b)) {
|
|
|
|
smallintmap::insert[t](cx.vb.types, root_c, t_b);
|
|
|
|
ret unres_ok;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
case (some[t](?t_a)) {
|
|
|
|
alt (smallintmap::find[t](cx.vb.types, root_b)) {
|
|
|
|
case (none[t]) {
|
|
|
|
smallintmap::insert[t](cx.vb.types, root_c, t_a);
|
|
|
|
ret unres_ok;
|
|
|
|
}
|
|
|
|
case (some[t](?t_b)) {
|
|
|
|
alt (unify_step(cx, t_a, t_b)) {
|
|
|
|
case (ures_ok(?t_c)) {
|
|
|
|
smallintmap::insert[t](cx.vb.types, root_c,
|
|
|
|
t_c);
|
|
|
|
ret unres_ok;
|
|
|
|
}
|
|
|
|
case (ures_err(?terr)) { ret unres_err(terr); }
|
2011-05-19 18:06:23 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2011-05-20 20:36:35 -05:00
|
|
|
}
|
|
|
|
fn record_var_binding(&@ctxt cx, int key, t typ) -> result {
|
|
|
|
ufind::grow(cx.vb.sets, (key as uint) + 1u);
|
2011-06-09 15:55:56 -05:00
|
|
|
auto root = ufind::find(cx.vb.sets, key as uint);
|
2011-05-20 20:36:35 -05:00
|
|
|
auto result_type = typ;
|
2011-06-09 15:55:56 -05:00
|
|
|
alt (smallintmap::find[t](cx.vb.types, root)) {
|
2011-05-20 20:36:35 -05:00
|
|
|
case (some(?old_type)) {
|
|
|
|
alt (unify_step(cx, old_type, typ)) {
|
|
|
|
case (ures_ok(?unified_type)) {
|
|
|
|
result_type = unified_type;
|
|
|
|
}
|
|
|
|
case (?res) { ret res; }
|
|
|
|
}
|
|
|
|
}
|
2011-06-15 13:19:50 -05:00
|
|
|
case (none) {/* fall through */ }
|
2011-05-20 20:36:35 -05:00
|
|
|
}
|
2011-06-09 15:55:56 -05:00
|
|
|
smallintmap::insert[t](cx.vb.types, root, result_type);
|
2011-05-19 18:06:23 -05:00
|
|
|
ret ures_ok(typ);
|
|
|
|
}
|
|
|
|
|
2010-12-21 19:47:13 -06:00
|
|
|
// Wraps the given type in an appropriate cname.
|
|
|
|
//
|
|
|
|
// TODO: This doesn't do anything yet. We should carry the cname up from
|
|
|
|
// the expected and/or actual types when unification results in a type
|
|
|
|
// identical to one or both of the two. The precise algorithm for this is
|
|
|
|
// something we'll probably need to develop over time.
|
|
|
|
|
|
|
|
// Simple structural type comparison.
|
2011-04-22 19:00:46 -05:00
|
|
|
fn struct_cmp(@ctxt cx, t expected, t actual) -> result {
|
2011-04-25 14:15:55 -05:00
|
|
|
if (struct(cx.tcx, expected) == struct(cx.tcx, actual)) {
|
2010-12-21 19:47:13 -06:00
|
|
|
ret ures_ok(expected);
|
|
|
|
}
|
2011-05-20 20:36:35 -05:00
|
|
|
ret ures_err(terr_mismatch);
|
2010-12-21 19:47:13 -06:00
|
|
|
}
|
|
|
|
|
2011-03-18 13:49:06 -05:00
|
|
|
// Unifies two mutability flags.
|
2011-06-15 13:19:50 -05:00
|
|
|
fn unify_mut(ast::mutability expected, ast::mutability actual) ->
|
|
|
|
option::t[ast::mutability] {
|
|
|
|
if (expected == actual) { ret some[ast::mutability](expected); }
|
|
|
|
if (expected == ast::maybe_mut) { ret some[ast::mutability](actual); }
|
|
|
|
if (actual == ast::maybe_mut) { ret some[ast::mutability](expected); }
|
2011-05-12 10:24:54 -05:00
|
|
|
ret none[ast::mutability];
|
2011-03-18 13:49:06 -05:00
|
|
|
}
|
2011-02-23 10:59:07 -06:00
|
|
|
tag fn_common_res {
|
2011-04-21 13:46:31 -05:00
|
|
|
fn_common_res_err(result);
|
2011-04-22 14:27:28 -05:00
|
|
|
fn_common_res_ok(vec[arg], t);
|
2011-02-23 10:59:07 -06:00
|
|
|
}
|
2011-06-15 13:19:50 -05:00
|
|
|
fn unify_fn_common(&@ctxt cx, &t expected, &t actual,
|
2011-05-09 15:09:20 -05:00
|
|
|
&vec[arg] expected_inputs, &t expected_output,
|
2011-06-15 13:19:50 -05:00
|
|
|
&vec[arg] actual_inputs, &t actual_output) ->
|
|
|
|
fn_common_res {
|
2011-05-17 13:41:41 -05:00
|
|
|
auto expected_len = vec::len[arg](expected_inputs);
|
|
|
|
auto actual_len = vec::len[arg](actual_inputs);
|
2011-02-18 19:30:57 -06:00
|
|
|
if (expected_len != actual_len) {
|
2011-05-20 20:36:35 -05:00
|
|
|
ret fn_common_res_err(ures_err(terr_arg_count));
|
2011-02-18 19:30:57 -06:00
|
|
|
}
|
|
|
|
// TODO: as above, we should have an iter2 iterator.
|
2011-06-15 13:19:50 -05:00
|
|
|
|
2011-05-16 20:21:22 -05:00
|
|
|
let vec[arg] result_ins = [];
|
2011-02-18 19:30:57 -06:00
|
|
|
auto i = 0u;
|
|
|
|
while (i < expected_len) {
|
|
|
|
auto expected_input = expected_inputs.(i);
|
|
|
|
auto actual_input = actual_inputs.(i);
|
2011-06-08 19:57:06 -05:00
|
|
|
// Unify the result modes.
|
2011-06-15 13:19:50 -05:00
|
|
|
|
2011-02-18 19:30:57 -06:00
|
|
|
auto result_mode;
|
2011-06-08 19:57:06 -05:00
|
|
|
if (expected_input.mode != actual_input.mode) {
|
2011-05-13 08:17:24 -05:00
|
|
|
// FIXME this is the wrong error
|
2010-12-31 11:48:54 -06:00
|
|
|
|
2011-06-15 13:19:50 -05:00
|
|
|
ret fn_common_res_err(ures_err(terr_arg_count));
|
|
|
|
} else { result_mode = expected_input.mode; }
|
2011-06-02 19:48:40 -05:00
|
|
|
auto result = unify_step(cx, expected_input.ty, actual_input.ty);
|
2011-02-18 19:30:57 -06:00
|
|
|
alt (result) {
|
|
|
|
case (ures_ok(?rty)) {
|
2011-05-16 20:21:22 -05:00
|
|
|
result_ins += [rec(mode=result_mode, ty=rty)];
|
2011-02-18 19:30:57 -06:00
|
|
|
}
|
2011-06-15 13:19:50 -05:00
|
|
|
case (_) { ret fn_common_res_err(result); }
|
2011-02-18 19:30:57 -06:00
|
|
|
}
|
|
|
|
i += 1u;
|
2010-12-31 11:48:54 -06:00
|
|
|
}
|
2011-02-18 19:30:57 -06:00
|
|
|
// Check the output.
|
2011-06-15 13:19:50 -05:00
|
|
|
|
2011-04-21 14:10:53 -05:00
|
|
|
auto result = unify_step(cx, expected_output, actual_output);
|
2011-02-18 19:30:57 -06:00
|
|
|
alt (result) {
|
2011-06-15 13:19:50 -05:00
|
|
|
case (ures_ok(?rty)) { ret fn_common_res_ok(result_ins, rty); }
|
|
|
|
case (_) { ret fn_common_res_err(result); }
|
2010-12-31 11:48:54 -06:00
|
|
|
}
|
2011-02-23 10:59:07 -06:00
|
|
|
}
|
2011-06-15 13:19:50 -05:00
|
|
|
fn unify_fn(&@ctxt cx, &ast::proto e_proto, &ast::proto a_proto,
|
|
|
|
&t expected, &t actual, &vec[arg] expected_inputs,
|
|
|
|
&t expected_output, &vec[arg] actual_inputs, &t actual_output,
|
2011-06-09 11:48:16 -05:00
|
|
|
&controlflow expected_cf, &controlflow actual_cf,
|
2011-06-15 17:14:30 -05:00
|
|
|
&vec[@constr_def] expected_constrs,
|
|
|
|
&vec[@constr_def] actual_constrs) -> result {
|
2011-06-15 13:19:50 -05:00
|
|
|
if (e_proto != a_proto) { ret ures_err(terr_mismatch); }
|
2011-05-20 16:15:39 -05:00
|
|
|
alt (expected_cf) {
|
2011-06-15 13:19:50 -05:00
|
|
|
case (ast::return) { }
|
|
|
|
case ( // ok
|
|
|
|
ast::noreturn) {
|
2011-05-20 16:15:39 -05:00
|
|
|
alt (actual_cf) {
|
|
|
|
case (ast::noreturn) {
|
|
|
|
// ok
|
2011-06-15 13:19:50 -05:00
|
|
|
|
2011-05-20 16:15:39 -05:00
|
|
|
}
|
|
|
|
case (_) {
|
|
|
|
/* even though typestate checking is mostly
|
|
|
|
responsible for checking control flow annotations,
|
|
|
|
this check is necessary to ensure that the
|
|
|
|
annotation in an object method matches the
|
|
|
|
declared object type */
|
2011-06-15 13:19:50 -05:00
|
|
|
|
2011-05-20 20:36:35 -05:00
|
|
|
ret ures_err(terr_controlflow_mismatch);
|
2011-05-20 16:15:39 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2011-06-15 13:19:50 -05:00
|
|
|
auto t =
|
|
|
|
unify_fn_common(cx, expected, actual, expected_inputs,
|
|
|
|
expected_output, actual_inputs, actual_output);
|
2011-02-23 10:59:07 -06:00
|
|
|
alt (t) {
|
2011-06-15 13:19:50 -05:00
|
|
|
case (fn_common_res_err(?r)) { ret r; }
|
2011-02-23 10:59:07 -06:00
|
|
|
case (fn_common_res_ok(?result_ins, ?result_out)) {
|
2011-06-15 13:19:50 -05:00
|
|
|
auto t2 =
|
|
|
|
mk_fn(cx.tcx, e_proto, result_ins, result_out, actual_cf,
|
|
|
|
actual_constrs);
|
2011-02-23 10:59:07 -06:00
|
|
|
ret ures_ok(t2);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2011-06-15 13:19:50 -05:00
|
|
|
fn unify_native_fn(&@ctxt cx, &ast::native_abi e_abi,
|
|
|
|
&ast::native_abi a_abi, &t expected, &t actual,
|
2011-05-09 15:09:20 -05:00
|
|
|
&vec[arg] expected_inputs, &t expected_output,
|
2011-06-15 13:19:50 -05:00
|
|
|
&vec[arg] actual_inputs, &t actual_output) -> result {
|
2011-05-20 20:36:35 -05:00
|
|
|
if (e_abi != a_abi) { ret ures_err(terr_mismatch); }
|
2011-06-15 13:19:50 -05:00
|
|
|
auto t =
|
|
|
|
unify_fn_common(cx, expected, actual, expected_inputs,
|
|
|
|
expected_output, actual_inputs, actual_output);
|
2011-02-23 10:59:07 -06:00
|
|
|
alt (t) {
|
2011-06-15 13:19:50 -05:00
|
|
|
case (fn_common_res_err(?r)) { ret r; }
|
2011-02-23 10:59:07 -06:00
|
|
|
case (fn_common_res_ok(?result_ins, ?result_out)) {
|
2011-06-15 13:19:50 -05:00
|
|
|
auto t2 = mk_native_fn(cx.tcx, e_abi, result_ins, result_out);
|
2011-02-23 10:59:07 -06:00
|
|
|
ret ures_ok(t2);
|
|
|
|
}
|
|
|
|
}
|
2010-12-31 11:48:54 -06:00
|
|
|
}
|
2011-06-15 13:19:50 -05:00
|
|
|
fn unify_obj(&@ctxt cx, &t expected, &t actual,
|
|
|
|
&vec[method] expected_meths, &vec[method] actual_meths) ->
|
|
|
|
result {
|
|
|
|
let vec[method] result_meths = [];
|
|
|
|
let uint i = 0u;
|
|
|
|
let uint expected_len = vec::len[method](expected_meths);
|
|
|
|
let uint actual_len = vec::len[method](actual_meths);
|
|
|
|
if (expected_len != actual_len) { ret ures_err(terr_meth_count); }
|
|
|
|
while (i < expected_len) {
|
|
|
|
auto e_meth = expected_meths.(i);
|
|
|
|
auto a_meth = actual_meths.(i);
|
|
|
|
if (!str::eq(e_meth.ident, a_meth.ident)) {
|
|
|
|
ret ures_err(terr_obj_meths(e_meth.ident, a_meth.ident));
|
|
|
|
}
|
|
|
|
auto r =
|
|
|
|
unify_fn(cx, e_meth.proto, a_meth.proto, expected, actual,
|
|
|
|
e_meth.inputs, e_meth.output, a_meth.inputs,
|
|
|
|
a_meth.output, e_meth.cf, a_meth.cf, e_meth.constrs,
|
|
|
|
a_meth.constrs);
|
|
|
|
alt (r) {
|
|
|
|
case (ures_ok(?tfn)) {
|
|
|
|
alt (struct(cx.tcx, tfn)) {
|
|
|
|
case (ty_fn(?proto, ?ins, ?out, ?cf, ?constrs)) {
|
|
|
|
result_meths +=
|
|
|
|
[rec(inputs=ins,
|
|
|
|
output=out,
|
|
|
|
cf=cf,
|
|
|
|
constrs=constrs with e_meth)];
|
|
|
|
}
|
2011-03-06 12:56:38 -06:00
|
|
|
}
|
|
|
|
}
|
2011-06-15 13:19:50 -05:00
|
|
|
case (_) { ret r; }
|
2011-03-06 12:56:38 -06:00
|
|
|
}
|
2011-06-15 13:19:50 -05:00
|
|
|
i += 1u;
|
2010-12-31 12:26:29 -06:00
|
|
|
}
|
2011-06-15 13:19:50 -05:00
|
|
|
auto t = mk_obj(cx.tcx, result_meths);
|
|
|
|
ret ures_ok(t);
|
2010-12-31 12:26:29 -06:00
|
|
|
}
|
|
|
|
|
2011-06-08 20:39:34 -05:00
|
|
|
// If the given type is a variable, returns the structure of that type.
|
2011-06-15 13:19:50 -05:00
|
|
|
fn resolve_type_structure(&ty_ctxt tcx, &@var_bindings vb, t typ) ->
|
|
|
|
fixup_result {
|
2011-06-08 20:39:34 -05:00
|
|
|
alt (struct(tcx, typ)) {
|
|
|
|
case (ty_var(?vid)) {
|
2011-06-15 13:19:50 -05:00
|
|
|
if (vid as uint >= ufind::set_count(vb.sets)) {
|
2011-06-08 20:39:34 -05:00
|
|
|
ret fix_err(vid);
|
|
|
|
}
|
|
|
|
auto root_id = ufind::find(vb.sets, vid as uint);
|
|
|
|
alt (smallintmap::find[t](vb.types, root_id)) {
|
|
|
|
case (none[t]) { ret fix_err(vid); }
|
|
|
|
case (some[t](?rt)) { ret fix_ok(rt); }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
case (_) { ret fix_ok(typ); }
|
|
|
|
}
|
|
|
|
}
|
2011-05-09 15:09:20 -05:00
|
|
|
fn unify_step(&@ctxt cx, &t expected, &t actual) -> result {
|
2010-12-21 19:47:13 -06:00
|
|
|
// TODO: rewrite this using tuple pattern matching when available, to
|
|
|
|
// avoid all this rightward drift and spikiness.
|
|
|
|
|
2011-02-18 16:52:33 -06:00
|
|
|
// TODO: occurs check, to make sure we don't loop forever when
|
|
|
|
// unifying e.g. 'a and option['a]
|
|
|
|
|
2011-04-22 12:51:32 -05:00
|
|
|
// Fast path.
|
|
|
|
|
2011-06-15 13:19:50 -05:00
|
|
|
if (eq_ty(expected, actual)) { ret ures_ok(expected); }
|
2011-05-20 20:36:35 -05:00
|
|
|
// Stage 1: Handle the cases in which one side or another is a type
|
|
|
|
// variable.
|
2011-05-26 22:14:00 -05:00
|
|
|
|
2011-05-20 20:36:35 -05:00
|
|
|
alt (struct(cx.tcx, actual)) {
|
2011-06-15 13:19:50 -05:00
|
|
|
case (
|
|
|
|
// If the RHS is a variable type, then just do the
|
|
|
|
// appropriate binding.
|
|
|
|
ty::ty_var(?actual_id)) {
|
2011-05-20 20:36:35 -05:00
|
|
|
auto actual_n = actual_id as uint;
|
2011-04-25 14:15:55 -05:00
|
|
|
alt (struct(cx.tcx, expected)) {
|
2011-05-12 10:24:54 -05:00
|
|
|
case (ty::ty_var(?expected_id)) {
|
2011-05-20 20:36:35 -05:00
|
|
|
auto expected_n = expected_id as uint;
|
2011-06-17 13:23:32 -05:00
|
|
|
alt(union(cx, expected_n, actual_n)) {
|
|
|
|
case (unres_ok) { /* fall through */ }
|
|
|
|
case (unres_err(?t_e)) {
|
|
|
|
ret ures_err(t_e);
|
|
|
|
}
|
|
|
|
}
|
2011-04-08 16:53:16 -05:00
|
|
|
}
|
|
|
|
case (_) {
|
2011-06-15 13:19:50 -05:00
|
|
|
|
2011-04-08 16:53:16 -05:00
|
|
|
// Just bind the type variable to the expected type.
|
2011-05-20 20:36:35 -05:00
|
|
|
alt (record_var_binding(cx, actual_id, expected)) {
|
2011-06-15 13:19:50 -05:00
|
|
|
case (ures_ok(_)) {/* fall through */ }
|
2011-05-19 18:06:23 -05:00
|
|
|
case (?res) { ret res; }
|
2011-04-08 16:53:16 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2011-05-20 20:36:35 -05:00
|
|
|
ret ures_ok(mk_var(cx.tcx, actual_id));
|
2010-12-21 19:47:13 -06:00
|
|
|
}
|
2011-06-15 13:19:50 -05:00
|
|
|
case (_) {/* empty */ }
|
2011-05-20 20:36:35 -05:00
|
|
|
}
|
|
|
|
alt (struct(cx.tcx, expected)) {
|
|
|
|
case (ty::ty_var(?expected_id)) {
|
|
|
|
// Add a binding. (`actual` can't actually be a var here.)
|
2011-06-15 13:19:50 -05:00
|
|
|
|
2011-05-20 20:36:35 -05:00
|
|
|
alt (record_var_binding(cx, expected_id, actual)) {
|
2011-06-15 13:19:50 -05:00
|
|
|
case (ures_ok(_)) {/* fall through */ }
|
2011-05-20 20:36:35 -05:00
|
|
|
case (?res) { ret res; }
|
2011-01-18 19:18:51 -06:00
|
|
|
}
|
2011-05-20 20:36:35 -05:00
|
|
|
ret ures_ok(mk_var(cx.tcx, expected_id));
|
2011-01-04 18:52:06 -06:00
|
|
|
}
|
2011-06-15 13:19:50 -05:00
|
|
|
case (_) {/* fall through */ }
|
2011-05-20 20:36:35 -05:00
|
|
|
}
|
|
|
|
// Stage 2: Handle all other cases.
|
|
|
|
|
|
|
|
alt (struct(cx.tcx, actual)) {
|
2011-06-15 13:19:50 -05:00
|
|
|
case (ty::ty_bot) { ret ures_ok(expected); }
|
|
|
|
case (_) {/* fall through */ }
|
2010-12-21 19:47:13 -06:00
|
|
|
}
|
2011-04-25 14:15:55 -05:00
|
|
|
alt (struct(cx.tcx, expected)) {
|
2011-06-15 13:19:50 -05:00
|
|
|
case (ty::ty_nil) { ret struct_cmp(cx, expected, actual); }
|
|
|
|
case (
|
|
|
|
// _|_ unifies with anything
|
|
|
|
ty::ty_bot) {
|
|
|
|
ret ures_ok(actual);
|
|
|
|
}
|
|
|
|
case (ty::ty_bool) { ret struct_cmp(cx, expected, actual); }
|
|
|
|
case (ty::ty_int) { ret struct_cmp(cx, expected, actual); }
|
|
|
|
case (ty::ty_uint) { ret struct_cmp(cx, expected, actual); }
|
2011-05-12 10:24:54 -05:00
|
|
|
case (ty::ty_machine(_)) { ret struct_cmp(cx, expected, actual); }
|
2011-06-15 13:19:50 -05:00
|
|
|
case (ty::ty_float) { ret struct_cmp(cx, expected, actual); }
|
|
|
|
case (ty::ty_char) { ret struct_cmp(cx, expected, actual); }
|
|
|
|
case (ty::ty_str) { ret struct_cmp(cx, expected, actual); }
|
|
|
|
case (ty::ty_istr) { ret struct_cmp(cx, expected, actual); }
|
|
|
|
case (ty::ty_type) { ret struct_cmp(cx, expected, actual); }
|
|
|
|
case (ty::ty_native) { ret struct_cmp(cx, expected, actual); }
|
|
|
|
case (ty::ty_param(_)) { ret struct_cmp(cx, expected, actual); }
|
2011-05-12 10:24:54 -05:00
|
|
|
case (ty::ty_tag(?expected_id, ?expected_tps)) {
|
2011-04-25 14:15:55 -05:00
|
|
|
alt (struct(cx.tcx, actual)) {
|
2011-05-12 10:24:54 -05:00
|
|
|
case (ty::ty_tag(?actual_id, ?actual_tps)) {
|
2011-02-17 18:23:31 -06:00
|
|
|
if (expected_id._0 != actual_id._0 ||
|
|
|
|
expected_id._1 != actual_id._1) {
|
2011-05-20 20:36:35 -05:00
|
|
|
ret ures_err(terr_mismatch);
|
2010-12-21 19:47:13 -06:00
|
|
|
}
|
2011-02-17 18:23:31 -06:00
|
|
|
// TODO: factor this cruft out, see the TODO in the
|
2011-05-12 10:24:54 -05:00
|
|
|
// ty::ty_tup case
|
2011-06-15 13:19:50 -05:00
|
|
|
|
2011-05-16 20:21:22 -05:00
|
|
|
let vec[t] result_tps = [];
|
2011-02-17 18:23:31 -06:00
|
|
|
auto i = 0u;
|
2011-05-17 13:41:41 -05:00
|
|
|
auto expected_len = vec::len[t](expected_tps);
|
2011-02-17 18:23:31 -06:00
|
|
|
while (i < expected_len) {
|
|
|
|
auto expected_tp = expected_tps.(i);
|
|
|
|
auto actual_tp = actual_tps.(i);
|
2011-06-15 13:19:50 -05:00
|
|
|
auto result =
|
|
|
|
unify_step(cx, expected_tp, actual_tp);
|
2011-02-17 18:23:31 -06:00
|
|
|
alt (result) {
|
|
|
|
case (ures_ok(?rty)) {
|
2011-05-17 13:41:41 -05:00
|
|
|
vec::push[t](result_tps, rty);
|
2011-02-17 18:23:31 -06:00
|
|
|
}
|
2011-06-15 13:19:50 -05:00
|
|
|
case (_) { ret result; }
|
2011-02-17 18:23:31 -06:00
|
|
|
}
|
|
|
|
i += 1u;
|
|
|
|
}
|
2011-04-25 14:15:55 -05:00
|
|
|
ret ures_ok(mk_tag(cx.tcx, expected_id, result_tps));
|
2010-12-21 19:47:13 -06:00
|
|
|
}
|
2011-06-15 13:19:50 -05:00
|
|
|
case (_) {/* fall through */ }
|
2010-12-21 19:47:13 -06:00
|
|
|
}
|
2011-05-20 20:36:35 -05:00
|
|
|
ret ures_err(terr_mismatch);
|
2010-12-21 19:47:13 -06:00
|
|
|
}
|
2011-05-12 10:24:54 -05:00
|
|
|
case (ty::ty_box(?expected_mt)) {
|
2011-04-25 14:15:55 -05:00
|
|
|
alt (struct(cx.tcx, actual)) {
|
2011-05-12 10:24:54 -05:00
|
|
|
case (ty::ty_box(?actual_mt)) {
|
2011-03-18 13:49:06 -05:00
|
|
|
auto mut;
|
|
|
|
alt (unify_mut(expected_mt.mut, actual_mt.mut)) {
|
2011-05-20 20:36:35 -05:00
|
|
|
case (none) { ret ures_err(terr_box_mutability); }
|
2011-05-30 23:39:19 -05:00
|
|
|
case (some(?m)) { mut = m; }
|
2011-03-17 19:39:47 -05:00
|
|
|
}
|
2011-06-15 13:19:50 -05:00
|
|
|
auto result =
|
|
|
|
unify_step(cx, expected_mt.ty, actual_mt.ty);
|
2010-12-21 19:47:13 -06:00
|
|
|
alt (result) {
|
|
|
|
case (ures_ok(?result_sub)) {
|
2011-03-18 13:49:06 -05:00
|
|
|
auto mt = rec(ty=result_sub, mut=mut);
|
2011-04-25 14:15:55 -05:00
|
|
|
ret ures_ok(mk_box(cx.tcx, mt));
|
2010-12-21 19:47:13 -06:00
|
|
|
}
|
2011-06-15 13:19:50 -05:00
|
|
|
case (_) { ret result; }
|
2010-12-21 19:47:13 -06:00
|
|
|
}
|
|
|
|
}
|
2011-05-20 20:36:35 -05:00
|
|
|
case (_) { ret ures_err(terr_mismatch); }
|
2010-12-21 19:47:13 -06:00
|
|
|
}
|
|
|
|
}
|
2011-05-12 10:24:54 -05:00
|
|
|
case (ty::ty_vec(?expected_mt)) {
|
2011-04-25 14:15:55 -05:00
|
|
|
alt (struct(cx.tcx, actual)) {
|
2011-05-12 10:24:54 -05:00
|
|
|
case (ty::ty_vec(?actual_mt)) {
|
2011-03-18 13:49:06 -05:00
|
|
|
auto mut;
|
|
|
|
alt (unify_mut(expected_mt.mut, actual_mt.mut)) {
|
2011-05-20 20:36:35 -05:00
|
|
|
case (none) { ret ures_err(terr_vec_mutability); }
|
2011-05-30 23:39:19 -05:00
|
|
|
case (some(?m)) { mut = m; }
|
2011-03-17 19:39:47 -05:00
|
|
|
}
|
2011-06-15 13:19:50 -05:00
|
|
|
auto result =
|
|
|
|
unify_step(cx, expected_mt.ty, actual_mt.ty);
|
2010-12-21 19:47:13 -06:00
|
|
|
alt (result) {
|
|
|
|
case (ures_ok(?result_sub)) {
|
2011-03-18 13:49:06 -05:00
|
|
|
auto mt = rec(ty=result_sub, mut=mut);
|
2011-04-25 14:15:55 -05:00
|
|
|
ret ures_ok(mk_vec(cx.tcx, mt));
|
2010-12-21 19:47:13 -06:00
|
|
|
}
|
2011-06-15 13:19:50 -05:00
|
|
|
case (_) { ret result; }
|
2010-12-21 19:47:13 -06:00
|
|
|
}
|
|
|
|
}
|
2011-05-20 20:36:35 -05:00
|
|
|
case (_) { ret ures_err(terr_mismatch); }
|
2010-12-21 19:47:13 -06:00
|
|
|
}
|
|
|
|
}
|
2011-06-09 19:11:21 -05:00
|
|
|
case (ty::ty_ivec(?expected_mt)) {
|
|
|
|
alt (struct(cx.tcx, actual)) {
|
|
|
|
case (ty::ty_ivec(?actual_mt)) {
|
|
|
|
auto mut;
|
|
|
|
alt (unify_mut(expected_mt.mut, actual_mt.mut)) {
|
|
|
|
case (none) { ret ures_err(terr_vec_mutability); }
|
|
|
|
case (some(?m)) { mut = m; }
|
|
|
|
}
|
2011-06-15 13:19:50 -05:00
|
|
|
auto result =
|
|
|
|
unify_step(cx, expected_mt.ty, actual_mt.ty);
|
2011-06-09 19:11:21 -05:00
|
|
|
alt (result) {
|
|
|
|
case (ures_ok(?result_sub)) {
|
|
|
|
auto mt = rec(ty=result_sub, mut=mut);
|
|
|
|
ret ures_ok(mk_ivec(cx.tcx, mt));
|
|
|
|
}
|
2011-06-15 13:19:50 -05:00
|
|
|
case (_) { ret result; }
|
2011-06-09 19:11:21 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
case (_) { ret ures_err(terr_mismatch); }
|
|
|
|
}
|
|
|
|
}
|
2011-06-16 19:05:59 -05:00
|
|
|
case (ty::ty_ptr(?expected_mt)) {
|
|
|
|
alt (struct(cx.tcx, actual)) {
|
|
|
|
case (ty::ty_ptr(?actual_mt)) {
|
|
|
|
auto mut;
|
|
|
|
alt (unify_mut(expected_mt.mut, actual_mt.mut)) {
|
|
|
|
case (none) { ret ures_err(terr_vec_mutability); }
|
|
|
|
case (some(?m)) { mut = m; }
|
|
|
|
}
|
|
|
|
auto result =
|
|
|
|
unify_step(cx, expected_mt.ty, actual_mt.ty);
|
|
|
|
alt (result) {
|
|
|
|
case (ures_ok(?result_sub)) {
|
|
|
|
auto mt = rec(ty=result_sub, mut=mut);
|
|
|
|
ret ures_ok(mk_ptr(cx.tcx, mt));
|
|
|
|
}
|
|
|
|
case (_) { ret result; }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
case (_) { ret ures_err(terr_mismatch); }
|
|
|
|
}
|
|
|
|
}
|
2011-05-12 10:24:54 -05:00
|
|
|
case (ty::ty_port(?expected_sub)) {
|
2011-04-25 14:15:55 -05:00
|
|
|
alt (struct(cx.tcx, actual)) {
|
2011-05-12 10:24:54 -05:00
|
|
|
case (ty::ty_port(?actual_sub)) {
|
2011-06-15 13:19:50 -05:00
|
|
|
auto result =
|
|
|
|
unify_step(cx, expected_sub, actual_sub);
|
2011-03-10 21:58:55 -06:00
|
|
|
alt (result) {
|
|
|
|
case (ures_ok(?result_sub)) {
|
2011-04-25 14:15:55 -05:00
|
|
|
ret ures_ok(mk_port(cx.tcx, result_sub));
|
2011-03-10 21:58:55 -06:00
|
|
|
}
|
2011-06-15 13:19:50 -05:00
|
|
|
case (_) { ret result; }
|
2011-03-10 21:58:55 -06:00
|
|
|
}
|
|
|
|
}
|
2011-05-20 20:36:35 -05:00
|
|
|
case (_) { ret ures_err(terr_mismatch); }
|
2011-03-10 21:58:55 -06:00
|
|
|
}
|
|
|
|
}
|
2011-05-12 10:24:54 -05:00
|
|
|
case (ty::ty_chan(?expected_sub)) {
|
2011-04-25 14:15:55 -05:00
|
|
|
alt (struct(cx.tcx, actual)) {
|
2011-05-12 10:24:54 -05:00
|
|
|
case (ty::ty_chan(?actual_sub)) {
|
2011-06-15 13:19:50 -05:00
|
|
|
auto result =
|
|
|
|
unify_step(cx, expected_sub, actual_sub);
|
2011-03-10 21:58:55 -06:00
|
|
|
alt (result) {
|
|
|
|
case (ures_ok(?result_sub)) {
|
2011-04-25 14:15:55 -05:00
|
|
|
ret ures_ok(mk_chan(cx.tcx, result_sub));
|
2011-03-10 21:58:55 -06:00
|
|
|
}
|
2011-06-15 13:19:50 -05:00
|
|
|
case (_) { ret result; }
|
2011-03-10 21:58:55 -06:00
|
|
|
}
|
|
|
|
}
|
2011-05-20 20:36:35 -05:00
|
|
|
case (_) { ret ures_err(terr_mismatch); }
|
2011-03-10 21:58:55 -06:00
|
|
|
}
|
|
|
|
}
|
2011-05-12 10:24:54 -05:00
|
|
|
case (ty::ty_tup(?expected_elems)) {
|
2011-04-25 14:15:55 -05:00
|
|
|
alt (struct(cx.tcx, actual)) {
|
2011-05-12 10:24:54 -05:00
|
|
|
case (ty::ty_tup(?actual_elems)) {
|
2011-05-17 13:41:41 -05:00
|
|
|
auto expected_len = vec::len[ty::mt](expected_elems);
|
|
|
|
auto actual_len = vec::len[ty::mt](actual_elems);
|
2010-12-21 19:47:13 -06:00
|
|
|
if (expected_len != actual_len) {
|
2011-06-15 13:19:50 -05:00
|
|
|
auto err =
|
|
|
|
terr_tuple_size(expected_len, actual_len);
|
2011-05-20 20:36:35 -05:00
|
|
|
ret ures_err(err);
|
2010-12-21 19:47:13 -06:00
|
|
|
}
|
|
|
|
// TODO: implement an iterator that can iterate over
|
|
|
|
// two arrays simultaneously.
|
2011-06-15 13:19:50 -05:00
|
|
|
|
2011-05-16 20:21:22 -05:00
|
|
|
let vec[ty::mt] result_elems = [];
|
2010-12-21 19:47:13 -06:00
|
|
|
auto i = 0u;
|
|
|
|
while (i < expected_len) {
|
|
|
|
auto expected_elem = expected_elems.(i);
|
|
|
|
auto actual_elem = actual_elems.(i);
|
2011-03-18 13:49:06 -05:00
|
|
|
auto mut;
|
|
|
|
alt (unify_mut(expected_elem.mut,
|
|
|
|
actual_elem.mut)) {
|
2011-05-30 23:39:19 -05:00
|
|
|
case (none) {
|
2011-03-18 13:49:06 -05:00
|
|
|
auto err = terr_tuple_mutability;
|
2011-05-20 20:36:35 -05:00
|
|
|
ret ures_err(err);
|
2011-03-18 13:49:06 -05:00
|
|
|
}
|
2011-05-30 23:39:19 -05:00
|
|
|
case (some(?m)) { mut = m; }
|
2010-12-21 19:47:13 -06:00
|
|
|
}
|
2011-06-15 13:19:50 -05:00
|
|
|
auto result =
|
|
|
|
unify_step(cx, expected_elem.ty,
|
|
|
|
actual_elem.ty);
|
2010-12-21 19:47:13 -06:00
|
|
|
alt (result) {
|
|
|
|
case (ures_ok(?rty)) {
|
2011-03-18 13:49:06 -05:00
|
|
|
auto mt = rec(ty=rty, mut=mut);
|
2011-05-16 20:21:22 -05:00
|
|
|
result_elems += [mt];
|
2010-12-21 19:47:13 -06:00
|
|
|
}
|
2011-06-15 13:19:50 -05:00
|
|
|
case (_) { ret result; }
|
2010-12-21 19:47:13 -06:00
|
|
|
}
|
|
|
|
i += 1u;
|
|
|
|
}
|
2011-04-25 14:15:55 -05:00
|
|
|
ret ures_ok(mk_tup(cx.tcx, result_elems));
|
2010-12-21 19:47:13 -06:00
|
|
|
}
|
2011-05-20 20:36:35 -05:00
|
|
|
case (_) { ret ures_err(terr_mismatch); }
|
2010-12-21 19:47:13 -06:00
|
|
|
}
|
|
|
|
}
|
2011-05-12 10:24:54 -05:00
|
|
|
case (ty::ty_rec(?expected_fields)) {
|
2011-04-25 14:15:55 -05:00
|
|
|
alt (struct(cx.tcx, actual)) {
|
2011-05-12 10:24:54 -05:00
|
|
|
case (ty::ty_rec(?actual_fields)) {
|
2011-05-17 13:41:41 -05:00
|
|
|
auto expected_len = vec::len[field](expected_fields);
|
|
|
|
auto actual_len = vec::len[field](actual_fields);
|
2010-12-21 19:47:13 -06:00
|
|
|
if (expected_len != actual_len) {
|
2011-06-15 13:19:50 -05:00
|
|
|
auto err =
|
|
|
|
terr_record_size(expected_len, actual_len);
|
2011-05-20 20:36:35 -05:00
|
|
|
ret ures_err(err);
|
2010-12-21 19:47:13 -06:00
|
|
|
}
|
|
|
|
// TODO: implement an iterator that can iterate over
|
|
|
|
// two arrays simultaneously.
|
2011-06-15 13:19:50 -05:00
|
|
|
|
2011-05-16 20:21:22 -05:00
|
|
|
let vec[field] result_fields = [];
|
2010-12-21 19:47:13 -06:00
|
|
|
auto i = 0u;
|
|
|
|
while (i < expected_len) {
|
|
|
|
auto expected_field = expected_fields.(i);
|
|
|
|
auto actual_field = actual_fields.(i);
|
2011-03-18 13:49:06 -05:00
|
|
|
auto mut;
|
|
|
|
alt (unify_mut(expected_field.mt.mut,
|
|
|
|
actual_field.mt.mut)) {
|
2011-05-30 23:39:19 -05:00
|
|
|
case (none) {
|
2011-05-20 20:36:35 -05:00
|
|
|
ret ures_err(terr_record_mutability);
|
2011-03-18 13:49:06 -05:00
|
|
|
}
|
2011-05-30 23:39:19 -05:00
|
|
|
case (some(?m)) { mut = m; }
|
2010-12-21 19:47:13 -06:00
|
|
|
}
|
2011-05-17 13:41:41 -05:00
|
|
|
if (!str::eq(expected_field.ident,
|
2011-03-17 19:39:47 -05:00
|
|
|
actual_field.ident)) {
|
2010-12-21 19:47:13 -06:00
|
|
|
auto err =
|
|
|
|
terr_record_fields(expected_field.ident,
|
|
|
|
actual_field.ident);
|
2011-05-20 20:36:35 -05:00
|
|
|
ret ures_err(err);
|
2010-12-21 19:47:13 -06:00
|
|
|
}
|
2011-06-15 13:19:50 -05:00
|
|
|
auto result =
|
|
|
|
unify_step(cx, expected_field.mt.ty,
|
|
|
|
actual_field.mt.ty);
|
2010-12-21 19:47:13 -06:00
|
|
|
alt (result) {
|
|
|
|
case (ures_ok(?rty)) {
|
2011-03-18 13:49:06 -05:00
|
|
|
auto mt = rec(ty=rty, mut=mut);
|
2011-06-15 13:19:50 -05:00
|
|
|
vec::push[field](result_fields,
|
|
|
|
rec(mt=mt
|
|
|
|
with
|
|
|
|
expected_field));
|
2010-12-21 19:47:13 -06:00
|
|
|
}
|
2011-06-15 13:19:50 -05:00
|
|
|
case (_) { ret result; }
|
2010-12-21 19:47:13 -06:00
|
|
|
}
|
|
|
|
i += 1u;
|
|
|
|
}
|
2011-04-25 14:15:55 -05:00
|
|
|
ret ures_ok(mk_rec(cx.tcx, result_fields));
|
2010-12-21 19:47:13 -06:00
|
|
|
}
|
2011-05-20 20:36:35 -05:00
|
|
|
case (_) { ret ures_err(terr_mismatch); }
|
2010-12-21 19:47:13 -06:00
|
|
|
}
|
|
|
|
}
|
2011-06-15 13:19:50 -05:00
|
|
|
case (ty::ty_fn(?ep, ?expected_inputs, ?expected_output,
|
|
|
|
?expected_cf, ?expected_constrs)) {
|
2011-04-25 14:15:55 -05:00
|
|
|
alt (struct(cx.tcx, actual)) {
|
2011-06-15 13:19:50 -05:00
|
|
|
case (ty::ty_fn(?ap, ?actual_inputs, ?actual_output,
|
|
|
|
?actual_cf, ?actual_constrs)) {
|
|
|
|
ret unify_fn(cx, ep, ap, expected, actual,
|
2011-02-18 19:30:57 -06:00
|
|
|
expected_inputs, expected_output,
|
2011-05-20 16:15:39 -05:00
|
|
|
actual_inputs, actual_output,
|
2011-06-15 13:19:50 -05:00
|
|
|
expected_cf, actual_cf, expected_constrs,
|
|
|
|
actual_constrs);
|
2010-12-21 19:47:13 -06:00
|
|
|
}
|
2011-05-20 20:36:35 -05:00
|
|
|
case (_) { ret ures_err(terr_mismatch); }
|
2010-12-21 19:47:13 -06:00
|
|
|
}
|
|
|
|
}
|
2011-05-12 10:24:54 -05:00
|
|
|
case (ty::ty_native_fn(?e_abi, ?expected_inputs,
|
2011-06-15 13:19:50 -05:00
|
|
|
?expected_output)) {
|
2011-04-25 14:15:55 -05:00
|
|
|
alt (struct(cx.tcx, actual)) {
|
2011-05-12 10:24:54 -05:00
|
|
|
case (ty::ty_native_fn(?a_abi, ?actual_inputs,
|
2011-06-15 13:19:50 -05:00
|
|
|
?actual_output)) {
|
|
|
|
ret unify_native_fn(cx, e_abi, a_abi, expected,
|
|
|
|
actual, expected_inputs,
|
|
|
|
expected_output, actual_inputs,
|
|
|
|
actual_output);
|
2011-02-23 10:59:07 -06:00
|
|
|
}
|
2011-05-20 20:36:35 -05:00
|
|
|
case (_) { ret ures_err(terr_mismatch); }
|
2011-02-23 10:59:07 -06:00
|
|
|
}
|
|
|
|
}
|
2011-05-12 10:24:54 -05:00
|
|
|
case (ty::ty_obj(?expected_meths)) {
|
2011-04-25 14:15:55 -05:00
|
|
|
alt (struct(cx.tcx, actual)) {
|
2011-05-12 10:24:54 -05:00
|
|
|
case (ty::ty_obj(?actual_meths)) {
|
2011-06-15 13:19:50 -05:00
|
|
|
ret unify_obj(cx, expected, actual, expected_meths,
|
|
|
|
actual_meths);
|
2011-02-18 19:30:57 -06:00
|
|
|
}
|
2011-05-20 20:36:35 -05:00
|
|
|
case (_) { ret ures_err(terr_mismatch); }
|
2010-12-31 12:26:29 -06:00
|
|
|
}
|
|
|
|
}
|
2011-05-20 20:36:35 -05:00
|
|
|
}
|
|
|
|
}
|
2011-06-15 13:19:50 -05:00
|
|
|
fn unify(&t expected, &t actual, &@var_bindings vb, &ty_ctxt tcx) ->
|
|
|
|
result {
|
2011-05-20 20:36:35 -05:00
|
|
|
auto cx = @rec(vb=vb, tcx=tcx);
|
|
|
|
ret unify_step(cx, expected, actual);
|
|
|
|
}
|
|
|
|
fn dump_var_bindings(ty_ctxt tcx, @var_bindings vb) {
|
|
|
|
auto i = 0u;
|
|
|
|
while (i < vec::len[ufind::node](vb.sets.nodes)) {
|
|
|
|
auto sets = "";
|
|
|
|
auto j = 0u;
|
|
|
|
while (j < vec::len[option::t[uint]](vb.sets.nodes)) {
|
|
|
|
if (ufind::find(vb.sets, j) == i) { sets += #fmt(" %u", j); }
|
|
|
|
j += 1u;
|
|
|
|
}
|
|
|
|
auto typespec;
|
|
|
|
alt (smallintmap::find[t](vb.types, i)) {
|
|
|
|
case (none[t]) { typespec = ""; }
|
|
|
|
case (some[t](?typ)) {
|
2011-06-09 11:48:16 -05:00
|
|
|
typespec = " =" + pretty::ppaux::ty_to_str(tcx, typ);
|
2010-12-21 19:47:13 -06:00
|
|
|
}
|
|
|
|
}
|
2011-05-20 20:36:35 -05:00
|
|
|
log_err #fmt("set %u:%s%s", i, typespec, sets);
|
|
|
|
i += 1u;
|
2010-12-21 19:47:13 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-05-20 20:36:35 -05:00
|
|
|
// Fixups and substitutions
|
|
|
|
fn fixup_vars(ty_ctxt tcx, @var_bindings vb, t typ) -> fixup_result {
|
2011-06-08 01:03:41 -05:00
|
|
|
fn subst_vars(ty_ctxt tcx, @var_bindings vb,
|
2011-06-09 13:20:47 -05:00
|
|
|
@mutable option::t[int] unresolved, int vid) -> t {
|
2011-06-15 13:19:50 -05:00
|
|
|
if (vid as uint >= ufind::set_count(vb.sets)) {
|
2011-06-09 13:20:47 -05:00
|
|
|
*unresolved = some[int](vid);
|
|
|
|
ret ty::mk_var(tcx, vid);
|
|
|
|
}
|
|
|
|
auto root_id = ufind::find(vb.sets, vid as uint);
|
|
|
|
alt (smallintmap::find[t](vb.types, root_id)) {
|
|
|
|
case (none[t]) {
|
|
|
|
*unresolved = some[int](vid);
|
|
|
|
ret ty::mk_var(tcx, vid);
|
|
|
|
}
|
|
|
|
case (some[t](?rt)) {
|
|
|
|
ret fold_ty(tcx,
|
2011-06-15 13:19:50 -05:00
|
|
|
fm_var(bind subst_vars(tcx, vb, unresolved,
|
|
|
|
_)), rt);
|
2011-02-18 16:52:33 -06:00
|
|
|
}
|
2011-04-08 16:53:16 -05:00
|
|
|
}
|
|
|
|
}
|
2011-06-08 01:03:41 -05:00
|
|
|
auto unresolved = @mutable none[int];
|
2011-06-15 13:19:50 -05:00
|
|
|
auto rty =
|
|
|
|
fold_ty(tcx, fm_var(bind subst_vars(tcx, vb, unresolved, _)),
|
|
|
|
typ);
|
2011-06-08 01:03:41 -05:00
|
|
|
auto ur = *unresolved;
|
|
|
|
alt (ur) {
|
|
|
|
case (none[int]) { ret fix_ok(rty); }
|
|
|
|
case (some[int](?var_id)) { ret fix_err(var_id); }
|
|
|
|
}
|
2011-04-08 16:53:16 -05:00
|
|
|
}
|
2011-06-15 13:19:50 -05:00
|
|
|
fn resolve_type_var(&ty_ctxt tcx, &@var_bindings vb, int vid) ->
|
|
|
|
fixup_result {
|
|
|
|
if (vid as uint >= ufind::set_count(vb.sets)) { ret fix_err(vid); }
|
2011-05-20 20:36:35 -05:00
|
|
|
auto root_id = ufind::find(vb.sets, vid as uint);
|
|
|
|
alt (smallintmap::find[t](vb.types, root_id)) {
|
2011-06-08 14:23:44 -05:00
|
|
|
case (none[t]) { ret fix_err(vid); }
|
2011-06-08 01:03:41 -05:00
|
|
|
case (some[t](?rt)) { ret fixup_vars(tcx, vb, rt); }
|
2011-05-19 18:06:23 -05:00
|
|
|
}
|
2011-02-07 16:11:43 -06:00
|
|
|
}
|
2010-12-21 19:47:13 -06:00
|
|
|
}
|
|
|
|
|
2011-05-12 10:24:54 -05:00
|
|
|
fn type_err_to_str(&ty::type_err err) -> str {
|
2010-12-21 19:47:13 -06:00
|
|
|
alt (err) {
|
2011-06-15 13:19:50 -05:00
|
|
|
case (terr_mismatch) { ret "types differ"; }
|
2011-05-20 16:15:39 -05:00
|
|
|
case (terr_controlflow_mismatch) {
|
2011-06-15 13:19:50 -05:00
|
|
|
ret "returning function used where non-returning function" +
|
|
|
|
" was expected";
|
2011-05-20 16:15:39 -05:00
|
|
|
}
|
2011-03-18 13:49:06 -05:00
|
|
|
case (terr_box_mutability) {
|
|
|
|
ret "boxed values differ in mutability";
|
|
|
|
}
|
2011-06-15 13:19:50 -05:00
|
|
|
case (terr_vec_mutability) { ret "vectors differ in mutability"; }
|
2010-12-21 19:47:13 -06:00
|
|
|
case (terr_tuple_size(?e_sz, ?a_sz)) {
|
2011-05-17 13:41:41 -05:00
|
|
|
ret "expected a tuple with " + uint::to_str(e_sz, 10u) +
|
2011-06-15 13:19:50 -05:00
|
|
|
" elements but found one with " + uint::to_str(a_sz, 10u)
|
|
|
|
+ " elements";
|
2010-12-21 19:47:13 -06:00
|
|
|
}
|
|
|
|
case (terr_tuple_mutability) {
|
|
|
|
ret "tuple elements differ in mutability";
|
|
|
|
}
|
|
|
|
case (terr_record_size(?e_sz, ?a_sz)) {
|
2011-05-17 13:41:41 -05:00
|
|
|
ret "expected a record with " + uint::to_str(e_sz, 10u) +
|
2011-06-15 13:19:50 -05:00
|
|
|
" fields but found one with " + uint::to_str(a_sz, 10u) +
|
|
|
|
" fields";
|
2010-12-21 19:47:13 -06:00
|
|
|
}
|
|
|
|
case (terr_record_mutability) {
|
|
|
|
ret "record elements differ in mutability";
|
|
|
|
}
|
|
|
|
case (terr_record_fields(?e_fld, ?a_fld)) {
|
|
|
|
ret "expected a record with field '" + e_fld +
|
2011-06-15 13:19:50 -05:00
|
|
|
"' but found one with field '" + a_fld + "'";
|
2010-12-21 19:47:13 -06:00
|
|
|
}
|
|
|
|
case (terr_arg_count) {
|
|
|
|
ret "incorrect number of function parameters";
|
|
|
|
}
|
2011-06-15 13:19:50 -05:00
|
|
|
case (terr_meth_count) { ret "incorrect number of object methods"; }
|
2010-12-31 12:26:29 -06:00
|
|
|
case (terr_obj_meths(?e_meth, ?a_meth)) {
|
|
|
|
ret "expected an obj with method '" + e_meth +
|
2011-06-15 13:19:50 -05:00
|
|
|
"' but found one with method '" + a_meth + "'";
|
2010-12-31 12:26:29 -06:00
|
|
|
}
|
2010-12-21 19:47:13 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-06-15 13:19:50 -05:00
|
|
|
|
2011-05-20 20:36:35 -05:00
|
|
|
// Converts type parameters in a type to type variables and returns the
|
|
|
|
// resulting type along with a list of type variable IDs.
|
2011-06-15 13:19:50 -05:00
|
|
|
fn bind_params_in_type(&ctxt cx, fn() -> int next_ty_var, t typ,
|
2011-06-09 13:20:47 -05:00
|
|
|
uint ty_param_count) -> tup(vec[int], t) {
|
2011-05-20 20:36:35 -05:00
|
|
|
let vec[int] param_var_ids = [];
|
|
|
|
auto i = 0u;
|
2011-06-15 13:19:50 -05:00
|
|
|
while (i < ty_param_count) { param_var_ids += [next_ty_var()]; i += 1u; }
|
|
|
|
fn binder(ctxt cx, vec[int] param_var_ids, fn() -> int next_ty_var,
|
2011-06-09 13:20:47 -05:00
|
|
|
uint index) -> t {
|
|
|
|
ret mk_var(cx, param_var_ids.(index));
|
2011-02-24 21:24:12 -06:00
|
|
|
}
|
2011-06-15 13:19:50 -05:00
|
|
|
auto new_typ =
|
|
|
|
fold_ty(cx, fm_param(bind binder(cx, param_var_ids, next_ty_var, _)),
|
|
|
|
typ);
|
2011-05-20 20:36:35 -05:00
|
|
|
ret tup(param_var_ids, new_typ);
|
2011-02-24 21:24:12 -06:00
|
|
|
}
|
|
|
|
|
2011-06-15 13:19:50 -05:00
|
|
|
|
2011-05-20 20:36:35 -05:00
|
|
|
// Replaces type parameters in the given type using the given list of
|
|
|
|
// substitions.
|
|
|
|
fn substitute_type_params(&ctxt cx, vec[ty::t] substs, t typ) -> t {
|
|
|
|
if (!type_contains_params(cx, typ)) { ret typ; }
|
2011-06-09 13:20:47 -05:00
|
|
|
fn substituter(ctxt cx, vec[ty::t] substs, uint idx) -> t {
|
2011-06-10 21:12:42 -05:00
|
|
|
// FIXME: bounds check can fail
|
2011-06-15 13:19:50 -05:00
|
|
|
|
2011-06-09 13:20:47 -05:00
|
|
|
ret substs.(idx);
|
2011-04-08 23:27:54 -05:00
|
|
|
}
|
2011-06-09 13:20:47 -05:00
|
|
|
ret fold_ty(cx, fm_param(bind substituter(cx, substs, _)), typ);
|
2011-04-08 23:27:54 -05:00
|
|
|
}
|
|
|
|
|
2011-05-12 10:24:54 -05:00
|
|
|
fn def_has_ty_params(&ast::def def) -> bool {
|
2011-03-30 19:23:25 -05:00
|
|
|
alt (def) {
|
2011-06-15 13:19:50 -05:00
|
|
|
case (ast::def_fn(_)) { ret true; }
|
|
|
|
case (ast::def_obj(_)) { ret true; }
|
|
|
|
case (ast::def_obj_field(_)) { ret false; }
|
|
|
|
case (ast::def_mod(_)) { ret false; }
|
|
|
|
case (ast::def_const(_)) { ret false; }
|
|
|
|
case (ast::def_arg(_)) { ret false; }
|
|
|
|
case (ast::def_local(_)) { ret false; }
|
|
|
|
case (ast::def_variant(_, _)) { ret true; }
|
|
|
|
case (ast::def_ty(_)) { ret false; }
|
|
|
|
case (ast::def_ty_arg(_)) { ret false; }
|
|
|
|
case (ast::def_binding(_)) { ret false; }
|
|
|
|
case (ast::def_use(_)) { ret false; }
|
|
|
|
case (ast::def_native_ty(_)) { ret false; }
|
|
|
|
case (ast::def_native_fn(_)) { ret true; }
|
2011-03-30 19:23:25 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-05-19 19:21:21 -05:00
|
|
|
|
|
|
|
// Tag information
|
|
|
|
type variant_info = rec(vec[ty::t] args, ty::t ctor_ty, ast::def_id id);
|
|
|
|
|
|
|
|
fn tag_variants(&ctxt cx, &ast::def_id id) -> vec[variant_info] {
|
|
|
|
if (cx.sess.get_targ_crate_num() != id._0) {
|
|
|
|
ret creader::get_tag_variants(cx, id);
|
|
|
|
}
|
|
|
|
assert (cx.items.contains_key(id));
|
|
|
|
alt (cx.items.get(id)) {
|
|
|
|
case (any_item_rust(?item)) {
|
|
|
|
alt (item.node) {
|
2011-06-16 04:53:06 -05:00
|
|
|
case (ast::item_tag(?variants, _)) {
|
2011-05-19 19:21:21 -05:00
|
|
|
let vec[variant_info] result = [];
|
|
|
|
for (ast::variant variant in variants) {
|
|
|
|
auto ctor_ty = ann_to_monotype(cx, variant.node.ann);
|
|
|
|
let vec[t] arg_tys = [];
|
2011-06-15 13:19:50 -05:00
|
|
|
if (vec::len[ast::variant_arg](variant.node.args) >
|
|
|
|
0u) {
|
2011-05-19 19:21:21 -05:00
|
|
|
for (arg a in ty_fn_args(cx, ctor_ty)) {
|
|
|
|
arg_tys += [a.ty];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
auto did = variant.node.id;
|
2011-06-15 13:19:50 -05:00
|
|
|
result +=
|
|
|
|
[rec(args=arg_tys, ctor_ty=ctor_ty, id=did)];
|
2011-05-19 19:21:21 -05:00
|
|
|
}
|
|
|
|
ret result;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-06-15 13:19:50 -05:00
|
|
|
|
2011-05-19 19:21:21 -05:00
|
|
|
// Returns information about the tag variant with the given ID:
|
2011-06-15 13:19:50 -05:00
|
|
|
fn tag_variant_with_id(&ctxt cx, &ast::def_id tag_id, &ast::def_id variant_id)
|
|
|
|
-> variant_info {
|
2011-05-19 19:21:21 -05:00
|
|
|
auto variants = tag_variants(cx, tag_id);
|
|
|
|
auto i = 0u;
|
|
|
|
while (i < vec::len[variant_info](variants)) {
|
|
|
|
auto variant = variants.(i);
|
2011-06-15 17:14:30 -05:00
|
|
|
if (def_eq(variant.id, variant_id)) { ret variant; }
|
2011-05-19 19:21:21 -05:00
|
|
|
i += 1u;
|
|
|
|
}
|
2011-06-07 15:50:30 -05:00
|
|
|
cx.sess.bug("tag_variant_with_id(): no variant exists with that ID");
|
2011-05-19 19:21:21 -05:00
|
|
|
}
|
|
|
|
|
2011-06-15 13:19:50 -05:00
|
|
|
|
2011-03-30 19:23:25 -05:00
|
|
|
// 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.
|
2011-05-19 19:21:21 -05:00
|
|
|
fn lookup_item_type(ctxt cx, ast::def_id did) -> ty_param_count_and_ty {
|
|
|
|
if (did._0 == cx.sess.get_targ_crate_num()) {
|
2011-03-30 19:23:25 -05:00
|
|
|
// The item is in this crate. The caller should have added it to the
|
|
|
|
// type cache already; we simply return it.
|
2011-06-15 13:19:50 -05:00
|
|
|
|
2011-05-19 17:47:15 -05:00
|
|
|
ret cx.tcache.get(did);
|
2011-03-30 19:23:25 -05:00
|
|
|
}
|
2011-05-19 17:47:15 -05:00
|
|
|
alt (cx.tcache.find(did)) {
|
2011-05-30 23:39:19 -05:00
|
|
|
case (some(?tpt)) { ret tpt; }
|
|
|
|
case (none) {
|
2011-05-19 19:21:21 -05:00
|
|
|
auto tyt = creader::get_type(cx, did);
|
2011-05-19 17:47:15 -05:00
|
|
|
cx.tcache.insert(did, tyt);
|
2011-04-22 12:19:22 -05:00
|
|
|
ret tyt;
|
|
|
|
}
|
2011-03-30 19:23:25 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-06-07 17:07:27 -05:00
|
|
|
fn ret_ty_of_fn_ty(ctxt cx, t a_ty) -> t {
|
|
|
|
alt (ty::struct(cx, a_ty)) {
|
2011-06-15 13:19:50 -05:00
|
|
|
case (ty::ty_fn(_, _, ?ret_ty, _, _)) { ret ret_ty; }
|
2011-05-19 19:21:21 -05:00
|
|
|
case (_) {
|
2011-06-07 17:07:27 -05:00
|
|
|
cx.sess.bug("ret_ty_of_fn_ty() called on non-function type");
|
2011-05-14 21:02:30 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-06-07 17:07:27 -05:00
|
|
|
fn ret_ty_of_fn(ctxt cx, ast::ann ann) -> t {
|
|
|
|
ret ret_ty_of_fn_ty(cx, ann_to_type(cx, ann));
|
2011-05-14 21:02:30 -05:00
|
|
|
}
|
2011-03-30 19:23:25 -05:00
|
|
|
|
2011-06-15 13:19:50 -05:00
|
|
|
|
2011-06-12 01:15:16 -05:00
|
|
|
// NB: This function requires that the given type has no variables. So, inside
|
|
|
|
// typeck, you should use typeck::strip_boxes() instead.
|
|
|
|
fn strip_boxes(&ctxt cx, &ty::t t) -> ty::t {
|
|
|
|
auto t1 = t;
|
|
|
|
while (true) {
|
|
|
|
alt (struct(cx, t1)) {
|
|
|
|
case (ty::ty_box(?inner)) { t1 = inner.ty; }
|
|
|
|
case (_) { ret t1; }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
fail;
|
|
|
|
}
|
2011-01-13 19:42:28 -06:00
|
|
|
// Local Variables:
|
|
|
|
// mode: rust
|
|
|
|
// fill-column: 78;
|
|
|
|
// indent-tabs-mode: nil
|
|
|
|
// c-basic-offset: 4
|
|
|
|
// buffer-file-coding-system: utf-8-unix
|
2011-03-25 17:07:27 -05:00
|
|
|
// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
|
2011-01-13 19:42:28 -06:00
|
|
|
// End:
|