Skip to content

Commit b17ef07

Browse files
committed
improve subtyping
1 parent 6e0e975 commit b17ef07

File tree

2 files changed

+88
-12
lines changed

2 files changed

+88
-12
lines changed

typed-racket-lib/typed-racket/rep/object-rep.rkt

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
obj-seq-next
3838
scale-obj
3939
uninterpreted-PE?
40+
intersect-objects
4041
(rename-out [make-LExp* make-LExp]
4142
[make-LExp raw-make-LExp])
4243
(all-from-out "fme-utils.rkt"))
@@ -395,4 +396,12 @@
395396
(define (add-path-to-lexp p l)
396397
(match l
397398
[(LExp: const terms)
398-
(make-LExp* const (terms-set terms p (add1 (terms-ref terms p))))]))
399+
(make-LExp* const (terms-set terms p (add1 (terms-ref terms p))))]))
400+
401+
402+
(define (intersect-objects o1 o2)
403+
(match* (o1 o2)
404+
[(o o) o]
405+
[((Empty:) _) o2]
406+
[(_ (Empty:)) o1]
407+
[(_ _) o1]))

typed-racket-lib/typed-racket/types/subtype.rkt

Lines changed: 78 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
one-of/c))
2222

2323
(lazy-require
24-
("../infer/infer.rkt" (infer))
24+
("../infer/infer.rkt" (infer intersect))
2525
("prop-ops.rkt" (-and))
2626
("../typecheck/tc-subst.rkt" (instantiate-obj+simplify))
2727
("../typecheck/tc-envops.rkt" (env+ implies-in-env?)))
@@ -186,7 +186,7 @@
186186
;; NOTE: This function takes into account that domains are
187187
;; contravariant w.r.t. subtyping, i.e. callers should NOT
188188
;; flip argument order.
189-
(define/cond-contract (Arrow-domain-subtypes* A dom1 rst1 dom2 rst2 [objs #f])
189+
(define/cond-contract (positional-domain-subtypes* A dom1 rst1 dom2 rst2 [objs #f])
190190
(->* (list?
191191
(listof Type?)
192192
(or/c #f Rest? RestDots?)
@@ -198,12 +198,26 @@
198198
[((cons t1 ts1) (cons t2 ts2))
199199
(subtype-seq A
200200
(subtype* t2 t1 (and objs (car objs)))
201-
(Arrow-domain-subtypes* ts1 rst1 ts2 rst2 (and objs (cdr objs))))]
201+
(positional-domain-subtypes* ts1 rst1 ts2 rst2 (and objs (cdr objs))))]
202202
[(_ _)
203203
(subtype* A
204204
(-Tuple* dom2 (Rest->Type rst2))
205205
(-Tuple* dom1 (Rest->Type rst1)))]))
206206

207+
(define/cond-contract (Arrow-domain-subtypes* A dom1 rst1 kws1 dom2 rst2 kws2 [objs #f])
208+
(->* (list?
209+
(listof Type?)
210+
(or/c #f Rest? RestDots?)
211+
(listof Keyword?)
212+
(listof Type?)
213+
(or/c #f Rest? RestDots?)
214+
(listof Keyword?))
215+
((listof Object?))
216+
(or/c #f list?))
217+
(subtype-seq A
218+
(positional-domain-subtypes* dom1 rst1 dom2 rst2 objs)
219+
(kw-subtypes* kws1 kws2)))
220+
207221
(define-syntax-rule (with-fresh-ids len ids . body)
208222
(let-values ([(ids seq) (for/fold ([ids '()]
209223
[seq (temp-ids)])
@@ -220,7 +234,7 @@
220234
[((Arrow: dom1 rst1 kws1 raw-rng1)
221235
(Arrow: dom2 rst2 kws2 raw-rng2))
222236
(define A* (subtype-seq A
223-
(Arrow-domain-subtypes* dom1 rst1 dom2 rst2)
237+
(positional-domain-subtypes* dom1 rst1 dom2 rst2)
224238
(kw-subtypes* kws1 kws2)))
225239
(cond
226240
[(not A*) #f]
@@ -254,7 +268,7 @@
254268
(instantiate-obj d ids)))
255269
(define A* (subtype-seq A
256270
(kw-subtypes* kws1 '())
257-
(Arrow-domain-subtypes* dom1 rst1 dom2 #f (map -id-path ids))))
271+
(positional-domain-subtypes* dom1 rst1 dom2 #f (map -id-path ids))))
258272
(cond
259273
[(not A*) #f]
260274
[else
@@ -310,7 +324,7 @@
310324
(define rst (match raw-rst
311325
[(? Type?) (make-Rest (list raw-rst))]
312326
[_ raw-rst]))
313-
(Arrow-domain-subtypes* A dom rst argtys #f))
327+
(positional-domain-subtypes* A dom rst argtys #f))
314328

315329

316330
;;************************************************************
@@ -812,11 +826,35 @@
812826
[((Fun: arrows2) _)
813827
(cond
814828
[(null? arrows1) #f]
815-
[else (for/fold ([A A])
816-
([a2 (in-list arrows2)]
817-
#:break (not A))
818-
(for/or ([a1 (in-list arrows1)])
819-
(arrow-subtype* A a1 a2)))])]
829+
[else
830+
(for/fold ([A A])
831+
([a2 (in-list arrows2)]
832+
#:break (not A))
833+
(match-define (Arrow: dom2 rst2 kws2 raw-cdom2) a2)
834+
;; A <: C₁ ∩ ... ∩ Cₙ
835+
;; D₁ ∩ ... ∩ Dₙ <: B
836+
;; ------------------------
837+
;; (C₁→D₁∩...∩Cₙ→Dₙ) <: A→B
838+
(define raw-cdom1
839+
(for/fold ([cdom #f])
840+
([a1 (in-list arrows1)])
841+
(match-define (Arrow: dom1 rst1 kws1 raw-cdom1) a1)
842+
(cond
843+
[(Arrow-domain-subtypes* A dom1 rst1 kws1 dom2 rst2 kws2)
844+
(if cdom (intersect-values cdom raw-cdom1) raw-cdom1)]
845+
[else cdom])))
846+
(cond
847+
[(not raw-cdom1) #f]
848+
[else
849+
(with-fresh-ids (length dom2) ids
850+
(define mapping
851+
(for/list ([idx (in-naturals)]
852+
[id (in-list ids)]
853+
[t (in-list dom2)])
854+
(list* idx id t)))
855+
(subval* A
856+
(instantiate-obj+simplify raw-cdom1 mapping)
857+
(instantiate-obj raw-cdom2 ids)))]))])]
820858
[((? DepFun? dfun) _)
821859
(for/or ([a1 (in-list arrows1)])
822860
(arrow-subtype-dfun* A a1 dfun))]
@@ -1229,3 +1267,32 @@
12291267
#false]
12301268
[_ (continue<: A t1 t2 obj)])]
12311269
[else: (continue<: A t1 t2 obj)])
1270+
1271+
1272+
;; intersects two monomorphic Values (i.e. see rep/values-rep)
1273+
;; if the values are strictly incompatible, we return ⊥,
1274+
(define (intersect-values v1 v2)
1275+
(match* (v1 v2)
1276+
[(v v) v]
1277+
[((ValuesDots: rs1 dty1 dbound)
1278+
(ValuesDots: rs2 dty2 dbound))
1279+
(make-ValuesDots (map intersect-results rs1 rs2) (intersect dty1 dty2) dbound)]
1280+
[((? ValuesDots?) _) v1]
1281+
[(_ (? ValuesDots?)) v2]
1282+
[((AnyValues: p1) (AnyValues: p2)) (make-AnyValues (-and p1 p2))]
1283+
[((AnyValues: p) (Values: (cons (Result: t (PropSet: p+ p-) o) rst)))
1284+
(make-Values (cons (make-Result t (-PS (-and p p+) (-and p p-)) o) rst))]
1285+
[((Values: (cons (Result: t (PropSet: p+ p-) o) rst)) (AnyValues: p))
1286+
(make-Values (cons (make-Result t (-PS (-and p p+) (-and p p-)) o) rst))]
1287+
[((Values: rs1) (Values: rs2))
1288+
(cond
1289+
[(= (length rs1) (length rs2))
1290+
(make-Values (map intersect-results rs1 rs2))]
1291+
[else (make-AnyValues -ff)])]))
1292+
1293+
;; intersects two Results (i.e. see rep/core-rep.rkt) pointwise
1294+
(define (intersect-results r1 r2)
1295+
(match* (r1 r2)
1296+
[((Result: t1 (PropSet: p1+ p1-) o1)
1297+
(Result: t2 (PropSet: p2+ p2-) o2))
1298+
(make-Result (intersect t1 t2) (-PS (-and p1+ p2+) (-and p1- p2-)) (intersect-objects o1 o2))]))

0 commit comments

Comments
 (0)