speculative

https://github.com/borkdude/speculative
FiVo 2020-01-24T12:13:46.003100Z

Hey there, I am running into some issues with speculative. Here is a small example to reproduce the issue

(set! *print-level* 10)
  (set! *print-length* 10)
  (require '[clojure.tools.analyzer.jvm :as ana])
  (require '[clojure.tools.deps.alpha.util.maven :as mvn])
  (require '[clojure.tools.deps.alpha.repl :refer [add-lib]]) ;; using the add-lib branch of tools.deps.alpha
  (require 'speculative.instrument) ;; without loading speculative it works
  (add-lib 'edos {:mvn/version "0.1.0-SNAPSHOT"})
  (ana/analyze-ns 'edos.core)
I am actually not using speculative in my project itself but rather analyzing some clojure code and one of the projects is speculative. I am doing something along the lines of
(require 'speculative.instrument) 
(ana/analyze-ns 'speculative.instrument)
(remove-ns 'speculative.instrument)
Is speculative like the clojure namespace and can not be removed?

borkdude 2020-01-24T12:23:04.004Z

> ;; without loading speculative it works what works?

borkdude 2020-01-24T12:23:15.004200Z

what is going wrong?

FiVo 2020-01-24T12:31:48.004600Z

@borkdude I am getting an ClassCastException

FiVo 2020-01-24T12:32:58.004900Z

Execution error (ClassCastException) at speculative.core/fn (core.cljc:274).
class clojure.lang.LazySeq cannot be cast to class java.util.Map$Entry (clojure.lang.LazySeq is in unnamed module of loader 'app'; java.util.Map$Entry is in module java.base of loader 'bootstrap')

FiVo 2020-01-24T12:33:49.005300Z

The last line of the first code snippet fails.

borkdude 2020-01-24T12:46:01.006400Z

speculative.core/fn ... hmm, not sure what that is and this is at core.cljc 274: https://github.com/borkdude/speculative/blob/master/src/speculative/core.cljc#L274 I have no clue if I have to go by just that snippet. Maybe you can post the entire exception somewhere?

borkdude 2020-01-24T12:47:22.007300Z

You can also try to call (speculative.instrument/unstrument) before removing the ns, maybe that helps

borkdude 2020-01-24T12:48:02.008100Z

remove-ns just deletes an in-memory object, but maybe spec instrumentation breaks when you try to do that

borkdude 2020-01-24T12:52:19.008400Z

also it seems you're using jdk11. do you get the same error with jdk8?

FiVo 2020-01-24T13:37:31.008700Z

It's the spec for map

FiVo 2020-01-24T13:37:45.009400Z

One of the key access fails

borkdude 2020-01-24T13:39:49.009900Z

can you put a println before that key access to see what is the value of args or ret?

FiVo 2020-01-24T13:50:44.010600Z

output of having added (println args ret)

[:seqable {:f #object[clojure.tools.analyzer.utils$dissoc_env 0x24f3d208 clojure.tools.analyzer.utils$dissoc_env@24f3d208], :colls [[{:env {:locals {}, :ns edos.core, :file jar:file:/home/fv/.m2/repository/edos/edos/0.1.0-SNAPSHOT/edos-0.1.0-SNAPSHOT.jar!/edos/core.cljc, :end-column 33, :column 1, :line 156, :once false, :end-line 162, :context :ctx/expr}, :form events, :name events, :variadic? true, :op :binding, :arg-id 0, :local :arg}]]}] ({:form events, :name events, :variadic? true, :op :binding, :arg-id 0, :local :arg})

borkdude 2020-01-24T13:53:31.011Z

so it seems ret here is a lazy-seq instead of a map-entry...

FiVo 2020-01-24T13:53:58.011300Z

no changes with respect to jdk8

FiVo 2020-01-24T14:01:54.012800Z

The edos lib I am analyzing depends on orchestra. Is this somehow incompatible? But more of a guess?

borkdude 2020-01-24T14:02:13.013200Z

ehm, yeah could very well be. can you try with plain spec?

borkdude 2020-01-24T14:02:35.013600Z

fwiw the specs in speculative are tested quite well, even using generative testing

borkdude 2020-01-24T14:04:26.013900Z

user=> (instance? clojure.lang.MapEntry (s/conform (s/or :seqable seqable? :transducer any?) (map inc [1 2 3])))
true
user=> (instance? clojure.lang.MapEntry (s/conform (s/or :seqable seqable? :transducer any?) (map inc)))
true

borkdude 2020-01-24T14:07:54.014400Z

@finn.volkel There was an issue about this exact problem here: https://github.com/jeaye/orchestra/issues/26

FiVo 2020-01-24T14:14:22.016Z

Ok. I am not familiar enough with spec. But why would this only surface if one adds speculative?

FiVo 2020-01-24T14:14:37.016500Z

What do you mean by "trying with plain spec"?

borkdude 2020-01-24T14:15:10.017200Z

because speculative has specs for clojure.core. if a library patches spec incorrectly, you'll get problems when you run core functions

borkdude 2020-01-24T14:15:55.018Z

what are you trying to accomplish? do you actually want to run with clojure.core specs instrumentation or do you just want to analyze code?

FiVo 2020-01-24T14:17:09.018800Z

Just analyze code and learn something along the way, but I get your point that issue is somewhere else.

borkdude 2020-01-24T14:17:33.019700Z

speculative.instrument is a "special" namespace that enables instrumentation when required.

borkdude 2020-01-24T14:17:54.020200Z

so it would be better to not require that namespace if you don't want instrumentation

FiVo 2020-01-24T14:17:55.020300Z

The main thing is I guess why speculative still shows up even if I used remove-ns

borkdude 2020-01-24T14:18:13.020800Z

because by then the namespace has already been loaded

borkdude 2020-01-24T14:19:39.021100Z

sorry my bad, it doesn't do that automatically, but only when you call i/instrument

borkdude 2020-01-24T14:20:30.022200Z

I think your workflow is as follows: you load all specs from speculative (by requiring speculative.instrument) and orchestra instruments them. Now when you call a core function, you run into a bug with orchestra.

borkdude 2020-01-24T14:20:38.022500Z

removing namespaces does not unstrument functions.

borkdude 2020-01-24T14:21:42.023200Z

but maybe you can get rid of the problem by calling i/unstrument before doing anything else after loading speculative.instrument

borkdude 2020-01-24T14:22:00.023500Z

(still not clear to me why you would load this in the first place)

FiVo 2020-01-24T14:26:56.026500Z

I ran into the issue because I analysed speculativewith analyze-ns itself. I am just pulling jars with the clojars api, analyze the namespaces and then remove them again. I guess the easiest thing is to blacklist speculative in this case. I don't know though if the problem will show up again if some project depends on speculative .

FiVo 2020-01-24T14:27:36.026800Z

thanks for the help anyway

borkdude 2020-01-24T14:29:06.027800Z

@finn.volkel but if you're not actively instrumenting the clojure.core specs from speculative, how could you run into a bug with one of them?

FiVo 2020-01-24T14:29:30.028100Z

I should maybe add that analyze-ns also evaluates the stuff in the namespace.

borkdude 2020-01-24T14:29:50.028300Z

even then

borkdude 2020-01-24T14:30:08.028600Z

does it execute snippets from comment sections?

borkdude 2020-01-24T14:30:50.029100Z

or does orchestra have a hook that once you enable instrumentation and a new spec gets loaded it's automatically instrumented? something fishy there

FiVo 2020-01-24T14:32:57.030100Z

The end of the stacktrace looks as follows:

[[clojure.core$key invokeStatic core.clj 1567]
  [clojure.core$key invoke core.clj 1567]
  [speculative.core$fn__106968 invokeStatic NO_SOURCE_FILE 102]
  [speculative.core$fn__106968 invoke NO_SOURCE_FILE 101]
  [clojure.spec.alpha$spec_impl$reify__2059 conform_STAR_ alpha.clj 923]
  [clojure.spec.alpha$conform invokeStatic alpha.clj 164]
  [clojure.spec.alpha$conform invoke alpha.clj 160]
  [orchestra.spec.test$spec_checking_fn$conform_BANG___391943 invoke test.clj 97]
  [orchestra.spec.test$spec_checking_fn$fn__391949 doInvoke test.clj 129]
  [clojure.lang.RestFn invoke RestFn.java 421]
  [clj_astminer.retrieve$analyze_from_clojar_map invokeStatic retrieve.clj 133]
don't know if that helps. Goes through orchestra as well as speculative

borkdude 2020-01-24T14:33:50.031Z

yeah, so somehow something has instrumented the specs in speculative.

FiVo 2020-01-24T14:33:59.031300Z

I don't think analyze-ns evaluates anything in the comments.

borkdude 2020-01-24T14:34:44.031900Z

maybe disable orchestra 🙂

borkdude 2020-01-24T14:35:08.032700Z

if you have a repro using vanilla clojure spec and speculative, an issue is welcome

borkdude 2020-01-24T14:35:27.033Z

which version of orchestra are you using?

FiVo 2020-01-24T14:36:29.033600Z

well orchestra is just loaded via edos which uses [orchestra "2018.09.10-1"]

borkdude 2020-01-24T14:36:40.034Z

ah, that explains it then

borkdude 2020-01-24T14:36:52.034300Z

it's an old version which still has that bug from the issue I linked to earlier

FiVo 2020-01-24T14:37:02.034500Z

I see thanks