x + 0, 0 + x, x - 0, x * 1, 1 * x and x / 1 to x. #8871 Semantic Diff
1 commit, rendered from its record.
| Range | Commits | Changelog | Areas | JS output changes | Formats | Failed checks |
|---|---|---|---|---|---|---|
fb7a59bd8313d39098af4659332079695d0a54b9..pr-8871 | 1 | ๐ Polish | codegentests | 1 | none | 0 |
x + 0, 0 + x, x - 0, x * 1, 1 * x and x / 1 to x. #8871 fb7a59bd8313d39098af4659332079695d0a54b9..pr-8871Integer x + 0, 0 + x, x - 0, x * 1, 1 * x and x / 1 compile to x. A ReScript int value is a 32-bit integer in JavaScript, so the | 0 truncation (or << 0 for * 1) that these operations emitted leaves the value unchanged. The JavaScript expression builders in Js_exp_make (int32_add, int32_minus, int32_mul, int32_div) return the other operand when one operand is the literal identity. The dropped operand is a literal, so evaluation of the kept operand is unchanged.
let addZero = (x: int) => x + 0let subZero = (x: int) => x - 0let mulOne = (x: int) => x * 1let divOne = (x: int) => x / 1
function addZero(x) { return x + 0 | 0;} function subZero(x) { return x - 0 | 0;} function mulOne(x) { return (x << 0);} function divOne(x) { return x / 1 | 0;}
function addZero(x) { return x;} function subZero(x) { return x;} function mulOne(x) { return x;} function divOne(x) { return x;}
Source bsc Example.res (CommonJS, to stdout) with bsc built from aa2078e3d (Before) and from this commit (After); function bodies shown, the module header and exports are identical.
x + 0, 0 + x, x - 0, x * 1, 1 * x and x / 1 to x. #8871 int operand hold a value outside the 32-bit range? Every int the compiler computes is already truncated: compiling -x, Int.fromFloat(f) and Int.shiftRightUnsigned(x, y) with this commit gives -x | 0, f | 0 and (x >>> y) | 0. A value outside the range reaches an int only through an external or %raw typed int; for those the result changes, for example Number.MAX_SAFE_INTEGER + 0 gave -1 and gives 9007199254740991. The compiler already relies on the same assumption: Plsrint by the literal 0 compiles to the operand (compiler/core/lam_compile_primitive.ml, [e1; 0] -> e1), dropping (x >>> 0) | 0. x / 1 still check for division by zero? The divisor is the literal 1, so no check applies; the existing rule for a nonzero literal divisor already skipped the runtime div call. + 0, 0 +, - 0, * 1, 1 *, / 1 on a non-literal operand, now the bare operand; in tests/tests/src one existing snapshot changes (gpr_3609_test.mjs, 0 + state._0 | 0 -> state._0) and in the gentype example Docstrings.res.js six + 0 functions drop the addition (a + 0 | 0 -> a), and the stdlib build (make lib) emits no changed JStests/tests/src/+ int_identity_ops_test.res+ int_identity_ops_test.mjs~ gpr_3609_test.mjs| A | changes/int-identity-ops.polish.md | +1 | โ0 |
| M | compiler/core/js_exp_make.ml | +15 | โ3 |
| M | tests/gentype_tests/typescript-react-example/src/Docstrings.res.js | +6 | โ6 |
| M | tests/tests/src/gpr_3609_test.mjs | +1 | โ1 |
| A | tests/tests/src/int_identity_ops_test.mjs | +69 | โ0 |
| A | tests/tests/src/int_identity_ops_test.res | +32 | โ0 |