Skip to content

Commit

Permalink
rustc: Implement floating point literal inference. r=nmatsakis
Browse files Browse the repository at this point in the history
  • Loading branch information
pcwalton committed Nov 12, 2012
1 parent f05e2da commit fe02814
Show file tree
Hide file tree
Showing 20 changed files with 363 additions and 46 deletions.
5 changes: 5 additions & 0 deletions src/librustc/metadata/tyencode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,11 @@ fn enc_sty(w: io::Writer, cx: @ctxt, st: ty::sty) {
w.write_char('I');
w.write_uint(id.to_uint());
}
ty::ty_infer(ty::FloatVar(id)) => {
w.write_char('X');
w.write_char('F');
w.write_uint(id.to_uint());
}
ty::ty_param({idx: id, def_id: did}) => {
w.write_char('p');
w.write_str(cx.ds(did));
Expand Down
2 changes: 2 additions & 0 deletions src/librustc/middle/const_eval.rs
Original file line number Diff line number Diff line change
Expand Up @@ -389,6 +389,8 @@ fn lit_to_const(lit: @lit) -> const_val {
lit_uint(n, _) => const_uint(n),
lit_int_unsuffixed(n) => const_int(n),
lit_float(n, _) => const_float(float::from_str(*n).get() as f64),
lit_float_unsuffixed(n) =>
const_float(float::from_str(*n).get() as f64),
lit_nil => const_int(0i64),
lit_bool(b) => const_bool(b)
}
Expand Down
13 changes: 13 additions & 0 deletions src/librustc/middle/trans/consts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,19 @@ fn const_lit(cx: @crate_ctxt, e: @ast::expr, lit: ast::lit)
}
}
ast::lit_float(fs, t) => C_floating(*fs, T_float_ty(cx, t)),
ast::lit_float_unsuffixed(fs) => {
let lit_float_ty = ty::node_id_to_type(cx.tcx, e.id);
match ty::get(lit_float_ty).sty {
ty::ty_float(t) => {
C_floating(*fs, T_float_ty(cx, t))
}
_ => {
cx.sess.span_bug(lit.span,
~"floating point literal doesn't have the right \
type");
}
}
}
ast::lit_bool(b) => C_bool(b),
ast::lit_nil => C_nil(),
ast::lit_str(s) => C_estr_slice(cx, *s)
Expand Down
58 changes: 46 additions & 12 deletions src/librustc/middle/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ use util::ppaux::{ty_to_str, proto_ty_to_str, tys_to_str};

export ProvidedMethodSource;
export InstantiatedTraitRef;
export TyVid, IntVid, FnVid, RegionVid, vid;
export TyVid, IntVid, FloatVid, FnVid, RegionVid, vid;
export br_hashmap;
export is_instantiable;
export node_id_to_type;
Expand Down Expand Up @@ -86,6 +86,7 @@ export ty_fn, FnTy, FnTyBase, FnMeta, FnSig, mk_fn;
export ty_fn_proto, ty_fn_purity, 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 mk_f32, mk_f64;
export ty_estr, mk_estr, type_is_str;
export ty_evec, mk_evec, type_is_vec;
export ty_unboxed_vec, mk_unboxed_vec, mk_mut_unboxed_vec;
Expand All @@ -102,8 +103,8 @@ export ty_tup, mk_tup;
export ty_type, mk_type;
export ty_uint, mk_uint, mk_mach_uint;
export ty_uniq, mk_uniq, mk_imm_uniq, type_is_unique_box;
export ty_infer, mk_infer, type_is_ty_var, mk_var, mk_int_var;
export InferTy, TyVar, IntVar;
export ty_infer, mk_infer, type_is_ty_var, mk_var, mk_int_var, mk_float_var;
export InferTy, TyVar, IntVar, FloatVar;
export ty_self, mk_self, type_has_self;
export ty_class;
export Region, bound_region, encl_region;
Expand Down Expand Up @@ -172,7 +173,8 @@ export ty_sort_str;
export normalize_ty;
export to_str;
export bound_const;
export terr_no_integral_type, terr_ty_param_size, terr_self_substs;
export terr_no_integral_type, terr_no_floating_point_type;
export terr_ty_param_size, terr_self_substs;
export terr_in_field, terr_record_fields, terr_vstores_differ, terr_arg_count;
export terr_sorts, terr_vec, terr_str, terr_record_size, terr_tuple_size;
export terr_regions_does_not_outlive, terr_mutability, terr_purity_mismatch;
Expand Down Expand Up @@ -666,6 +668,7 @@ enum type_err {
terr_sorts(expected_found<t>),
terr_self_substs,
terr_no_integral_type,
terr_no_floating_point_type,
}

enum param_bound {
Expand All @@ -678,21 +681,24 @@ enum param_bound {

enum TyVid = uint;
enum IntVid = uint;
enum FloatVid = uint;
enum FnVid = uint;
#[auto_serialize]
#[auto_deserialize]
enum RegionVid = uint;

enum InferTy {
TyVar(TyVid),
IntVar(IntVid)
IntVar(IntVid),
FloatVar(FloatVid)
}

impl InferTy : to_bytes::IterBytes {
pure fn iter_bytes(+lsb0: bool, f: to_bytes::Cb) {
match self {
TyVar(ref tv) => to_bytes::iter_bytes_2(&0u8, tv, lsb0, f),
IntVar(ref iv) => to_bytes::iter_bytes_2(&1u8, iv, lsb0, f)
IntVar(ref iv) => to_bytes::iter_bytes_2(&1u8, iv, lsb0, f),
FloatVar(ref fv) => to_bytes::iter_bytes_2(&2u8, fv, lsb0, f)
}
}
}
Expand Down Expand Up @@ -758,6 +764,11 @@ impl IntVid: vid {
pure fn to_str() -> ~str { fmt!("<VI%u>", self.to_uint()) }
}

impl FloatVid: vid {
pure fn to_uint() -> uint { *self }
pure fn to_str() -> ~str { fmt!("<VF%u>", self.to_uint()) }
}

impl FnVid: vid {
pure fn to_uint() -> uint { *self }
pure fn to_str() -> ~str { fmt!("<F%u>", self.to_uint()) }
Expand All @@ -773,13 +784,15 @@ impl InferTy {
match self {
TyVar(v) => v.to_uint() << 1,
IntVar(v) => (v.to_uint() << 1) + 1,
FloatVar(v) => (v.to_uint() << 1) + 2
}
}

pure fn to_str() -> ~str {
match self {
TyVar(v) => v.to_str(),
IntVar(v) => v.to_str(),
FloatVar(v) => v.to_str()
}
}
}
Expand Down Expand Up @@ -812,6 +825,12 @@ impl IntVid : to_bytes::IterBytes {
}
}

impl FloatVid : to_bytes::IterBytes {
pure fn iter_bytes(+lsb0: bool, f: to_bytes::Cb) {
(*self).iter_bytes(lsb0, f)
}
}

impl FnVid : to_bytes::IterBytes {
pure fn iter_bytes(+lsb0: bool, f: to_bytes::Cb) {
(*self).iter_bytes(lsb0, f)
Expand Down Expand Up @@ -1030,6 +1049,10 @@ 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_f32(cx: ctxt) -> t { mk_t(cx, ty_float(ast::ty_f32)) }

fn mk_f64(cx: ctxt) -> t { mk_t(cx, ty_float(ast::ty_f64)) }

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)) }
Expand Down Expand Up @@ -1110,9 +1133,9 @@ fn mk_class(cx: ctxt, class_id: ast::def_id, +substs: substs) -> t {

fn mk_var(cx: ctxt, v: TyVid) -> t { mk_infer(cx, TyVar(v)) }

fn mk_int_var(cx: ctxt, v: IntVid) -> t {
mk_infer(cx, IntVar(v))
}
fn mk_int_var(cx: ctxt, v: IntVid) -> t { mk_infer(cx, IntVar(v)) }

fn mk_float_var(cx: ctxt, v: FloatVid) -> t { mk_infer(cx, FloatVar(v)) }

fn mk_infer(cx: ctxt, it: InferTy) -> t { mk_t(cx, ty_infer(it)) }

Expand Down Expand Up @@ -1661,7 +1684,8 @@ pure fn type_is_unique(ty: t) -> bool {
pure fn type_is_scalar(ty: t) -> bool {
match get(ty).sty {
ty_nil | ty_bool | ty_int(_) | ty_float(_) | ty_uint(_) |
ty_infer(IntVar(_)) | ty_type | ty_ptr(_) => true,
ty_infer(IntVar(_)) | ty_infer(FloatVar(_)) | ty_type |
ty_ptr(_) => true,
_ => false
}
}
Expand Down Expand Up @@ -2428,7 +2452,7 @@ fn type_is_integral(ty: t) -> bool {

fn type_is_fp(ty: t) -> bool {
match get(ty).sty {
ty_float(_) => true,
ty_infer(FloatVar(_)) | ty_float(_) => true,
_ => false
}
}
Expand Down Expand Up @@ -3260,6 +3284,7 @@ fn ty_sort_str(cx: ctxt, t: t) -> ~str {
ty_tup(_) => ~"tuple",
ty_infer(TyVar(_)) => ~"inferred type",
ty_infer(IntVar(_)) => ~"integral variable",
ty_infer(FloatVar(_)) => ~"floating-point variable",
ty_param(_) => ~"type parameter",
ty_self => ~"self"
}
Expand Down Expand Up @@ -3387,6 +3412,10 @@ fn type_err_to_str(cx: ctxt, err: &type_err) -> ~str {
~"couldn't determine an appropriate integral type for integer \
literal"
}
terr_no_floating_point_type => {
~"couldn't determine an appropriate floating point type for \
floating point literal"
}
}
}

Expand Down Expand Up @@ -4000,7 +4029,7 @@ fn is_binopable(_cx: ctxt, ty: t, op: ast::binop) -> bool {
match get(ty).sty {
ty_bool => tycat_bool,
ty_int(_) | ty_uint(_) | ty_infer(IntVar(_)) => tycat_int,
ty_float(_) => tycat_float,
ty_float(_) | ty_infer(FloatVar(_)) => tycat_float,
ty_rec(_) | ty_tup(_) | ty_enum(_, _) => tycat_struct,
ty_bot => tycat_bot,
_ => tycat_other
Expand Down Expand Up @@ -4230,6 +4259,11 @@ impl IntVid : cmp::Eq {
pure fn ne(other: &IntVid) -> bool { *self != *(*other) }
}

impl FloatVid : cmp::Eq {
pure fn eq(other: &FloatVid) -> bool { *self == *(*other) }
pure fn ne(other: &FloatVid) -> bool { *self != *(*other) }
}

impl FnVid : cmp::Eq {
pure fn eq(other: &FnVid) -> bool { *self == *(*other) }
pure fn ne(other: &FnVid) -> bool { *self != *(*other) }
Expand Down
5 changes: 5 additions & 0 deletions src/librustc/middle/typeck/check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -850,6 +850,11 @@ fn check_lit(fcx: @fn_ctxt, lit: @ast::lit) -> ty::t {
ty::mk_int_var(tcx, fcx.infcx().next_int_var_id())
}
ast::lit_float(_, t) => ty::mk_mach_float(tcx, t),
ast::lit_float_unsuffixed(_) => {
// An unsuffixed floating point literal could have any floating point
// type, so we create a floating point type variable for it.
ty::mk_float_var(tcx, fcx.infcx().next_float_var_id())
}
ast::lit_nil => ty::mk_nil(tcx),
ast::lit_bool(_) => ty::mk_bool(tcx)
}
Expand Down
1 change: 1 addition & 0 deletions src/librustc/middle/typeck/check/method.rs
Original file line number Diff line number Diff line change
Expand Up @@ -664,6 +664,7 @@ impl LookupContext {
match ty::get(self_ty).sty {
ty_box(*) | ty_uniq(*) | ty_rptr(*) |
ty_infer(IntVar(_)) | // FIXME(#3211)---should be resolved
ty_infer(FloatVar(_)) | // FIXME(#3211)---should be resolved
ty_self | ty_param(*) | ty_nil | ty_bot | ty_bool |
ty_int(*) | ty_uint(*) |
ty_float(*) | ty_enum(*) | ty_ptr(*) | ty_rec(*) |
Expand Down
26 changes: 24 additions & 2 deletions src/librustc/middle/typeck/infer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,8 @@ overconstrains the type, it's a type error; if we reach the point at
which type variables must be resolved and an integral type variable is
still underconstrained, it defaults to `int` as a last resort.
Floating point types are handled similarly to integral types.
## GLB/LUB
Computing the greatest-lower-bound and least-upper-bound of two
Expand Down Expand Up @@ -250,8 +252,8 @@ use std::smallintmap;
use std::smallintmap::smallintmap;
use std::map::HashMap;
use middle::ty;
use middle::ty::{TyVid, IntVid, RegionVid, vid,
ty_int, ty_uint, get, terr_fn, TyVar, IntVar};
use middle::ty::{TyVid, IntVid, FloatVid, RegionVid, vid,
ty_int, ty_uint, get, terr_fn, TyVar, IntVar, FloatVar};
use syntax::{ast, ast_util};
use syntax::ast::{ret_style, purity};
use util::ppaux::{ty_to_str, mt_to_str};
Expand All @@ -272,6 +274,7 @@ use resolve::{resolve_nested_tvar, resolve_rvar, resolve_ivar, resolve_all,
resolve_and_force_all_but_regions, resolver};
use unify::{vals_and_bindings, root};
use integral::{int_ty_set, int_ty_set_all};
use floating::{float_ty_set, float_ty_set_all};
use combine::{combine_fields, eq_tys};
use assignment::Assign;
use to_str::ToStr;
Expand Down Expand Up @@ -318,12 +321,17 @@ enum infer_ctxt = @{
// represented by an int_ty_set.
int_var_bindings: vals_and_bindings<ty::IntVid, int_ty_set>,

// The types that might instantiate a floating-point type variable are
// represented by an float_ty_set.
float_var_bindings: vals_and_bindings<ty::FloatVid, float_ty_set>,

// For region variables.
region_vars: RegionVarBindings,

// For keeping track of existing type and region variables.
ty_var_counter: @mut uint,
int_var_counter: @mut uint,
float_var_counter: @mut uint,
region_var_counter: @mut uint
};

Expand Down Expand Up @@ -359,9 +367,11 @@ fn new_infer_ctxt(tcx: ty::ctxt) -> infer_ctxt {
infer_ctxt(@{tcx: tcx,
ty_var_bindings: new_vals_and_bindings(),
int_var_bindings: new_vals_and_bindings(),
float_var_bindings: new_vals_and_bindings(),
region_vars: RegionVarBindings(tcx),
ty_var_counter: @mut 0u,
int_var_counter: @mut 0u,
float_var_counter: @mut 0u,
region_var_counter: @mut 0u})}

fn mk_subty(cx: infer_ctxt, a_is_expected: bool, span: span,
Expand Down Expand Up @@ -627,6 +637,18 @@ impl infer_ctxt {
ty::mk_int_var(self.tcx, self.next_int_var_id())
}

fn next_float_var_id() -> FloatVid {
let id = *self.float_var_counter;
*self.float_var_counter += 1;

self.float_var_bindings.vals.insert(id, root(float_ty_set_all(), 0));
return FloatVid(id);
}

fn next_float_var() -> ty::t {
ty::mk_float_var(self.tcx, self.next_float_var_id())
}

fn next_region_var_nb(span: span) -> ty::Region {
ty::re_infer(ty::ReVar(self.region_vars.new_region_var(span)))
}
Expand Down
11 changes: 11 additions & 0 deletions src/librustc/middle/typeck/infer/combine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -385,6 +385,17 @@ fn super_tys<C:combine>(
self.infcx().t_sub_int_var(a, b_id).then(|| Ok(a) )
}

// Relate floating-point variables to other types
(ty::ty_infer(FloatVar(a_id)), ty::ty_infer(FloatVar(b_id))) => {
self.infcx().float_vars(a_id, b_id).then(|| Ok(a) )
}
(ty::ty_infer(FloatVar(a_id)), ty::ty_float(_)) => {
self.infcx().float_var_sub_t(a_id, b).then(|| Ok(a) )
}
(ty::ty_float(_), ty::ty_infer(FloatVar(b_id))) => {
self.infcx().t_sub_float_var(a, b_id).then(|| Ok(a) )
}

(ty::ty_int(_), _) |
(ty::ty_uint(_), _) |
(ty::ty_float(_), _) => {
Expand Down
Loading

0 comments on commit fe02814

Please sign in to comment.