2 * Copyright (c) 2015, Facebook, Inc.
5 * This source code is licensed under the MIT license found in the
6 * LICENSE file in the "hack" directory of this source tree.
12 module Reason
= Typing_reason
13 module Env
= Typing_env
14 module SubType
= Typing_subtype
15 module Phase
= Typing_phase
16 module MakeType
= Typing_make_type
18 (*****************************************************************************)
20 (*****************************************************************************)
22 (* Tries to add constraint that ty_sub is subtype of ty_super in envs *)
23 let sub_type p ur env ty_sub ty_super
=
24 Typing_log.(log_with_level env
"sub" 1 (fun () ->
26 [Log_head
("Typing_ops.sub_type",
27 [Log_type
("ty_sub", ty_sub
);
28 Log_type
("ty_super", ty_super
)])]));
29 let env = { env with Env.pos
= p
; Env.outer_pos
= p
; Env.outer_reason
= ur
} in
30 Errors.try_add_err p
(Reason.string_of_ureason ur
)
31 (fun () -> SubType.sub_type env ty_sub ty_super
)
34 let coerce_type ?sub_fn
:(sub
=sub_type) p ur
env ty_have ty_expect
=
35 Typing_coercion.coerce_type ~sub_fn
:sub p ur
env ty_have ty_expect
37 let can_coerce env ty_have ty_expect
=
38 Typing_coercion.can_coerce env ty_have ty_expect
40 let sub_type_decl p ur
env ty_sub ty_super
=
41 let env, ty_super
= Phase.localize_with_self
env ty_super
in
42 let env, ty_sub
= Phase.localize_with_self
env ty_sub
in
43 ignore
(sub_type p ur
env ty_sub ty_super
)
45 (* Ensure that types are equivalent i.e. subtypes of each other *)
46 let unify_decl p ur
env ty1 ty2
=
47 let env, ty1
= Phase.localize_with_self
env ty1
in
48 let env, ty2
= Phase.localize_with_self
env ty2
in
49 ignore
(sub_type p ur
env ty2 ty1
);
50 ignore
(sub_type p ur
env ty1 ty2
)
52 module LeastUpperBound
= struct
56 let exact_least_upper_bound e1 e2
=
58 | Exact
, Exact
-> Exact
61 let prim_least_up_bound tprim1 tprim2
=
62 match tprim1
, tprim2
with
63 | Tint
, Tstring
| Tstring
, Tint
-> Some Tarraykey
64 | Tint
, Tfloat
| Tfloat
, Tint
-> Some Tnum
67 let rec type_visitor ~f ~default ty1 ty2
=
68 let array_kind ak1 ak2
=
70 | AKmap
(ty1
, ty2
), AKmap
(ty3
, ty4
) ->
71 let ty1_ = type_visitor ~f ~default ty1 ty3
in
72 let ty2_ = type_visitor ~f ~default ty2 ty4
in
73 Some
(AKmap
(ty1_, ty2_))
74 | AKdarray
(ty1
, ty2
), AKdarray
(ty3
, ty4
) ->
75 let ty1_ = type_visitor ~f ~default ty1 ty3
in
76 let ty2_ = type_visitor ~f ~default ty2 ty4
in
77 Some
(AKdarray
(ty1_, ty2_))
78 | AKvarray ty1
, AKvarray ty2
->
79 let ty = type_visitor ~f ~default ty1 ty2
in
81 | AKvec ty1
, AKvec ty2
->
82 let ty = type_visitor ~f ~default ty1 ty2
in
86 let (r1
, ty_1
), (_
, ty_2
) = (ty1
, ty2
) in
88 | Ttuple tyl1
, Ttuple tyl2
->
89 begin try let tyl = List.map2_exn ~f
:(type_visitor ~f ~default
) tyl1 tyl2
in
93 | Tclass
((p
, id1
), e1
, tyl1
), Tclass
((_
, id2
), e2
, tyl2
) ->
95 begin try let tyl = List.map2_exn ~f
:(type_visitor ~f ~default
) tyl1 tyl2
in
96 r1
, Tclass
((p
, id1
), exact_least_upper_bound e1 e2
, tyl)
101 | Tarraykind ak1
, Tarraykind ak2
->
102 begin match array_kind ak1 ak2
with
104 | Some ak
-> r1
, Tarraykind ak
106 | Tprim tprim1
, Tprim tprim2
->
107 begin match prim_least_up_bound tprim1 tprim2
with
109 | Some
ty -> r1
, Tprim
ty
111 | Toption ty1
, Toption ty2
->
112 let ty = type_visitor ~f ~default ty1 ty2
in r1
, Toption
ty
113 | Toption ty1
, ty_2
| ty_2
, Toption ty1
->
114 let ty = type_visitor ~f ~default ty1
(r1
, ty_2
) in r1
, Toption
ty
117 (* @TODO expand this match to refine more types*)
118 let pairwise_least_upper_bound env ~default ty1 ty2
=
119 if SubType.is_sub_type
env ty1 ty2
then ty2
120 else if SubType.is_sub_type
env ty2 ty1
then ty1
123 let rec full env types
=
127 | (r
, _
as ty1
) :: ty2
:: ts
->
128 let default = MakeType.mixed r
in
131 ~f
:(pairwise_least_upper_bound env ~
default)
136 let rec compute types
=
140 | (tenv
, p
, k
, (r
, _
as ty1
)) :: (_
, _
, _
, ty2
) :: ts
->
141 let default = MakeType.mixed r
in
144 ~f
:(pairwise_least_upper_bound tenv ~
default)
147 compute ((tenv
, p
, k
, ty) :: ts
)