Commit 6fde2fcd51

Andrew Kelley <andrew@ziglang.org>
2022-05-08 22:05:16
allow in-memory coercion of differently-named floats with same bits
For example, this allows passing a `*c_longdouble` where a `*f80` is expected, provided that `c_longdouble` maps to `f80` for this target.
1 parent 663b677
Changed files (3)
src
test
behavior
src/stage1/ir.cpp
@@ -4480,6 +4480,12 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted
         return result;
     }
 
+    if (wanted_type->id == ZigTypeIdFloat && actual_type->id == ZigTypeIdFloat) {
+        if (wanted_type->data.floating.bit_count == actual_type->data.floating.bit_count) {
+            return result;
+        }
+    }
+
     if (wanted_type->id == ZigTypeIdVector && actual_type->id == ZigTypeIdVector) {
         if (actual_type->data.vector.len != wanted_type->data.vector.len) {
             result.id = ConstCastResultIdVectorLength;
src/Sema.zig
@@ -18673,6 +18673,15 @@ fn coerceInMemoryAllowed(
         }
     }
 
+    // Differently-named floats with the same number of bits.
+    if (dest_ty.zigTypeTag() == .Float and src_ty.zigTypeTag() == .Float) {
+        const dest_bits = dest_ty.floatBits(target);
+        const src_bits = src_ty.floatBits(target);
+        if (dest_bits == src_bits) {
+            return .ok;
+        }
+    }
+
     // Pointers / Pointer-like Optionals
     var dest_buf: Type.Payload.ElemType = undefined;
     var src_buf: Type.Payload.ElemType = undefined;
test/behavior/cast.zig
@@ -1426,3 +1426,23 @@ test "pointer to empty struct literal to mutable slice" {
     var x: []i32 = &.{};
     try expect(x.len == 0);
 }
+
+test "coerce between pointers of compatible differently-named floats" {
+    if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
+    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
+    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
+    if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
+
+    const F = switch (@typeInfo(c_longdouble).Float.bits) {
+        16 => f16,
+        32 => f32,
+        64 => f64,
+        80 => f80,
+        128 => f128,
+        else => @compileError("unreachable"),
+    };
+    var f1: F = 12.34;
+    var f2: *c_longdouble = &f1;
+    f2.* += 1;
+    try expect(f1 == @as(F, 12.34) + 1);
+}