Skip to content

Commit 1d0e0b0

Browse files
capfredfsamth
authored andcommitted
type constrs: improve type app and variances.
1. type applications are not resolved until the results are used closes #1234 2. streamline the handling of variances
1 parent 76f4cc5 commit 1d0e0b0

21 files changed

+415
-256
lines changed

typed-racket-lib/typed-racket/base-env/top-interaction.rkt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
"../types/utils.rkt"
4848
"../types/abbrev.rkt"
4949
"../types/printer.rkt"
50+
"../types/resolve.rkt"
5051
"../typecheck/possible-domains.rkt"
5152
"../typecheck/typechecker.rkt"
5253
"../rep/type-rep.rkt"
@@ -70,7 +71,9 @@
7071
[current-type-names
7172
(if (attribute verbose-kw) '() (current-type-names))]
7273
[current-print-unexpanded (box '())])
73-
(define type (pretty-format-rep (parse-type #'ty)))
74+
(define type (pretty-format-rep (match (parse-type #'ty)
75+
[(? App? ty) (resolve ty)]
76+
[ty ty])))
7477
(define unexpanded
7578
(remove-duplicates (unbox (current-print-unexpanded))))
7679
(define cue (if (null? unexpanded)

typed-racket-lib/typed-racket/env/init-envs.rkt

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
"signature-env.rkt"
1313
"struct-name-env.rkt"
1414
"../private/user-defined-type-constr.rkt"
15-
"../typecheck/struct-type-constr.rkt"
1615
"../rep/core-rep.rkt"
1716
"../rep/type-rep.rkt"
1817
"../rep/type-constr.rkt"
@@ -364,9 +363,11 @@
364363
;; Most Top types are in the predefined table, the ones here
365364
;; are not
366365
[(StructTop: name) `(make-StructTop ,(type->sexp name))]
367-
[(TypeConstructor constr arity kind*? productive?)
366+
[(TypeConstructor constr arity kind*? productive? variances)
368367
(define constr^ (gen-serialize-type-rep constr type->sexp))
369-
`(make-type-constr ,constr^ ,arity ,productive? #:kind*? ,kind*?)]))
368+
`(make-type-constr ,constr^ ,arity ,productive? #:kind*? ,kind*?
369+
#:variances
370+
(list #,@(map variance->binding variances)))]))
370371

371372
;; Helper for class/row clauses
372373
(define (convert-row-clause members [inits? #f])
@@ -459,10 +460,6 @@
459460
type-name-env-map
460461
(λ (id ty) #`(register-type-name #'#,id #,(quote-type ty)))))
461462

462-
(define (tvariance-env-init-code)
463-
(make-init-code
464-
type-variance-env-map
465-
(λ (id var) #`(register-type-variance! #'#,id (list #,@(map variance->binding var))))))
466463

467464
(define (talias-env-init-code)
468465
(make-init-code
@@ -489,10 +486,11 @@
489486
kind-env-map
490487
(lambda (id v)
491488
;; TODO: turn this into a function
492-
(match-define (TypeConstructor constr arity kind*? productive?) v)
489+
(match-define (TypeConstructor constr arity kind*? productive? variances) v)
493490
(define constr^ (gen-serialize-type-rep constr type->sexp))
494491
#`(register-type-constructor! #'#,id
495-
(make-type-constr #,constr^ #,arity #,productive? #:kind*? #,kind*?)))))
492+
(make-type-constr #,constr^ #,arity #,productive? #:kind*? #,kind*?
493+
#:variances (list #,@(map variance->binding variances)))))))
496494

497495
;; see 'finalize-signatures!' in 'env/signature-env.rkt',
498496
;; which forces these delays after all the signatures are parsed
@@ -519,7 +517,6 @@
519517
(list (env-init-code)
520518
(talias-env-init-code)
521519
(tname-env-init-code)
522-
(tvariance-env-init-code)
523520
(mvar-env-init-code mvar-env)
524521
(signature-env-init-code)
525522
(make-struct-table-code)

typed-racket-lib/typed-racket/env/type-alias-helper.rkt

Lines changed: 52 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,12 @@
88
"type-alias-env.rkt"
99
"type-name-env.rkt"
1010
"../rep/type-rep.rkt"
11+
"../rep/free-variance.rkt"
1112
"../rep/type-constr.rkt"
1213
"tvar-env.rkt"
1314
"type-constr-env.rkt"
1415
"../private/parse-type.rkt"
16+
"../private/user-defined-type-constr.rkt"
1517
"../typecheck/internal-forms.rkt"
1618
"../types/resolve.rkt"
1719
"../types/base-abbrev.rkt"
@@ -70,11 +72,13 @@
7072
;; start registering type alias names
7173
(start-type-alias-registration! id (make-Name id (length args) #f))
7274
(values id (list id type-stx args))))
73-
(register-all-type-alias-info type-alias-names type-alias-map)
74-
(unless (zero? (free-id-table-count (incomplete-name-alias-map)))
75-
(define names (free-id-table-keys (incomplete-name-alias-map)))
76-
(int-err "not all type alias names are fully registered: ~n ~a"
77-
names))))
75+
76+
(begin0
77+
(register-all-type-alias-info type-alias-names type-alias-map)
78+
(unless (zero? (free-id-table-count (incomplete-name-alias-map)))
79+
(define names (free-id-table-keys (incomplete-name-alias-map)))
80+
(int-err "not all type alias names are fully registered: ~n ~a"
81+
names)))))
7882

7983
;; Identifier -> Type
8084
;; Construct a fresh placeholder type
@@ -198,20 +202,31 @@
198202
;; Note that the connected component algorithm returns results
199203
;; in topologically sorted order, so we want to go through in the
200204
;; reverse order of that to avoid unbound type aliases.
201-
(for ([id (in-list acyclic-singletons)])
202-
(match-define (list _ type-stx args) (free-id-table-ref type-alias-map id))
203-
(cond
204-
[(not (null? args))
205-
(define ty-op (parse-type-operator-abstraction id args type-stx #f
206-
type-alias-productivity-map))
207-
(register-type-constructor! id ty-op)]
208-
[else
209-
;; id can be a simple abbreviation for another type constructor
210-
(define rv (parse-type-or-type-constructor type-stx))
211-
((if (TypeConstructor? rv)
212-
register-type-constructor!
213-
register-resolved-type-alias) id rv)])
214-
(complete-type-alias-registration! id))
205+
(define acyclic-constr-names
206+
(for/fold ([acc '()])
207+
([id (in-list acyclic-singletons)])
208+
(match-define (list _ type-stx args) (free-id-table-ref type-alias-map id))
209+
(define acc^
210+
(cond
211+
[(not (null? args))
212+
(define ty-op (parse-type-operator-abstraction id args type-stx #f
213+
type-alias-productivity-map))
214+
215+
(register-type-constructor! id ty-op)
216+
(cons id acc)]
217+
[else
218+
;; id can be a simple abbreviation for another type constructor
219+
(define rv (parse-type-or-type-constructor type-stx))
220+
(match rv
221+
[(? TypeConstructor?)
222+
(register-type-constructor! id rv)
223+
(if (user-defined-type-constr? rv)
224+
(cons id acc)
225+
acc)]
226+
[else (register-resolved-type-alias id rv)
227+
acc])]))
228+
(complete-type-alias-registration! id)
229+
acc^))
215230

216231
;; Clear the resolver cache of Name types from this block
217232

@@ -250,41 +265,40 @@
250265
(for/lists (_1 _2 _3)
251266
([record (in-list type-records)])
252267
(match-define (list id type-stx args) record)
253-
;; TODO try parse-type
254268
(define type (parse-type type-stx type-alias-productivity-map))
255269
(reset-resolver-cache!)
256270
(register-type-name id type)
257271
(complete-type-alias-registration! id)
258-
(add-constant-variance! id args)
259272
(values id type (map syntax-e args))))
260273

261-
;; do a pass to refine the variance
262-
(refine-variance! names-to-refine types-to-refine tvarss)
263-
264274
(define-values (productive unproductive)
265275
(partition (match-lambda
266276
[(cons a _)
267277
(equal? (free-id-table-ref type-alias-productivity-map a #f) #t)])
268278
type-op-records))
269279

270-
(let (;; sort unproductive constructors by the number of dependent
271-
;; user-defined constructors in increasing order
272-
[unproductive (sort unproductive <
280+
;; sort unproductive constructors by the number of dependent
281+
;; user-defined constructors in increasing order
282+
(let ([unproductive (sort unproductive <
273283
#:key
274284
(match-lambda
275285
[(cons a _)
276286
(length (free-id-table-ref type-alias-dependency-map a #f))]))])
277-
(for/list ([record (in-list (append productive unproductive))])
278-
(match-define (list id type-stx args) record)
279-
(define ty-op (parse-type-operator-abstraction id args type-stx
280-
(lambda (x)
281-
(define res (in-same-component? id x))
282-
res)
283-
type-alias-productivity-map))
284-
(register-type-constructor! id ty-op)
285-
(complete-type-alias-registration! id)
286-
(reset-resolver-cache!)
287-
(add-constant-variance! id args))))
287+
(define constr-names
288+
(for/list ([record (in-list (append productive unproductive))])
289+
(match-define (list id type-stx args) record)
290+
(define ty-op (parse-type-operator-abstraction id args type-stx
291+
(lambda (x)
292+
(define res (in-same-component? id x))
293+
res)
294+
type-alias-productivity-map
295+
#:delay-variances? #t))
296+
(register-type-constructor! id ty-op)
297+
(complete-type-alias-registration! id)
298+
(reset-resolver-cache!)
299+
id))
300+
(refine-user-defined-constructor-variances! constr-names)
301+
(append acyclic-constr-names constr-names)))
288302

289303
;; Syntax -> Syntax Syntax (Listof Syntax)
290304
;; Parse a type alias internal declaration

typed-racket-lib/typed-racket/env/type-name-env.rkt

Lines changed: 1 addition & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -21,25 +21,10 @@
2121
[add-alias (-> identifier? identifier? any)]
2222
[type-name-env-map
2323
(-> (-> identifier? (or/c #t Type?) any) any)]
24-
[type-variance-env-map
25-
(-> (-> identifier? (listof variance?) any) any)]
2624
[type-name-env-for-each
2725
(-> (-> identifier? (or/c #t Type?) any) void?)]
28-
[type-variance-env-for-each
29-
(-> (-> identifier? (listof variance?) any) void?)]
3026
[lookup-type-name
31-
(->* (identifier?) (procedure?) (or/c #t Type?))]
32-
[register-type-variance!
33-
(-> identifier? (listof variance?) any)]
34-
[lookup-type-variance
35-
(-> identifier? (listof variance?))]
36-
[add-constant-variance!
37-
(-> identifier? (or/c #f (listof identifier?)) any)]
38-
[refine-variance!
39-
(-> (listof identifier?)
40-
(listof Type?)
41-
(listof (or/c #f (listof symbol?)))
42-
any)])
27+
(->* (identifier?) (procedure?) (or/c #t Type?))])
4328

4429
;; a mapping from id -> type (where id is the name of the type)
4530
(define the-mapping
@@ -82,46 +67,3 @@
8267
(register-type-constructor! from v))]))
8368

8469

85-
;; a mapping from id -> listof[Variance] (where id is the name of the type)
86-
(define variance-mapping
87-
(make-free-id-table))
88-
89-
;; add a name to the mapping
90-
(define (register-type-variance! id variance)
91-
(free-id-table-set! variance-mapping id variance))
92-
93-
(define (lookup-type-variance id)
94-
(free-id-table-ref
95-
variance-mapping id
96-
(lambda () (lookup-variance-fail id))))
97-
98-
;; map over the-mapping, producing a list
99-
;; (id variance -> T) -> listof[T]
100-
(define (type-variance-env-map f)
101-
(sorted-free-id-table-map variance-mapping f))
102-
103-
(define (type-variance-env-for-each f)
104-
(sorted-free-id-table-for-each variance-mapping f))
105-
106-
;; Refines the variance of a type in the name environment
107-
(define (refine-variance! names types tvarss)
108-
(let loop ()
109-
(define sames?
110-
(for/and ([name (in-list names)]
111-
[type (in-list types)]
112-
[tvars (in-list tvarss)])
113-
(cond
114-
[(or (not tvars) (null? tvars)) #t]
115-
[else
116-
(define free-vars (free-vars-hash (free-vars* type)))
117-
(define variance (map (λ (v) (hash-ref free-vars v variance:const)) tvars))
118-
(define old-variance (lookup-type-variance name))
119-
120-
(register-type-variance! name variance)
121-
(equal? variance old-variance)])))
122-
(unless sames? (loop))))
123-
124-
;; Initialize variance of the given id to Constant for all type vars
125-
(define (add-constant-variance! name vars)
126-
(unless (or (not vars) (null? vars))
127-
(register-type-variance! name (map (lambda (_) variance:const) vars))))

typed-racket-lib/typed-racket/private/parse-type.rkt

Lines changed: 29 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
"../rep/free-ids.rkt"
1111
"../rep/rep-utils.rkt"
1212
"../rep/type-constr.rkt"
13+
"../rep/free-variance.rkt"
1314
"../types/abbrev.rkt"
1415
"user-defined-type-constr.rkt"
1516
"../types/utils.rkt"
@@ -43,6 +44,7 @@
4344
racket/format
4445
racket/match
4546
syntax/id-table
47+
syntax/id-set
4648
"parse-classes.rkt"
4749
(for-template "../base-env/base-types-extra.rkt"
4850
racket/base)
@@ -63,7 +65,8 @@
6365
Type?)]
6466
[parse-type-operator-abstraction (c:->* (identifier? (c:listof identifier?) syntax?)
6567
((c:or/c (c:-> identifier? boolean?) #f)
66-
(free-id-table/c identifier? boolean?))
68+
(free-id-table/c identifier? boolean?)
69+
#:delay-variances? boolean?)
6770
TypeConstructor?)]
6871
[parse-for-effects (c:-> identifier? (c:cons/c (c:listof identifier?) syntax?)
6972
(values (c:listof identifier?)
@@ -646,7 +649,9 @@
646649
;; type-op-productivity-map: maps names of constructors to their productivity.
647650

648651
(define (parse-type-operator-abstraction name arg-names stx [opt-in-same-component? #f]
649-
[type-op-productivity-map (make-immutable-free-id-table)])
652+
[type-op-productivity-map (make-immutable-free-id-table)]
653+
#:delay-variances?
654+
[delay-variances? #f])
650655
(define syms (map syntax-e arg-names))
651656
(define mode (synth-mode name syms opt-in-same-component?))
652657
(define var-kind-level-env
@@ -664,9 +669,14 @@
664669
(parse stx INIT-LEVEL
665670
var-kind-level-env
666671
#:mode mode)))
672+
667673
(make-type-constr (user-defined-type-op syms res)
668674
(length syms)
669-
(free-id-table-ref type-op-productivity-map name #f)))
675+
(free-id-table-ref type-op-productivity-map name #f)
676+
#:variances
677+
(if delay-variances?
678+
(build-default-variances syms)
679+
(variances-in-type res syms))))
670680

671681
(define (parse-type-or-type-constructor stx)
672682
(parse stx 0 (make-immutable-free-id-table) #:mode #f #:ret-type-op? #t))
@@ -1357,16 +1367,25 @@
13571367
[var (in-list (synth-mode-args mode))])
13581368
(check-argument rand var))))
13591369
(match rator
1360-
[(? TypeConstructor?)
1370+
[(struct* TypeConstructor ([arity arity]))
1371+
(define (err expected given)
1372+
(tc-error (~a "wrong number of arguments to type constructor"
1373+
"\n type: " #'id
1374+
"\n expected: " expected
1375+
"\n given: " given
1376+
"\n arguments...: " #'(args ...))))
1377+
13611378
(with-handlers ([exn:fail:contract:arity:type-constructor?
13621379
(lambda (e)
13631380
(match-define (exn:fail:contract:arity:type-constructor _ _ expected given) e)
1364-
(tc-error (~a "wrong number of arguments to type constructor"
1365-
"\n type: " #'id
1366-
"\n expected: " expected
1367-
"\n given: " given
1368-
"\n arguments...: " #'(args ...))))])
1369-
(apply rator args^))]
1381+
(err expected given))])
1382+
(define alias (lookup-type-alias #'id (lambda (x) x) (lambda () #f)))
1383+
(match alias
1384+
[(? Name?)
1385+
(if (equal? arity (length args^))
1386+
(make-App alias args^)
1387+
(err arity (length args^)))]
1388+
[_ (apply rator args^)]))]
13701389
[(? Name?)
13711390
(resolve-app-check-error rator args^ stx)
13721391
(define app (make-App rator args^))

0 commit comments

Comments
 (0)