about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEric Holk <eric.holk@gmail.com>2012-06-14 21:03:41 -0700
committerEric Holk <eric.holk@gmail.com>2012-06-14 21:03:41 -0700
commit56bd68976715caa808ad9a3f2efdf422d38d631c (patch)
treee834f8c865ef120791cabf991f636d04b546ca82
parent8ab15c0266260faadd2804623c729efcb14e7315 (diff)
parent77e6573929702731bc0bd2c41724e6a587c7f268 (diff)
downloadrust-56bd68976715caa808ad9a3f2efdf422d38d631c.tar.gz
rust-56bd68976715caa808ad9a3f2efdf422d38d631c.zip
Merge branch 'incoming' of github.com:mozilla/rust into newsnap
-rw-r--r--src/libsyntax/ast.rs2
-rw-r--r--src/libsyntax/parse/classify.rs2
-rw-r--r--src/libsyntax/parse/lexer.rs2
-rw-r--r--src/libsyntax/parse/parser.rs6
-rw-r--r--src/libsyntax/parse/token.rs10
-rw-r--r--src/libsyntax/print/pprust.rs10
-rw-r--r--src/rustc/metadata/tyencode.rs3
-rw-r--r--src/rustc/middle/const_eval.rs2
-rw-r--r--src/rustc/middle/trans/base.rs28
-rw-r--r--src/rustc/middle/ty.rs30
-rw-r--r--src/rustc/middle/typeck/check.rs26
-rw-r--r--src/rustc/middle/typeck/infer.rs223
12 files changed, 201 insertions, 143 deletions
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index 5381a9f345d..edc90fe8676 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -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),
diff --git a/src/libsyntax/parse/classify.rs b/src/libsyntax/parse/classify.rs
index aff0334a946..a3d55df320b 100644
--- a/src/libsyntax/parse/classify.rs
+++ b/src/libsyntax/parse/classify.rs
@@ -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 }
         }
diff --git a/src/libsyntax/parse/lexer.rs b/src/libsyntax/parse/lexer.rs
index 115a9957c28..72b2462feb1 100644
--- a/src/libsyntax/parse/lexer.rs
+++ b/src/libsyntax/parse/lexer.rs
@@ -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);
     }
 }
 
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 20452cd8724..62ec5cc50f6 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -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 }
diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs
index 6bf6347704d..4f4c2ee0064 100644
--- a/src/libsyntax/parse/token.rs
+++ b/src/libsyntax/parse/token.rs
@@ -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 }
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index a63e3139b5b..43b498eae62 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -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) {
diff --git a/src/rustc/metadata/tyencode.rs b/src/rustc/metadata/tyencode.rs
index a158b0b01fd..f21b3850a98 100644
--- a/src/rustc/metadata/tyencode.rs
+++ b/src/rustc/metadata/tyencode.rs
@@ -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');
diff --git a/src/rustc/middle/const_eval.rs b/src/rustc/middle/const_eval.rs
index a72e7fb0208..661ad87dfa8 100644
--- a/src/rustc/middle/const_eval.rs
+++ b/src/rustc/middle/const_eval.rs
@@ -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) }
diff --git a/src/rustc/middle/trans/base.rs b/src/rustc/middle/trans/base.rs
index d46a47f0bd0..590440ecb7f 100644
--- a/src/rustc/middle/trans/base.rs
+++ b/src/rustc/middle/trans/base.rs
@@ -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);
diff --git a/src/rustc/middle/ty.rs b/src/rustc/middle/ty.rs
index 421bbf38e14..b7ceaa8ab47 100644
--- a/src/rustc/middle/ty.rs
+++ b/src/rustc/middle/ty.rs
@@ -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 }
diff --git a/src/rustc/middle/typeck/check.rs b/src/rustc/middle/typeck/check.rs
index c142b22452f..56050c0af58 100644
--- a/src/rustc/middle/typeck/check.rs
+++ b/src/rustc/middle/typeck/check.rs
@@ -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
@@ -624,29 +622,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) }
diff --git a/src/rustc/middle/typeck/infer.rs b/src/rustc/middle/typeck/infer.rs
index 1c080ba8c5c..b5770528a3e 100644
--- a/src/rustc/middle/typeck/infer.rs
+++ b/src/rustc/middle/typeck/infer.rs
@@ -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)
           }