Skip to content

Commit fa041d9

Browse files
thhellerswannodette
authored andcommitted
CLJS-1992: declare after def should have no effect
1 parent 114a528 commit fa041d9

File tree

2 files changed

+68
-51
lines changed

2 files changed

+68
-51
lines changed

src/main/clojure/cljs/analyzer.cljc

Lines changed: 56 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1346,8 +1346,6 @@
13461346
*file-defs*
13471347
(get @*file-defs* sym))
13481348
(warning :redef-in-file env {:sym sym :line (:line v)})))
1349-
(when *file-defs*
1350-
(swap! *file-defs* conj sym))
13511349
(let [env (if (or (and (not= ns-name 'cljs.core)
13521350
(core-name? env sym))
13531351
(some? (get-in @env/*compiler* [::namespaces ns-name :uses sym])))
@@ -1380,55 +1378,62 @@
13801378
(when (and (not (-> sym meta :declared))
13811379
(and (true? (:fn-var v)) (not fn-var?)))
13821380
(warning :fn-var env {:ns-name ns-name :sym sym})))
1383-
(swap! env/*compiler* assoc-in [::namespaces ns-name :defs sym]
1384-
(merge
1385-
{:name var-name}
1386-
;; remove actual test metadata, as it includes non-valid EDN and
1387-
;; cannot be present in analysis cached to disk - David
1388-
(cond-> sym-meta
1389-
(:test sym-meta) (assoc :test true))
1390-
{:meta (-> sym-meta
1391-
(dissoc :test)
1392-
(update-in [:file]
1393-
(fn [f]
1394-
(if (= (-> env :ns :name) 'cljs.core)
1395-
"cljs/core.cljs"
1396-
f))))}
1397-
(when doc {:doc doc})
1398-
(when const?
1399-
(let [const-expr
1400-
(binding [*passes* (conj *passes* (replace-env-pass {:context :expr}))]
1401-
(analyze env (:init args)))]
1402-
(when (constant-value? const-expr)
1403-
{:const-expr const-expr})))
1404-
(when (true? dynamic) {:dynamic true})
1405-
(source-info var-name env)
1406-
;; the protocol a protocol fn belongs to
1407-
(when protocol
1408-
{:protocol protocol})
1409-
;; symbol for reified protocol
1410-
(when-let [protocol-symbol (-> sym meta :protocol-symbol)]
1411-
{:protocol-symbol protocol-symbol
1412-
:info (-> protocol-symbol meta :protocol-info)
1413-
:impls #{}})
1414-
(when fn-var?
1415-
(let [params (map #(vec (map :name (:params %))) (:methods init-expr))]
1416-
(merge
1417-
{:fn-var (not (:macro sym-meta))
1418-
;; protocol implementation context
1419-
:protocol-impl (:protocol-impl init-expr)
1420-
;; inline protocol implementation context
1421-
:protocol-inline (:protocol-inline init-expr)}
1422-
(if-some [top-fn-meta (:top-fn sym-meta)]
1423-
top-fn-meta
1424-
{:variadic (:variadic init-expr)
1425-
:max-fixed-arity (:max-fixed-arity init-expr)
1426-
:method-params params
1427-
:arglists (:arglists sym-meta)
1428-
:arglists-meta (doall (map meta (:arglists sym-meta)))}))))
1429-
(if (and fn-var? (some? tag))
1430-
{:ret-tag tag}
1431-
(when tag {:tag tag}))))
1381+
1382+
;; declare must not replace any analyzer data of an already def'd sym
1383+
(when (or (nil? (get-in @env/*compiler* [::namespaces ns-name :defs sym]))
1384+
(not (:declared sym-meta)))
1385+
(when *file-defs*
1386+
(swap! *file-defs* conj sym))
1387+
1388+
(swap! env/*compiler* assoc-in [::namespaces ns-name :defs sym]
1389+
(merge
1390+
{:name var-name}
1391+
;; remove actual test metadata, as it includes non-valid EDN and
1392+
;; cannot be present in analysis cached to disk - David
1393+
(cond-> sym-meta
1394+
(:test sym-meta) (assoc :test true))
1395+
{:meta (-> sym-meta
1396+
(dissoc :test)
1397+
(update-in [:file]
1398+
(fn [f]
1399+
(if (= (-> env :ns :name) 'cljs.core)
1400+
"cljs/core.cljs"
1401+
f))))}
1402+
(when doc {:doc doc})
1403+
(when const?
1404+
(let [const-expr
1405+
(binding [*passes* (conj *passes* (replace-env-pass {:context :expr}))]
1406+
(analyze env (:init args)))]
1407+
(when (constant-value? const-expr)
1408+
{:const-expr const-expr})))
1409+
(when (true? dynamic) {:dynamic true})
1410+
(source-info var-name env)
1411+
;; the protocol a protocol fn belongs to
1412+
(when protocol
1413+
{:protocol protocol})
1414+
;; symbol for reified protocol
1415+
(when-let [protocol-symbol (-> sym meta :protocol-symbol)]
1416+
{:protocol-symbol protocol-symbol
1417+
:info (-> protocol-symbol meta :protocol-info)
1418+
:impls #{}})
1419+
(when fn-var?
1420+
(let [params (map #(vec (map :name (:params %))) (:methods init-expr))]
1421+
(merge
1422+
{:fn-var (not (:macro sym-meta))
1423+
;; protocol implementation context
1424+
:protocol-impl (:protocol-impl init-expr)
1425+
;; inline protocol implementation context
1426+
:protocol-inline (:protocol-inline init-expr)}
1427+
(if-some [top-fn-meta (:top-fn sym-meta)]
1428+
top-fn-meta
1429+
{:variadic (:variadic init-expr)
1430+
:max-fixed-arity (:max-fixed-arity init-expr)
1431+
:method-params params
1432+
:arglists (:arglists sym-meta)
1433+
:arglists-meta (doall (map meta (:arglists sym-meta)))}))))
1434+
(if (and fn-var? (some? tag))
1435+
{:ret-tag tag}
1436+
(when tag {:tag tag})))))
14321437
(merge
14331438
{:env env
14341439
:op :def

src/test/clojure/cljs/analyzer_tests.clj

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -709,6 +709,18 @@
709709
(let [form (with-meta 'js/goog.DEBUG {:tag 'boolean})]
710710
(is (= (-> (ana-api/analyze (a/empty-env) form) :tag) 'boolean))))
711711

712+
(deftest test-cljs-1992 ;; declare after def should have no effect
713+
(let [test-cenv (e/default-compiler-env)]
714+
(e/with-compiler-env test-cenv
715+
(a/analyze-form-seq
716+
'[(ns test.cljs-1992)
717+
(defn test-fn [a b c] :foo)
718+
(declare test-fn)]
719+
))
720+
721+
(let [def (get-in @test-cenv [::a/namespaces 'test.cljs-1992 :defs 'test-fn])]
722+
(is (:fn-var def)))))
723+
712724
(comment
713725
(binding [a/*cljs-ns* a/*cljs-ns*]
714726
(a/no-warn

0 commit comments

Comments
 (0)