mirror of
https://github.com/rust-lang/rust.git
synced 2026-05-29 20:46:07 +03:00
Add ty_var_integral (WIP on issue #1425).
This commit is contained in:
@@ -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));
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
@@ -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) }
|
||||
|
||||
@@ -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) })
|
||||
}
|
||||
|
||||
|
||||
@@ -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)])
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user