Running compiler twice on same input produces different results

I’ve been struggling (not for the first time) trying to get VSCode to play nicely with PureScript and have come to the realisation that the compiler itself, not just the VSCode plugin, exhibits behaviours that I do not understand.

% npx spago build
[bunch of files being compiled]
[1/1 UnusedName] src/Bindings2.purs:32:15

  32  dom (ρ :- x ↦ v)  = singleton x `union` dom ρ
  Name v was introduced but not used.
  in value declaration dom

           Src   Lib   All
Warnings   0/4   0     0/4
Errors     1     0     1  
[error] Failed to build.

That sounds reasonable to me. But if I repeat the same command:

% npx spago build
           Src   Lib   All
Warnings   0     0     0  
Errors     0     0     0  
[info] Build succeeded.

  dist/app/app.js  984.3kb

⚡ Done in 102ms
[info] Bundle succeeded and output file to dist/app/app.js

then the error goes away. Can anyone help me make sense of this? Do I need to rm -rf output each time to get a reproducible build?


The second time around the compiler will realize that the there is a generated output of this file and will not recompile it - that’s why you don’t see the warning again (which is somewhat nice if you have dependencies that yield errors ;))

So yes I guess you’ll have to clear the output (maybe there is a switch for spago or purs to recompile/clean but I’m not aware of one and I did not find one after a quick glance but I’m sure someone will give a hint if there is one)

PS: Maybe we can help with your issues inside VS - for me every issue I ever had went away after restarting the language server (there is a action inside vs.code for that) maybe together with doing spago build before (the plugin is very output/ dependent)

1 Like

Gotcha. For now I’ll manually clean the subfolder of output that corresponds to my application, as I can’t see a purs or spago option to clean/force compile. I keep getting caught out because my local compile is clean but there are errors when I push the changes to GitHub and my CI builds the application from scratch.

One of the (many) VSCode issues I’m facing is that errors don’t reliably appear inside VSCode (sometimes they are reported, sometimes not) so perhaps there is a similar thing going on there.

Yeah I can understand that - IMHO it’s not the worst idea to do a full rebuild before pushing to CI first.

After looking again at your output: What’s really puzzling me is why the error went away too - the warning is AFAIK normal but the error should not vanish like that - the file where the error was should be recompiled.
Maybe there is some strange error here but I guess you’d have to figure out a smallish reproducible instance of that and open an issue with it.

I cannot say that I’d seen this with spago/purs itself before.

1 Like

BTW the only thing I can remember that comes close is if I rename modules (where the old ones are very likely still in output after) - in this case I either delete the folder manually or kill output.

And one thing to remember as well: the language server will compile files for you (producing output-files) if you just use the editor/save your files.

1 Like

I’ll see if I can come up with a MWE.

1 Like

Actually yes I hope this is a bug as it is quite inconvenient to clean output each time. If I clean the whole folder, recompiling takes a long time. If I only delete my app folders then I need to delete one folder for each top-level module.

It appears that you are using purescript-psa with its --strict flag enabled, which takes warnings like UnusedName and reports them as errors. Since the compiler doesn’t recompile the code on the second run, the warning isn’t found again and thus doesn’t fail the command.

However, I don’t understand how that’s possible if you are just running npx spago build as opposed to npx spago build --purs-args "--strict", which passes the --strict flag to psa.


Ah, you’re right – I had a more complicated command-line so I verified that I could reproduce the problem with npm spago build and then edited my example to include the simpler command-line. I didn’t notice that the compiler’s output also changed (from “error” to “warning”) so I didn’t replace the output as well as the command-line. Sorry about that.

Ok, so it sounds like I can’t use --strict if I want the compiler to behave like a pure function (so that my local compile is consistent with my CI).

1 Like

It’s maybe stupid but a way around could be to remove the output with psa if an error was reported? (Something you could not do by yourself but maybe @JordanMartinez has some input to this?)

1 Like

If you’re using purescript-psa (to give you the --strict flag), then you can also use the --stash flag to make it “remember” warnings from one invocation to the next. The only issue here is you can get messed up by the language server in the IDE by this as Carsten points out, because the IDE can end up compiling your files for you and messing up your stash of warnings.

One trick that I’ve done is to point the language server at a different output folder (so in my VS Code settings, I change the PureScript output directory to “.ide_modules”) while leaving my normal build command still pointed to the “output” folder. That gets around the issue where the IDE is messing up your stash, and you consistently get the same warnings on every invocation of spago build, but it can also get a little confusing where your IDE can get out of sync. I have a second npm script to do a full spago build pointed to the “.ide_modules” folder just to run in case the IDE is weirding out.

You might also have some luck by changing the PureScript “build command” setting in VS Code to also use --strict, which would make sure that your IDE isn’t compiling a file that fails to compile by just a spago build


These are useful tips, thanks. It sounds like it would be nice (and a whole lot easier) if the compiler simply treated warnings as bona-fide outputs (in the sense of being stateless/functional with respect to warnings as well as errors).

See Compiler should persist warnings · Issue #2308 · purescript/purescript · GitHub

We want to, but it needs someone to implement it.

1 Like