Remove side-effecting variants from `typing_phase`
[hiphop-php.git] / hphp / hack / src / typing / typing_env_from_def.ml
blobac05f86c07ec010d34f081060078714e3d90984f
1 (*
2 * Copyright (c) 2018, Facebook, Inc.
3 * All rights reserved.
5 * This source code is licensed under the MIT license found in the
6 * LICENSE file in the "hack" directory of this source tree.
8 *)
10 open Hh_prelude
11 open Typing_defs
12 module Env = Typing_env
13 module MakeType = Typing_make_type
15 (*****************************************************************************)
16 (* Construct a Typing_env from an AAST toplevel definition.
18 (*****************************************************************************)
20 open Aast
22 let fun_env ?origin ctx fd =
23 let f = fd.fd_fun in
24 let file = Pos.filename (fst f.f_name) in
25 let droot = Some (Typing_deps.Dep.Fun (snd f.f_name)) in
26 let env = Typing_env_types.empty ?origin ctx file ~mode:fd.fd_mode ~droot in
27 Typing_inference_env.Identifier_provider.reinitialize ();
28 env
30 (* Given a class definition construct a type consisting of the
31 * class instantiated at its generic parameters. *)
32 let get_self_from_c c =
33 let tparams =
34 List.map c.c_tparams ~f:(fun { tp_name = (p, s); _ } ->
36 ( Reason.Rwitness_from_decl (Pos_or_decl.of_raw_pos p),
37 Tgeneric (s, []) ))
39 let (name_pos, name) = c.c_name in
40 let name_pos = Pos_or_decl.of_raw_pos name_pos in
41 mk (Reason.Rwitness_from_decl name_pos, Tapply ((name_pos, name), tparams))
43 (** Set 'self' identifier and type in environment. *)
44 let set_self env c =
45 let self_id = snd c.c_name in
46 let self = get_self_from_c c in
47 (* For enums, localize makes self:: into an abstract type, which we don't
48 * want *)
49 let (env, self_ty) =
50 match c.c_kind with
51 | Ast_defs.Cenum_class _
52 | Ast_defs.Cenum ->
53 ( env,
54 MakeType.class_type (Reason.Rwitness (fst c.c_name)) (snd c.c_name) []
56 | Ast_defs.Cinterface
57 | Ast_defs.Cclass _
58 | Ast_defs.Ctrait ->
59 let ((env, ty_err_opt), res) =
60 Typing_phase.localize_no_subst env ~ignore_errors:true self
62 Option.iter ty_err_opt ~f:Errors.add_typing_error;
63 (env, res)
65 let env = Env.set_self env self_id self_ty in
66 let env =
67 Env.add_upper_bound env Naming_special_names.Typehints.this self_ty
69 let env =
70 if c.c_final then
71 Env.add_lower_bound env Naming_special_names.Typehints.this self_ty
72 else
73 env
75 env
77 let set_parent env c =
78 (* In order to type-check a class, we need to know what "parent"
79 * refers to. Sometimes people write "parent::", when that happens,
80 * we need to know the type of parent.
82 match c.c_extends with
83 | ((_, Happly ((_, parent_id), _)) as parent_ty) :: _ ->
84 let parent_ty = Decl_hint.hint env.Typing_env_types.decl_env parent_ty in
85 Env.set_parent env parent_id parent_ty
86 (* The only case where we have more than one parent class is when
87 * dealing with interfaces and interfaces cannot use parent.
89 | _ :: _
90 | _ ->
91 env
93 let class_env ?origin ctx c =
94 let file = Pos.filename (fst c.c_name) in
95 let droot = Some (Typing_deps.Dep.Type (snd c.c_name)) in
96 let env = Typing_env_types.empty ?origin ctx file ~mode:c.c_mode ~droot in
97 Typing_inference_env.Identifier_provider.reinitialize ();
98 let env = set_self env c in
99 let env = set_parent env c in
102 let typedef_env ?origin ctx t =
103 let file = Pos.filename (fst t.t_kind) in
104 let droot = Some (Typing_deps.Dep.Type (snd t.t_name)) in
105 let env = Typing_env_types.empty ?origin ctx file ~mode:t.t_mode ~droot in
106 Typing_inference_env.Identifier_provider.reinitialize ();
109 let gconst_env ?origin ctx cst =
110 let file = Pos.filename (fst cst.cst_name) in
111 let droot = Some (Typing_deps.Dep.GConst (snd cst.cst_name)) in
112 let env = Typing_env_types.empty ?origin ctx file ~mode:cst.cst_mode ~droot in
113 Typing_inference_env.Identifier_provider.reinitialize ();