1.8.0/1.9.0/1.10.0-RC1 -> 1.10.0 regression: Extending protocols with metadata / datafy combined with macros/symbols

2019-02-28 Thread Alex Miller
Please file a jira with this info at https://dev.clojure.org/jira/browse/CLJ

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


1.8.0/1.9.0/1.10.0-RC1 -> 1.10.0 regression: Extending protocols with metadata / datafy combined with macros/symbols

2019-02-27 Thread 'somewhat-functional-programmer' via Clojure
I finally moved one of my clojure projects from 1.10.0-RC1 to 1.10.0 and 
encountered some very strange behaviour.  Code that had previously compiled 
fine under 1.8.0, 1.9.0, and 1.10.0-RC1 no longer compiled under 1.10.0 with 
the following error:

Execution error (IllegalArgumentException) at bug.core$eval7278/ 
(form-init3641919424619236070.clj:49).
No matching ctor found for class clojure.reflect$typesym$fn__11912

Basically, symbols used inside of macros that had the new datafy protocol added 
to their metadata caused this failure.

My use case that lead my to having this issue in the first place:
  - I use macros in my project to help wrap Java APIs, or convert Java objects 
to/from clojure data structures.
  - In these macros I often use clojure.reflect to aid in adding Java type tags 
to the code I am generating.
  - New in 1.10.0, the symbols you get back from clojure.reflect now contain a 
datafy protocol implementation in their metadata.
  (Note that in 1.10.0-RC1 there was no datafy protocol implementation 
returned in the metadata)
  - The strange exception above occurs when the returned symbol from 
clojure.reflect is used within a macro

I narrowed down a minimalist test case to help illustrate what I am saying:

(require 'clojure.reflect)

;; returns the symbol int, which now in 1.10.0 includes a datafy protocol 
implementation in the metadata of the returned symbol
(defn example-reflect-type-return []
  (->>
   java.lang.String
   (clojure.reflect/reflect)
   (:members)
   (filter #(= (:name %) 'length))
   (first)
   (:return-type)))

;; this macro fails on 1.10.0, but works in 1.10.0-RC1, 1.9.0, and 1.8.0
(defmacro has-the-bug []
  `{:should-have-int-val '~(example-reflect-type-return)})

;; this macro works in 1.10.0, 1.9.0, and 1.8.0
;;  (Basically I had to manually remove the datafy protocol implementation from 
the symbol's metadata)
(defmacro this-works []
  `{:should-have-int-val '~(with-meta
 (example-reflect-type-return)
 nil)})

Works under 1.10.0, 1.9.0, and 1.8.0:
(this-works) => {:should-have-int-val int}

Fails /only/ under 1.10.0:
(has-the-bug)

Failure error:
#error {
:cause "No matching ctor found for class clojure.reflect$typesym$fn__11912"
:via
[{:type java.lang.ExceptionInInitializerError
   :message nil
   :at [jdk.internal.reflect.NativeConstructorAccessorImpl newInstance0 
"NativeConstructorAccessorImpl.java" -2]}
  {:type java.lang.IllegalArgumentException
   :message "No matching ctor found for class clojure.reflect$typesym$fn__11912"
   :at [clojure.lang.Reflector invokeConstructor "Reflector.java" 288]}]
:trace
[[clojure.lang.Reflector invokeConstructor "Reflector.java" 288]
  [clojure.lang.LispReader$EvalReader invoke "LispReader.java" 1317]
  [clojure.lang.LispReader$DispatchReader invoke "LispReader.java" 853]
  [clojure.lang.LispReader read "LispReader.java" 285]
  [clojure.lang.LispReader read "LispReader.java" 216]
  [clojure.lang.LispReader read "LispReader.java" 205]
  [clojure.lang.RT readString "RT.java" 1874]
  [clojure.lang.RT readString "RT.java" 1869]
  [bug.core$eval7278  "form-init3641919424619236070.clj" 49]
  [jdk.internal.reflect.NativeConstructorAccessorImpl newInstance0 
"NativeConstructorAccessorImpl.java" -2]
  [jdk.internal.reflect.NativeConstructorAccessorImpl newInstance 
"NativeConstructorAccessorImpl.java" 62]
  [jdk.internal.reflect.DelegatingConstructorAccessorImpl newInstance 
"DelegatingConstructorAccessorImpl.java" 45]
  [java.lang.reflect.Constructor newInstance "Constructor.java" 488]
  [java.lang.Class newInstance "Class.java" 560]
  [clojure.lang.Compiler$ObjExpr eval "Compiler.java" 4996]
  [clojure.lang.Compiler eval "Compiler.java" 7175]
  [clojure.lang.Compiler eval "Compiler.java" 7131]
  [clojure.core$eval invokeStatic "core.clj" 3214]
  [clojure.core$eval invoke "core.clj" 3210]
  [clojure.main$repl$read_eval_print__9068$fn__9071 invoke "main.clj" 414]
  [clojure.main$repl$read_eval_print__9068 invoke "main.clj" 414]
  [clojure.main$repl$fn__9077 invoke "main.clj" 435]
  [clojure.main$repl invokeStatic "main.clj" 435]
  [clojure.main$repl doInvoke "main.clj" 345]
  [clojure.lang.RestFn invoke "RestFn.java" 1523]
  [clojure.tools.nrepl.middleware.interruptible_eval$evaluate$fn__1115 invoke 
"interruptible_eval.clj" 87]
  [clojure.lang.AFn applyToHelper "AFn.java" 152]
  [clojure.lang.AFn applyTo "AFn.java" 144]
  [clojure.core$apply invokeStatic "core.clj" 665]
  [clojure.core$with_bindings_STAR_ invokeStatic "core.clj" 1973]
  [clojure.core$with_bindings_STAR_ doInvoke "core.clj" 1973]
  [clojure.lang.RestFn invoke "RestFn.java" 425]
  [clojure.tools.nrepl.middleware.interruptible_eval$evaluate invokeStatic 
"interruptible_eval.clj" 85]
  [clojure.tools.nrepl.middleware.interruptible_eval$evaluate invoke 
"interruptible_eval.clj" 55]
  
[clojure.tools.nrepl.middleware.interruptible_eval$interruptible_eval$fn__1160$fn__1163
 invoke "interruptible_eval.clj" 222