[spec] s/& does not check preds if regex matches empty collection

Description

In the following example, the ::x key is required in the map but it will conform without error for an empty collection:

(s/def ::x integer?) (s/conform (s/keys* :req-un [::x]) []) ;; nil, expected error (s/explain (s/keys* :req-un [::x]) []) ;; Success!, expected explanation

Cause: At the moment, (s/keys* :req-un [::x]) is expanded to a form equivalent to the following one:

(s/& (s/* (s/cat ::s/k keyword? ::s/v)) ::s/kvs->map (s/keys :req-un [::x]))

The issue seems to be in the implementation of s/&, specifically the ::amp branch of accept-nil? which expects that either the conformed regex returns empty or that the preds are not invalid. This seems like a false assumption that an empty conformed regex ret does not require the s/& preds to be valid. In this case we are using a conformer to transform the input and do another check, so it's certainly not valid here.

Proposed: Modify s/& to always validate the preds when accepting nil.

user=> (s/conform (s/keys* :req-un [::x]) []) :clojure.spec.alpha/invalid user=> (-> (s/explain-data (s/keys* :req-un [::x]) []) ::s/problems first :pred) (clojure.core/fn [%] (clojure.core/contains? % :x))

Patch: clj-2182-2.patch

Screened by: Stu Halloway

Environment

None

Attachments

2
  • 29 Jun 2017, 10:20 PM
  • 13 Jun 2017, 02:42 PM

Activity

Alex Miller 
June 26, 2018 at 4:59 PM

Applied

Alex Miller 
June 29, 2017 at 10:20 PM

-2 patch includes a test

Completed

Details

Assignee

Reporter

Labels

Approval

Patch

Priority

Affects versions

Fix versions

Created June 8, 2017 at 10:51 AM
Updated June 26, 2018 at 4:59 PM
Resolved June 26, 2018 at 4:59 PM