parse: typeck: enabling trivial casts of tail-call return values
introduces ctypes::m_* machine type aliases for int, uint, float depending on cfg(target_arch) that are used in tests
This commit is contained in:
parent
29f7cdffa4
commit
4ba3158e4f
@ -4088,10 +4088,8 @@ fn trans_expr(bcx: @block_ctxt, e: @ast::expr, dest: dest) -> @block_ctxt {
|
||||
}
|
||||
ast::expr_cast(val, _) {
|
||||
alt tcx.cast_map.find(e.id) {
|
||||
option::none. { ret trans_cast(bcx, val, e.id, dest); }
|
||||
some { alt option::get(some) {
|
||||
ty::triv_cast. { ret trans_expr(bcx, val, dest); }
|
||||
} }
|
||||
some(ty::triv_cast.) { ret trans_expr(bcx, val, dest); }
|
||||
_ { ret trans_cast(bcx, val, e.id, dest); }
|
||||
}
|
||||
}
|
||||
ast::expr_anon_obj(anon_obj) {
|
||||
@ -4122,7 +4120,7 @@ fn trans_expr(bcx: @block_ctxt, e: @ast::expr, dest: dest) -> @block_ctxt {
|
||||
// that is_call_expr(ex) -- but we don't support that
|
||||
// yet
|
||||
// FIXME
|
||||
check (ast_util::is_call_expr(ex));
|
||||
check (ast_util::is_tail_call_expr(ex));
|
||||
ret trans_be(bcx, ex);
|
||||
}
|
||||
ast::expr_fail(expr) {
|
||||
@ -4455,7 +4453,8 @@ fn trans_ret(bcx: @block_ctxt, e: option::t<@ast::expr>) -> @block_ctxt {
|
||||
fn build_return(bcx: @block_ctxt) { Br(bcx, bcx_fcx(bcx).llreturn); }
|
||||
|
||||
// fn trans_be(cx: &@block_ctxt, e: &@ast::expr) -> result {
|
||||
fn trans_be(cx: @block_ctxt, e: @ast::expr) : ast_util::is_call_expr(e) ->
|
||||
fn trans_be(cx: @block_ctxt, e: @ast::expr) :
|
||||
ast_util::is_tail_call_expr(e) ->
|
||||
@block_ctxt {
|
||||
// FIXME: Turn this into a real tail call once
|
||||
// calling convention issues are settled
|
||||
|
@ -1501,7 +1501,7 @@ fn eq_ty(&&a: t, &&b: t) -> bool { ret a == b; }
|
||||
// Convert type to machine type
|
||||
// (i.e. replace uint, int, float with target architecture machine types)
|
||||
//
|
||||
// Somewhat expensive but casts that need this should be rare
|
||||
// FIXME somewhat expensive but this should only be called rarely
|
||||
fn ty_to_machine_ty(cx: ctxt, ty: t) -> t {
|
||||
fn sub_fn(cx: ctxt, uint_ty: t, int_ty: t, float_ty: t, in: t) -> t {
|
||||
alt struct(cx, in) {
|
||||
@ -1525,12 +1525,9 @@ fn ty_to_machine_ty(cx: ctxt, ty: t) -> t {
|
||||
// equal or if they are equal after substituting all occurences of
|
||||
// machine independent primitive types by their machine type equivalents
|
||||
// for the current target architecture
|
||||
//
|
||||
// Somewhat expensive but casts that need this should be rare
|
||||
fn triv_eq_ty(cx: ctxt, &&a: t, &&b: t) -> bool {
|
||||
let mach_a = ty_to_machine_ty(cx, a);
|
||||
let mach_b = ty_to_machine_ty(cx, b );
|
||||
ret eq_ty(a, b) || eq_ty(mach_a, mach_b);
|
||||
ret eq_ty(a, b)
|
||||
|| eq_ty(ty_to_machine_ty(cx, a), ty_to_machine_ty(cx, b));
|
||||
}
|
||||
|
||||
// Type lookups
|
||||
|
@ -1846,8 +1846,21 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier,
|
||||
}
|
||||
ast::expr_be(e) {
|
||||
// FIXME: prove instead of assert
|
||||
assert (ast_util::is_call_expr(e));
|
||||
assert (ast_util::is_tail_call_expr(e));
|
||||
check_expr_with(fcx, e, fcx.ret_ty);
|
||||
|
||||
alt e.node {
|
||||
ast::expr_cast(_, _) {
|
||||
alt tcx.cast_map.find(e.id) {
|
||||
option::some(ty::triv_cast.) { }
|
||||
_ { tcx.sess.span_err(expr.span,
|
||||
"non-trivial cast of tail-call return value");
|
||||
}
|
||||
}
|
||||
}
|
||||
_ { /* regular tail call */ }
|
||||
}
|
||||
|
||||
bot = true;
|
||||
write::nil_ty(tcx, id);
|
||||
}
|
||||
@ -2112,8 +2125,10 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier,
|
||||
ty_to_str(tcx, t_1));
|
||||
}
|
||||
|
||||
// mark as triv_cast for later dropping in trans
|
||||
if ty::triv_eq_ty(tcx, t_1, t_e)
|
||||
{ tcx.cast_map.insert(expr.id, ty::triv_cast); }
|
||||
|
||||
write::ty_only_fixup(fcx, id, t_1);
|
||||
}
|
||||
ast::expr_vec(args, mut) {
|
||||
|
@ -175,6 +175,14 @@ pure fn is_call_expr(e: @expr) -> bool {
|
||||
alt e.node { expr_call(_, _, _) { true } _ { false } }
|
||||
}
|
||||
|
||||
pure fn is_tail_call_expr(e: @expr) -> bool {
|
||||
alt e.node {
|
||||
expr_call(_, _, _) { true }
|
||||
expr_cast(inner_e, _) { is_call_expr(inner_e) }
|
||||
_ { false }
|
||||
}
|
||||
}
|
||||
|
||||
fn is_constraint_arg(e: @expr) -> bool {
|
||||
alt e.node {
|
||||
expr_lit(_) { ret true; }
|
||||
|
@ -962,7 +962,7 @@ fn parse_bottom_expr(p: parser) -> @ast::expr {
|
||||
let e = parse_expr(p);
|
||||
|
||||
// FIXME: Is this the right place for this check?
|
||||
if /*check*/ast_util::is_call_expr(e) {
|
||||
if /*check*/ ast_util::is_tail_call_expr(e) {
|
||||
hi = e.span.hi;
|
||||
ex = ast::expr_be(e);
|
||||
} else { p.fatal("Non-call expression in tail call"); }
|
||||
|
@ -5,6 +5,7 @@ Definitions useful for C interop
|
||||
*/
|
||||
|
||||
type c_int = i32;
|
||||
type c_uint = u32;
|
||||
|
||||
type void = int; // Not really the same as C
|
||||
type long = int;
|
||||
@ -15,8 +16,20 @@ type intptr_t = uint;
|
||||
type uintptr_t = uint;
|
||||
type uint32_t = u32;
|
||||
|
||||
// This *must* match with "import c_float = fXX" in std::math per arch
|
||||
type c_float = f64;
|
||||
// machine type equivalents of rust int, uint, float
|
||||
|
||||
#[cfg(target_arch="x86")]
|
||||
type m_int = i32;
|
||||
#[cfg(target_arch="x86_64")]
|
||||
type m_int = i64;
|
||||
|
||||
#[cfg(target_arch="x86")]
|
||||
type m_uint = u32;
|
||||
#[cfg(target_arch="x86_64")]
|
||||
type m_uint = u64;
|
||||
|
||||
// This *must* match with "import m_float = fXX" in std::math per arch
|
||||
type m_float = f64;
|
||||
|
||||
type size_t = uint;
|
||||
type ssize_t = int;
|
||||
|
@ -18,11 +18,11 @@ export
|
||||
|
||||
// These two must match in width according to architecture
|
||||
|
||||
import ctypes::c_float;
|
||||
import ctypes::m_float;
|
||||
import ctypes::c_int;
|
||||
import c_float = math_f64;
|
||||
import m_float = math_f64;
|
||||
|
||||
// FIXME replace with redirect to c_float::consts::FOO as soon as it works
|
||||
// FIXME replace with redirect to m_float::consts::FOO as soon as it works
|
||||
mod consts {
|
||||
/*
|
||||
Const: pi
|
||||
@ -140,7 +140,7 @@ Function: acos
|
||||
Returns the arccosine of an angle (measured in rad)
|
||||
*/
|
||||
pure fn acos(x: float) -> float
|
||||
{ c_float::acos(x as c_float) as float }
|
||||
{ m_float::acos(x as m_float) as float }
|
||||
|
||||
/*
|
||||
Function: asin
|
||||
@ -148,7 +148,7 @@ Function: asin
|
||||
Returns the arcsine of an angle (measured in rad)
|
||||
*/
|
||||
pure fn asin(x: float) -> float
|
||||
{ c_float::asin(x as c_float) as float }
|
||||
{ m_float::asin(x as m_float) as float }
|
||||
|
||||
/*
|
||||
Function: atan
|
||||
@ -156,7 +156,7 @@ Function: atan
|
||||
Returns the arctangents of an angle (measured in rad)
|
||||
*/
|
||||
pure fn atan(x: float) -> float
|
||||
{ c_float::atan(x as c_float) as float }
|
||||
{ m_float::atan(x as m_float) as float }
|
||||
|
||||
|
||||
/*
|
||||
@ -165,7 +165,7 @@ Function: atan2
|
||||
Returns the arctangent of an angle (measured in rad)
|
||||
*/
|
||||
pure fn atan2(y: float, x: float) -> float
|
||||
{ c_float::atan2(y as c_float, x as c_float) as float }
|
||||
{ m_float::atan2(y as m_float, x as m_float) as float }
|
||||
|
||||
/*
|
||||
Function: ceil
|
||||
@ -173,7 +173,7 @@ Function: ceil
|
||||
Returns the smallest integral value less than or equal to `n`
|
||||
*/
|
||||
pure fn ceil(n: float) -> float
|
||||
{ c_float::ceil(n as c_float) as float }
|
||||
{ m_float::ceil(n as m_float) as float }
|
||||
|
||||
/*
|
||||
Function: cos
|
||||
@ -181,7 +181,7 @@ Function: cos
|
||||
Returns the cosine of an angle `x` (measured in rad)
|
||||
*/
|
||||
pure fn cos(x: float) -> float
|
||||
{ c_float::cos(x as c_float) as float }
|
||||
{ m_float::cos(x as m_float) as float }
|
||||
|
||||
/*
|
||||
Function: cosh
|
||||
@ -190,7 +190,7 @@ Returns the hyperbolic cosine of `x`
|
||||
|
||||
*/
|
||||
pure fn cosh(x: float) -> float
|
||||
{ c_float::cosh(x as c_float) as float }
|
||||
{ m_float::cosh(x as m_float) as float }
|
||||
|
||||
|
||||
/*
|
||||
@ -199,7 +199,7 @@ Function: exp
|
||||
Returns `consts::e` to the power of `n*
|
||||
*/
|
||||
pure fn exp(n: float) -> float
|
||||
{ c_float::exp(n as c_float) as float }
|
||||
{ m_float::exp(n as m_float) as float }
|
||||
|
||||
/*
|
||||
Function: abs
|
||||
@ -207,7 +207,7 @@ Function: abs
|
||||
Returns the absolute value of `n`
|
||||
*/
|
||||
pure fn abs(n: float) -> float
|
||||
{ c_float::abs(n as c_float) as float }
|
||||
{ m_float::abs(n as m_float) as float }
|
||||
|
||||
/*
|
||||
Function: floor
|
||||
@ -215,7 +215,7 @@ Function: floor
|
||||
Returns the largest integral value less than or equal to `n`
|
||||
*/
|
||||
pure fn floor(n: float) -> float
|
||||
{ c_float::floor(n as c_float) as float }
|
||||
{ m_float::floor(n as m_float) as float }
|
||||
|
||||
/*
|
||||
Function: fmod
|
||||
@ -223,7 +223,7 @@ Function: fmod
|
||||
Returns the floating-point remainder of `x/y`
|
||||
*/
|
||||
pure fn fmod(x: float, y: float) -> float
|
||||
{ c_float::fmod(x as c_float, y as c_float) as float }
|
||||
{ m_float::fmod(x as m_float, y as m_float) as float }
|
||||
|
||||
/*
|
||||
Function: ln
|
||||
@ -231,7 +231,7 @@ Function: ln
|
||||
Returns the natural logaritm of `n`
|
||||
*/
|
||||
pure fn ln(n: float) -> float
|
||||
{ c_float::ln(n as c_float) as float }
|
||||
{ m_float::ln(n as m_float) as float }
|
||||
|
||||
/*
|
||||
Function: ldexp
|
||||
@ -239,7 +239,7 @@ Function: ldexp
|
||||
Returns `x` multiplied by 2 to the power of `n`
|
||||
*/
|
||||
pure fn ldexp(n: float, i: int) -> float
|
||||
{ c_float::ldexp(n as c_float, i as c_int) as float }
|
||||
{ m_float::ldexp(n as m_float, i as c_int) as float }
|
||||
|
||||
/*
|
||||
Function: ln1p
|
||||
@ -248,7 +248,7 @@ Returns the natural logarithm of `1+n` accurately,
|
||||
even for very small values of `n`
|
||||
*/
|
||||
pure fn ln1p(n: float) -> float
|
||||
{ c_float::ln1p(n as c_float) as float }
|
||||
{ m_float::ln1p(n as m_float) as float }
|
||||
|
||||
/*
|
||||
Function: log10
|
||||
@ -256,7 +256,7 @@ Function: log10
|
||||
Returns the logarithm to base 10 of `n`
|
||||
*/
|
||||
pure fn log10(n: float) -> float
|
||||
{ c_float::log10(n as c_float) as float }
|
||||
{ m_float::log10(n as m_float) as float }
|
||||
|
||||
/*
|
||||
Function: log2
|
||||
@ -264,7 +264,7 @@ Function: log2
|
||||
Returns the logarithm to base 2 of `n`
|
||||
*/
|
||||
pure fn log2(n: float) -> float
|
||||
{ c_float::log2(n as c_float) as float }
|
||||
{ m_float::log2(n as m_float) as float }
|
||||
|
||||
|
||||
/*
|
||||
@ -281,8 +281,8 @@ The fractional part of `n`
|
||||
*/
|
||||
pure fn modf(n: float, &iptr: float) -> float {
|
||||
unchecked {
|
||||
let f = iptr as c_float;
|
||||
let r = c_float::modf(n as c_float, f) as float;
|
||||
let f = iptr as m_float;
|
||||
let r = m_float::modf(n as m_float, f) as float;
|
||||
iptr = f as float;
|
||||
ret r;
|
||||
}
|
||||
@ -303,13 +303,13 @@ Returns:
|
||||
The fractional part of `n`
|
||||
*/
|
||||
pure fn frexp(n: float, &exp: c_int) -> float
|
||||
{ c_float::frexp(n as c_float, exp) as float }
|
||||
{ m_float::frexp(n as m_float, exp) as float }
|
||||
|
||||
/*
|
||||
Function: pow
|
||||
*/
|
||||
pure fn pow(v: float, e: float) -> float
|
||||
{ c_float::pow(v as c_float, e as c_float) as float }
|
||||
{ m_float::pow(v as m_float, e as m_float) as float }
|
||||
|
||||
|
||||
/*
|
||||
@ -319,7 +319,7 @@ Returns the integral value nearest to `x` (according to the
|
||||
prevailing rounding mode) in floating-point format
|
||||
*/
|
||||
pure fn rint(x: float) -> float
|
||||
{ c_float::rint(x as c_float) as float }
|
||||
{ m_float::rint(x as m_float) as float }
|
||||
|
||||
/*
|
||||
Function: round
|
||||
@ -329,7 +329,7 @@ Return the integral value nearest to `x` rounding half-way
|
||||
cases away from zero, regardless of the current rounding direction.
|
||||
*/
|
||||
pure fn round(x: float) -> float
|
||||
{ c_float::round(x as c_float) as float }
|
||||
{ m_float::round(x as m_float) as float }
|
||||
|
||||
/*
|
||||
Function: sin
|
||||
@ -337,7 +337,7 @@ Function: sin
|
||||
Returns the sine of an angle `x` (measured in rad)
|
||||
*/
|
||||
pure fn sin(x: float) -> float
|
||||
{ c_float::sin(x as c_float) as float }
|
||||
{ m_float::sin(x as m_float) as float }
|
||||
|
||||
/*
|
||||
Function: sinh
|
||||
@ -345,7 +345,7 @@ Function: sinh
|
||||
Returns the hyperbolic sine of an angle `x` (measured in rad)
|
||||
*/
|
||||
pure fn sinh(x: float) -> float
|
||||
{ c_float::sinh(x as c_float) as float }
|
||||
{ m_float::sinh(x as m_float) as float }
|
||||
|
||||
/*
|
||||
Function: sqrt
|
||||
@ -353,7 +353,7 @@ Function: sqrt
|
||||
Returns the square root of `x`
|
||||
*/
|
||||
pure fn sqrt(x: float) -> float
|
||||
{ c_float::sqrt(x as c_float) as float }
|
||||
{ m_float::sqrt(x as m_float) as float }
|
||||
|
||||
/*
|
||||
Function: tan
|
||||
@ -362,7 +362,7 @@ Returns the tangent of an angle `x` (measured in rad)
|
||||
|
||||
*/
|
||||
pure fn tan(x: float) -> float
|
||||
{ c_float::tan(x as c_float) as float }
|
||||
{ m_float::tan(x as m_float) as float }
|
||||
|
||||
/*
|
||||
Function: tanh
|
||||
@ -371,7 +371,7 @@ Returns the hyperbolic tangent of an angle `x` (measured in rad)
|
||||
|
||||
*/
|
||||
pure fn tanh(x: float) -> float
|
||||
{ c_float::tanh(x as c_float) as float }
|
||||
{ m_float::tanh(x as m_float) as float }
|
||||
|
||||
/*
|
||||
Function: trunc
|
||||
@ -380,7 +380,7 @@ Returns the integral value nearest to but no larger in magnitude than `x`
|
||||
|
||||
*/
|
||||
pure fn trunc(x: float) -> float
|
||||
{ c_float::trunc(x as c_float) as float }
|
||||
{ m_float::trunc(x as m_float) as float }
|
||||
|
||||
|
||||
|
||||
|
19
src/test/compile-fail/non-triv-cast-be.rs
Normal file
19
src/test/compile-fail/non-triv-cast-be.rs
Normal file
@ -0,0 +1,19 @@
|
||||
// error-pattern: non-trivial cast of tail-call return value
|
||||
use std;
|
||||
|
||||
import std::ctypes::*;
|
||||
|
||||
fn foo_float() -> m_float { ret 0.0 as m_float; }
|
||||
fn bar_float() -> bool { be foo_float() as bool; }
|
||||
|
||||
fn foo_int() -> m_int { ret 0 as m_int; }
|
||||
fn bar_int() -> bool { be foo_int() as bool; }
|
||||
|
||||
fn foo_uint() -> m_uint { ret 0u as m_uint; }
|
||||
fn bar_uint() -> bool { be foo_uint() as bool; }
|
||||
|
||||
fn main() {
|
||||
assert bar_float() == 0.0;
|
||||
assert bar_int() == 0.0;
|
||||
assert bar_uint() == 0.0;
|
||||
}
|
26
src/test/run-pass/triv-cast-be.rs
Normal file
26
src/test/run-pass/triv-cast-be.rs
Normal file
@ -0,0 +1,26 @@
|
||||
use std;
|
||||
|
||||
import std::ctypes::*;
|
||||
|
||||
fn foo_float() -> m_float { ret 0.0 as m_float; }
|
||||
fn bar_float() -> float { be foo_float() as float; }
|
||||
|
||||
fn foo_int() -> m_int { ret 0 as m_int; }
|
||||
fn bar_int() -> int { be foo_int() as int; }
|
||||
|
||||
fn foo_uint() -> m_uint { ret 0u as m_uint; }
|
||||
fn bar_uint() -> uint { be foo_uint() as uint; }
|
||||
|
||||
fn foo_long() -> long { ret 0 as long; }
|
||||
fn bar_long() -> int { be foo_long() as int; }
|
||||
|
||||
fn foo_ulong() -> ulong { ret 0u as ulong; }
|
||||
fn bar_ulong() -> uint { be foo_uint() as uint; }
|
||||
|
||||
fn main() {
|
||||
assert bar_float() == 0.0;
|
||||
assert bar_int() == 0;
|
||||
assert bar_uint() == 0u;
|
||||
assert bar_long() == 0;
|
||||
assert bar_ulong() == 0u;
|
||||
}
|
Loading…
Reference in New Issue
Block a user