purescript-backend-optimizer
purescript-backend-optimizer copied to clipboard
Name clash between module and constructor name
When a data constructor has the same name as an imported module, in the generated javascript they also have the same name resulting in an error when run
Here is a minimal example
Bar.purs
module Bar where
import Prelude
-- This function does not do anything it only needs to be significantly complicated
-- so that it won't be inlined and instead the module it is in imported
placeHolder :: Int -> String
placeHolder i | mod 2 i == 0 = "2"
placeHolder i | mod 3 i == 0 = "2"
placeHolder i | mod 5 i == 0 = "2"
placeHolder i | mod 7 i == 0 = "2"
placeHolder _ = "yipee"
Main.purs
module Main where
import Prelude
import Bar (placeHolder)
import Effect (Effect)
import Effect.Console (log)
data FooBar = Foo | Bar
main :: Effect Unit
main = do
-- use placeholder to ensure it is actually in the generated javascript
log $ placeHolder 3
Here Bar is the name of a data constructor for the `FooBar' type and the name of a module The generated javascript using purescript-backend-optimizer is:
import * as Bar from "../Bar/index.js";
import * as Effect$dConsole from "../Effect.Console/index.js";
const $FooBar = tag => tag;
const Foo = /* #__PURE__ */ $FooBar("Foo");
const Bar = /* #__PURE__ */ $FooBar("Bar");
const main = /* #__PURE__ */ Effect$dConsole.log(/* #__PURE__ */ Bar.placeHolder(3));
export {$FooBar, Bar, Foo, main};
Running this gives an error
✘ [ERROR] The symbol "Bar" has already been declared
output-es/Main/index.js:5:6:
5 │ const Bar = /* #__PURE__ */ $FooBar("Bar");
╵ ~~~
The symbol "Bar" was originally declared here:
output-es/Main/index.js:1:12:
1 │ import * as Bar from "../Bar/index.js";
╵ ~~~
The default purescript backend renames the imported module to "Bar_1" when generating the javascript removing the name clash and this seems like the easiest way to fix this issue. Javascript generated by default backend
import * as Bar_1 from "../Bar/index.js";
import * as Effect_Console from "../Effect.Console/index.js";
var Foo = /* #__PURE__ */ (function () {
function Foo() {
};
Foo.value = new Foo();
return Foo;
})();
var Bar = /* #__PURE__ */ (function () {
function Bar() {
};
Bar.value = new Bar();
return Bar;
})();
var main = /* #__PURE__ */ Effect_Console.log(/* #__PURE__ */ Bar_1.placeHolder(3));
export {
Foo,
Bar,
main
};
purs-backend-es v1.4.2 used
Thanks! This is an easy bit of hygiene to forget.