Skip to content

Commit 179ee90

Browse files
mfikesswannodette
authored andcommitted
CLJS-3031: loop / recur inference, warnings not suppressed on initial pass
1 parent a8a8c83 commit 179ee90

File tree

2 files changed

+45
-8
lines changed

2 files changed

+45
-8
lines changed

src/main/clojure/cljs/analyzer.cljc

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
:cljs (:refer-clojure :exclude [macroexpand-1 ns-interns ensure js-reserved]))
1212
#?(:cljs (:require-macros
1313
[cljs.analyzer.macros
14-
:refer [no-warn wrapping-errors
14+
:refer [no-warn wrapping-errors with-warning-handlers
1515
disallowing-recur allowing-redef disallowing-ns*]]
1616
[cljs.env.macros :refer [ensure]]))
1717
#?(:clj (:require [cljs.util :as util :refer [ns->relpath topo-sort]]
@@ -722,6 +722,14 @@
722722
(doseq [handler *cljs-warning-handlers*]
723723
(handler warning-type env extra)))
724724

725+
(defn- accumulating-warning-handler [warn-acc]
726+
(fn [warning-type env extra]
727+
(when (warning-type *cljs-warnings*)
728+
(swap! warn-acc conj [warning-type env extra]))))
729+
730+
(defn- replay-accumulated-warnings [warn-acc]
731+
(run! #(apply warning %) @warn-acc))
732+
725733
(defn- error-data
726734
([env phase]
727735
(error-data env phase nil))
@@ -2323,20 +2331,30 @@
23232331
loop-lets (cond
23242332
(true? is-loop) *loop-lets*
23252333
(some? *loop-lets*) (cons {:params bes} *loop-lets*))
2326-
expr (analyze-let-body env context exprs recur-frames loop-lets)
2334+
;; Accumulate warnings for deferred replay iff there's a possibility of re-analyzing
2335+
warn-acc (when (and is-loop
2336+
(not widened-tags))
2337+
(atom []))
2338+
expr (if warn-acc
2339+
(with-warning-handlers [(accumulating-warning-handler warn-acc)]
2340+
(analyze-let-body env context exprs recur-frames loop-lets))
2341+
(analyze-let-body env context exprs recur-frames loop-lets))
23272342
children [:bindings :body]
23282343
nil->any (fnil identity 'any)]
23292344
(if (and is-loop
23302345
(not widened-tags)
23312346
(not= (mapv nil->any @(:tags recur-frame))
23322347
(mapv (comp nil->any :tag) bes)))
23332348
(recur encl-env form is-loop @(:tags recur-frame))
2334-
{:op op
2335-
:env encl-env
2336-
:bindings bes
2337-
:body (assoc expr :body? true)
2338-
:form form
2339-
:children children})))
2349+
(do
2350+
(when warn-acc
2351+
(replay-accumulated-warnings warn-acc))
2352+
{:op op
2353+
:env encl-env
2354+
:bindings bes
2355+
:body (assoc expr :body? true)
2356+
:form form
2357+
:children children}))))
23402358

23412359
(defmethod parse 'let*
23422360
[op encl-env form _ _]

src/test/clojure/cljs/analyzer_tests.clj

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1958,3 +1958,22 @@
19581958
(analyze ns-env
19591959
'(def *foo* 1)))
19601960
(is (string/starts-with? (first @ws) "*foo* not declared dynamic and thus"))))
1961+
1962+
(deftest test-cljs-3031
1963+
(let [ws (atom [])]
1964+
(a/with-warning-handlers [(collecting-warning-handler ws)]
1965+
(analyze ns-env
1966+
'(loop [x "a"]
1967+
(if (identical? "a" x)
1968+
(recur true)
1969+
(+ 3 x)))))
1970+
(is (= 1 (count @ws)))
1971+
(is (string/starts-with? (first @ws) "cljs.core/+, all arguments must be numbers, got [number #{boolean string}] instead")))
1972+
(let [ws (atom [])]
1973+
(a/with-warning-handlers [(collecting-warning-handler ws)]
1974+
(analyze ns-env
1975+
'(loop [x "a"]
1976+
(if (identical? "a" x)
1977+
(recur 1)
1978+
(+ 3 x)))))
1979+
(is (zero? (count @ws)))))

0 commit comments

Comments
 (0)