Improperly widened cross-param loop/recur inference

Description

Inference for loop locals was improved with 1.10.516 using a simple algorithm that widens the initially inferred types by additionally considering the type inferred for recur parameters. [1]

If a recur parameter is a loop local, the 1.10.516 algorithm can infer an overly narrow type.

Consider the following simple example:

1 2 3 4 (loop [a "x" b "y"] (if (= a 1) (+ a 2) (recur b 1)))

This code will produce the correct result of 3, but it will emit a diagnostic that illustrates the problem:

1 WARNING: cljs.core/+, all arguments must be numbers, got [string number] instead at line 3

In this case, the loop local a is inferred to be of string type owing to the use of the un-widened type for b.

This can be more critical if the incorrectly inferred type cause incorrect code gen. For example, this should evaluate to :done, but instead doesn't halt

1 2 3 4 (loop [a false b false] (if a :done (recur b 0)))

[1] https://clojurescript.org/news/2019-01-31-release#_improved_loop_recur_inference

Environment

None

Status

Assignee

Mike Fikes

Reporter

Mike Fikes

Labels

None

Approval

None

Patch

None

Priority

Major