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.
This commit is contained in:
Andrew Kelley 2022-05-02 12:13:55 -07:00
parent a3f56154d0
commit 9af4cada73

View File

@ -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;