Haxe 4 Int-to-Float coercion behaves differently on JS and eval targets after migrating shared numeric code
0 reputation · 07 Jun 2020, 22:21 UTC
0 reputation · 07 Jun 2020, 22:21 UTC
I maintain a Haxe 4 library that is compiled to both JavaScript (hxnodejs) and the eval target. The codebase relies on implicit conversions between Int and Float in arithmetic and function arguments, and I am trying to decide whether I can keep that style or must normalize everything to explicit conversions.
The language documentation indicates that implicit numeric conversions are target-dependent: some back-ends insert runtime casts while others reject the same code at compile time. What is not clear to me is where the exact boundary sits for Haxe 4.x — which targets silently coerce, which raise compile errors, and whether the behavior changed between minor releases. I also cannot tell from the docs whether the strictness applies uniformly to function argument passing, return types, and arithmetic expressions, or only to some of these cases.
I would like to keep a single source tree without per-target conditional compilation for numeric code if that is realistically safe.
1. For Haxe 4.x, which documented targets permit implicit Int↔Float coercion at compile time, and which require explicit casts or Std.int / float conversion?
2. Does the coercion rule differ between arithmetic expressions and typed function signatures on the same target?
3. Is there a compiler flag or typedef pattern that makes numeric conversion behavior consistent across targets without sprinkling #if blocks?
35275 reputation · 08 Jun 2020, 09:15 UTC
1. Which targets permit implicit Int↔Float coercion?
Int where a Float is expected and injects a runtime cast. The same applies to Float → Int when the target language can represent the value.Int and Float. Both arithmetic expressions and typed function signatures require an explicit cast (e.g. Std.int / Float).2. Do arithmetic and function signatures behave the same?
Int literals to Float and inserts a cast where needed. On eval, the same expression causes a compile‑time error unless you cast explicitly.function foo(x:Float) and allows foo(42) without error. Eval requires foo(42) to be written as foo(42.0) or foo(Std.int(42)) (or a @:fast annotation).3. Can a flag or typedef make the behaviour uniform?
typedef FloatOrInt = Float (or a wrapper type) and use that in signatures, then perform the cast inside the function body.Test.hx:
class Test {
static function main() {
trace(f(42)); // Int literal
}
static function f(x:Float):Float {
return x * 2;
}
}
haxe -main Test -js test.js
node test.js
# Output: 84
haxe -main Test -eval
# You will see: "Error: Incompatible types: Int and Float"
static function f(x:Float):Float {
return x * 2;
}
static function main() {
trace(f(42.0));
}
What exact Haxe version are you using? The coercion rules are stable across 4.x, but minor releases can introduce subtle changes, so confirming the version will help rule out version‑specific quirks.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.