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.
10 (*****************************************************************************)
11 (* Converts a type hint into a type *)
12 (*****************************************************************************)
17 (* Unpacking a hint for typing *)
18 let rec hint env
(p
, h
) =
19 let h = hint_ p env
h in
20 mk
(Typing_reason.Rhint
(Decl_env.make_decl_pos env p
), h)
22 and shape_field_info_to_shape_field_type
23 env
{ sfi_optional
; sfi_hint
; sfi_name
= _
} =
24 { sft_optional
= sfi_optional
; sft_ty
= hint env sfi_hint
}
26 and aast_user_attribute_to_decl_user_attribute env
{ ua_name
; ua_params
} =
28 Typing_defs.ua_name
= Decl_env.make_decl_posed env ua_name
;
30 List.filter_map ua_params ~f
:(function
31 | (_
, Class_const
((_
, CI
(_
, cls
)), (_
, name
)))
32 when String.equal name
SN.Members.mClass
->
37 and aast_contexts_to_decl_capability env ctxs default_pos
=
38 let default_pos = Decl_env.make_decl_pos env
default_pos in
41 let pos = Decl_env.make_decl_pos env
pos in
42 let hl = List.map ~f
:(hint env
) hl in
43 CapTy
(Typing_make_type.intersection
(Reason.Rhint
pos) hl)
44 | None
-> CapDefaults
default_pos
46 and aast_tparam_to_decl_tparam env t
=
48 tp_variance
= t
.Aast.tp_variance
;
49 tp_name
= Decl_env.make_decl_posed env t
.Aast.tp_name
;
51 List.map ~f
:(aast_tparam_to_decl_tparam env
) t
.Aast.tp_parameters
;
53 List.map ~f
:(Tuple.T2.map_snd ~f
:(hint env
)) t
.Aast.tp_constraints
;
54 tp_reified
= t
.Aast.tp_reified
;
57 ~f
:(aast_user_attribute_to_decl_user_attribute env
)
58 t
.Aast.tp_user_attributes
;
61 and hint_ p env
= function
62 | Hany
-> Typing_defs.make_tany
()
65 | Hnonnull
-> Tnonnull
67 | Hdynamic
-> Tdynamic
68 | Hnothing
-> Tunion
[]
69 | Hdarray
(h1
, h2
) -> Tdarray
(hint env h1
, hint env h2
)
70 | Hvarray
h -> Tvarray
(hint env
h)
71 | Hvarray_or_darray
(h1
, h2
) ->
74 | Some
h -> hint env
h
75 | None
-> mk
(Typing_reason.Rvarray_or_darray_key p
, Tprim
Aast.Tarraykey
)
77 Tvarray_or_darray
(t1, hint env h2
)
78 | Hvec_or_dict
(h1
, h2
) ->
81 | Some
h -> hint env
h
82 | None
-> mk
(Typing_reason.Rvec_or_dict_key p
, Tprim
Aast.Tarraykey
)
84 Tvec_or_dict
(t1, hint env h2
)
87 let argl = List.map
argl (hint env
) in
92 | Hlike
h -> Tlike
(hint env
h)
95 hf_reactive_kind
= reactivity
;
101 hf_is_mutable_return
= mut_ret
;
102 hf_is_readonly_return
= readonly_ret
;
104 let make_param ((p
, _
) as x
) param_info
=
105 let (mutability
, readonly
, kind
) =
106 match param_info
with
109 match p
.hfparam_mutability
with
110 | Some PMutable
-> Some Param_borrowed_mutable
111 | Some POwnedMutable
-> Some Param_owned_mutable
112 | Some PMaybeMutable
-> Some Param_maybe_mutable
116 match p
.hfparam_readonlyness
with
117 | Some
Ast_defs.Readonly
-> true
120 let param_kind = get_param_mode p
.hfparam_kind
in
121 (mutability, readonly, param_kind)
122 | None
-> (None
, false, FPnormal
)
125 fp_pos
= Decl_env.make_decl_pos env p
;
127 fp_type
= possibly_enforced_hint env x
;
131 ~accept_disposable
:false
135 (* Currently do not support external and cancall on parameters of function parameters *)
140 ~const_function
:false;
141 fp_rx_annotation
= None
;
145 match readonly_ret with
146 | Some
Ast_defs.Readonly
-> true
149 let paraml = List.map2_exn
hl pil ~f
:make_param in
150 let implicit_params =
151 let capability = aast_contexts_to_decl_capability env ctxs p
in
154 let ret = possibly_enforced_hint env
h in
157 | Some t
-> Fvariadic
(make_param t None
)
161 match reactivity with
163 | FNonreactive
-> Nonreactive
169 ft_where_constraints
= [];
171 ft_implicit_params
= implicit_params;
177 ~return_disposable
:false
178 ~returns_void_to_rx
:false
179 ~returns_mutable
:mut_ret
180 ~returns_readonly
:readonly_ret
183 (* TODO: The constness of a function type hint is associated with
184 an attribute on the parameter, not on the hint itself.
185 Thus it's always false here, but we check for the attribute
186 in readonly_check.ml. When we decide actual syntax for this,
187 this will likely change.
190 ft_reactive
= reactivity;
191 (* TODO: handle function parameters with <<CanCall>> *)
192 ft_ifc_decl
= default_ifc_fun_decl
;
194 | Happly
(id
, argl) ->
195 let id = Decl_env.make_decl_posed env
id in
196 let argl = List.map
argl (hint env
) in
198 | Haccess
((_
, Hvar n
), [(_
, id)]) -> Tgeneric
("T" ^ n ^
"@" ^
id, [])
199 | Haccess
(root_ty
, ids
) ->
200 let root_ty = hint_ p env
(snd
root_ty) in
201 let rec translate res ids
=
207 ( mk
(Typing_reason.Rhint
(Decl_env.make_decl_pos env p
), res
),
208 Decl_env.make_decl_posed env
id ))
211 translate root_ty ids
213 let tyl = List.map
hl (hint env
) in
216 let tyl = List.map
hl (hint env
) in
218 | Hintersection
hl ->
219 let tyl = List.map
hl (hint env
) in
221 | Hshape
{ nsi_allows_unknown_fields
; nsi_field_map
} ->
223 if nsi_allows_unknown_fields
then
232 (TShapeField.of_ast
(Decl_env.make_decl_pos env
) i
.sfi_name
)
233 (shape_field_info_to_shape_field_type env i
)
235 ~init
:TShapeMap.empty
238 Tshape
(shape_kind, fdm)
239 | Hsoft
(p
, h_
) -> hint_ p env h_
240 | Hfun_context n
-> Tgeneric
("Tctx" ^ n
, [])
241 | Hvar n
-> Tgeneric
("T" ^ n
, [])
243 and possibly_enforced_hint env
h =
244 (* Initially we assume that a type is not enforced at runtime.
245 * We refine this during localization
247 { et_enforced
= false; et_type
= hint env
h }