Javascript backend -O1 breaks referential transparency in a function having a Double argument and doing String concatenation
Summary
A pure String
value shows up as two different values when output via putStrLn
and via console.log
.
The following factors seem to concur in triggering this behaviour:
- The optimization level is
-O1
(does not happen with-O0
or-O2
) - The affected function has a
Double
argument (does not happen if the argument isInt
, see the commentedtestInt
function in the repro case) - The
String
concatenation has certain characteristics (eg. does not happen for the commentedtestDouble2
function in the repro case and for other similar tweaks to theString
concatenation)
Steps to reproduce
See attached repro case Test.hs
.
$ for i in $(seq 0 2); do rm -rf Test Test.hi Test.o Test.jsexe; echo compiling with -O$i; javascript-unknown-ghcjs-ghc-9.8.2 -v -O$i -dcore-lint Test.hs > ghc.log.O$i 2>&1; echo results with -O$i; ./Test; done
compiling with -O0
results with -O0
1 ab bd
2 ab bd
compiling with -O1
results with -O1
1 ab bd
2 ab
compiling with -O2
results with -O2
1 ab bd
2 ab bd
Loading index.html
in a web browser also exhibits the same behaviour in the JS console log.
Expected behavior
The program's output to be identical regardless of the optimization level. The second part of the second line of the -O1
results to be the same as the second part of the first line, i.e. "ab bd"
instead of just "ab "
.
Environment
- GHC version used: 9.8.2 JS backend
- Nodejs version used: v20.11.0
- Google Chrome version used: 121.0.6167.184 (Official build) (64 bit)
Optional:
- Operating System:
- System Architecture:
$ uname -a
Linux abcde 6.7.5-gentoo #1 SMP Mon Feb 19 15:51:31 CET 2024 x86_64 Intel(R) Core(TM) i7-1065G7 CPU @ 1.30GHz GenuineIntel GNU/Linux