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.
15 module Env
= Typing_env
16 module TUtils
= Typing_utils
17 module Reason
= Typing_reason
19 (* Mapper used by update_array* functions. It traverses Tunion and
20 * modifies the type "inside" the Tvars - so it has side effects on the input
21 * type (the type variables inside env change)! *)
22 class update_array_type_mapper
: type_mapper_type
= object
23 inherit shallow_type_mapper
24 inherit! tunion_type_mapper
25 inherit! tvar_substituting_type_mapper
28 (* Abstract types declared "as array<...>" permit array operations, but if
29 * those operations modify the array it has to be downgraded from generic
31 class virtual downcast_tabstract_to_array_type_mapper
= object(this
)
32 method on_tabstract env r ak cstr
=
33 let ty = (r
, Tabstract
(ak
, cstr
)) in
34 match TUtils.get_all_supertypes env
ty with
37 let is_array = function
38 | _
, Tarraykind _
-> true
40 match List.filter tyl
is_array with
44 (* If the abstract type has multiple concrete supertypes
45 which are arrays, just take the first one.
46 TODO(jjwu): Try all of them and find one that works
50 method virtual on_type
: env
-> locl
ty -> result
53 let union env tyl
= match tyl
with
54 | [] -> Env.fresh_unresolved_type env
Pos.none
(* TODO: position *)
55 | ty::tyl'
-> List.fold_left_env env tyl' ~init
:ty ~f
:TUtils.union
57 let union_keys = union
59 let union_values env values
=
60 let unknown = List.find values
(fun ty ->
61 snd
(snd
(TUtils.fold_unresolved env
ty)) = Tany
) in
63 | Some
(r
, _
) -> env
, (r
, TUtils.tany env
)
64 | None
-> union env values
66 (* Apply this function to a type after lvalue array access that should update
67 * array type (e.g from AKempty to AKmap after using it as a map). *)
68 let update_array_type p ~is_map env
ty =
70 inherit update_array_type_mapper
71 inherit! downcast_tabstract_to_array_type_mapper
73 method! on_tarraykind_akempty env _
=
76 let env, tk
= Env.fresh_unresolved_type
env p
in
77 let env, tv
= Env.fresh_unresolved_type
env p
in
78 env, (Reason.Rused_as_map p
, Tarraykind
(AKmap
(tk
, tv
)))
80 let env, tv
= Env.fresh_unresolved_type
env p
in
81 env, (Reason.Rappend p
, Tarraykind
(AKvec tv
))
84 let env, ty = mapper#on_type
(fresh_env
env) ty in