metosin / malli

High-performance data-driven data specification library for Clojure/Script.
Eclipse Public License 2.0
1.47k stars 209 forks source link

`:merge` with registries does not round-trip #1088

Open frenchy64 opened 1 month ago

frenchy64 commented 1 month ago

If schemas with registries are merged with :merge, the dereferenced schema often cannot be round-tripped.

Notice the following schema is missing a ::z binding so is no longer well-formed.

(-> (m/deref
      [:merge
       [:map {:registry {::y int?}}
        [:y ::y]]
       [:map {:registry {::z boolean?}}
        [:z ::z]]]
      options)
    m/form)
=>
[:map {:registry {::y boolean?}}
 [:y ::y]
 [:z ::z]]

We might be able to fix this by merging the registries, but something else is needed if the registries both define the same names.

For example, here the schema for :y is being captured by the wrong scope, and becomes [:y boolean?] instead of [:y int?].

(-> (m/deref
      [:merge
       [:map {:registry {::y int?}}
        [:y ::y]]
       [:map {:registry {::y boolean?}}
        [:z ::y]]]
      options)
    m/form)
=>
[:map {:registry {::y boolean?}}
 [:y ::y]
 [:z ::y]]
frenchy64 commented 1 month ago

This example doesn't work at all, and complains that ::y is not in scope.

[:merge
 [:map
  {::y boolean?}
  [:y ::y]]
 [:map]]