aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/comp/middle/trans.rs13
-rw-r--r--src/comp/middle/ty.rs242
2 files changed, 183 insertions, 72 deletions
diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs
index 40294862..8d8c9926 100644
--- a/src/comp/middle/trans.rs
+++ b/src/comp/middle/trans.rs
@@ -120,7 +120,7 @@ type local_ctxt = rec(vec[str] path,
vec[ast.ty_param] obj_typarams,
vec[ast.obj_field] obj_fields,
@crate_ctxt ccx);
-
+
type self_vt = rec(ValueRef v, ty.t t);
@@ -1565,7 +1565,7 @@ fn get_tydesc(&@block_ctxt cx, ty.t t) -> result {
// Does it contain a type param? If so, generate a derived tydesc.
let uint n_params = ty.count_ty_params(cx.fcx.lcx.ccx.tcx, t);
- if (ty.count_ty_params(cx.fcx.lcx.ccx.tcx, t) > 0u) {
+ if (n_params > 0u) {
auto tys = linearize_ty_params(cx, t);
check (n_params == _vec.len[uint](tys._0));
@@ -4312,7 +4312,8 @@ fn trans_bind_thunk(@local_ctxt cx,
if (out_arg.mode == ast.val) {
val = bcx.build.Load(val);
- } else if (ty.count_ty_params(cx.ccx.tcx, out_arg.ty) > 0u) {
+ } else if (ty.type_contains_params(cx.ccx.tcx,
+ out_arg.ty)) {
check (out_arg.mode == ast.alias);
val = bcx.build.PointerCast(val, llout_arg_ty);
}
@@ -4325,7 +4326,7 @@ fn trans_bind_thunk(@local_ctxt cx,
case (none[@ast.expr]) {
let ValueRef passed_arg = llvm.LLVMGetParam(llthunk, a);
- if (ty.count_ty_params(cx.ccx.tcx, out_arg.ty) > 0u) {
+ if (ty.type_contains_params(cx.ccx.tcx, out_arg.ty)) {
check (out_arg.mode == ast.alias);
passed_arg = bcx.build.PointerCast(passed_arg,
llout_arg_ty);
@@ -4593,7 +4594,7 @@ fn trans_arg_expr(@block_ctxt cx,
bcx = re.bcx;
}
- if (ty.count_ty_params(cx.fcx.lcx.ccx.tcx, arg.ty) > 0u) {
+ if (ty.type_contains_params(cx.fcx.lcx.ccx.tcx, arg.ty)) {
auto lldestty = lldestty0;
if (arg.mode == ast.val) {
// FIXME: we'd prefer to use &&, but rustboot doesn't like it
@@ -4655,7 +4656,7 @@ fn trans_args(@block_ctxt cx,
if (ty.type_has_dynamic_size(cx.fcx.lcx.ccx.tcx, retty)) {
llargs += vec(bcx.build.PointerCast
(llretslot, T_typaram_ptr(cx.fcx.lcx.ccx.tn)));
- } else if (ty.count_ty_params(cx.fcx.lcx.ccx.tcx, retty) != 0u) {
+ } else if (ty.type_contains_params(cx.fcx.lcx.ccx.tcx, retty)) {
// It's possible that the callee has some generic-ness somewhere in
// its return value -- say a method signature within an obj or a fn
// type deep in a structure -- which the caller has a concrete view
diff --git a/src/comp/middle/ty.rs b/src/comp/middle/ty.rs
index 71a98e77..194dcf44 100644
--- a/src/comp/middle/ty.rs
+++ b/src/comp/middle/ty.rs
@@ -61,7 +61,14 @@ fn method_ty_to_fn_ty(ctxt cx, method m) -> t {
//
// TODO: It'd be really nice to be able to hide this definition from the
// outside world, to enforce the above invariants.
-type raw_t = rec(sty struct, option.t[str] cname, uint magic, uint hash);
+type raw_t = rec(sty struct,
+ option.t[str] cname,
+ uint magic,
+ uint hash,
+ bool has_params,
+ bool has_bound_params,
+ bool has_vars,
+ bool has_locals);
type t = @raw_t;
// NB: If you change this, you'll probably want to change the corresponding
@@ -145,6 +152,7 @@ type type_store = rec(vec[ty.t] empty_vec_ty,
ty.t t_char,
ty.t t_str,
+ ty.t t_task,
ty.t t_native,
ty.t t_type,
@@ -164,7 +172,7 @@ fn mk_type_store() -> @type_store {
t_int = mk_ty_full(ty_int, none[str]),
t_float = mk_ty_full(ty_float, none[str]),
t_uint = mk_ty_full(ty_uint, none[str]),
-
+
t_i8 = mk_ty_full(ty_machine(ty_i8), none[str]),
t_i16 = mk_ty_full(ty_machine(ty_i16), none[str]),
t_i32 = mk_ty_full(ty_machine(ty_i32), none[str]),
@@ -181,6 +189,7 @@ fn mk_type_store() -> @type_store {
t_char = mk_ty_full(ty_char, none[str]),
t_str = mk_ty_full(ty_str, none[str]),
+ t_task = mk_ty_full(ty_task, none[str]),
t_native = mk_ty_full(ty_native, none[str]),
t_type = mk_ty_full(ty_type, none[str]),
@@ -195,20 +204,140 @@ fn mk_ctxt() -> ctxt { ret rec(ts=mk_type_store()); }
// Type constructors
-// These are private constructors to this module. External users should always
-// use the mk_foo() functions below.
-fn gen_ty(ctxt cx, &sty st) -> t {
- ret gen_ty_full(cx, st, none[str]);
-}
-
fn mk_ty_full(&sty st, option.t[str] cname) -> t {
auto h = hash_type_info(st, cname);
auto magic = mk_magic(st);
- ret @rec(struct=st, cname=cname, magic=magic, hash=h);
+
+ let bool has_params = false;
+ let bool has_bound_params = false;
+ let bool has_vars = false;
+ let bool has_locals = false;
+
+ fn derive_flags_t(&mutable bool has_params,
+ &mutable bool has_bound_params,
+ &mutable bool has_vars,
+ &mutable bool has_locals,
+ &t tt) {
+ has_params = has_params || tt.has_params;
+ has_bound_params = has_bound_params || tt.has_bound_params;
+ has_vars = has_vars || tt.has_vars;
+ has_locals = has_locals || tt.has_locals;
+ }
+
+ fn derive_flags_mt(&mutable bool has_params,
+ &mutable bool has_bound_params,
+ &mutable bool has_vars,
+ &mutable bool has_locals,
+ &mt m) {
+ derive_flags_t(has_params, has_bound_params,
+ has_vars, has_locals, m.ty);
+ }
+
+
+ fn derive_flags_arg(&mutable bool has_params,
+ &mutable bool has_bound_params,
+ &mutable bool has_vars,
+ &mutable bool has_locals,
+ &arg a) {
+ derive_flags_t(has_params, has_bound_params,
+ has_vars, has_locals, a.ty);
+ }
+
+ fn derive_flags_sig(&mutable bool has_params,
+ &mutable bool has_bound_params,
+ &mutable bool has_vars,
+ &mutable bool has_locals,
+ &vec[arg] args,
+ &t tt) {
+ for (arg a in args) {
+ derive_flags_arg(has_params, has_bound_params,
+ has_vars, has_locals, a);
+ }
+ derive_flags_t(has_params, has_bound_params,
+ has_vars, has_locals, tt);
+ }
+
+ alt (st) {
+ case (ty_param(_)) { has_params = true; }
+ case (ty_bound_param(_)) { has_bound_params = true; }
+ case (ty_var(_)) { has_vars = true; }
+ case (ty_local(_)) { has_locals = true; }
+ case (ty_tag(_, ?tys)) {
+ for (t tt in tys) {
+ derive_flags_t(has_params, has_bound_params,
+ has_vars, has_locals, tt);
+ }
+ }
+ case (ty_box(?m)) {
+ derive_flags_mt(has_params, has_bound_params,
+ has_vars, has_locals, m);
+ }
+
+ case (ty_vec(?m)) {
+ derive_flags_mt(has_params, has_bound_params,
+ has_vars, has_locals, m);
+ }
+
+ case (ty_port(?tt)) {
+ derive_flags_t(has_params, has_bound_params,
+ has_vars, has_locals, tt);
+ }
+
+ case (ty_chan(?tt)) {
+ derive_flags_t(has_params, has_bound_params,
+ has_vars, has_locals, tt);
+ }
+
+ case (ty_tup(?mts)) {
+ for (mt m in mts) {
+ derive_flags_mt(has_params, has_bound_params,
+ has_vars, has_locals, m);
+ }
+ }
+
+ case (ty_rec(?flds)) {
+ for (field f in flds) {
+ derive_flags_mt(has_params, has_bound_params,
+ has_vars, has_locals, f.mt);
+ }
+ }
+
+ case (ty_fn(_, ?args, ?tt)) {
+ derive_flags_sig(has_params, has_bound_params,
+ has_vars, has_locals, args, tt);
+ }
+
+ case (ty_native_fn(_, ?args, ?tt)) {
+ derive_flags_sig(has_params, has_bound_params,
+ has_vars, has_locals, args, tt);
+ }
+
+ case (ty_obj(?meths)) {
+ for (method m in meths) {
+ derive_flags_sig(has_params, has_bound_params,
+ has_vars, has_locals,
+ m.inputs, m.output);
+ }
+ }
+ case (_) { }
+ }
+
+ ret @rec(struct=st, cname=cname, magic=magic, hash=h,
+ has_params = has_params,
+ has_bound_params = has_bound_params,
+ has_vars = has_vars,
+ has_locals = has_locals);
}
fn gen_ty_full(ctxt cx, &sty st, option.t[str] cname) -> t {
auto new_type = mk_ty_full(st, cname);
+
+ // Do not intern anything with locals or vars; it'll be nearly
+ // single-use anyways, easier to regenerate than fill up the table.
+ if (new_type.has_locals || new_type.has_vars) {
+ ret new_type;
+ }
+
// Is it interned?
alt (cx.ts.others.find(new_type)) {
case (some[t](?typ)) {
@@ -217,16 +346,23 @@ fn gen_ty_full(ctxt cx, &sty st, option.t[str] cname) -> t {
case (none[t]) {
// Nope. Insert it and return.
cx.ts.others.insert(new_type, new_type);
+ // log_err "added: " + ty_to_str(tystore, new_type);
ret new_type;
}
}
}
-fn mk_nil(ctxt cx) -> t { ret cx.ts.t_nil; }
-fn mk_bool(ctxt cx) -> t { ret cx.ts.t_bool; }
-fn mk_int(ctxt cx) -> t { ret cx.ts.t_int; }
-fn mk_float(ctxt cx) -> t { ret cx.ts.t_float; }
-fn mk_uint(ctxt cx) -> t { ret cx.ts.t_uint; }
+// These are private constructors to this module. External users should always
+// use the mk_foo() functions below.
+fn gen_ty(ctxt cx, &sty st) -> t {
+ ret gen_ty_full(cx, st, none[str]);
+}
+
+fn mk_nil(ctxt cx) -> t { ret cx.ts.t_nil; }
+fn mk_bool(ctxt cx) -> t { ret cx.ts.t_bool; }
+fn mk_int(ctxt cx) -> t { ret cx.ts.t_int; }
+fn mk_float(ctxt cx) -> t { ret cx.ts.t_float; }
+fn mk_uint(ctxt cx) -> t { ret cx.ts.t_uint; }
fn mk_mach(ctxt cx, util.common.ty_mach tm) -> t {
alt (tm) {
@@ -291,17 +427,12 @@ fn mk_obj(ctxt cx, vec[method] meths) -> t {
ret gen_ty(cx, ty_obj(meths));
}
-fn mk_var(ctxt cx, int v) -> t {
- let int i = _vec.len[t](cx.ts.t_vars) as int;
- while (i <= v) {
- cx.ts.t_vars += vec(mk_ty_full(ty_var(i), none[str]));
- i += 1;
- }
- ret cx.ts.t_vars.(v);
+fn mk_var(ctxt cx, int v) -> t {
+ ret mk_ty_full(ty_var(v), none[str]);
}
fn mk_local(ctxt cx, ast.def_id did) -> t {
- ret gen_ty(cx, ty_local(did));
+ ret mk_ty_full(ty_local(did), none[str]);
}
fn mk_param(ctxt cx, uint n) -> t {
@@ -414,6 +545,7 @@ fn ty_to_str(ctxt cx, &t typ) -> str {
}
auto s = "";
+
alt (struct(cx, typ)) {
case (ty_native) { s += "native"; }
case (ty_nil) { s += "()"; }
@@ -1041,7 +1173,6 @@ fn hash_ty(&t typ) -> uint { ret typ.hash; }
// Type equality. This function is private to this module (and slow); external
// users should use `eq_ty()` instead.
fn equal_type_structures(&sty a, &sty b) -> bool {
- fn equal_ty(t a, t b) -> bool { ret Box.ptr_eq[raw_t](a, b); }
fn equal_proto(ast.proto a, ast.proto b) -> bool {
alt (a) {
@@ -1124,22 +1255,21 @@ fn equal_type_structures(&sty a, &sty b) -> bool {
}
fn equal_mt(&mt a, &mt b) -> bool {
- ret equal_mut(a.mut, b.mut) && equal_ty(a.ty, b.ty);
+ ret equal_mut(a.mut, b.mut) && eq_ty(a.ty, b.ty);
}
fn equal_fn(vec[arg] args_a, t rty_a,
vec[arg] args_b, t rty_b) -> bool {
- if (!equal_ty(rty_a, rty_b)) { ret false; }
+ if (!eq_ty(rty_a, rty_b)) { ret false; }
auto len = _vec.len[arg](args_a);
if (len != _vec.len[arg](args_b)) { ret false; }
+
auto i = 0u;
while (i < len) {
auto arg_a = args_a.(i); auto arg_b = args_b.(i);
- if (!equal_mode(arg_a.mode, arg_b.mode) ||
- !equal_ty(arg_a.ty, arg_b.ty)) {
- ret false;
- }
+ if (!equal_mode(arg_a.mode, arg_b.mode)) { ret false; }
+ if (!eq_ty(arg_a.ty, arg_b.ty)) { ret false; }
i += 1u;
}
ret true;
@@ -1209,7 +1339,7 @@ fn equal_type_structures(&sty a, &sty b) -> bool {
if (len != _vec.len[t](tys_b)) { ret false; }
auto i = 0u;
while (i < len) {
- if (!equal_ty(tys_a.(i), tys_b.(i))) { ret false; }
+ if (!eq_ty(tys_a.(i), tys_b.(i))) { ret false; }
i += 1u;
}
ret true;
@@ -1231,13 +1361,13 @@ fn equal_type_structures(&sty a, &sty b) -> bool {
}
case (ty_port(?t_a)) {
alt (b) {
- case (ty_port(?t_b)) { ret equal_ty(t_a, t_b); }
+ case (ty_port(?t_b)) { ret eq_ty(t_a, t_b); }
case (_) { ret false; }
}
}
case (ty_chan(?t_a)) {
alt (b) {
- case (ty_chan(?t_b)) { ret equal_ty(t_a, t_b); }
+ case (ty_chan(?t_b)) { ret eq_ty(t_a, t_b); }
case (_) { ret false; }
}
}
@@ -1394,7 +1524,17 @@ fn eq_ty_full(&t a, &t b) -> bool {
// This is the equality function the public should use. It works as long as
// the types are interned.
-fn eq_ty(&t a, &t b) -> bool { ret Box.ptr_eq[raw_t](a, b); }
+fn eq_ty(&t a, &t b) -> bool {
+ let bool full = false;
+ full = full || a.has_vars;
+ full = full || a.has_locals;
+ full = full || b.has_vars;
+ full = full || b.has_locals;
+ if (full) {
+ ret eq_ty_full(a, b);
+ }
+ ret Box.ptr_eq[raw_t](a, b);
+}
fn ann_to_type(&ast.ann ann) -> t {
@@ -1480,45 +1620,15 @@ fn count_ty_params(ctxt cx, t ty) -> uint {
}
fn type_contains_vars(ctxt cx, t typ) -> bool {
- fn checker(ctxt cx, @mutable bool flag, t typ) {
- alt (struct(cx, typ)) {
- case (ty_var(_)) { *flag = true; }
- case (_) { /* fall through */ }
- }
- }
-
- let @mutable bool flag = @mutable false;
- auto f = bind checker(cx, flag, _);
- walk_ty(cx, f, typ);
- ret *flag;
+ ret typ.has_vars;
}
fn type_contains_params(ctxt cx, t typ) -> bool {
- fn checker(ctxt cx, @mutable bool flag, t typ) {
- alt (struct(cx, typ)) {
- case (ty_param(_)) { *flag = true; }
- case (_) { /* fall through */ }
- }
- }
-
- let @mutable bool flag = @mutable false;
- auto f = bind checker(cx, flag, _);
- walk_ty(cx, f, typ);
- ret *flag;
+ ret typ.has_params;
}
fn type_contains_bound_params(ctxt cx, t typ) -> bool {
- fn checker(ctxt cx, @mutable bool flag, t typ) {
- alt (struct(cx, typ)) {
- case (ty_bound_param(_)) { *flag = true; }
- case (_) { /* fall through */ }
- }
- }
-
- let @mutable bool flag = @mutable false;
- auto f = bind checker(cx, flag, _);
- walk_ty(cx, f, typ);
- ret *flag;
+ ret typ.has_bound_params;
}
// Type accessors for substructures of types