@@ -14,6 +14,8 @@ module E = Ir_effect
14
14
15
15
(* TODO: check escape of free mutables via actors *)
16
16
17
+
18
+
17
19
(* Helpers *)
18
20
19
21
let (==>) p q = not p || q
@@ -54,6 +56,9 @@ type con_env = T.ConSet.t
54
56
55
57
type lvl = TopLvl | NotTopLvl
56
58
59
+ module Set = Set. Make (T. Ord )
60
+ module MapPair = Map. Make (T. OrdPair )
61
+
57
62
type env =
58
63
{ flavor : Ir .flavor ;
59
64
lvl : lvl ;
@@ -64,6 +69,9 @@ type env =
64
69
async : T .con option ;
65
70
seen : con_env ref ;
66
71
check_run : int ;
72
+ check_typ_cache : Set .t ref ;
73
+ sub_cache : bool MapPair .t ref ;
74
+ lub_cache : T .typ MapPair .t ref ;
67
75
}
68
76
69
77
let last_run : int ref = ref 0
@@ -82,8 +90,28 @@ let initial_env flavor : env =
82
90
| QueryCap c | AwaitCap c | AsyncCap c | CompositeCap c | CompositeAwaitCap c | SystemCap c -> Some c);
83
91
seen = ref T.ConSet. empty;
84
92
check_run;
93
+ check_typ_cache = ref Set. empty;
94
+ sub_cache = ref MapPair. empty;
95
+ lub_cache = ref MapPair. empty
85
96
}
86
97
98
+ let sub env t1 t2 =
99
+ if t1 == t2 then true else
100
+ match MapPair. find_opt (t1, t2) ! (env.sub_cache) with
101
+ | Some b -> b
102
+ | None ->
103
+ let b = T. sub t1 t2 in
104
+ env.sub_cache := MapPair. add (t1, t2) b ! (env.sub_cache);
105
+ b
106
+
107
+ let lub env t1 t2 =
108
+ if t1 == t2 then t1 else
109
+ match MapPair. find_opt (t1, t2) ! (env.lub_cache) with
110
+ | Some t -> t
111
+ | None ->
112
+ let t = T. lub t1 t2 in
113
+ env.lub_cache := MapPair. add (t1, t2) t ! (env.lub_cache);
114
+ t
87
115
88
116
(* More error bookkeeping *)
89
117
@@ -125,7 +153,7 @@ let disjoint_union env at fmt env1 env2 =
125
153
126
154
(* FIX ME: these error reporting functions are eager and will construct unnecessary type strings !*)
127
155
let check_sub env at t1 t2 =
128
- if not (T. sub t1 t2) then
156
+ if not (sub env t1 t2) then
129
157
error env at " subtype violation:\n %s\n %s\n "
130
158
(T. string_of_typ_expand t1) (T. string_of_typ_expand t2)
131
159
@@ -317,7 +345,7 @@ and check_typ_bounds env (tbs : T.bind list) typs at : unit =
317
345
error env at " too few type arguments" ;
318
346
List. iter2
319
347
(fun tb typ ->
320
- check env at (T. sub typ (T. open_ typs tb.T. bound))
348
+ check env at (sub env typ (T. open_ typs tb.T. bound))
321
349
" type argument does not match parameter bound" )
322
350
tbs typs
323
351
@@ -326,6 +354,11 @@ and check_inst_bounds env tbs typs at =
326
354
List. iter (check_typ env) typs;
327
355
check_typ_bounds env tbs typs at
328
356
357
+ let check_typ env typ =
358
+ if Set. mem typ ! (env.check_typ_cache) then () else
359
+ check_typ env typ;
360
+ env.check_typ_cache := Set. add typ ! (env.check_typ_cache);
361
+
329
362
(* Literals *)
330
363
331
364
open Ir
@@ -968,7 +1001,7 @@ and check_case env t_pat t {it = {pat; exp}; _} =
968
1001
let ve = check_pat env pat in
969
1002
check_sub env pat.at t_pat pat.note;
970
1003
check_exp (adjoin_vals env ve) exp;
971
- check env pat.at (T. sub (typ exp) t) " bad case"
1004
+ check env pat.at (sub env (typ exp) t) " bad case"
972
1005
973
1006
(* Arguments *)
974
1007
@@ -1003,7 +1036,7 @@ and gather_pat env const ve0 pat : val_env =
1003
1036
List. fold_left go ve (pats_of_obj_pat pfs)
1004
1037
| AltP (pat1 , pat2 ) ->
1005
1038
let ve1, ve2 = go ve pat1, go ve pat2 in
1006
- let common i1 i2 = { typ = T. lub i1.typ i2.typ; loc_known = i1.loc_known && i2.loc_known; const = i1.const && i2.const } in
1039
+ let common i1 i2 = { typ = lub env i1.typ i2.typ; loc_known = i1.loc_known && i2.loc_known; const = i1.const && i2.const } in
1007
1040
T.Env. merge (fun _ -> Lib.Option. map2 common) ve1 ve2
1008
1041
| OptP pat1
1009
1042
| TagP (_ , pat1 ) ->
@@ -1053,7 +1086,7 @@ and check_pat env pat : val_env =
1053
1086
t < : pat2.note;
1054
1087
if T.Env. (keys ve1 <> keys ve2) then
1055
1088
error env pat.at " set of bindings differ for alternative pattern" ;
1056
- let common i1 i2 = { typ = T. lub i1.typ i2.typ; loc_known = i1.loc_known && i2.loc_known; const = i1.const && i2.const } in
1089
+ let common i1 i2 = { typ = lub env i1.typ i2.typ; loc_known = i1.loc_known && i2.loc_known; const = i1.const && i2.const } in
1057
1090
T.Env. merge (fun _ -> Lib.Option. map2 common) ve1 ve2
1058
1091
1059
1092
and check_pats at env pats ve : val_env =
0 commit comments