Skip to content

Commit 3993863

Browse files
samumbachdnolen
authored andcommitted
CLJS-1477: Do not attempt to resolve "native" type symbols
- The analyzer tags expressions with "native" JavaScript types with unqualified symbols (e.g., `'string`, `'array`). - When the compiler encounters a protocol method invocation, it attempts to resolve the first argument's type tag to locate the protocol implementation. This does not behave as expected for these native types (see also `cljs.core/base-type`): - `clj-nil` - `number` - `string` - `boolean` - `function` - `object` - `array` - This could similarly affect other type tags: - `any` - `clj` - `clj-or-nil` - `seq` - `not-native` - `long` - `double` Add tests demonstrating unexpected `undeclared Var` warning
1 parent d63c223 commit 3993863

File tree

2 files changed

+47
-2
lines changed

2 files changed

+47
-2
lines changed

src/main/clojure/cljs/compiler.cljc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -930,7 +930,7 @@
930930
(or (= protocol tag)
931931
;; ignore new type hints for now - David
932932
(and (not (set? tag))
933-
(not ('#{any clj clj-or-nil} tag))
933+
(not ('#{any clj clj-or-nil clj-nil number string boolean function object array} tag))
934934
(when-let [ps (:protocols (ana/resolve-existing-var (dissoc env :locals) tag))]
935935
(ps protocol)))))))
936936
opt-not? (and (= (:name info) 'cljs.core/not)

src/test/clojure/cljs/compiler_tests.clj

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@
33
(:require [cljs.analyzer :as ana]
44
[cljs.compiler :as comp]
55
[cljs.env :as env]
6-
[cljs.util :as util])
6+
[cljs.util :as util]
7+
[cljs.tagged-literals :as tags])
78
(:import [java.io File]))
89

910
(def aenv (assoc-in (ana/empty-env) [:ns :name] 'cljs.user))
@@ -87,6 +88,50 @@
8788
'(defn foo ([a]) ([a b])))))
8889
)
8990

91+
(defn capture-warnings* [f]
92+
(let [capture (atom [])
93+
tracker (fn [warning-type env & [extra]]
94+
(when (warning-type ana/*cljs-warnings*)
95+
(let [err (ana/error-message warning-type extra)
96+
msg (ana/message env (str "WARNING: " err))]
97+
(swap! capture conj [warning-type msg]))))]
98+
(ana/with-warning-handlers [tracker]
99+
(f))
100+
@capture))
101+
102+
(defmacro capture-warnings [& body]
103+
`(capture-warnings* (fn [] ~@body)))
104+
105+
(deftest no-warn-on-emit-invoke-protocol-method
106+
(let [define-foo #(assoc-in % [::ana/namespaces 'cljs.user :defs 'foo]
107+
{:ns 'cljs.user
108+
:name 'cljs.user/foo
109+
:fn-var true
110+
:method-params '([x])
111+
:protocol 'cljs.user/Foo})
112+
aenv-with-foo (define-foo aenv)
113+
cenv-with-foo (define-foo @cenv)]
114+
(binding [ana/*cljs-static-fns* true]
115+
(are [form]
116+
(empty?
117+
(capture-warnings
118+
(env/with-compiler-env (atom cenv-with-foo)
119+
(with-out-str
120+
(comp/emit
121+
(ana/analyze aenv-with-foo form))))))
122+
123+
'(cljs.user/foo nil)
124+
'(cljs.user/foo 0)
125+
'(cljs.user/foo (inc 0))
126+
'(cljs.user/foo "")
127+
'(cljs.user/foo true)
128+
'(cljs.user/foo false)
129+
'(cljs.user/foo (nil? nil))
130+
'(cljs.user/foo (fn [x] x))
131+
`(cljs.user/foo ~(tags/->JSValue {}))
132+
`(cljs.user/foo ~(tags/->JSValue []))
133+
'(cljs.user/foo (make-array 0))))))
134+
90135
;; CLJS-1225
91136

92137
(comment

0 commit comments

Comments
 (0)