Skip to content

Investigate smarter inference on binary ops with numeric literal on the LHS #2514

Open
@dcodeIO

Description

@dcodeIO

Right now, the body in

export function test1(x: f32): bool {
  return 5.0 < x
}

infers as someF64 < f64(someF32) (sees 5.0, eagerly picks f64), compiling to

local.get $0
f64.promote_f32
f64.const 5
f64.gt

while inverting the operation to

export function test1_inv(x: f32): bool {
  return x >= 5.0;
}

compiles to

local.get $0
f32.const 5
f32.ge

Similarly,

export function test2(x: f32): bool {
  return 5 < x
}

infers as someI32 < someF32 (sees 5, picks i32), then refuses to compile with

ERROR TS2365: Operator '<' cannot be applied to types 'i32' and 'f32'.

while inverting the operation to

export function test2_inv(x: f32): bool {
  return x >= 5;
}

compiles to

local.get $0
f32.const 5
f32.gt

In other places, like the max<T> builtin, what we instead do is to infer based on the RHS if the LHS is a numeric literal, which can be done because the numeric literal on the LHS has no side-effects anyway, so the RHS can be compiled prior. The mechanism could be extended to binary operations like the above, but then is a breaking change. There are arguments to be made that right now, the rules are at least straight-forward, while after, the rules would become somewhat magical, including potential unexpected precision loss. The latter can be mitigated by a) consequently warning when a literal does not fit into the designated respectively inferred type or b) by upgrading, say, an f32 to an f64 literal if the value otherwise wouldn't fit. Option b) highlights other magical properties that might be unexpected.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions