Skip to content

Commit 8957a93

Browse files
committed
CLJ-1180 Resolve classname for tag metadata on defprotocol
Signed-off-by: Alex Miller <alex.miller@cognitect.com>
1 parent fc98f92 commit 8957a93

File tree

3 files changed

+40
-7
lines changed

3 files changed

+40
-7
lines changed

src/clj/clojure/core_deftype.clj

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -652,7 +652,15 @@
652652
[opts sigs]))
653653
sigs (when sigs
654654
(reduce1 (fn [m s]
655-
(let [name-meta (meta (first s))
655+
(let [tag-to-class (fn [tag]
656+
(if-let [c (and (instance? clojure.lang.Symbol tag)
657+
(= (.indexOf (.getName ^clojure.lang.Symbol tag) ".") -1)
658+
(not (contains? '#{int long float double char short byte boolean void
659+
ints longs floats doubles chars shorts bytes booleans objects} tag))
660+
(resolve tag))]
661+
(symbol (.getName c))
662+
tag))
663+
name-meta (update-in (meta (first s)) [:tag] tag-to-class)
656664
mname (with-meta (first s) nil)
657665
[arglists doc]
658666
(loop [as [] rs (rest s)]

test/clojure/test_clojure/protocols.clj

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -47,13 +47,13 @@
4747
(deftest protocols-test
4848
(testing "protocol fns have useful metadata"
4949
(let [common-meta {:ns (find-ns 'clojure.test-clojure.protocols.examples)
50-
:protocol #'ExampleProtocol}]
51-
(are [m f] (= (merge (quote m) common-meta)
50+
:protocol #'ExampleProtocol :tag nil}]
51+
(are [m f] (= (merge common-meta m)
5252
(meta (var f)))
53-
{:name foo :arglists ([a]) :doc "method with one arg"} foo
54-
{:name bar :arglists ([a b]) :doc "method with two args"} bar
55-
{:name baz :arglists ([a] [a b]) :doc "method with multiple arities" :tag String} baz
56-
{:name with-quux :arglists ([a]) :doc "method name with a hyphen"} with-quux)))
53+
{:name 'foo :arglists '([a]) :doc "method with one arg"} foo
54+
{:name 'bar :arglists '([a b]) :doc "method with two args"} bar
55+
{:name 'baz :arglists '([a] [a b]) :doc "method with multiple arities" :tag 'java.lang.String} baz
56+
{:name 'with-quux :arglists '([a]) :doc "method name with a hyphen"} with-quux)))
5757
(testing "protocol fns throw IllegalArgumentException if no impl matches"
5858
(is (thrown-with-msg?
5959
IllegalArgumentException
@@ -682,3 +682,26 @@
682682
(reduce-kv #(assoc %1 %3 %2)
683683
{}
684684
(seq {:a 1 :b 2})))))
685+
686+
(defn aget-long-hinted ^long [x] (aget (longs-hinted x) 0))
687+
688+
(deftest test-longs-hinted-proto
689+
(is (= 1
690+
(aget-long-hinted
691+
(reify LongsHintedProto
692+
(longs-hinted [_] (long-array [1])))))))
693+
694+
;; CLJ-1180 - resolve type hints in protocol methods
695+
696+
(import 'clojure.lang.ISeq)
697+
(defprotocol P
698+
(^ISeq f [_]))
699+
(ns clojure.test-clojure.protocols.other
700+
(:use clojure.test))
701+
(defn cf [val]
702+
(let [aseq (clojure.test-clojure.protocols/f val)]
703+
(count aseq)))
704+
(extend-protocol clojure.test-clojure.protocols/P String
705+
(f [s] (seq s)))
706+
(deftest test-resolve-type-hints-in-protocol-methods
707+
(is (= 4 (clojure.test-clojure.protocols/f "test"))))

test/clojure/test_clojure/protocols/examples.clj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,5 @@
1717
(hinted [^int i])
1818
(hinted [^String s]))
1919

20+
(defprotocol LongsHintedProto
21+
(^longs longs-hinted [_]))

0 commit comments

Comments
 (0)