further documentation of assumePureVars
matthewleon opened this issue · 4 comments
Could you give an example/counterexample in the documentation for what you mean by variable assignment being "pure"?
Also, I quickly browsed through the code and was unable to find any uses of it, just mentions in the TODOs. Perhaps you could give an example of the kind of optimization setting assumePureVars
to true
permits?
@matthewleon PureScript uses curried functions, and often times a function is created by calling an existing function:
function add(x) {
return function (y) {
return x + y;
};
}
// add5 is a function that adds 5 to its argument
var add5 = add(5);
In the above example, even if add
and add5
are not used, they will be included in the bundle, because rollup-plugin-purs
does not know whether the add(5)
call has side effects or not, so it errs on the side of caution and leaves it in.
If you use assumePureVars
, then rollup-plugin-purs
can assume that the add(5)
call is pure, and therefore add5
and add
will be correctly removed.
Essentially, when you use var foo = ...
it assumes that ...
is pure. Right now this only affects the dead code elimination.
For a concrete example of this problem, see #8. The unsafeCompare
, EQ
, GT
, LT
, unsafeCompareImpl__private_do_not_use_export__0
, and unsafeCompareImpl__private_do_not_use_export__0$0__private_do_not_use_uncurried__5__1$0
variables are included, even though none of them are used.
And this was just from a tiny "hello world" program: the problem is even worse in a big program.
The psc-bundle
program already assumes purity, so if your code works with psc-bundle
then it should also work with assumePureVars
You can also try running rollup-plugin-purs
with and without assumePureVars
, and then run a diff between the results. That gives some insight into how big of a difference it makes.
The assumePureVars
setting is used here.
Thank you very much for a fantastic, and thorough, explanation. Is it worth paraphrasing this and including it in the docs somewhere?
Would also be nice to document any potential gotchas with this. I naively assume that practices that would break this would be either a) abusing the FFI or b) abusing any functions in the standard library marked as "unsafe". Is there anything else one should avoid?
@matthewleon I think there's only three situations where this could be a problem:
-
Doing weird stuff with the FFI (e.g. calling an impure function, assigning the result to a variable, never using that variable, and expecting the impure function to still be called)
-
The same as 1, but using an unsafe function in PureScript (which are rarely used)
-
The same as 1, except you are importing a JavaScript library (e.g. using npm / bower)
In general it shouldn't cause any problems, especially for PureScript code, but it might be a problem when using a JavaScript library.
I updated the README to give an explanation for assumePureVars
Also, if you are using the uncurrying optimization, then dead code elimination works fine with currying, even when not using assumePureVars
.
But it still includes _LT2
, _GT2
, and _EQ2
, because of the .value
assignment (which is impure). So assumePureVars
is currently needed to solve cases like that.
If the PureScript compiler changed its code output, then maybe assumePureVars
wouldn't be needed anymore.
Alternatively, I can try to make the pure detection smarter in rollup-plugin-purs
, which is also doable.