Further work on integer literal suffix inference (#1425)

In this commit:

  * Change the lit_int_unsuffixed AST node to not carry a type, since
    it doesn't need one

  * Don't print "(unsuffixed)" when pretty-printing unsuffixed integer
    literals

  * Just print "I" instead of "(integral)" for integral type variables

  * Set up trans to use the information that will be gathered during
    typeck to construct the appropriate constants for unsuffixed int
    literals

  * Add logic for handling int_ty_sets in typeck::infer

  * Clean up unnecessary code in typeck::infer

  * Add missing mk_ functions to middle::ty

  * Add ty_var_integral to a few of the type utility functions it was
    missing from in middle::ty
This commit is contained in:
Lindsey Kuper 2012-06-14 19:41:40 -07:00
parent d953462d03
commit 77e6573929
12 changed files with 201 additions and 143 deletions

View file

@ -402,7 +402,7 @@ enum lit_ {
lit_str(@str),
lit_int(i64, int_ty),
lit_uint(u64, uint_ty),
lit_int_unsuffixed(i64, int_ty),
lit_int_unsuffixed(i64),
lit_float(@str, float_ty),
lit_nil,
lit_bool(bool),

View file

@ -54,7 +54,7 @@ fn ends_in_lit_int(ex: @ast::expr) -> bool {
ast::expr_lit(node) {
alt node {
@{node: ast::lit_int(_, ast::ty_i), _} |
@{node: ast::lit_int_unsuffixed(_, ast::ty_i), _}
@{node: ast::lit_int_unsuffixed(_), _}
{ true }
_ { false }
}

View file

@ -285,7 +285,7 @@ fn scan_number(c: char, rdr: reader) -> token::token {
#debug["lexing %s as an unsuffixed integer literal",
num_str];
ret token::LIT_INT_UNSUFFIXED(parsed as i64, ast::ty_i);
ret token::LIT_INT_UNSUFFIXED(parsed as i64);
}
}

View file

@ -501,7 +501,7 @@ class parser {
let lo = self.span.lo;
self.bump();
alt copy self.token {
token::LIT_INT_UNSUFFIXED(num, _) {
token::LIT_INT_UNSUFFIXED(num) {
self.bump();
some(mac_var(num as uint))
}
@ -534,7 +534,7 @@ class parser {
token::UNDERSCORE {
self.bump(); some(vstore_fixed(none))
}
token::LIT_INT_UNSUFFIXED(i, _) if i >= 0i64 {
token::LIT_INT_UNSUFFIXED(i) if i >= 0i64 {
self.bump(); some(vstore_fixed(some(i as uint)))
}
token::BINOP(token::AND) {
@ -553,7 +553,7 @@ class parser {
alt tok {
token::LIT_INT(i, it) { lit_int(i, it) }
token::LIT_UINT(u, ut) { lit_uint(u, ut) }
token::LIT_INT_UNSUFFIXED(i, it) { lit_int_unsuffixed(i, it) }
token::LIT_INT_UNSUFFIXED(i) { lit_int_unsuffixed(i) }
token::LIT_FLOAT(s, ft) { lit_float(self.get_str(s), ft) }
token::LIT_STR(s) { lit_str(self.get_str(s)) }
token::LPAREN { self.expect(token::RPAREN); lit_nil }

View file

@ -57,7 +57,7 @@ enum token {
/* Literals */
LIT_INT(i64, ast::int_ty),
LIT_UINT(u64, ast::uint_ty),
LIT_INT_UNSUFFIXED(i64, ast::int_ty),
LIT_INT_UNSUFFIXED(i64),
LIT_FLOAT(str_num, ast::float_ty),
LIT_STR(str_num),
@ -129,8 +129,8 @@ fn to_str(in: interner<@str>, t: token) -> str {
LIT_UINT(u, t) {
uint::to_str(u as uint, 10u) + ast_util::uint_ty_to_str(t)
}
LIT_INT_UNSUFFIXED(i, t) {
int::to_str(i as int, 10u) + ast_util::int_ty_to_str(t)
LIT_INT_UNSUFFIXED(i) {
int::to_str(i as int, 10u)
}
LIT_FLOAT(s, t) {
*interner::get(in, s) +
@ -160,7 +160,7 @@ pure fn can_begin_expr(t: token) -> bool {
TILDE { true }
LIT_INT(_, _) { true }
LIT_UINT(_, _) { true }
LIT_INT_UNSUFFIXED(_, _) { true }
LIT_INT_UNSUFFIXED(_) { true }
LIT_FLOAT(_, _) { true }
LIT_STR(_) { true }
POUND { true }
@ -178,7 +178,7 @@ fn is_lit(t: token) -> bool {
alt t {
LIT_INT(_, _) { true }
LIT_UINT(_, _) { true }
LIT_INT_UNSUFFIXED(_, _) { true }
LIT_INT_UNSUFFIXED(_) { true }
LIT_FLOAT(_, _) { true }
LIT_STR(_) { true }
_ { false }

View file

@ -1628,15 +1628,11 @@ fn print_literal(s: ps, &&lit: @ast::lit) {
u64::to_str(u, 10u)
+ ast_util::uint_ty_to_str(t));
}
ast::lit_int_unsuffixed(i, t) {
ast::lit_int_unsuffixed(i) {
if i < 0_i64 {
word(s.s,
"-" + u64::to_str(-i as u64, 10u)
+ ast_util::int_ty_to_str(t));
word(s.s, "-" + u64::to_str(-i as u64, 10u));
} else {
word(s.s,
u64::to_str(i as u64, 10u)
+ ast_util::int_ty_to_str(t));
word(s.s, u64::to_str(i as u64, 10u));
}
}
ast::lit_float(f, t) {

View file

@ -278,10 +278,9 @@ fn enc_sty(w: io::writer, cx: @ctxt, st: ty::sty) {
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_char('I');
w.write_uint(id.to_uint());
w.write_str("(integral)");
}
ty::ty_param(id, did) {
w.write_char('p');

View file

@ -111,7 +111,7 @@ fn lit_to_const(lit: @lit) -> const_val {
lit_str(s) { const_str(*s) }
lit_int(n, _) { const_int(n) }
lit_uint(n, _) { const_uint(n) }
lit_int_unsuffixed(n, _) { const_int(n) }
lit_int_unsuffixed(n) { const_int(n) }
lit_float(n, _) { const_float(option::get(float::from_str(*n)) as f64) }
lit_nil { const_int(0i64) }
lit_bool(b) { const_int(b as i64) }

View file

@ -1473,15 +1473,25 @@ fn store_temp_expr(cx: block, action: copy_action, dst: ValueRef,
ret move_val(cx, action, dst, src, t);
}
fn trans_crate_lit(cx: @crate_ctxt, lit: ast::lit) -> ValueRef {
fn trans_crate_lit(cx: @crate_ctxt, e: @ast::expr, lit: ast::lit)
-> ValueRef {
let _icx = cx.insn_ctxt("trans_crate_lit");
alt lit.node {
ast::lit_int(i, t) { C_integral(T_int_ty(cx, t), i as u64, True) }
ast::lit_uint(u, t) { C_integral(T_uint_ty(cx, t), u, False) }
ast::lit_int_unsuffixed(i, t) {
// FIXME (#1425): should we be using cx.fcx.infcx to figure out what
// to actually generate from this?
C_integral(T_int_ty(cx, t), i as u64, True)
ast::lit_int_unsuffixed(i) {
let lit_int_ty = ty::node_id_to_type(cx.tcx, e.id);
alt ty::get(lit_int_ty).struct {
ty::ty_int(t) {
C_integral(T_int_ty(cx, t), i as u64, True)
}
ty::ty_uint(t) {
C_integral(T_uint_ty(cx, t), i as u64, False)
}
_ { cx.sess.span_bug(lit.span,
"integer literal doesn't have a type");
}
}
}
ast::lit_float(fs, t) { C_floating(*fs, T_float_ty(cx, t)) }
ast::lit_bool(b) { C_bool(b) }
@ -1492,13 +1502,13 @@ fn trans_crate_lit(cx: @crate_ctxt, lit: ast::lit) -> ValueRef {
}
}
fn trans_lit(cx: block, lit: ast::lit, dest: dest) -> block {
fn trans_lit(cx: block, e: @ast::expr, lit: ast::lit, dest: dest) -> block {
let _icx = cx.insn_ctxt("trans_lit");
if dest == ignore { ret cx; }
alt lit.node {
ast::lit_str(s) { tvec::trans_estr(cx, s, ast::vstore_uniq, dest) }
_ {
store_in_dest(cx, trans_crate_lit(cx.ccx(), lit), dest)
store_in_dest(cx, trans_crate_lit(cx.ccx(), e, lit), dest)
}
}
}
@ -3584,7 +3594,7 @@ fn trans_expr(bcx: block, e: @ast::expr, dest: dest) -> block {
}
ast::expr_tup(args) { ret trans_tup(bcx, args, dest); }
ast::expr_vstore(e, v) { ret tvec::trans_vstore(bcx, e, v, dest); }
ast::expr_lit(lit) { ret trans_lit(bcx, *lit, dest); }
ast::expr_lit(lit) { ret trans_lit(bcx, e, *lit, dest); }
ast::expr_vec(args, _) {
ret tvec::trans_evec(bcx, args, ast::vstore_uniq, e.id, dest);
}
@ -4684,7 +4694,7 @@ fn trans_enum_variant(ccx: @crate_ctxt, enum_id: ast::node_id,
fn trans_const_expr(cx: @crate_ctxt, e: @ast::expr) -> ValueRef {
let _icx = cx.insn_ctxt("trans_const_expr");
alt e.node {
ast::expr_lit(lit) { ret trans_crate_lit(cx, *lit); }
ast::expr_lit(lit) { ret trans_crate_lit(cx, e, *lit); }
ast::expr_binary(b, e1, e2) {
let te1 = trans_const_expr(cx, e1);
let te2 = trans_const_expr(cx, e2);

View file

@ -84,6 +84,7 @@ export ty_float, mk_float, mk_mach_float, type_is_fp;
export ty_fn, fn_ty, mk_fn;
export ty_fn_proto, ty_fn_ret, ty_fn_ret_style, tys_in_fn_ty;
export ty_int, mk_int, mk_mach_int, mk_char;
export mk_i8, mk_u8, mk_i16, mk_u16, mk_i32, mk_u32, mk_i64, mk_u64;
export ty_str, mk_str, type_is_str;
export ty_vec, mk_vec, type_is_vec;
export ty_estr, mk_estr;
@ -416,7 +417,8 @@ enum type_err {
terr_vstores_differ(terr_vstore_kind, vstore, vstore),
terr_in_field(@type_err, ast::ident),
terr_sorts(t, t),
terr_self_substs
terr_self_substs,
terr_no_integral_type,
}
enum param_bound {
@ -442,7 +444,7 @@ impl of vid for tv_vid {
impl of vid for tvi_vid {
fn to_uint() -> uint { *self }
fn to_str() -> str { #fmt["<V (integral) %u>", self.to_uint()] }
fn to_str() -> str { #fmt["<VI%u>", self.to_uint()] }
}
impl of vid for region_vid {
@ -619,12 +621,26 @@ fn mk_bool(cx: ctxt) -> t { mk_t(cx, ty_bool) }
fn mk_int(cx: ctxt) -> t { mk_t(cx, ty_int(ast::ty_i)) }
fn mk_i8(cx: ctxt) -> t { mk_t(cx, ty_int(ast::ty_i8)) }
fn mk_i16(cx: ctxt) -> t { mk_t(cx, ty_int(ast::ty_i16)) }
fn mk_i32(cx: ctxt) -> t { mk_t(cx, ty_int(ast::ty_i32)) }
fn mk_i64(cx: ctxt) -> t { mk_t(cx, ty_int(ast::ty_i64)) }
fn mk_float(cx: ctxt) -> t { mk_t(cx, ty_float(ast::ty_f)) }
fn mk_uint(cx: ctxt) -> t { mk_t(cx, ty_uint(ast::ty_u)) }
fn mk_u8(cx: ctxt) -> t { mk_t(cx, ty_uint(ast::ty_u8)) }
fn mk_u16(cx: ctxt) -> t { mk_t(cx, ty_uint(ast::ty_u16)) }
fn mk_u32(cx: ctxt) -> t { mk_t(cx, ty_uint(ast::ty_u32)) }
fn mk_u64(cx: ctxt) -> t { mk_t(cx, ty_uint(ast::ty_u64)) }
fn mk_mach_int(cx: ctxt, tm: ast::int_ty) -> t { mk_t(cx, ty_int(tm)) }
fn mk_mach_uint(cx: ctxt, tm: ast::uint_ty) -> t { mk_t(cx, ty_uint(tm)) }
@ -1188,7 +1204,7 @@ pure fn type_is_unique(ty: t) -> bool {
pure fn type_is_scalar(ty: t) -> bool {
alt get(ty).struct {
ty_nil | ty_bool | ty_int(_) | ty_float(_) | ty_uint(_) |
ty_type | ty_ptr(_) | ty_rptr(_, _) { true }
ty_var_integral(_) | ty_type | ty_ptr(_) | ty_rptr(_, _) { true }
_ { false }
}
}
@ -1827,7 +1843,7 @@ fn type_structurally_contains_uniques(cx: ctxt, ty: t) -> bool {
fn type_is_integral(ty: t) -> bool {
alt get(ty).struct {
ty_int(_) | ty_uint(_) | ty_bool { true }
ty_var_integral(_) | ty_int(_) | ty_uint(_) | ty_bool { true }
_ { false }
}
}
@ -2531,6 +2547,10 @@ fn type_err_to_str(cx: ctxt, err: type_err) -> str {
terr_self_substs {
ret "inconsistent self substitution"; // XXX this is more of a bug
}
terr_no_integral_type {
ret "couldn't determine an appropriate integral type for integer \
literal";
}
}
}
@ -2966,7 +2986,7 @@ fn is_binopable(_cx: ctxt, ty: t, op: ast::binop) -> bool {
fn tycat(ty: t) -> int {
alt get(ty).struct {
ty_bool { tycat_bool }
ty_int(_) | ty_uint(_) { tycat_int }
ty_int(_) | ty_uint(_) | ty_var_integral(_) { tycat_int }
ty_float(_) { tycat_float }
ty_estr(_) | ty_str { tycat_str }
ty_evec(_, _) | ty_vec(_) { tycat_vec }

View file

@ -73,11 +73,9 @@ 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 syntax::ast::{ty_char, 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
@ -623,29 +621,13 @@ fn check_lit(fcx: @fn_ctxt, lit: @ast::lit) -> ty::t {
ast::lit_str(_) { ty::mk_str(tcx) }
ast::lit_int(_, t) { ty::mk_mach_int(tcx, t) }
ast::lit_uint(_, t) { ty::mk_mach_uint(tcx, t) }
ast::lit_int_unsuffixed(v, t) {
ast::lit_int_unsuffixed(v) {
// An unsuffixed integer literal could have any integral type,
// so we create an integral type variable for it.
let vid = fcx.infcx.next_ty_var_integral_id();
// We need to sniff at the value `v` and figure out how big of
// an int it is; that determines the range of possible types
// that the integral type variable 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 and return the integral
// type variable.
fcx.infcx.set(fcx.infcx.tvib, vid,
root(possible_types));
ty::mk_var_integral(tcx, vid);
ty::mk_var_integral(tcx, fcx.infcx.next_ty_var_integral_id());
// FIXME: remove me when #1425 is finished.
ty::mk_mach_int(tcx, t)
ty::mk_mach_int(tcx, ty_i)
}
ast::lit_float(_, t) { ty::mk_mach_float(tcx, t) }
ast::lit_nil { ty::mk_nil(tcx) }

View file

@ -147,7 +147,8 @@ import std::smallintmap::smallintmap;
import std::smallintmap::map;
import std::map::hashmap;
import middle::ty;
import middle::ty::{tv_vid, tvi_vid, region_vid, vid};
import middle::ty::{tv_vid, tvi_vid, region_vid, vid,
ty_int, ty_uint, get};
import syntax::{ast, ast_util};
import syntax::ast::{ret_style, purity};
import util::ppaux::{ty_to_str, mt_to_str};
@ -174,7 +175,7 @@ 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;
export int_ty_set_all;
// Bitvector to represent sets of integral types
enum int_ty_set = uint;
@ -193,9 +194,7 @@ 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 {
fn int_ty_set_all() -> 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 |
@ -203,22 +202,58 @@ fn min_8bit_tys() -> int_ty_set {
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 intersection(a: int_ty_set, b: int_ty_set) -> int_ty_set {
int_ty_set(*a & *b)
}
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 single_type_contained_in(tcx: ty::ctxt, a: int_ty_set) ->
option<ty::t> {
#debug["type_contained_in(a=%s)", uint::to_str(*a, 10u)];
if *a == INT_TY_SET_i8 { ret some(ty::mk_i8(tcx)); }
if *a == INT_TY_SET_u8 { ret some(ty::mk_u8(tcx)); }
if *a == INT_TY_SET_i16 { ret some(ty::mk_i16(tcx)); }
if *a == INT_TY_SET_u16 { ret some(ty::mk_u16(tcx)); }
if *a == INT_TY_SET_i32 { ret some(ty::mk_i32(tcx)); }
if *a == INT_TY_SET_u32 { ret some(ty::mk_u32(tcx)); }
if *a == INT_TY_SET_i64 { ret some(ty::mk_i64(tcx)); }
if *a == INT_TY_SET_u64 { ret some(ty::mk_u64(tcx)); }
if *a == INT_TY_SET_i { ret(some(ty::mk_int(tcx))); }
if *a == INT_TY_SET_u { ret(some(ty::mk_uint(tcx))); }
ret none;
}
fn min_64bit_tys() -> int_ty_set {
int_ty_set(INT_TY_SET_i64 | INT_TY_SET_u64)
fn is_subset_of(a: int_ty_set, b: int_ty_set) -> bool {
(*a & *b) == *a
}
fn convert_integral_ty_to_int_ty_set(tcx: ty::ctxt, t: ty::t)
-> int_ty_set {
alt get(t).struct {
ty_int(int_ty) {
alt int_ty {
ast::ty_i8 { int_ty_set(INT_TY_SET_i8) }
ast::ty_i16 { int_ty_set(INT_TY_SET_i16) }
ast::ty_i32 { int_ty_set(INT_TY_SET_i32) }
ast::ty_i64 { int_ty_set(INT_TY_SET_i64) }
ast::ty_i { int_ty_set(INT_TY_SET_i) }
ast::ty_char { tcx.sess.bug(
"char type passed to convert_integral_ty_to_int_ty_set()"); }
}
}
ty_uint(uint_ty) {
alt uint_ty {
ast::ty_u8 { int_ty_set(INT_TY_SET_u8) }
ast::ty_u16 { int_ty_set(INT_TY_SET_u16) }
ast::ty_u32 { int_ty_set(INT_TY_SET_u32) }
ast::ty_u64 { int_ty_set(INT_TY_SET_u64) }
ast::ty_u { int_ty_set(INT_TY_SET_u) }
}
}
_ { tcx.sess.bug("non-integral type passed to \
convert_integral_ty_to_int_ty_set()"); }
}
}
// Extra information needed to perform an assignment that may borrow.
@ -265,6 +300,7 @@ enum infer_ctxt = @{
};
enum fixup_err {
unresolved_int_ty(tvi_vid),
unresolved_ty(tv_vid),
cyclic_ty(tv_vid),
unresolved_region(region_vid),
@ -273,6 +309,7 @@ enum fixup_err {
fn fixup_err_to_str(f: fixup_err) -> str {
alt f {
unresolved_int_ty(_) { "unconstrained integral type" }
unresolved_ty(_) { "unconstrained type" }
cyclic_ty(_) { "cyclic type of infinite size" }
unresolved_region(_) { "unconstrained region" }
@ -410,7 +447,7 @@ impl<V:copy to_str> of to_str for bound<V> {
fn to_str(cx: infer_ctxt) -> str {
alt self {
some(v) { v.to_str(cx) }
none { "none " }
none { "none" }
}
}
}
@ -555,7 +592,7 @@ impl methods for infer_ctxt {
*self.ty_var_integral_counter += 1u;
self.tvib.vals.insert(id,
root(mk_int_ty_set()));
root(int_ty_set_all()));
ret tvi_vid(id);
}
@ -771,9 +808,24 @@ 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.
vb: vals_and_bindings<V, int_ty_set>,
a_id: V, b_id: V) -> ures {
let {root: a_id, possible_types: a_pt} = self.get(vb, a_id);
let {root: b_id, possible_types: b_pt} = self.get(vb, b_id);
// If we're already dealing with the same two variables,
// there's nothing to do.
if a_id == b_id { ret uok(); }
// Otherwise, take the intersection of the two sets of
// possible types.
let intersection = intersection(a_pt, b_pt);
if *intersection == INT_TY_SET_EMPTY {
ret err(ty::terr_no_integral_type);
}
self.set(vb, a_id, root(intersection));
self.set(vb, b_id, redirect(a_id));
uok()
}
@ -789,11 +841,21 @@ 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.
fn vart_integral<V: copy vid>(
vb: vals_and_bindings<V, int_ty_set>,
a_id: V, b: ty::t) -> ures {
assert ty::type_is_integral(b);
let {root: a_id, possible_types: a_pt} = self.get(vb, a_id);
let intersection =
intersection(a_pt, convert_integral_ty_to_int_ty_set(
self.tcx, b));
if *intersection == INT_TY_SET_EMPTY {
ret err(ty::terr_no_integral_type);
}
self.set(vb, a_id, root(intersection));
uok()
}
@ -809,10 +871,21 @@ impl unify_methods for infer_ctxt {
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.
fn tvar_integral<V: copy vid>(
vb: vals_and_bindings<V, int_ty_set>,
a: ty::t, b_id: V) -> ures {
assert ty::type_is_integral(a);
let {root: b_id, possible_types: b_pt} = self.get(vb, b_id);
let intersection =
intersection(b_pt, convert_integral_ty_to_int_ty_set(
self.tcx, a));
if *intersection == INT_TY_SET_EMPTY {
ret err(ty::terr_no_integral_type);
}
self.set(vb, b_id, root(intersection));
uok()
}
@ -1066,13 +1139,26 @@ impl methods for resolve_state {
}
fn resolve_ty_var_integral(vid: tvi_vid) -> ty::t {
let {root:_, possible_types: its} =
let {root:_, possible_types: pt} =
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;
// If there's only one type in the set of possible types, then
// that's the answer.
alt single_type_contained_in(self.infcx.tcx, pt) {
some(t) { t }
none {
if self.force_vars {
// As a last resort, default to int.
let ty = ty::mk_int(self.infcx.tcx);
self.infcx.set(
self.infcx.tvib, vid,
root(convert_integral_ty_to_int_ty_set(self.infcx.tcx,
ty)));
ty
} else {
ty::mk_var_integral(self.infcx.tcx, vid)
}
}
}
}
}
@ -1324,7 +1410,6 @@ 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>;
@ -1516,12 +1601,6 @@ 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> {
@ -1539,6 +1618,20 @@ fn super_tys<C:combine>(
b.to_str(self.infcx())]);
}
// Have to handle these first
(ty::ty_var_integral(a_id), ty::ty_var_integral(b_id)) {
self.infcx().vars_integral(self.infcx().tvib, a_id, b_id).then {||
ok(a) }
}
(ty::ty_var_integral(a_id), _) {
self.infcx().vart_integral(self.infcx().tvib, a_id, b).then {||
ok(a) }
}
(_, ty::ty_var_integral(b_id)) {
self.infcx().tvar_integral(self.infcx().tvib, a, b_id).then {||
ok(a) }
}
(ty::ty_int(_), _) |
(ty::ty_uint(_), _) |
(ty::ty_float(_), _) {
@ -1787,21 +1880,6 @@ 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)
}
@ -1847,10 +1925,6 @@ 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)
}
@ -2029,10 +2103,6 @@ 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)
}
@ -2236,10 +2306,6 @@ 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)
}
@ -2333,21 +2399,6 @@ 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)
}