*Description*
If you instrument a function, you may get a spec error like the following:
(defn f [x] (inc x))
(s/fdef f
  :args (s/cat :x (s/and integer? even?))
  :ret (s/and integer? odd?))
(t/instrument)
(f 3)
;; ExceptionInfo Call to #'user/f did not conform to spec:
;; In: [0] val: 3 fails at: [:args :x] predicate: even?
;; :clojure.spec.alpha/spec  #object[clojure.spec.alpha$regex_spec_impl$reify__1200
 0x19b3f9a "clojure.spec.alpha$regex_spec_impl$reify__1200@19b3f9a"]
;; :clojure.spec.alpha/value  (3)
;; :clojure.spec.alpha/args  (3)
;; :clojure.spec.alpha/failure  :instrument
;; :clojure.spec.test.alpha/caller  {:file "form-init3240393046310519022.clj", :lin
e 1, :var-scope user/eval1413}
;; clojure.core/ex-info (core.clj:4725)
(ex-data *e) 
;; {:clojure.spec.alpha/problems
;;   [{:path [:args :x],
;;     :pred clojure.core/even?,
;;     :val 3,
;;     :via [],
;;     :in [0]}],
;;  :clojure.spec.alpha/spec #object[clojure.spec.alpha$regex_spec_impl$reify__1200 0x19b3f9a "clojure.spec.alpha$regex_spec_impl$reify__1200@19b3f9a"],
;;  :clojure.spec.alpha/value (3),
;;  :clojure.spec.alpha/args (3),
;;  :clojure.spec.alpha/failure :instrument,
;;  :clojure.spec.test.alpha/caller {:file "form-init3240393046310519022.clj", :line 1, :var-scope user/eval1413}} 
As you can see,
- the explain-data has a regex (ie.  the spec for the args of f) in it as {{::s/spec}}
- each problem contains {{:args}} in their {{:path}}
These facts can cause a confusion to spec error reporters because the spec for the args of {{f}} ({{(s/and integer? even?)}}) has no subspec corresponding to the key {{:args}} (I believe {{:path}} should only contains keys that is a clue to indicate which subspec to be chosen from a spec).
*Possible resolutions*
To resolve this confusing situation and improve the consistency of explain-data for instrument check, I think there are two options as follows:
- *Solution 1.* removing {{:args}} from {{:path}}
- *Solution 2.* modifying explain-data for instrument check so that they have fspec (rather than {{:args}} of it) as {{::s/spec}}
Personally, I prefer *Solution 2.* since adding fspec in explain-data makes it possible to provide richer error information to {{\*explain-out\*}} implementors.
The same goes for {{macroexpand-check}}.