Eliminate dead code for clj-nil and types that don't admit falsey


If the test of an if has a tag of clj-nil then the else branch will always be taken so we can replace such code with the else branch.

Likewise if the test of an if has a tag that cannot yield a falsey value (for example #{number string}), then the then branch will always be taken and we can replace such code with the then branch.

We already have dead code elimination for constants, this ticket asks that we extend it to cases where we can definitely determine a branch will be taken based on inferred types.




Mike Fikes
August 22, 2019, 9:30 PM
Mike Fikes
August 22, 2019, 9:59 PM

In Canary, Planck was one of the failures, but this can be reproduced directly in a plain Node REPL when CLJS-2875-3.patch is applied:

Mike Fikes
August 23, 2019, 1:14 AM

In Canary, a test in Coal Mine is one of the failures. It appears to be a consequence of an improperly inferred clj-nil type for a loop local (as a result of ) causing the optimization in this ticket to result in bad code gen. (In other words, not a defect in this patch.)

Mike Fikes
August 25, 2019, 2:35 PM

The ns-publics issue is related to the use of reify inside cljs.core/nil-iter's definition and incorrect type information being established: A Var is created, which is tagged as being of function type, when in fact the Var's value is nil. Then when the var special is applied to the Var's symbol, there is a bit of code that would normally conditionally include test meta in the generated Var:


but, since the type tag on the Var is (incorrectly) function, the optimization in this ticket causes unconditional code to be generated, which derails when the cljs$lang$test field is extracted from the nil Var value.

A simple way to repro what is being describe above is to force a REPL, which would return a Var for a def, to fail to do so by tagging the Var with a type and then violating that type hint by initializing it with nil:

See CLJS-3160.


Mike Fikes


Mike Fikes






Code and Test