Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fails to report spec error when a non-fn IFn value doesn't conform to a fspec #41

Closed
athos opened this issue Oct 30, 2017 · 5 comments
Closed
Labels

Comments

@athos
Copy link

athos commented Oct 30, 2017

Repro:

=> (ex/expound (s/fspec :args (s/cat :x int?) :ret int?) :inc)

clojure.lang.ExceptionInfo: Cannot convert path. This can be caused by using conformers to transform values, which is not supported in Expound
=> (ex/expound (s/fspec :args (s/cat :x int?) :ret int?) 'inc)

clojure.lang.ExceptionInfo: Cannot convert path. This can be caused by using conformers to transform values, which is not supported in Expound
=> (ex/expound (s/fspec :args (s/cat :x int?) :ret int?) #'str)

clojure.lang.ExceptionInfo: Cannot convert path. This can be caused by using conformers to transform values, which is not supported in Expound

Expected Expound would report the spec error that the input value didn't conform to the fspec, but throws a misleading error that says there may be a conformer (which is not true, in fact).

@bhb bhb added the bug label Oct 30, 2017
@bhb
Copy link
Owner

bhb commented Oct 30, 2017

Thanks very much for reporting this bug!

This is a tricky one to solve in general.

A little context: Expound uses the data returned by explain-data to print an error message.

This "explain-data" contains a "value" (which is the top-level form) and a sequence of problems, each of which contains (among other things) a "val" (which points to the bad value) and an "in" (which is the path to the bad value). For example:

(require '[clojure.spec.alpha :as s])
(s/explain-data (s/coll-of int?) [1 2 :a])

;; explain-data is:
;; #:clojure.spec.alpha{:problems ({:path [], :pred int?, :val :a, :via [], :in [2]}), :spec #object[clojure.spec.alpha$every_impl$reify__934 0xdfe0a61 "clojure.spec.alpha$every_impl$reify__934@dfe0a61"], :value [1 2 :a]}

In this example, there is just one "problem". The value is [1 2 :a], the val is :a and the :in is [2].

In this simple case, the :in path is easy to interpret. However, in general, there are cases where it's tricky to figure out how to interpret the :in path - see https://dev.clojure.org/jira/browse/CLJ-2192

Expound has a lot of code dedicated to figuring out the :in path. One heuristic I use is that the :val should be located somewhere within the :value (that is, the part of the data that is invalid should exist within the top-level form).

However, in the case of fspec failures, this assumption is not true - see https://dev.clojure.org/jira/browse/CLJ-2258

As a result, we get this bug - Expound can't figure out how to interpret the :in path and crashes.

My first impression is that it's not possible to solve this in general until one or both of the above Jira issues are fixed. However, there may be a way to solve this in at least some cases. I'll think more about this.

@bhb
Copy link
Owner

bhb commented Oct 31, 2017

@athos Thanks again for reporting this! I don't think it's possible to fix this in every case, but I think I have a heuristic for the more common cases. Can you try out 0.3.3-SNAPSHOT and see if it works in your case?

@athos
Copy link
Author

athos commented Oct 31, 2017

Thank you for the quick reply and polite explanation about the context.
I'm a little bit familiar with those things since I'm also working on a library similar to Expound (named Pinpointer) for more than a year 😃

I looked into the issue today, and now I see the difficulty of giving a general solution to it. In general, a return value generated by a fspec could not be mapped into the input value, which is a very similar situation where a conformer transforms the input value.

So, yeah, I think your new PR now resolves the issue to some extent, and it would be sufficient for practical problems IMHO.

@bhb
Copy link
Owner

bhb commented Oct 31, 2017

@athos

I'm a little bit familiar with those things since I'm also working on a library similar to Expound (named Pinpointer) for more than a year

Excellent! I took a quick look at Pinpointer and it looks great! I'll look take a look at Jira issues you've opened for spec and vote them up. Anything that makes it easier to build something like Expound or Pinpointer helps everyone :)

@bhb bhb closed this as completed in #42 Nov 1, 2017
@bhb
Copy link
Owner

bhb commented Nov 2, 2017

@athos I've released version 0.3.3 which contains this fix. Thanks for your help!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants