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.
13 module ExprDepTy
= struct
15 module Env
= Typing_env
16 module TUtils
= Typing_utils
19 let eid = Ident.tmp
() in
20 (Reason.ERexpr
eid, DTexpr
eid)
22 let from_cid env reason cid
=
23 let pos = Reason.to_pos reason
in
24 let (pos, expr_dep_reason
, dep
) =
27 (match Env.get_parent_id env
with
28 | Some cls
-> (pos, Reason.ERparent cls
, DTcls cls
)
30 let (ereason
, dep
) = new_ () in
33 (match get_node
(Env.get_self env
) with
34 | Tclass
((_
, cls
), _
, _
) -> (pos, Reason.ERself cls
, DTcls cls
)
36 let (ereason
, dep
) = new_ () in
38 | N.CI
(p
, cls
) -> (p
, Reason.ERclass cls
, DTcls cls
)
39 | N.CIstatic
-> (pos, Reason.ERstatic
, DTthis
)
40 | N.CIexpr
(p
, N.This
) -> (p
, Reason.ERstatic
, DTthis
)
41 (* If it is a local variable then we look up the expression id associated
42 * with it. If one doesn't exist we generate a new one. We are being
43 * conservative here because the new expression id we create isn't
44 * added to the local enviornment.
46 | N.CIexpr
(p
, N.Lvar
(_
, x
)) ->
48 match Env.get_local_expr_id env x
with
49 | Some
eid -> (Reason.ERexpr
eid, DTexpr
eid)
53 (* If all else fails we generate a new identifier for our expression
57 let (ereason
, dep
) = new_ () in
60 (Reason.Rexpr_dep_type
(reason
, pos, expr_dep_reason
), dep
)
62 (****************************************************************************)
63 (* A type access "this::T" is translated to "<this>::T" during the
64 * naming phase. While typing a body, "<this>" is a type hole that needs to
65 * be filled with a final concrete type. Resolution is specified in typing.ml,
66 * here is a high level break down:
68 * 1) When a class member "bar" is accessed via "[CID]->bar" or "[CID]::bar"
69 * we resolve "<this>" in the type of "bar" to "<[CID]>"
71 * 2) When typing a method, we resolve "<this>" in the return type to
74 * 3) When typing a method, we resolve "<this>" in parameters of the
75 * function to "<static>" in static methods or "<$this>" in non-static
78 * More specific details are explained inline
80 (****************************************************************************)
81 let make env ~cid ty
=
82 let (r_dep_ty
, dep_ty
) = from_cid env
(get_reason ty
) cid
in
83 let apply env ty
= (env
, mk
(r_dep_ty
, Tdependent
(dep_ty
, ty
))) in
85 let (env
, ety
) = Env.expand_type env ty
in
87 | (_
, Tclass
(_
, Exact
, _
)) -> (env
, ty
)
88 | (_
, Tclass
(((_
, x
) as c
), Nonexact
, tyl
)) ->
89 let class_ = Env.get_class env x
in
90 (* If a class is both final and variant, we must treat it as non-final
91 * since we can't statically guarantee what the runtime type
95 Option.value_map
class_ ~default
:false ~f
:(fun class_ty
->
96 TUtils.class_is_final_and_not_contravariant class_ty
)
101 | DTcls n
when String.equal n x
->
102 (env
, mk
(r_dep_ty
, Tclass
(c
, Exact
, tyl
)))
105 | (_
, Tgeneric
(s
, _tyargs
)) when DependentKind.is_generic_dep_ty s
->
106 (* TODO(T69551141) handle type arguments *)
109 (* TODO(T69551141) handle type arguments here? *)
110 let (env
, tyl
) = Typing_utils.get_concrete_supertypes env ty
in
111 let (env
, tyl'
) = List.fold_map tyl ~init
:env ~f
:make in
112 if tyl_equal tyl tyl'
then
116 | (_
, Tpu _
) -> apply env ty
118 let (env
, ty
) = make env ty
in
119 (env
, mk
(r
, Toption ty
))
120 | (r
, Tnewtype
(n
, p
, ty
)) ->
121 let (env
, ty
) = make env ty
in
122 (env
, mk
(r
, Tnewtype
(n
, p
, ty
)))
123 | (_
, Tdependent
(_
, _
)) -> (env
, ty
)
125 let (env
, tyl
) = List.fold_map tyl ~init
:env ~f
:make in
126 (env
, mk
(r
, Tunion tyl
))
127 | (r
, Tintersection tyl
) ->
128 let (env
, tyl
) = List.fold_map tyl ~init
:env ~f
:make in
129 (env
, mk
(r
, Tintersection tyl
))
130 (* TODO(T36532263) check if this is legal *)
132 ( Tobject
| Tnonnull
| Tprim _
| Tshape _
| Ttuple _
| Tdynamic
133 | Tvarray _
| Tdarray _
| Tvarray_or_darray _
| Tfun _
| Tany _
134 | Tvar _
| Terr
| Tpu_type_access _
) ) ->