typedclojure / typedclojure

An optional type system for Clojure
Eclipse Public License 1.0
487 stars 7 forks source link

Union Types not working as expected #164

Open sstraust opened 1 month ago

sstraust commented 1 month ago

Hi! I'm getting some behavior I can't make sense of: I defined the following type, which correctly passes type checking when I call it

(t/ann ^:no-check mc/find-one-as-map
(t/U
        [com.mongodb.DB
         (t/Value "eventplanner_tags")
         (t/Map t/Any t/Any)
         ->
         TagType]))

(t/cf (mc/find-one-as-map db "eventplanner_tags" {})) ==> TagType

but adding an additional type to the union causes this to fail:

(t/ann ^:no-check mc/find-one-as-map
       (t/U
        [com.mongodb.DB
         (t/Value "eventplanner_tags")
         (t/Map t/Any t/Any)
         ->
         TagType]
        [com.mongodb.DB
         (t/Value "events2")
         (t/Map t/Any t/Any)
         ->
         EventType]))

(t/cf (mc/find-one-as-map db "eventplanner_tags" {}))  ==> Error

Viewing the error message, it's giving:

Type Error (/Users/sam/sstraust/eventplanner/src/eventplanner/tables.clj:127:7) 
Function mc/find-one-as-map could not be applied to arguments:

Domains:
    com.mongodb.DB (t/Val "events2") (t/Map t/Any t/Any)

Arguments:
    com.mongodb.DB (t/Val "eventplanner_tags") (t/HMap :complete? true)

Ranges:
    eventplanner.tables/EventType

so it looks like adding a second type to the union causes it to not find the first type??

I'm having trouble debugging this/figuring out what's going wrong here

frenchy64 commented 2 days ago

I think you want an intersection type. A function union type can only be invoked if arguments are compatible with all types. A function intersection only requires one type.

       (t/IFn
        [com.mongodb.DB
         (t/Value "eventplanner_tags")
         (t/Map t/Any t/Any)
         ->
         TagType]
        [com.mongodb.DB
         (t/Value "events2")
         (t/Map t/Any t/Any)
         ->
         EventType]))