Commit 2e037fd827

Vexu <git@vexu.eu>
2020-07-10 16:30:50
use correct cast function when doing `@floatCast` at comptime
1 parent eddc68a
Changed files (3)
src
test
src/ir.cpp
@@ -13020,7 +13020,11 @@ static IrInstGen *ir_resolve_cast(IrAnalyze *ira, IrInst *source_instr, IrInstGe
 {
     if (instr_is_comptime(value) || !type_has_bits(ira->codegen, wanted_type)) {
         IrInstGen *result = ir_const(ira, source_instr, wanted_type);
-        if (!eval_const_expr_implicit_cast(ira, source_instr, cast_op, value->value, value->value->type,
+        ZigValue *val = ir_resolve_const(ira, value, UndefBad);
+        if (val == nullptr)
+            return ira->codegen->invalid_inst_gen;
+
+        if (!eval_const_expr_implicit_cast(ira, source_instr, cast_op, val, val->type,
             result->value, wanted_type))
         {
             return ira->codegen->invalid_inst_gen;
@@ -26680,6 +26684,10 @@ static IrInstGen *ir_analyze_instruction_int_cast(IrAnalyze *ira, IrInstSrcIntCa
     }
 
     if (instr_is_comptime(target) || dest_type->id == ZigTypeIdComptimeInt) {
+        ZigValue *val = ir_resolve_const(ira, target, UndefBad);
+        if (val == nullptr)
+            return ira->codegen->invalid_inst_gen;
+
         return ir_implicit_cast2(ira, &instruction->target->base, target, dest_type);
     }
 
@@ -26718,13 +26726,11 @@ static IrInstGen *ir_analyze_instruction_float_cast(IrAnalyze *ira, IrInstSrcFlo
     }
 
     if (instr_is_comptime(target) || dest_type->id == ZigTypeIdComptimeFloat) {
-        return ir_implicit_cast2(ira, &instruction->target->base, target, dest_type);
-    }
+        ZigValue *val = ir_resolve_const(ira, target, UndefBad);
+        if (val == nullptr)
+            return ira->codegen->invalid_inst_gen;
 
-    if (target->value->type->id != ZigTypeIdFloat) {
-        ir_add_error(ira, &instruction->target->base, buf_sprintf("expected float type, found '%s'",
-                    buf_ptr(&target->value->type->name)));
-        return ira->codegen->invalid_inst_gen;
+        return ir_analyze_widen_or_shorten(ira, &instruction->target->base, target, dest_type);
     }
 
     return ir_analyze_widen_or_shorten(ira, &instruction->base.base, target, dest_type);
test/stage1/behavior/cast.zig
@@ -384,6 +384,19 @@ test "@intCast i32 to u7" {
     expect(z == 0xff);
 }
 
+test "@floatCast cast down" {
+    {
+        var double: f64 = 0.001534;
+        var single = @floatCast(f32, double);
+        expect(single == 0.001534);
+    }
+    {
+        const double: f64 = 0.001534;
+        const single = @floatCast(f32, double);
+        expect(single == 0.001534);
+    }
+}
+
 test "implicit cast undefined to optional" {
     expect(MakeType(void).getNull() == null);
     expect(MakeType(void).getNonNull() != null);
test/compile_errors.zig
@@ -2,6 +2,22 @@ const tests = @import("tests.zig");
 const std = @import("std");
 
 pub fn addCases(cases: *tests.CompileErrorContext) void {
+    cases.addTest("int/float conversion to comptime_int/float",
+        \\export fn foo() void {
+        \\    var a: f32 = 2;
+        \\    _ = @floatToInt(comptime_int, a);
+        \\}
+        \\export fn bar() void {
+        \\    var a: u32 = 2;
+        \\    _ = @intToFloat(comptime_float, a);
+        \\}
+    , &[_][]const u8{
+        "tmp.zig:3:35: error: unable to evaluate constant expression",
+        "tmp.zig:3:9: note: referenced here",
+        "tmp.zig:7:37: error: unable to evaluate constant expression",
+        "tmp.zig:7:9: note: referenced here",
+    });
+
     cases.add("extern variable has no type",
         \\extern var foo;
         \\pub export fn entry() void {
@@ -90,19 +106,13 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
         \\    var a: u32 = 2;
         \\    _ = @floatToInt(u32, a);
         \\}
-        \\export fn qux() void {
-        \\    var a: u32 = 2;
-        \\    _ = @intCast(comptime_int, a);
-        \\}
     , &[_][]const u8{
-        "tmp.zig:3:32: error: expected type 'comptime_int', found 'u32'",
+        "tmp.zig:3:32: error: unable to evaluate constant expression",
         "tmp.zig:3:9: note: referenced here",
         "tmp.zig:7:21: error: expected float type, found 'u32'",
         "tmp.zig:7:9: note: referenced here",
         "tmp.zig:11:26: error: expected float type, found 'u32'",
         "tmp.zig:11:9: note: referenced here",
-        "tmp.zig:15:32: error: expected type 'comptime_int', found 'u32'",
-        "tmp.zig:15:9: note: referenced here",
     });
 
     cases.addTest("invalid float casts",
@@ -118,19 +128,13 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
         \\    var a: f32 = 2;
         \\    _ = @intToFloat(f32, a);
         \\}
-        \\export fn qux() void {
-        \\    var a: f32 = 2;
-        \\    _ = @floatCast(comptime_float, a);
-        \\}
     , &[_][]const u8{
-        "tmp.zig:3:36: error: expected type 'comptime_float', found 'f32'",
+        "tmp.zig:3:36: error: unable to evaluate constant expression",
         "tmp.zig:3:9: note: referenced here",
         "tmp.zig:7:21: error: expected integer type, found 'f32'",
         "tmp.zig:7:9: note: referenced here",
         "tmp.zig:11:26: error: expected int type, found 'f32'",
         "tmp.zig:11:9: note: referenced here",
-        "tmp.zig:15:36: error: expected type 'comptime_float', found 'f32'",
-        "tmp.zig:15:9: note: referenced here",
     });
 
     cases.addTest("invalid assignments",