Pauan/rollup-plugin-purs

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?

Pauan commented

@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?

Pauan commented

@matthewleon I think there's only three situations where this could be a problem:

  1. 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)

  2. The same as 1, but using an unsafe function in PureScript (which are rarely used)

  3. 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.