Add ty_var_integral (WIP on issue #1425).

This commit is contained in:
Lindsey Kuper
2012-06-01 14:56:33 -07:00
parent 77c470d183
commit 7d0755529e
6 changed files with 81 additions and 34 deletions
+6
View File
@@ -276,6 +276,12 @@ fn enc_sty(w: io::writer, cx: @ctxt, st: ty::sty) {
w.write_char('X');
w.write_uint(id.to_uint());
}
ty::ty_var_integral(id) {
// TODO: should we have a different character for these? (Issue #1425)
w.write_char('X');
w.write_uint(id.to_uint());
w.write_str("(integral)");
}
ty::ty_param(id, did) {
w.write_char('p');
w.write_str(cx.ds(did));
+1 -1
View File
@@ -395,7 +395,7 @@ fn shape_of(ccx: @crate_ctxt, t: ty::t) -> [u8] {
ty::ty_fn({proto: ast::proto_bare, _}) { [shape_bare_fn] }
ty::ty_opaque_closure_ptr(_) { [shape_opaque_closure_ptr] }
ty::ty_constr(inner_t, _) { shape_of(ccx, inner_t) }
ty::ty_var(_) | ty::ty_self {
ty::ty_var(_) | ty::ty_var_integral(_) | ty::ty_self {
ccx.sess.bug("shape_of: unexpected type struct found");
}
}
+3
View File
@@ -161,6 +161,9 @@ fn type_of(cx: @crate_ctxt, t: ty::t) -> TypeRef {
}
ty::ty_self { cx.tcx.sess.unimpl("type_of: ty_self"); }
ty::ty_var(_) { cx.tcx.sess.bug("type_of shouldn't see a ty_var"); }
ty::ty_var_integral(_) {
cx.tcx.sess.bug("type_of shouldn't see a ty_var_integral");
}
}
};
cx.lltypes.insert(t, llty);
+47 -12
View File
@@ -102,6 +102,7 @@
export ty_uint, mk_uint, mk_mach_uint;
export ty_uniq, mk_uniq, mk_imm_uniq, type_is_unique_box;
export ty_var, mk_var, type_is_var;
export ty_var_integral, mk_var_integral, type_is_var_integral;
export ty_self, mk_self, type_has_self;
export region, bound_region, encl_region;
export get, type_has_params, type_needs_infer, type_has_regions;
@@ -299,6 +300,11 @@ enum closure_kind {
ck_uniq,
}
enum ty_var_kind {
tvk_regular,
tvk_integral,
}
type fn_ty = {purity: ast::purity,
proto: ast::proto,
inputs: [arg],
@@ -365,6 +371,8 @@ enum sty {
ty_tup([t]),
ty_var(ty_vid), // type variable during typechecking
ty_var_integral(ty_vid), // type variable during typechecking, for
// integral types only
ty_param(uint, def_id), // type parameter
ty_self, // special, implicit `self` type parameter
@@ -555,7 +563,7 @@ fn sflags(substs: substs) -> uint {
ty_str | ty_estr(_) | ty_type | ty_opaque_closure_ptr(_) |
ty_opaque_box {}
ty_param(_, _) { flags |= has_params as uint; }
ty_var(_) { flags |= needs_infer as uint; }
ty_var(_) | ty_var_integral(_) { flags |= needs_infer as uint; }
ty_self { flags |= has_self as uint; }
ty_enum(_, substs) | ty_class(_, substs) | ty_iface(_, substs) {
flags |= sflags(substs);
@@ -680,6 +688,8 @@ fn mk_res(cx: ctxt, did: ast::def_id,
fn mk_var(cx: ctxt, v: ty_vid) -> t { mk_t(cx, ty_var(v)) }
fn mk_var_integral(cx: ctxt, v: ty_vid) -> t { mk_t(cx, ty_var_integral(v)) }
fn mk_self(cx: ctxt) -> t { mk_t(cx, ty_self) }
fn mk_param(cx: ctxt, n: uint, k: def_id) -> t { mk_t(cx, ty_param(n, k)) }
@@ -729,7 +739,8 @@ fn maybe_walk_ty(ty: t, f: fn(t) -> bool) {
alt get(ty).struct {
ty_nil | ty_bot | ty_bool | ty_int(_) | ty_uint(_) | ty_float(_) |
ty_str | ty_estr(_) | ty_type | ty_opaque_box | ty_self |
ty_opaque_closure_ptr(_) | ty_var(_) | ty_param(_, _) {
ty_opaque_closure_ptr(_) | ty_var(_) | ty_var_integral(_) |
ty_param(_, _) {
}
ty_box(tm) | ty_vec(tm) | ty_evec(tm, _) |
ty_ptr(tm) | ty_rptr(_, tm) {
@@ -824,7 +835,7 @@ fn fold_substs(substs: substs, fldop: fn(t) -> t) -> substs {
}
ty_nil | ty_bot | ty_bool | ty_int(_) | ty_uint(_) | ty_float(_) |
ty_str | ty_estr(_) | ty_type | ty_opaque_closure_ptr(_) |
ty_opaque_box | ty_var(_) | ty_param(*) | ty_self {
ty_opaque_box | ty_var(_) | ty_var_integral(_) | ty_param(*) | ty_self {
sty
}
}
@@ -1038,6 +1049,13 @@ fn type_is_var(ty: t) -> bool {
}
}
fn type_is_var_integral(ty: t) -> bool {
alt get(ty).struct {
ty_var_integral(_) { true }
_ { false }
}
}
fn type_is_bool(ty: t) -> bool { get(ty).struct == ty_bool }
fn type_is_structural(ty: t) -> bool {
@@ -1553,8 +1571,9 @@ fn type_kind(cx: ctxt, ty: t) -> kind {
ty_constr(t, _) { type_kind(cx, t) }
// FIXME: is self ever const?
ty_self { kind_noncopyable() }
ty_var(_) { cx.sess.bug("Asked to compute kind of a type variable"); }
ty_var(_) | ty_var_integral(_) {
cx.sess.bug("Asked to compute kind of a type variable");
}
ty_type | ty_opaque_closure_ptr(_) | ty_opaque_box {
cx.sess.bug("Asked to compute kind of fictitious type");
}
@@ -1602,6 +1621,7 @@ fn subtypes_require(cx: ctxt, seen: @mut [def_id],
ty_estr(_) |
ty_fn(_) |
ty_var(_) |
ty_var_integral(_) |
ty_param(_, _) |
ty_self |
ty_type |
@@ -1878,12 +1898,25 @@ fn type_param(ty: t) -> option<uint> {
ret none;
}
// Returns a vec of all the type variables
// occurring in t. It may contain duplicates.
fn vars_in_type(ty: t) -> [ty_vid] {
// Returns a vec of all the type variables of kind `tvk` occurring in `ty`. It
// may contain duplicates.
fn vars_in_type(ty: t, tvk: ty_var_kind) -> [ty_vid] {
let mut rslt = [];
walk_ty(ty) {|ty|
alt get(ty).struct { ty_var(v) { rslt += [v]; } _ { } }
alt get(ty).struct {
ty_var(v) {
alt tvk {
tvk_regular { rslt += [v]; }
_ { }
}
}
ty_var_integral(v) {
alt tvk {
tvk_integral { rslt += [v]; }
_ { }
}
}
_ { } }
}
rslt
}
@@ -2037,7 +2070,8 @@ fn hash_substs(h: uint, substs: substs) -> uint {
for f.inputs.each {|a| h = hash_subty(h, a.ty); }
hash_subty(h, f.output)
}
ty_var(v) { hash_uint(30u, v.to_uint()) }
ty_var(v) { hash_uint(29u, v.to_uint()) }
ty_var_integral(v) { hash_uint(30u, v.to_uint()) }
ty_param(pid, did) { hash_def(hash_uint(31u, pid), did) }
ty_self { 28u }
ty_type { 32u }
@@ -2184,7 +2218,7 @@ fn is_pred_ty(fty: t) -> bool {
fn ty_var_id(typ: t) -> ty_vid {
alt get(typ).struct {
ty_var(vid) { ret vid; }
ty_var(vid) | ty_var_integral(vid) { ret vid; }
_ { #error("ty_var_id called on non-var ty"); fail; }
}
}
@@ -2276,7 +2310,7 @@ fn occurs_check(tcx: ctxt, sp: span, vid: ty_vid, rt: t) {
if !type_needs_infer(rt) { ret; }
// Occurs check!
if vec::contains(vars_in_type(rt), vid) {
if vec::contains(vars_in_type(rt, tvk_regular), vid) {
// Maybe this should be span_err -- however, there's an
// assertion later on that the type doesn't contain
// variables, so in this case we have to be sure to die.
@@ -2381,6 +2415,7 @@ fn ty_sort_str(cx: ctxt, t: t) -> str {
ty_res(id, _, _) { #fmt["resource %s", item_path_str(cx, id)] }
ty_tup(_) { "tuple" }
ty_var(_) { "variable" }
ty_var_integral(_) { "integral variable" }
ty_param(_, _) { "type parameter" }
ty_self { "self" }
ty_constr(t, _) { ty_sort_str(cx, t) }
+23 -21
View File
@@ -198,8 +198,9 @@ enum var_value<V:copy, T:copy> {
enum infer_ctxt = @{
tcx: ty::ctxt,
vb: vals_and_bindings<ty::ty_vid, ty::t>,
rb: vals_and_bindings<ty::region_vid, ty::region>,
tvb: vals_and_bindings<ty::ty_vid, ty::t>, // for type variables
tvib: vals_and_bindings<ty::ty_vid, ty::t>, // for integral type variables
rb: vals_and_bindings<ty::region_vid, ty::region>, // for region variables
// For keeping track of existing type/region variables.
ty_var_counter: @mut uint,
@@ -227,7 +228,8 @@ fn fixup_err_to_str(f: fixup_err) -> str {
fn new_infer_ctxt(tcx: ty::ctxt) -> infer_ctxt {
infer_ctxt(@{tcx: tcx,
vb: {vals: smallintmap::mk(), mut bindings: []},
tvb: {vals: smallintmap::mk(), mut bindings: []},
tvib: {vals: smallintmap::mk(), mut bindings: []},
rb: {vals: smallintmap::mk(), mut bindings: []},
ty_var_counter: @mut 0u,
region_var_counter: @mut 0u})}
@@ -423,14 +425,14 @@ impl transaction_methods for infer_ctxt {
#[doc = "Execute `f` and commit the bindings if successful"]
fn commit<T,E>(f: fn() -> result<T,E>) -> result<T,E> {
assert self.vb.bindings.len() == 0u;
assert self.tvb.bindings.len() == 0u;
assert self.rb.bindings.len() == 0u;
let r <- self.try(f);
// TODO---could use a vec::clear() that ran destructors but kept
// the vec at its currently allocated length
self.vb.bindings = [];
self.tvb.bindings = [];
self.rb.bindings = [];
ret r;
@@ -439,15 +441,15 @@ fn commit<T,E>(f: fn() -> result<T,E>) -> result<T,E> {
#[doc = "Execute `f`, unroll bindings on failure"]
fn try<T,E>(f: fn() -> result<T,E>) -> result<T,E> {
let vbl = self.vb.bindings.len();
let tvbl = self.tvb.bindings.len();
let rbl = self.rb.bindings.len();
#debug["try(vbl=%u, rbl=%u)", vbl, rbl];
#debug["try(tvbl=%u, rbl=%u)", tvbl, rbl];
let r <- f();
alt r {
result::ok(_) { #debug["try--ok"]; }
result::err(_) {
#debug["try--rollback"];
rollback_to(self.vb, vbl);
rollback_to(self.tvb, tvbl);
rollback_to(self.rb, rbl);
}
}
@@ -456,10 +458,10 @@ fn try<T,E>(f: fn() -> result<T,E>) -> result<T,E> {
#[doc = "Execute `f` then unroll any bindings it creates"]
fn probe<T,E>(f: fn() -> result<T,E>) -> result<T,E> {
assert self.vb.bindings.len() == 0u;
assert self.tvb.bindings.len() == 0u;
assert self.rb.bindings.len() == 0u;
let r <- f();
rollback_to(self.vb, 0u);
rollback_to(self.tvb, 0u);
rollback_to(self.rb, 0u);
ret r;
}
@@ -932,7 +934,7 @@ fn resolve_ty_var(vid: ty_vid) -> ty::t {
// tend to carry more restrictions or higher
// perf. penalties, so it pays to know more.
let {root:_, bounds} = self.infcx.get(self.infcx.vb, vid);
let {root:_, bounds} = self.infcx.get(self.infcx.tvb, vid);
let t1 = alt bounds {
{ ub:_, lb:some(t) } if !type_is_bot(t) { self.resolve1(t) }
{ ub:some(t), lb:_ } { self.resolve1(t) }
@@ -1025,21 +1027,21 @@ fn select(fst: option<ty::t>, snd: option<ty::t>) -> option<ty::t> {
}
(ty::ty_var(a_id), ty::ty_var(b_id)) {
let {root:_, bounds: a_bounds} = self.get(self.vb, a_id);
let {root:_, bounds: b_bounds} = self.get(self.vb, b_id);
let {root:_, bounds: a_bounds} = self.get(self.tvb, a_id);
let {root:_, bounds: b_bounds} = self.get(self.tvb, b_id);
let a_bnd = select(a_bounds.ub, a_bounds.lb);
let b_bnd = select(b_bounds.lb, b_bounds.ub);
self.assign_tys_or_sub(anmnt, a, b, a_bnd, b_bnd)
}
(ty::ty_var(a_id), _) {
let {root:_, bounds:a_bounds} = self.get(self.vb, a_id);
let {root:_, bounds:a_bounds} = self.get(self.tvb, a_id);
let a_bnd = select(a_bounds.ub, a_bounds.lb);
self.assign_tys_or_sub(anmnt, a, b, a_bnd, some(b))
}
(_, ty::ty_var(b_id)) {
let {root:_, bounds: b_bounds} = self.get(self.vb, b_id);
let {root:_, bounds: b_bounds} = self.get(self.tvb, b_id);
let b_bnd = select(b_bounds.lb, b_bounds.ub);
self.assign_tys_or_sub(anmnt, a, b, some(a), b_bnd)
}
@@ -1632,13 +1634,13 @@ fn tys(a: ty::t, b: ty::t) -> cres<ty::t> {
ok(a)
}
(ty::ty_var(a_id), ty::ty_var(b_id)) {
self.infcx().vars(self.vb, a_id, b_id).then {|| ok(a) }
self.infcx().vars(self.tvb, a_id, b_id).then {|| ok(a) }
}
(ty::ty_var(a_id), _) {
self.infcx().vart(self.vb, a_id, b).then {|| ok(a) }
self.infcx().vart(self.tvb, a_id, b).then {|| ok(a) }
}
(_, ty::ty_var(b_id)) {
self.infcx().tvar(self.vb, a, b_id).then {|| ok(a) }
self.infcx().tvar(self.tvb, a, b_id).then {|| ok(a) }
}
(_, ty::ty_bot) {
err(ty::terr_sorts(b, a))
@@ -2148,18 +2150,18 @@ fn lattice_tys<L:lattice_ops combine>(
(_, ty::ty_bot) { self.ty_bot(a) }
(ty::ty_var(a_id), ty::ty_var(b_id)) {
lattice_vars(self, self.infcx().vb,
lattice_vars(self, self.infcx().tvb,
a, a_id, b_id,
{|x, y| self.tys(x, y) })
}
(ty::ty_var(a_id), _) {
lattice_var_t(self, self.infcx().vb, a_id, b,
lattice_var_t(self, self.infcx().tvb, a_id, b,
{|x, y| self.tys(x, y) })
}
(_, ty::ty_var(b_id)) {
lattice_var_t(self, self.infcx().vb, b_id, a,
lattice_var_t(self, self.infcx().tvb, b_id, a,
{|x, y| self.tys(x, y) })
}
+1
View File
@@ -194,6 +194,7 @@ fn field_to_str(cx: ctxt, f: field) -> str {
f.output, f.ret_style, f.constraints)
}
ty_var(v) { v.to_str() }
ty_var_integral(v) { v.to_str() }
ty_param(id, _) {
"'" + str::from_bytes([('a' as u8) + (id as u8)])
}