From 9af4cada73e43fb98e906a0ed79197963d1a05ac Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 2 May 2022 12:13:55 -0700 Subject: [PATCH] Sema: coerce comptime_float to fixed-width float Instead of doing heterogeneous comparison at comptime. This makes the following test pass (as it already does for stage1): ```zig test { const x: f64 = 12.34; expect(x == 12.34); } ``` There is already behavior test coverage for this, however, other bugs in `std.fmt.parseFloat` are masking the failures. From a language specification perspective, this makes sense because it makes comptime comparisons with comptime_float work the same way they work with runtime comparisons. --- src/Sema.zig | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/src/Sema.zig b/src/Sema.zig index 012750e429..87cb7cc9d2 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -20787,14 +20787,14 @@ fn cmpNumeric( sema: *Sema, block: *Block, src: LazySrcLoc, - lhs: Air.Inst.Ref, - rhs: Air.Inst.Ref, + uncasted_lhs: Air.Inst.Ref, + uncasted_rhs: Air.Inst.Ref, op: std.math.CompareOperator, lhs_src: LazySrcLoc, rhs_src: LazySrcLoc, ) CompileError!Air.Inst.Ref { - const lhs_ty = sema.typeOf(lhs); - const rhs_ty = sema.typeOf(rhs); + const lhs_ty = sema.typeOf(uncasted_lhs); + const rhs_ty = sema.typeOf(uncasted_rhs); assert(lhs_ty.isNumeric()); assert(rhs_ty.isNumeric()); @@ -20803,6 +20803,19 @@ fn cmpNumeric( const rhs_ty_tag = rhs_ty.zigTypeTag(); const target = sema.mod.getTarget(); + // One exception to heterogeneous comparison: comptime_float needs to + // coerce to fixed-width float. + + const lhs = if (lhs_ty_tag == .ComptimeFloat and rhs_ty_tag == .Float) + try sema.coerce(block, rhs_ty, uncasted_lhs, lhs_src) + else + uncasted_lhs; + + const rhs = if (lhs_ty_tag == .Float and rhs_ty_tag == .ComptimeFloat) + try sema.coerce(block, lhs_ty, uncasted_rhs, rhs_src) + else + uncasted_rhs; + const runtime_src: LazySrcLoc = src: { if (try sema.resolveMaybeUndefVal(block, lhs_src, lhs)) |lhs_val| { if (try sema.resolveMaybeUndefVal(block, rhs_src, rhs)) |rhs_val| { @@ -20845,8 +20858,10 @@ fn cmpNumeric( .Float, .ComptimeFloat => true, else => false, }; + if (lhs_is_float and rhs_is_float) { - // Implicit cast the smaller one to the larger one. + // Smaller fixed-width floats coerce to larger fixed-width floats. + // comptime_float coerces to fixed-width float. const dest_ty = x: { if (lhs_ty_tag == .ComptimeFloat) { break :x rhs_ty;