diff --git a/src/rustc/metadata/tyencode.rs b/src/rustc/metadata/tyencode.rs index eb6631c7a503..4893275f9531 100644 --- a/src/rustc/metadata/tyencode.rs +++ b/src/rustc/metadata/tyencode.rs @@ -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)); diff --git a/src/rustc/middle/trans/shape.rs b/src/rustc/middle/trans/shape.rs index 707c8d0608e1..303b8995244d 100644 --- a/src/rustc/middle/trans/shape.rs +++ b/src/rustc/middle/trans/shape.rs @@ -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"); } } diff --git a/src/rustc/middle/trans/type_of.rs b/src/rustc/middle/trans/type_of.rs index fedd7c713cff..7ce9b5885b4b 100644 --- a/src/rustc/middle/trans/type_of.rs +++ b/src/rustc/middle/trans/type_of.rs @@ -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); diff --git a/src/rustc/middle/ty.rs b/src/rustc/middle/ty.rs index fd6b797d5590..c608a83319c4 100644 --- a/src/rustc/middle/ty.rs +++ b/src/rustc/middle/ty.rs @@ -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 { 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) } diff --git a/src/rustc/middle/typeck/infer.rs b/src/rustc/middle/typeck/infer.rs index 2896e8875dae..45726bff9661 100644 --- a/src/rustc/middle/typeck/infer.rs +++ b/src/rustc/middle/typeck/infer.rs @@ -198,8 +198,9 @@ enum var_value { enum infer_ctxt = @{ tcx: ty::ctxt, - vb: vals_and_bindings, - rb: vals_and_bindings, + tvb: vals_and_bindings, // for type variables + tvib: vals_and_bindings, // for integral type variables + rb: vals_and_bindings, // 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(f: fn() -> result) -> result { - 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(f: fn() -> result) -> result { #[doc = "Execute `f`, unroll bindings on failure"] fn try(f: fn() -> result) -> result { - 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(f: fn() -> result) -> result { #[doc = "Execute `f` then unroll any bindings it creates"] fn probe(f: fn() -> result) -> result { - 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, snd: option) -> option { } (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 { 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( (_, 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) }) } diff --git a/src/rustc/util/ppaux.rs b/src/rustc/util/ppaux.rs index 664bd2680390..60f4ea8dabff 100644 --- a/src/rustc/util/ppaux.rs +++ b/src/rustc/util/ppaux.rs @@ -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)]) }