about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2014-06-14 08:46:48 +0000
committerbors <bors@rust-lang.org>2014-06-14 08:46:48 +0000
commitdbd29ea96ef77a67496bb44de382140354c23632 (patch)
treea09ec4da5f5f91d2271a0534933d1df33b880657 /src
parent18c451fc497a23944b7b759cca5ff0b0be1122fd (diff)
parent30772d94b1e86a09723af1f137149b45e8c12ed7 (diff)
downloadrust-dbd29ea96ef77a67496bb44de382140354c23632.tar.gz
rust-dbd29ea96ef77a67496bb44de382140354c23632.zip
auto merge of #14874 : pcwalton/rust/enum-to-float-casts-part-deux, r=alexcrichton
Closes #14794.

If you're casting from an enum to a float, cast through an integer
first.

[breaking-change]

r? @alexcrichton
Diffstat (limited to 'src')
-rw-r--r--src/librustc/middle/trans/consts.rs3
-rw-r--r--src/librustc/middle/ty.rs8
-rw-r--r--src/librustc/middle/typeck/check/mod.rs19
-rw-r--r--src/test/compile-fail/enum-to-float-cast.rs (renamed from src/test/run-pass/enum-to-float-cast.rs)10
-rw-r--r--src/test/run-pass/const-enum-cast.rs8
-rw-r--r--src/test/run-pass/enum-disr-val-pretty.rs1
-rw-r--r--src/test/run-pass/tag-variant-disr-val.rs1
7 files changed, 32 insertions, 18 deletions
diff --git a/src/librustc/middle/trans/consts.rs b/src/librustc/middle/trans/consts.rs
index ae476fb9741..7e4bcb8f684 100644
--- a/src/librustc/middle/trans/consts.rs
+++ b/src/librustc/middle/trans/consts.rs
@@ -503,9 +503,8 @@ fn const_expr_unadjusted(cx: &CrateContext, e: &ast::Expr,
                         let s = ty::type_is_signed(ety) as Bool;
                         llvm::LLVMConstIntCast(iv, llty.to_ref(), s)
                     }
-                    expr::cast_float => llvm::LLVMConstSIToFP(iv, llty.to_ref()),
                     _ => cx.sess().bug("enum cast destination is not \
-                                        integral or float")
+                                        integral")
                 }
               }
               (expr::cast_pointer, expr::cast_pointer) => {
diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs
index 02300fccdae..443eec07cc2 100644
--- a/src/librustc/middle/ty.rs
+++ b/src/librustc/middle/ty.rs
@@ -1685,6 +1685,14 @@ pub fn type_is_scalar(ty: t) -> bool {
     }
 }
 
+/// Returns true if this type is a floating point type and false otherwise.
+pub fn type_is_floating_point(ty: t) -> bool {
+    match get(ty).sty {
+        ty_float(_) => true,
+        _ => false,
+    }
+}
+
 pub fn type_needs_drop(cx: &ctxt, ty: t) -> bool {
     type_contents(cx, ty).needs_drop(cx)
 }
diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs
index b9933fed296..b24b32bc81f 100644
--- a/src/librustc/middle/typeck/check/mod.rs
+++ b/src/librustc/middle/typeck/check/mod.rs
@@ -3042,12 +3042,24 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
                     let t_1_is_scalar = type_is_scalar(fcx, expr.span, t_1);
                     let t_1_is_char = type_is_char(fcx, expr.span, t_1);
                     let t_1_is_bare_fn = type_is_bare_fn(fcx, expr.span, t_1);
+                    let t_1_is_float = type_is_floating_point(fcx,
+                                                              expr.span,
+                                                              t_1);
 
                     // casts to scalars other than `char` and `bare fn` are trivial
                     let t_1_is_trivial = t_1_is_scalar &&
                         !t_1_is_char && !t_1_is_bare_fn;
 
-                    if type_is_c_like_enum(fcx, expr.span, t_e) && t_1_is_trivial {
+                    if type_is_c_like_enum(fcx, expr.span, t_e) &&
+                            t_1_is_trivial {
+                        if t_1_is_float {
+                            fcx.type_error_message(expr.span, |actual| {
+                                format!("illegal cast; cast through an \
+                                         integer first: `{}` as `{}`",
+                                        actual,
+                                        fcx.infcx().ty_to_str(t_1))
+                            }, t_e, None);
+                        }
                         // casts from C-like enums are allowed
                     } else if t_1_is_char {
                         let te = fcx.infcx().resolve_type_vars_if_possible(te);
@@ -4206,6 +4218,11 @@ pub fn type_is_bare_fn(fcx: &FnCtxt, sp: Span, typ: ty::t) -> bool {
     return ty::type_is_bare_fn(typ_s);
 }
 
+pub fn type_is_floating_point(fcx: &FnCtxt, sp: Span, typ: ty::t) -> bool {
+    let typ_s = structurally_resolved_type(fcx, sp, typ);
+    return ty::type_is_floating_point(typ_s);
+}
+
 pub fn type_is_unsafe_ptr(fcx: &FnCtxt, sp: Span, typ: ty::t) -> bool {
     let typ_s = structurally_resolved_type(fcx, sp, typ);
     return ty::type_is_unsafe_ptr(typ_s);
diff --git a/src/test/run-pass/enum-to-float-cast.rs b/src/test/compile-fail/enum-to-float-cast.rs
index eb6c078efcd..9c859cb0dde 100644
--- a/src/test/run-pass/enum-to-float-cast.rs
+++ b/src/test/compile-fail/enum-to-float-cast.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// Tests that enum-to-float-casts do *signed* integer-to-float conversion.
+// Tests that enum-to-float casts are disallowed.
 
 enum E {
     L0 = -1,
@@ -20,13 +20,13 @@ enum F {
     H1 = 0xFFFFFFFFFFFFFFFF
 }
 
-static C0: f32 = L0 as f32;
-static C1: f32 = H1 as f32;
+static C0: f32 = L0 as f32; //~ ERROR illegal cast
+static C1: f32 = H1 as f32; //~ ERROR illegal cast
 
 pub fn main() {
-    let a = L0 as f32;
+    let a = L0 as f32;  //~ ERROR illegal cast
     let b = C0;
-    let c = H1 as f32;
+    let c = H1 as f32;  //~ ERROR illegal cast
     let d = C1;
     assert_eq!(a, -1.0f32);
     assert_eq!(b, -1.0f32);
diff --git a/src/test/run-pass/const-enum-cast.rs b/src/test/run-pass/const-enum-cast.rs
index 75e942cb767..346d379aa14 100644
--- a/src/test/run-pass/const-enum-cast.rs
+++ b/src/test/run-pass/const-enum-cast.rs
@@ -14,18 +14,10 @@ enum B { B1=0, B2=2 }
 pub fn main () {
     static c1: int = A2 as int;
     static c2: int = B2 as int;
-    static c3: f64 = A2 as f64;
-    static c4: f64 = B2 as f64;
     let a1 = A2 as int;
     let a2 = B2 as int;
-    let a3 = A2 as f64;
-    let a4 = B2 as f64;
     assert_eq!(c1, 1);
     assert_eq!(c2, 2);
-    assert_eq!(c3, 1.0);
-    assert_eq!(c4, 2.0);
     assert_eq!(a1, 1);
     assert_eq!(a2, 2);
-    assert_eq!(a3, 1.0);
-    assert_eq!(a4, 2.0);
 }
diff --git a/src/test/run-pass/enum-disr-val-pretty.rs b/src/test/run-pass/enum-disr-val-pretty.rs
index 66b11aefd32..c34b2be6fb5 100644
--- a/src/test/run-pass/enum-disr-val-pretty.rs
+++ b/src/test/run-pass/enum-disr-val-pretty.rs
@@ -21,5 +21,4 @@ pub fn main() {
 
 fn test_color(color: color, val: int, _name: String) {
     assert!(color as int == val);
-    assert!(color as f64 == val as f64);
 }
diff --git a/src/test/run-pass/tag-variant-disr-val.rs b/src/test/run-pass/tag-variant-disr-val.rs
index 191a6a9c7e2..ac9af2b693d 100644
--- a/src/test/run-pass/tag-variant-disr-val.rs
+++ b/src/test/run-pass/tag-variant-disr-val.rs
@@ -40,7 +40,6 @@ pub fn main() {
 fn test_color(color: color, val: int, name: String) {
     //assert!(unsafe::transmute(color) == val);
     assert_eq!(color as int, val);
-    assert_eq!(color as f64, val as f64);
     assert!(get_color_alt(color) == name);
     assert!(get_color_if(color) == name);
 }