clojure-spec 2019-08-02

I am getting this exception "Additional data must be non-nil." when using st/check on my function. I have gotten this before and then it mysteriously went away. I am now getting it constantly and am curious what is going on. It is coming from these Spec lines: https://github.com/clojure/spec.alpha/blob/5228bb75fa10b7b13ea088d84f4d031cce74a969/src/main/clojure/clojure/spec/test/alpha.clj#L278-L284.

if you have a reproducible example case, please paste it @kenny

Working on that. It's pretty coupled to this code but I should be able to pull something out.

cool -- thanks!

this has been reported before, but AFAIK there's not a deterministically reproducible case

Hopefully I can get one! It's definitely reproducible for me right now.

Alex Miller (Clojure team) 2019-08-02T16:49:17.147400Z

the error occurs when you try to create an ex-info with nil data. the case where this happens here is when spec validation fails, but explain-data succeeds (which ideally should never happen). usually, this is a bug in spec. occasionally, it's a bad predicate in user code.

This error is quite confusing. Seems like a bug either way 😉

Alex Miller (Clojure team) 2019-08-02T16:50:13.147900Z

well the error should never happen

right, it's an invariant violation

haha, the best kind of bugs

I pulled some code out to get a repro case and was running st/check on it. It failed with a regular specification error. I thought that was weird because it hasn't failed yet. Turned on instrumentation and ran again and got the "Additional data must be non-nil." message. May be related to instrument.

Alex Miller (Clojure team) 2019-08-02T16:57:57.151600Z

this won't help you, but I've made a change in spec-alpha2 to better report this case

Alright, here's a repro: https://gist.github.com/kennyjwilli/f324b94eaadc404cb72fdfe41067b469. Not minimal but I've gotta go make some food. Within 3 or so runs of (st/check formula->fn)`, it will get the exception.

Alex Miller (Clojure team) 2019-08-02T18:23:45.154500Z

so I misdiagnosed above - even more subtle... s/conform and s/valid? are returning different answers when run on the same input

Alex Miller (Clojure team) 2019-08-02T18:24:03.154900Z

which is because the spec is an fspec, which generates its own source of random inputs

Alex Miller (Clojure team) 2019-08-02T18:25:11.155600Z

this is a known issue and generally we've been suggesting people don't use fspec because it has all these unexpected consequences

fspec has proven to be quite valuable though. What is the alternative? Just fn?

Alex Miller (Clojure team) 2019-08-02T18:56:45.156600Z

ifn?

Alex Miller (Clojure team) 2019-08-02T18:57:07.157Z

unfortunately it's not even easy to override in a spec alias or anything

Won't that just generate any old function during gen tests and pass it to my function?

Alex Miller (Clojure team) 2019-08-02T19:07:50.158100Z

yes, it is significantly harder to use it in check. I'm not saying any of this is good.

Alex Miller (Clojure team) 2019-08-02T19:09:02.158900Z

this is a known area I'm hoping to spend some rethink time on in spec 2, but we're going to overhaul the function return value stuff first

Oh ok. Any workaround for now to avoid this error?

Alex Miller (Clojure team) 2019-08-02T19:21:38.160100Z

I don't think I have any simple advice for you, other than to remove your :ret spec :(

:ret on the fspec of the top level fn?

Alex Miller (Clojure team) 2019-08-02T19:27:05.161Z

no, the :ret on the fdef

Alex Miller (Clojure team) 2019-08-02T19:27:12.161200Z

that is an fspec

I was trying to add some gen improvements to clojure.spec.alpha but I cannot load the ns in a REPL. I get

CompilerException java.lang.Exception: #object[clojure.spec.alpha$and_spec_impl$reify__2171 0x4a332076 "clojure.spec.alpha$and_spec_impl$reify__2171@4a332076"] is not a fn, expected predicate fn, compiling:(/home/kenny/Forks/spec.alpha/src/main/clojure/clojure/spec/alpha.clj:78:1) 
Is there some magic that needs to happen to have a REPL with Spec itself?

hi gents! How I can define spec of vector where I know only first element and don’t know length of vector. For example [:in 1 2 3 4]

it would be great to use something like

(s/tuple #{:in :or} & nat-int?)

Alex Miller (Clojure team) 2019-08-02T20:58:42.165Z

(s/cat :in #{:in :or} :nums (s/* nat-int?))

Alex Miller (Clojure team) 2019-08-02T20:59:00.165300Z

this is exactly the job the regex ops are made for

I see, thank you!