2 * Copyright (c) Facebook, Inc. and its affiliates.
4 * This source code is licensed under the MIT license found in the
5 * LICENSE file in the "hack" directory of this source tree.
12 tyvar_occurrences
: ISet.t
IMap.t
;
13 (** A map to track where each type variable occurs,
14 more precisely in the type of which other type variables.
15 E.g. if #1 is bound to (#2 | int), then this map contains the entry
17 This is based on shallow binding, i.e. in the example above, if #2
18 is mapped to #3, then tyvar_occurrences would be:
21 but we would not record that #3 occurs in #1.
22 When a type variable v gets solved or the type bound to it gets simplified,
23 we simplify the unions and intersections of the types bound to the
24 type variables associated to v in this map.
25 So in our example, if #2 gets solved to int,
26 we simplify #1 to (int | int) = int.
27 There are only entries for variables that are unsolved or contain
28 other unsolved type variables. Variables that are solved and contain
29 no other unsolved type variables get removed from this map. *)
30 tyvars_in_tyvar
: ISet.t
IMap.t
;
31 (** Mapping of type variables to the type variables contained in their
32 types which are either unsolved or themselves contain unsolved type
34 This is the dual of tyvar_occurrences. *)
40 let iset_imap_as_value map
=
43 (fun i vars m
-> SMap.add
(var_as_string i
) (varset_as_value vars
) m
)
47 let tyvar_occurrences_as_value = iset_imap_as_value
49 let tyvars_in_tyvar_as_value = iset_imap_as_value
52 let { tyvar_occurrences
; tyvars_in_tyvar
} = x
in
55 ("tyvar_occurrences", tyvar_occurrences_as_value tyvar_occurrences
);
56 ("tyvars_in_tyvar", tyvars_in_tyvar_as_value tyvars_in_tyvar
);
60 let init = { tyvar_occurrences
= IMap.empty
; tyvars_in_tyvar
= IMap.empty
}
62 let get_tyvar_occurrences x v
=
63 Option.value (IMap.find_opt v x
.tyvar_occurrences
) ~default
:ISet.empty
65 let get_tyvars_in_tyvar x v
=
66 Option.value (IMap.find_opt v x
.tyvars_in_tyvar
) ~default
:ISet.empty
68 let set_tyvar_occurrences x v vars
=
69 { x
with tyvar_occurrences
= IMap.add v vars x
.tyvar_occurrences
}
71 (** Make v occur in v', i.e. add v' to the occurrences of v. *)
72 let add_tyvar_occurrence x v ~occurs_in
:v'
=
73 let vars = get_tyvar_occurrences x v
in
74 let vars = ISet.add v'
vars in
75 let x = set_tyvar_occurrences x v
vars in
78 let add_tyvar_occurrences x vars ~occur_in
:v
=
79 ISet.fold
(fun v'
x -> add_tyvar_occurrence x v' ~occurs_in
:v
) vars x
81 let set_tyvars_in_tyvar x v
vars =
82 { x with tyvars_in_tyvar
= IMap.add v
vars x.tyvars_in_tyvar
}
84 let make_tyvars_occur_in_tyvar x vars ~occur_in
:v
=
85 let x = add_tyvar_occurrences x vars ~occur_in
:v
in
86 let x = set_tyvars_in_tyvar x v
vars in
89 let remove_tyvar_occurrence x v ~no_more_occurs_in
:v'
=
90 let vars = get_tyvar_occurrences x v
in
91 let vars = ISet.remove v'
vars in
92 let x = set_tyvar_occurrences x v
vars in
95 let remove_tyvar_from_tyvar x ~from
:v v'
=
96 let vars = get_tyvars_in_tyvar x v
in
97 let vars = ISet.remove v'
vars in
98 let x = set_tyvars_in_tyvar x v
vars in
101 let make_tyvar_no_more_occur_in_tyvar x v ~no_more_in
:v'
=
102 let x = remove_tyvar_occurrence x v ~no_more_occurs_in
:v'
in
103 let x = remove_tyvar_from_tyvar x ~from
:v' v
in
106 let contains_unsolved_tyvars x v
=
107 not
@@ ISet.is_empty
(get_tyvars_in_tyvar x v
)
109 (** Update the tyvar occurrences after unbinding a type variable. *)
110 let unbind_tyvar x v
=
111 let vars_in_v = get_tyvars_in_tyvar x v
in
112 (* update tyvar_occurrences. *)
115 (fun v'
x -> remove_tyvar_occurrence x v' ~no_more_occurs_in
:v
)
119 (* update tyvars_in_tyvar *)
120 let x = set_tyvars_in_tyvar x v
ISet.empty
in
123 let occurs_in x occuring_tv ~in_
:containing_tv
=
124 let occurs = ISet.mem containing_tv
(get_tyvar_occurrences x occuring_tv
) in
125 let contains = ISet.mem occuring_tv
(get_tyvars_in_tyvar x containing_tv
) in
126 assert (occurs = contains);
130 let occurrences = get_tyvar_occurrences x v
in
133 (fun occ
x -> make_tyvar_no_more_occur_in_tyvar x v ~no_more_in
:occ
)
137 let x = { x with tyvar_occurrences
= IMap.remove v
x.tyvar_occurrences
} in
138 let vars_in_v = get_tyvars_in_tyvar x v
in
142 make_tyvar_no_more_occur_in_tyvar x var_in_v ~no_more_in
:v
)
146 let x = { x with tyvars_in_tyvar
= IMap.remove v
x.tyvars_in_tyvar
} in