WIP on issue #1425: mostly infrastructure changes.

This commit is contained in:
Lindsey Kuper 2012-06-08 10:17:02 -07:00
parent d8d76738ec
commit b8af02e219
5 changed files with 314 additions and 111 deletions

View file

@ -346,7 +346,7 @@ fn parse_ty(st: @pstate, conv: conv_did) -> ty::t {
ret ty::mk_res(st.tcx, def, inner, substs);
}
'X' {
ret ty::mk_var(st.tcx, ty::ty_vid(parse_int(st) as uint));
ret ty::mk_var(st.tcx, ty::tv_vid(parse_int(st) as uint));
}
'Y' { ret ty::mk_type(st.tcx); }
'C' {

View file

@ -17,7 +17,7 @@ import middle::lint::{get_warning_level, vecs_not_implicitly_copyable,
import syntax::ast::*;
import syntax::print::pprust::*;
export ty_vid, region_vid, vid;
export tv_vid, tvi_vid, region_vid, vid;
export br_hashmap;
export is_instantiable;
export node_id_to_type;
@ -302,11 +302,6 @@ enum closure_kind {
ck_uniq,
}
enum ty_var_kind {
tvk_regular,
tvk_integral,
}
type fn_ty = {purity: ast::purity,
proto: ast::proto,
inputs: [arg],
@ -372,9 +367,9 @@ enum sty {
ty_res(def_id, t, substs),
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_var(tv_vid), // type variable during typechecking
ty_var_integral(tvi_vid), // type variable during typechecking, for
// integral types only
ty_param(uint, def_id), // type parameter
ty_self, // special, implicit `self` type parameter
ty_constr(t, [@type_constr]),
@ -429,7 +424,8 @@ enum param_bound {
bound_iface(t),
}
enum ty_vid = uint;
enum tv_vid = uint;
enum tvi_vid = uint;
enum region_vid = uint;
iface vid {
@ -437,11 +433,16 @@ iface vid {
fn to_str() -> str;
}
impl of vid for ty_vid {
impl of vid for tv_vid {
fn to_uint() -> uint { *self }
fn to_str() -> str { #fmt["<V%u>", self.to_uint()] }
}
impl of vid for tvi_vid {
fn to_uint() -> uint { *self }
fn to_str() -> str { #fmt["<V (integral) %u>", self.to_uint()] }
}
impl of vid for region_vid {
fn to_uint() -> uint { *self }
fn to_str() -> str { #fmt["<R%u>", self.to_uint()] }
@ -693,9 +694,11 @@ fn mk_res(cx: ctxt, did: ast::def_id,
mk_t(cx, ty_res(did, inner, substs))
}
fn mk_var(cx: ctxt, v: ty_vid) -> t { mk_t(cx, ty_var(v)) }
fn mk_var(cx: ctxt, v: tv_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_var_integral(cx: ctxt, v: tvi_vid) -> t {
mk_t(cx, ty_var_integral(v))
}
fn mk_self(cx: ctxt) -> t { mk_t(cx, ty_self) }
@ -1911,29 +1914,6 @@ fn type_param(ty: t) -> option<uint> {
ret none;
}
// 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) {
alt tvk {
tvk_regular { rslt += [v]; }
_ { }
}
}
ty_var_integral(v) {
alt tvk {
tvk_integral { rslt += [v]; }
_ { }
}
}
_ { } }
}
rslt
}
// Returns the type and mutability of *t.
//
// The parameter `expl` indicates if this is an *explicit* dereference. Some
@ -2229,13 +2209,21 @@ fn is_pred_ty(fty: t) -> bool {
is_fn_ty(fty) && type_is_bool(ty_fn_ret(fty))
}
fn ty_var_id(typ: t) -> ty_vid {
fn ty_var_id(typ: t) -> tv_vid {
alt get(typ).struct {
ty_var(vid) | ty_var_integral(vid) { ret vid; }
ty_var(vid) { ret vid; }
_ { #error("ty_var_id called on non-var ty"); fail; }
}
}
fn ty_var_integral_id(typ: t) -> tvi_vid {
alt get(typ).struct {
ty_var_integral(vid) { ret vid; }
_ { #error("ty_var_integral_id called on ty other than \
ty_var_integral");
fail; }
}
}
// Type accessors for AST nodes
fn block_ty(cx: ctxt, b: ast::blk) -> t {
@ -2311,12 +2299,23 @@ fn method_idx(id: ast::ident, meths: [method]) -> option<uint> {
ret none;
}
fn occurs_check(tcx: ctxt, sp: span, vid: ty_vid, rt: t) {
fn occurs_check(tcx: ctxt, sp: span, vid: tv_vid, rt: t) {
// Returns a vec of all the type variables occurring in `ty`. It may
// contain duplicates. (Integral type vars aren't counted.)
fn vars_in_type(ty: t) -> [tv_vid] {
let mut rslt = [];
walk_ty(ty) {|ty|
alt get(ty).struct { ty_var(v) { rslt += [v]; } _ { } }
}
rslt
}
// Fast path
if !type_needs_infer(rt) { ret; }
// Occurs check!
if vec::contains(vars_in_type(rt, tvk_regular), vid) {
if vec::contains(vars_in_type(rt), 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.

View file

@ -52,7 +52,6 @@ import pat_util::{pat_is_variant, pat_id_map};
import middle::ty;
import middle::ty::{arg, field, node_type_table, mk_nil,
ty_param_bounds_and_ty, lookup_public_fields};
import middle::ty::{ty_vid, region_vid, vid};
import middle::typeck::infer::methods;
import util::ppaux::{ty_to_str, tys_to_str, region_to_str,
bound_region_to_str, vstore_to_str};

View file

@ -69,10 +69,15 @@ type parameter).
import astconv::{ast_conv, ast_ty_to_ty};
import collect::{methods}; // ccx.to_ty()
import method::{methods}; // methods for method::lookup
import middle::ty::tys_in_fn_ty;
import middle::ty::{tv_vid, vid};
import regionmanip::{replace_bound_regions_in_fn_ty, region_of};
import rscope::{anon_rscope, binding_rscope, empty_rscope, in_anon_rscope};
import rscope::{in_binding_rscope, region_scope, type_rscope};
import syntax::ast::{ty_char, ty_i8, ty_i16, ty_i32, ty_i64, ty_i};
import typeck::infer::{root, to_str};
import typeck::infer::{unify_methods}; // infcx.set()
import typeck::infer::{min_8bit_tys, min_16bit_tys, min_32bit_tys,
min_64bit_tys};
type fn_ctxt =
// var_bindings, locals and next_var_id are shared
@ -84,7 +89,7 @@ type fn_ctxt =
indirect_ret_ty: option<ty::t>,
purity: ast::purity,
infcx: infer::infer_ctxt,
locals: hashmap<ast::node_id, ty_vid>,
locals: hashmap<ast::node_id, tv_vid>,
mut blocks: [ast::node_id], // stack of blocks in scope, may be empty
in_scope_regions: isr_alist,
@ -618,22 +623,49 @@ fn are_compatible(fcx: @fn_ctxt, expected: ty::t, actual: ty::t) -> bool {
}
}
// Local variable gathering. We gather up all locals and create variable IDs
// for them before typechecking the function.
type gather_result =
{infcx: infer::infer_ctxt,
locals: hashmap<ast::node_id, ty_vid>,
ty_var_counter: @mut uint};
// AST fragment checking
fn check_lit(ccx: @crate_ctxt, lit: @ast::lit) -> ty::t {
fn check_lit(fcx: @fn_ctxt, lit: @ast::lit) -> ty::t {
let tcx = fcx.ccx.tcx;
alt lit.node {
ast::lit_str(_) { ty::mk_str(ccx.tcx) }
ast::lit_int(_, t) { ty::mk_mach_int(ccx.tcx, t) }
ast::lit_uint(_, t) { ty::mk_mach_uint(ccx.tcx, t) }
ast::lit_float(_, t) { ty::mk_mach_float(ccx.tcx, t) }
ast::lit_nil { ty::mk_nil(ccx.tcx) }
ast::lit_bool(_) { ty::mk_bool(ccx.tcx) }
ast::lit_str(_) { ty::mk_str(tcx) }
ast::lit_int(v, t) {
alt t {
ty_char | ty_i8 | ty_i16 | ty_i32 | ty_i64 {
// If it's a char or has an explicit suffix, give it the
// appropriate integral type.
ty::mk_mach_int(tcx, t)
}
ty_i {
// Otherwise, an unsuffixed integer literal parses to a
// `ty_i`. In that case, it could have any integral type,
// so create an integral type variable for it.
let vid = fcx.infcx.next_ty_var_integral_id();
// We need to sniff at the value `v` provided and figure
// out how big of an int it is; that determines the set of
// possibly types it could take on.
let possible_types = alt v {
0i64 to 127i64 { min_8bit_tys() }
128i64 to 65535i64 { min_16bit_tys() }
65536i64 to 4294967295i64 { min_32bit_tys() }
_ { min_64bit_tys() }
};
// Store the set of possible types
fcx.infcx.set(fcx.infcx.tvib, vid,
root(possible_types));
ty::mk_var_integral(tcx, vid);
// FIXME: remove me when #1425 is finished.
ty::mk_mach_int(tcx, t)
}
}
}
ast::lit_uint(_, t) { ty::mk_mach_uint(tcx, t) }
ast::lit_float(_, t) { ty::mk_mach_float(tcx, t) }
ast::lit_nil { ty::mk_nil(tcx) }
ast::lit_bool(_) { ty::mk_bool(tcx) }
}
}
@ -1107,7 +1139,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt,
}
ast::expr_lit(lit) {
let typ = check_lit(fcx.ccx, lit);
let typ = check_lit(fcx, lit);
fcx.write_ty(id, typ);
}
@ -2067,7 +2099,7 @@ fn self_ref(fcx: @fn_ctxt, id: ast::node_id) -> bool {
ast_util::is_self)
}
fn lookup_local(fcx: @fn_ctxt, sp: span, id: ast::node_id) -> ty_vid {
fn lookup_local(fcx: @fn_ctxt, sp: span, id: ast::node_id) -> tv_vid {
alt fcx.locals.find(id) {
some(x) { x }
_ {

View file

@ -147,7 +147,7 @@ import std::smallintmap::smallintmap;
import std::smallintmap::map;
import std::map::hashmap;
import middle::ty;
import middle::ty::{ty_vid, tys_in_fn_ty, region_vid, vid};
import middle::ty::{tv_vid, tvi_vid, region_vid, vid};
import syntax::{ast, ast_util};
import syntax::ast::{ret_style, purity};
import util::ppaux::{ty_to_str, mt_to_str};
@ -169,9 +169,57 @@ export resolve_shallow;
export resolve_deep;
export resolve_deep_var;
export methods; // for infer_ctxt
export unify_methods; // for infer_ctxt
export compare_tys;
export fixup_err, fixup_err_to_str;
export assignment;
export root, to_str;
export min_8bit_tys, min_16bit_tys, min_32bit_tys, min_64bit_tys;
// Bitvector to represent sets of integral types
enum int_ty_set = uint;
// Constants representing singleton sets containing each of the
// integral types
const INT_TY_SET_EMPTY : uint = 0b00_0000_0000u;
const INT_TY_SET_i8 : uint = 0b00_0000_0001u;
const INT_TY_SET_u8 : uint = 0b00_0000_0010u;
const INT_TY_SET_i16 : uint = 0b00_0000_0100u;
const INT_TY_SET_u16 : uint = 0b00_0000_1000u;
const INT_TY_SET_i32 : uint = 0b00_0001_0000u;
const INT_TY_SET_u32 : uint = 0b00_0010_0000u;
const INT_TY_SET_i64 : uint = 0b00_0100_0000u;
const INT_TY_SET_u64 : uint = 0b00_1000_0000u;
const INT_TY_SET_i : uint = 0b01_0000_0000u;
const INT_TY_SET_u : uint = 0b10_0000_0000u;
fn mk_int_ty_set() -> int_ty_set { int_ty_set(INT_TY_SET_EMPTY) }
fn min_8bit_tys() -> int_ty_set {
int_ty_set(INT_TY_SET_i8 | INT_TY_SET_u8 |
INT_TY_SET_i16 | INT_TY_SET_u16 |
INT_TY_SET_i32 | INT_TY_SET_u32 |
INT_TY_SET_i64 | INT_TY_SET_u64 |
INT_TY_SET_i | INT_TY_SET_u)
}
fn min_16bit_tys() -> int_ty_set {
int_ty_set(INT_TY_SET_i16 | INT_TY_SET_u16 |
INT_TY_SET_i32 | INT_TY_SET_u32 |
INT_TY_SET_i64 | INT_TY_SET_u64 |
INT_TY_SET_i | INT_TY_SET_u)
}
fn min_32bit_tys() -> int_ty_set {
int_ty_set(INT_TY_SET_i32 | INT_TY_SET_u32 |
INT_TY_SET_i64 | INT_TY_SET_u64 |
// uh, can we count on ty_i and ty_u being 32 bits?
INT_TY_SET_i | INT_TY_SET_u)
}
fn min_64bit_tys() -> int_ty_set {
int_ty_set(INT_TY_SET_i64 | INT_TY_SET_u64)
}
// Extra information needed to perform an assignment that may borrow.
// The `expr_id` is the is of the expression whose type is being
@ -183,12 +231,11 @@ type assignment = {
};
type bound<T:copy> = option<T>;
type bounds<T:copy> = {lb: bound<T>, ub: bound<T>};
enum var_value<V:copy, T:copy> {
redirect(V),
bounded(bounds<T>)
root(T)
}
type vals_and_bindings<V:copy, T:copy> = {
@ -198,18 +245,28 @@ type vals_and_bindings<V:copy, T:copy> = {
enum infer_ctxt = @{
tcx: ty::ctxt,
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.
// We instantiate vals_and_bindings with bounds<ty::t> because the
// types that might instantiate a general type variable have an
// order, represented by its upper and lower bounds.
tvb: vals_and_bindings<ty::tv_vid, bounds<ty::t>>,
// The types that might instantiate an integral type variable are
// represented by an int_ty_set.
tvib: vals_and_bindings<ty::tvi_vid, int_ty_set>,
// For region variables.
rb: vals_and_bindings<ty::region_vid, bounds<ty::region>>,
// For keeping track of existing type and region variables.
ty_var_counter: @mut uint,
ty_var_integral_counter: @mut uint,
region_var_counter: @mut uint,
};
enum fixup_err {
unresolved_ty(ty_vid),
cyclic_ty(ty_vid),
unresolved_ty(tv_vid),
cyclic_ty(tv_vid),
unresolved_region(region_vid),
cyclic_region(region_vid)
}
@ -232,6 +289,7 @@ fn new_infer_ctxt(tcx: ty::ctxt) -> infer_ctxt {
tvib: {vals: smallintmap::mk(), mut bindings: []},
rb: {vals: smallintmap::mk(), mut bindings: []},
ty_var_counter: @mut 0u,
ty_var_integral_counter: @mut 0u,
region_var_counter: @mut 0u})}
fn mk_subty(cx: infer_ctxt, a: ty::t, b: ty::t) -> ures {
@ -290,7 +348,7 @@ fn resolve_shallow(cx: infer_ctxt, a: ty::t,
}
// See comment on the type `resolve_state` below
fn resolve_deep_var(cx: infer_ctxt, vid: ty_vid,
fn resolve_deep_var(cx: infer_ctxt, vid: tv_vid,
force_vars: bool) -> fres<ty::t> {
resolver(cx, true, force_vars).resolve(ty::mk_var(cx.tcx, vid))
}
@ -365,11 +423,19 @@ impl<T:copy to_str> of to_str for bounds<T> {
}
}
impl of to_str for int_ty_set {
fn to_str(_cx: infer_ctxt) -> str {
alt self {
int_ty_set(v) { uint::to_str(v, 10u) }
}
}
}
impl<V:copy vid, T:copy to_str> of to_str for var_value<V,T> {
fn to_str(cx: infer_ctxt) -> str {
alt self {
redirect(vid) { #fmt("redirect(%s)", vid.to_str()) }
bounded(bnds) { #fmt("bounded(%s)", bnds.to_str(cx)) }
root(pt) { #fmt("root(%s)", pt.to_str(cx)) }
}
}
}
@ -468,10 +534,12 @@ impl transaction_methods for infer_ctxt {
}
impl methods for infer_ctxt {
fn next_ty_var_id() -> ty_vid {
fn next_ty_var_id() -> tv_vid {
let id = *self.ty_var_counter;
*self.ty_var_counter += 1u;
ret ty_vid(id);
self.tvb.vals.insert(id,
root({lb: none, ub: none}));
ret tv_vid(id);
}
fn next_ty_var() -> ty::t {
@ -482,14 +550,29 @@ impl methods for infer_ctxt {
vec::from_fn(n) {|_i| self.next_ty_var() }
}
fn next_ty_var_integral_id() -> tvi_vid {
let id = *self.ty_var_integral_counter;
*self.ty_var_integral_counter += 1u;
self.tvib.vals.insert(id,
root(mk_int_ty_set()));
ret tvi_vid(id);
}
fn next_ty_var_integral() -> ty::t {
ty::mk_var_integral(self.tcx, self.next_ty_var_integral_id())
}
fn next_region_var_id() -> region_vid {
let id = *self.region_var_counter;
*self.region_var_counter += 1u;
self.rb.vals.insert(id,
root({lb: none, ub: none}));
ret region_vid(id);
}
fn next_region_var() -> ty::region {
ret ty::re_var(self.next_region_var_id());
ty::re_var(self.next_region_var_id())
}
fn ty_to_str(t: ty::t) -> str {
@ -521,23 +604,27 @@ impl unify_methods for infer_ctxt {
fn get<V:copy vid, T:copy>(
vb: vals_and_bindings<V, T>, vid: V)
-> {root: V, bounds:bounds<T>} {
-> {root: V, possible_types: T} {
alt vb.vals.find(vid.to_uint()) {
none {
let bnds = {lb: none, ub: none};
vb.vals.insert(vid.to_uint(), bounded(bnds));
{root: vid, bounds: bnds}
#error["failed lookup in infcx.get()"];
fail;
}
some(redirect(vid)) {
let {root, bounds} = self.get(vb, vid);
if root != vid {
vb.vals.insert(vid.to_uint(), redirect(root));
some(var_val) {
alt var_val {
redirect(vid) {
let {root: rt, possible_types: pt} = self.get(vb, vid);
if rt != vid {
// Path compression
vb.vals.insert(vid.to_uint(), redirect(rt));
}
{root: rt, possible_types: pt}
}
root(pt) {
{root: vid, possible_types: pt}
}
}
{root: root, bounds: bounds}
}
some(bounded(bounds)) {
{root: vid, bounds: bounds}
}
}
}
@ -596,7 +683,7 @@ impl unify_methods for infer_ctxt {
// b.lb <: c.lb
// If this cannot be achieved, the result is failure.
fn set_var_to_merged_bounds<V:copy vid, T:copy to_str st>(
vb: vals_and_bindings<V, T>,
vb: vals_and_bindings<V, bounds<T>>,
v_id: V, a: bounds<T>, b: bounds<T>) -> ures {
// Think of the two diamonds, we want to find the
@ -638,19 +725,19 @@ impl unify_methods for infer_ctxt {
// the new bounds must themselves
// be relatable:
self.bnds(bnds.lb, bnds.ub).then {||
self.set(vb, v_id, bounded(bnds));
self.set(vb, v_id, root(bnds));
uok()
}
}
}}}}}
}
fn vars<V:copy vid, T:copy to_str st>(
vb: vals_and_bindings<V, T>,
vb: vals_and_bindings<V, bounds<T>>,
a_id: V, b_id: V) -> ures {
// Need to make sub_id a subtype of sup_id.
let {root: a_id, bounds: a_bounds} = self.get(vb, a_id);
let {root: b_id, bounds: b_bounds} = self.get(vb, b_id);
let {root: a_id, possible_types: a_bounds} = self.get(vb, a_id);
let {root: b_id, possible_types: b_bounds} = self.get(vb, b_id);
#debug["vars(%s=%s <: %s=%s)",
a_id.to_str(), a_bounds.to_str(self),
@ -683,11 +770,18 @@ impl unify_methods for infer_ctxt {
}
}
fn vars_integral<V:copy vid>(
_vb: vals_and_bindings<V, int_ty_set>,
_a_id: V, _b_id: V) -> ures {
// FIXME (#1425): do something real here.
uok()
}
fn vart<V: copy vid, T: copy to_str st>(
vb: vals_and_bindings<V, T>,
vb: vals_and_bindings<V, bounds<T>>,
a_id: V, b: T) -> ures {
let {root: a_id, bounds: a_bounds} = self.get(vb, a_id);
let {root: a_id, possible_types: a_bounds} = self.get(vb, a_id);
#debug["vart(%s=%s <: %s)",
a_id.to_str(), a_bounds.to_str(self),
b.to_str(self)];
@ -695,18 +789,33 @@ impl unify_methods for infer_ctxt {
self.set_var_to_merged_bounds(vb, a_id, a_bounds, b_bounds)
}
// FIXME (#1425): this is a terrible name.
fn vart_integral<V: copy vid, T: copy to_str st>(
_vb: vals_and_bindings<V, int_ty_set>,
_a_id: V, _b: T) -> ures {
// FIXME (#1425): do something real here.
uok()
}
fn tvar<V: copy vid, T: copy to_str st>(
vb: vals_and_bindings<V, T>,
vb: vals_and_bindings<V, bounds<T>>,
a: T, b_id: V) -> ures {
let a_bounds = {lb: some(a), ub: none};
let {root: b_id, bounds: b_bounds} = self.get(vb, b_id);
let {root: b_id, possible_types: b_bounds} = self.get(vb, b_id);
#debug["tvar(%s <: %s=%s)",
a.to_str(self),
b_id.to_str(), b_bounds.to_str(self)];
self.set_var_to_merged_bounds(vb, b_id, a_bounds, b_bounds)
}
fn tvar_integral<V: copy vid, T: copy to_str st>(
_vb: vals_and_bindings<V, int_ty_set>,
_a: T, _b_id: V) -> ures {
// FIXME (#1425): do something real here.
uok()
}
fn constrs(
expected: @ty::type_constr,
actual_constr: @ty::type_constr) -> ures {
@ -823,7 +932,7 @@ type resolve_state = @{
force_vars: bool,
mut err: option<fixup_err>,
mut r_seen: [region_vid],
mut v_seen: [ty_vid]
mut v_seen: [tv_vid]
};
fn resolver(infcx: infer_ctxt, deep: bool, fvars: bool) -> resolve_state {
@ -871,6 +980,9 @@ impl methods for resolve_state {
ty::ty_var(vid) {
self.resolve_ty_var(vid)
}
ty::ty_var_integral(vid) {
self.resolve_ty_var_integral(vid)
}
_ if !ty::type_has_regions(typ) && !self.deep {
typ
}
@ -904,7 +1016,8 @@ impl methods for resolve_state {
ret ty::re_var(rid);
} else {
vec::push(self.r_seen, rid);
let {root:_, bounds} = self.infcx.get(self.infcx.rb, rid);
let {root:_, possible_types: bounds} =
self.infcx.get(self.infcx.rb, rid);
let r1 = alt bounds {
{ ub:_, lb:some(t) } { self.resolve_region(t) }
{ ub:some(t), lb:_ } { self.resolve_region(t) }
@ -920,7 +1033,7 @@ impl methods for resolve_state {
}
}
fn resolve_ty_var(vid: ty_vid) -> ty::t {
fn resolve_ty_var(vid: tv_vid) -> ty::t {
if vec::contains(self.v_seen, vid) {
self.err = some(cyclic_ty(vid));
ret ty::mk_var(self.infcx.tcx, vid);
@ -934,7 +1047,8 @@ impl methods for resolve_state {
// tend to carry more restrictions or higher
// perf. penalties, so it pays to know more.
let {root:_, bounds} = self.infcx.get(self.infcx.tvb, vid);
let {root:_, possible_types: 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) }
@ -950,6 +1064,17 @@ impl methods for resolve_state {
ret t1;
}
}
fn resolve_ty_var_integral(vid: tvi_vid) -> ty::t {
let {root:_, possible_types: its} =
self.infcx.get(self.infcx.tvib, vid);
let t1 = alt its {
// FIXME (#1425): do something real here.
int_ty_set(_) { ty::mk_int(self.infcx.tcx) }
};
ret t1;
}
}
// ______________________________________________________________________
@ -1027,21 +1152,21 @@ impl assignment for infer_ctxt {
}
(ty::ty_var(a_id), ty::ty_var(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 {root:_, possible_types: a_bounds} = self.get(self.tvb, a_id);
let {root:_, possible_types: 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.tvb, a_id);
let {root:_, possible_types: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.tvb, b_id);
let {root:_, possible_types: 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)
}
@ -1199,6 +1324,7 @@ iface combine {
fn mts(a: ty::mt, b: ty::mt) -> cres<ty::mt>;
fn contratys(a: ty::t, b: ty::t) -> cres<ty::t>;
fn tys(a: ty::t, b: ty::t) -> cres<ty::t>;
fn int_tys(a: ty::t, b: ty::t) -> cres<ty::t>;
fn tps(as: [ty::t], bs: [ty::t]) -> cres<[ty::t]>;
fn self_tys(a: option<ty::t>, b: option<ty::t>) -> cres<option<ty::t>>;
fn substs(as: ty::substs, bs: ty::substs) -> cres<ty::substs>;
@ -1389,6 +1515,12 @@ fn super_fns<C:combine>(
}
}
fn super_int_tys<C:combine>(
self: C, _a: ty::t, _b: ty::t) -> cres<ty::t> {
// FIXME (#1425): do something real here?
ok(ty::mk_int(self.infcx().tcx))
}
fn super_tys<C:combine>(
self: C, a: ty::t, b: ty::t) -> cres<ty::t> {
@ -1654,6 +1786,21 @@ impl of combine for sub {
(_, ty::ty_bot) {
err(ty::terr_sorts(b, a))
}
// FIXME (#1425): I'm not sure if these three cases
// belong here or if they belong in super_tys.
(ty::ty_var_integral(a_id), ty::ty_var_integral(b_id)) {
self.infcx().vars_integral(self.tvib, a_id, b_id).then {||
ok(a) }
}
(ty::ty_var_integral(a_id), _) {
self.infcx().vart_integral(self.tvib, a_id, b).then {||
ok(a) }
}
(_, ty::ty_var_integral(b_id)) {
self.infcx().tvar_integral(self.tvib, a, b_id).then {||
ok(a) }
}
_ {
super_tys(self, a, b)
}
@ -1699,6 +1846,10 @@ impl of combine for sub {
// Traits please:
fn int_tys(a: ty::t, b: ty::t) -> cres<ty::t> {
super_int_tys(self, a, b)
}
fn flds(a: ty::field, b: ty::field) -> cres<ty::field> {
super_flds(self, a, b)
}
@ -1877,6 +2028,10 @@ impl of combine for lub {
// Traits please:
fn int_tys(a: ty::t, b: ty::t) -> cres<ty::t> {
super_int_tys(self, a, b)
}
fn tys(a: ty::t, b: ty::t) -> cres<ty::t> {
lattice_tys(self, a, b)
}
@ -2080,6 +2235,10 @@ impl of combine for glb {
// Traits please:
fn int_tys(a: ty::t, b: ty::t) -> cres<ty::t> {
super_int_tys(self, a, b)
}
fn flds(a: ty::field, b: ty::field) -> cres<ty::field> {
super_flds(self, a, b)
}
@ -2173,6 +2332,20 @@ fn lattice_tys<L:lattice_ops combine>(
lattice_var_t(self, self.infcx().tvb, b_id, a,
{|x, y| self.tys(x, y) })
}
(ty::ty_var_integral(a_id), ty::ty_var_integral(b_id)) {
// FIXME (#1425): do something real here?
ok(a)
}
(ty::ty_var_integral(a_id), _) {
// FIXME (#1425): do something real here?
ok(a)
}
(_, ty::ty_var_integral(b_id)) {
// FIXME (#1425): do something real here?
ok(a)
}
_ {
super_tys(self, a, b)
@ -2210,7 +2383,7 @@ fn lattice_rvars<L:lattice_ops combine>(
}
fn lattice_vars<V:copy vid, T:copy to_str st, L:lattice_ops combine>(
self: L, vb: vals_and_bindings<V, T>,
self: L, vb: vals_and_bindings<V, bounds<T>>,
a_t: T, a_vid: V, b_vid: V,
c_ts: fn(T, T) -> cres<T>) -> cres<T> {
@ -2219,8 +2392,8 @@ fn lattice_vars<V:copy vid, T:copy to_str st, L:lattice_ops combine>(
// upper/lower/sub/super/etc.
// Need to find a type that is a supertype of both a and b:
let {root: a_vid, bounds: a_bounds} = self.infcx().get(vb, a_vid);
let {root: b_vid, bounds: b_bounds} = self.infcx().get(vb, b_vid);
let {root: a_vid, possible_types: a_bounds} = self.infcx().get(vb, a_vid);
let {root: b_vid, possible_types: b_bounds} = self.infcx().get(vb, b_vid);
#debug["%s.lattice_vars(%s=%s <: %s=%s)",
self.tag(),
@ -2252,11 +2425,11 @@ fn lattice_vars<V:copy vid, T:copy to_str st, L:lattice_ops combine>(
}
fn lattice_var_t<V:copy vid, T:copy to_str st, L:lattice_ops combine>(
self: L, vb: vals_and_bindings<V, T>,
self: L, vb: vals_and_bindings<V, bounds<T>>,
a_id: V, b: T,
c_ts: fn(T, T) -> cres<T>) -> cres<T> {
let {root: a_id, bounds: a_bounds} = self.infcx().get(vb, a_id);
let {root: a_id, possible_types: a_bounds} = self.infcx().get(vb, a_id);
// The comments in this function are written for LUB, but they
// apply equally well to GLB if you inverse upper/lower/sub/super/etc.
@ -2268,7 +2441,7 @@ fn lattice_var_t<V:copy vid, T:copy to_str st, L:lattice_ops combine>(
alt self.bnd(a_bounds) {
some(a_bnd) {
// If a has an upper bound, return it.
// If a has an upper bound, return the LUB(a.ub, b)
#debug["bnd=some(%s)", a_bnd.to_str(self.infcx())];
ret c_ts(a_bnd, b);
}
@ -2278,7 +2451,7 @@ fn lattice_var_t<V:copy vid, T:copy to_str st, L:lattice_ops combine>(
#debug["bnd=none"];
let a_bounds = self.with_bnd(a_bounds, b);
self.infcx().bnds(a_bounds.lb, a_bounds.ub).then {||
self.infcx().set(vb, a_id, bounded(a_bounds));
self.infcx().set(vb, a_id, root(a_bounds));
ok(b)
}
}