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.
16 open Typing_env_return_info
17 module Dep
= Typing_deps.Dep
18 module Inf
= Typing_inference_env
20 module SG
= SN.Superglobals
21 module LEnvC
= Typing_per_cont_env
22 module C
= Typing_continuations
23 module Cls
= Decl_provider.Class
24 module Fake
= Typing_fake_members
25 module ITySet
= Internal_type_set
26 module TPEnv
= Type_parameter_env
27 module KDefs
= Typing_kinding_defs
28 module TySet
= Typing_set
30 type class_or_typedef_result
=
31 | ClassResult
of Typing_classes_heap.Api.t
32 | TypedefResult
of Typing_defs.typedef_type
34 let show_env _
= "<env>"
36 let pp_env _ _
= Printf.printf
"%s\n" "<env>"
38 let get_tcopt env
= env
.genv
.tcopt
40 let map_tcopt env ~f
=
41 let tcopt = f env
.genv
.tcopt in
42 let genv = { env
.genv with tcopt } in
45 let get_deps_mode env
= Provider_context.get_deps_mode env
.decl_env
.Decl_env.ctx
47 let get_ctx env
= env
.decl_env
.Decl_env.ctx
49 let get_file env
= env
.genv.file
51 let get_tracing_info env
= env
.tracing_info
53 let set_log_level env key log_level
=
54 { env
with log_levels
= SMap.add key log_level env
.log_levels
}
56 let get_log_level env key
=
57 Option.value (SMap.find_opt key env
.log_levels
) ~default
:0
59 let env_log_function = ref (fun _pos _name _old_env _new_env
-> ())
61 let set_env_log_function f
= env_log_function := f
64 type res
. string -> ?level
:int -> env
-> env
* res
-> env
* res
=
65 fun name ?
(level
= 1) old_env
(new_env
, res
) ->
66 ( if get_log_level new_env name
>= 1 || get_log_level new_env
"env" >= level
70 (Inf.get_current_pos_from_tyvar_stack old_env
.inference_env
)
71 ~default
:old_env
.function_pos
73 !env_log_function pos name old_env new_env
);
76 let log_env_change name ?
(level
= 1) old_env new_env
=
77 let (env
, ()) = log_env_change_ name ~level old_env
(new_env
, ()) in
80 let wrap_inference_env_call :
81 type res
. env
-> (Inf.t
-> Inf.t
* res
) -> env
* res
=
83 let (inference_env
, res
) = f env
.inference_env
in
84 ({ env
with inference_env
}, res
)
86 let wrap_inference_env_call_res : type res
. env
-> (Inf.t
-> res
) -> res
=
89 wrap_inference_env_call env
(fun env
->
95 let wrap_inference_env_call_env : env
-> (Inf.t
-> Inf.t
) -> env
=
98 wrap_inference_env_call env
(fun env
->
104 let expand_var env r v
=
105 wrap_inference_env_call env (fun env -> Inf.expand_var env r v
)
107 let fresh_type_reason ?variance
env r
=
108 log_env_change_ "fresh_type_reason" env
109 @@ wrap_inference_env_call env (fun env ->
110 Inf.fresh_type_reason ?variance
env r
)
112 let fresh_type env p
=
113 log_env_change_ "fresh_type" env
114 @@ wrap_inference_env_call env (fun env -> Inf.fresh_type env p
)
116 let fresh_invariant_type_var env p
=
117 log_env_change_ "fresh_invariant_type_var" env
118 @@ wrap_inference_env_call env (fun env -> Inf.fresh_invariant_type_var env p
)
120 let new_global_tyvar env ?i r
=
121 log_env_change_ "new_global_tyvar" env
122 @@ wrap_inference_env_call env (fun env -> Inf.new_global_tyvar env ?i r
)
124 let add_subtype_prop env prop
=
125 log_env_change "add_subtype_prop" env
126 @@ wrap_inference_env_call_env env (fun env -> Inf.add_subtype_prop env prop
)
128 let is_global_tyvar env var
=
129 wrap_inference_env_call_res env (fun env -> Inf.is_global_tyvar env var
)
131 let get_global_tyvar_reason env var
=
132 wrap_inference_env_call_res env (fun env ->
133 Inf.get_global_tyvar_reason env var
)
135 let empty_bounds = TySet.empty
137 let tyvar_is_solved_or_skip_global env var
=
138 Inf.tyvar_is_solved_or_skip_global env.inference_env var
140 let make_tyvar_no_more_occur_in_tyvar env v ~no_more_in
:v'
=
141 wrap_inference_env_call_env env (fun env ->
142 Inf.make_tyvar_no_more_occur_in_tyvar env v ~no_more_in
:v'
)
144 let not_implemented s _
=
145 failwith
(Printf.sprintf
"Function %s not implemented" s
)
147 type simplify_unions
= env -> locl_ty
-> env * locl_ty
149 let (simplify_unions_ref
: simplify_unions
ref) =
150 ref (not_implemented "simplify_unions")
152 let simplify_unions x
= !simplify_unions_ref x
155 wrap_inference_env_call_env env (fun env -> Inf.bind env v ty
)
157 (** Unions and intersections containing unsolved type variables may remain
158 in an unsimplified form once those type variables get solved.
160 For example, consider the union (#1 | int) where #1 is an unsolved type variable.
161 If #1 gets solved to int, then this union will remain in the unsimplified form
162 (int | int) which compromise the robustness of some of our logic and might
163 cause performance issues (by creating big unsimplified unions).
165 To solve this problem, we wrap each union and intersection in a type var,
166 so we'd get `#2 -> (#1 | int)` (This is done in Typing_union and
167 Typing_intersection), and register that #1 occurs in #2 in
168 [env.tyvar_occurrences]. Then when #1 gets solved, we simplify #2.
170 This function deals with this simplification.
172 The simplification is recursive: simplifying a type variable will
173 trigger simplification of its own occurrences. *)
174 let simplify_occurrences env v
=
175 let rec simplify_occurrences env v ~seen_tyvars
=
176 let vars = Inf.get_tyvar_occurrences
env.inference_env v
in
177 let (env, seen_tyvars
) =
179 (fun v'
(env, seen_tyvars
) ->
180 (* This type variable is now solved and does not contain any unsolved
181 type variable, so we can remove it from its occurrences. *)
182 let env = make_tyvar_no_more_occur_in_tyvar env v ~no_more_in
:v'
in
183 (* Only simplify when the type of v' does not contain any more
184 unsolved type variables. *)
185 if not
@@ Inf.contains_unsolved_tyvars
env.inference_env v'
then
186 simplify_type_of_var
env v' ~seen_tyvars
193 and simplify_type_of_var
env v ~seen_tyvars
=
194 if ISet.mem v seen_tyvars
then
195 (* TODO raise exception. *)
198 let seen_tyvars = ISet.add v
seen_tyvars in
199 match Inf.get_direct_binding
env.inference_env v
with
200 | None
-> failwith
"Can only simplify type of bounded variables"
202 (* Only simplify the type of variables which are bound directly to a
203 concrete type to preserve the variable aliasings and save some memory. *)
205 match get_node ty
with
208 let (env, ty
) = simplify_unions env ty
in
209 (* we only call this function when v does not recursively contain unsolved
210 type variables, so ty here should not contain unsolved type variables and
211 it is safe to simply bind it without reupdating the type var occurrences. *)
212 let env = bind env v ty
in
215 simplify_occurrences env v ~
seen_tyvars
217 if not
@@ Inf.contains_unsolved_tyvars
env.inference_env v
then
218 fst
@@ simplify_occurrences env v ~
seen_tyvars:ISet.empty
222 let add env ?
(tyvar_pos
= Pos.none
) v ty
=
224 wrap_inference_env_call_env env (fun env -> Inf.add env ~tyvar_pos v ty
)
226 let env = simplify_occurrences env v
in
229 let get_type env r var
=
230 wrap_inference_env_call env (fun env -> Inf.get_type env r var
)
232 let expand_type env ty
=
233 wrap_inference_env_call env (fun env -> Inf.expand_type env ty
)
235 let expand_internal_type env ty
=
236 wrap_inference_env_call env (fun env -> Inf.expand_internal_type env ty
)
238 let get_tyvar_pos env var
=
239 wrap_inference_env_call_res env (fun env -> Inf.get_tyvar_pos env var
)
241 let get_tyvar_lower_bounds env var
=
242 wrap_inference_env_call_res env (fun env ->
243 Inf.get_tyvar_lower_bounds env var
)
245 let set_tyvar_lower_bounds env var tys
=
246 wrap_inference_env_call_env env (fun env ->
247 Inf.set_tyvar_lower_bounds env var tys
)
249 let get_tyvar_upper_bounds env var
=
250 wrap_inference_env_call_res env (fun env ->
251 Inf.get_tyvar_upper_bounds env var
)
253 let set_tyvar_upper_bounds env var tys
=
254 wrap_inference_env_call_env env (fun env ->
255 Inf.set_tyvar_upper_bounds env var tys
)
257 let get_tyvar_appears_covariantly env var
=
258 wrap_inference_env_call_res env (fun env ->
259 Inf.get_tyvar_appears_covariantly env var
)
261 let set_tyvar_appears_covariantly env var
=
262 wrap_inference_env_call_env env (fun env ->
263 Inf.set_tyvar_appears_covariantly env var
)
265 let get_tyvar_appears_contravariantly env var
=
266 wrap_inference_env_call_res env (fun env ->
267 Inf.get_tyvar_appears_contravariantly env var
)
269 let set_tyvar_appears_contravariantly env var
=
270 wrap_inference_env_call_env env (fun env ->
271 Inf.set_tyvar_appears_contravariantly env var
)
273 let get_tyvar_appears_invariantly env var
=
274 wrap_inference_env_call_res env (fun env ->
275 Inf.get_tyvar_appears_invariantly env var
)
277 let get_tyvar_eager_solve_fail env var
=
278 wrap_inference_env_call_res env (fun env ->
279 Inf.get_tyvar_eager_solve_fail env var
)
281 let set_tyvar_eager_solve_fail env var
=
282 wrap_inference_env_call_env env (fun env ->
283 Inf.set_tyvar_eager_solve_fail env var
)
285 let get_tyvar_type_consts env var
=
286 wrap_inference_env_call_res env (fun env -> Inf.get_tyvar_type_consts env var
)
288 let get_tyvar_type_const env var tid
=
289 wrap_inference_env_call_res env (fun env ->
290 Inf.get_tyvar_type_const env var tid
)
292 let set_tyvar_type_const env var tconstid ty
=
293 wrap_inference_env_call_env env (fun env ->
294 Inf.set_tyvar_type_const env var tconstid ty
)
296 let get_current_tyvars env =
297 wrap_inference_env_call_res env Inf.get_current_tyvars
299 let open_tyvars env p
=
300 wrap_inference_env_call_env env (fun env -> Inf.open_tyvars env p
)
302 let close_tyvars env = wrap_inference_env_call_env env Inf.close_tyvars
304 let extract_global_inference_env env =
305 wrap_inference_env_call env (fun env -> Inf.extract_global_inference_env env)
307 let wrap_ty_in_var env r ty
=
308 wrap_inference_env_call env (fun env -> Inf.wrap_ty_in_var env r ty
)
310 let get_shape_field_name = function
311 | Ast_defs.SFlit_int
(_
, s
)
312 | Ast_defs.SFlit_str
(_
, s
) ->
314 | Ast_defs.SFclass_const
((_
, s1
), (_
, s2
)) -> s1 ^
"::" ^ s2
316 let get_shape_field_name_pos = function
317 | Ast_defs.SFlit_int
(p
, _
)
318 | Ast_defs.SFlit_str
(p
, _
)
319 | Ast_defs.SFclass_const
((p
, _
), _
) ->
322 let next_cont_opt env = LEnvC.get_cont_option
C.Next
env.lenv
.per_cont_env
324 let all_continuations env = LEnvC.all_continuations env.lenv
.per_cont_env
327 match next_cont_opt env with
328 | None
-> TPEnv.empty
329 | Some entry
-> entry
.Typing_per_cont_env.tpenv
331 let get_global_tpenv env = env.global_tpenv
333 let get_pos_and_kind_of_generic env name
=
334 match TPEnv.get_with_pos name
(get_tpenv env) with
336 | None
-> TPEnv.get_with_pos name
env.global_tpenv
338 let get_lower_bounds env name tyargs
=
339 let tpenv = get_tpenv env in
340 let local = TPEnv.get_lower_bounds tpenv name tyargs
in
341 let global = TPEnv.get_lower_bounds env.global_tpenv name tyargs
in
342 TySet.union
local global
344 let get_upper_bounds env name tyargs
=
345 let tpenv = get_tpenv env in
346 let local = TPEnv.get_upper_bounds tpenv name tyargs
in
347 let global = TPEnv.get_upper_bounds env.global_tpenv name tyargs
in
348 TySet.union
local global
350 let get_reified env name
=
351 let tpenv = get_tpenv env in
352 let local = TPEnv.get_reified tpenv name
in
353 let global = TPEnv.get_reified env.global_tpenv name
in
354 match (local, global) with
359 | (_
, SoftReified
) ->
363 let get_enforceable env name
=
364 let tpenv = get_tpenv env in
365 let local = TPEnv.get_enforceable tpenv name
in
366 let global = TPEnv.get_enforceable env.global_tpenv name
in
369 let get_newable env name
=
370 let tpenv = get_tpenv env in
371 let local = TPEnv.get_newable tpenv name
in
372 let global = TPEnv.get_newable env.global_tpenv name
in
375 (* Get bounds that are both an upper and lower of a given generic *)
376 let get_equal_bounds env name tyargs
=
377 let lower = get_lower_bounds env name tyargs
in
378 let upper = get_upper_bounds env name tyargs
in
379 TySet.inter
lower upper
381 let env_with_tpenv env tpenv =
388 Typing_per_cont_env.(
389 update_cont_entry
C.Next
env.lenv
.per_cont_env
(fun entry
->
390 { entry
with tpenv }));
394 let env_with_global_tpenv env global_tpenv
= { env with global_tpenv
}
396 let add_upper_bound_global env name ty
=
398 let (env, ty
) = expand_type env ty
in
400 | (r
, Tgeneric
(formal_super
, [])) ->
401 TPEnv.add_lower_bound
404 (mk
(r
, Tgeneric
(name
, [])))
405 | (_r
, Tgeneric
(_formal_super
, _targs
)) ->
406 (* TODO(T70068435) Revisit this when implementing bounds on HK generic vars *)
408 | _
-> env.global_tpenv
410 { env with global_tpenv
= TPEnv.add_upper_bound
tpenv name ty
}
412 (* Add a single new upper bound [ty] to generic parameter [name] in the local
413 * type parameter environment of [env].
414 * If the optional [intersect] operation is supplied, then use this to avoid
415 * adding redundant bounds by merging the type with existing bounds. This makes
416 * sense because a conjunction of upper bounds
417 * (T <: t1) /\ ... /\ (T <: tn)
418 * is equivalent to a single upper bound
419 * T <: (t1 & ... & tn)
421 let add_upper_bound ?intersect
env name ty
=
422 env_with_tpenv env (TPEnv.add_upper_bound ?intersect
(get_tpenv env) name ty
)
424 (* Add a single new upper lower [ty] to generic parameter [name] in the
425 * local type parameter environment [env].
426 * If the optional [union] operation is supplied, then use this to avoid
427 * adding redundant bounds by merging the type with existing bounds. This makes
428 * sense because a conjunction of lower bounds
429 * (t1 <: T) /\ ... /\ (tn <: T)
430 * is equivalent to a single lower bound
431 * (t1 | ... | tn) <: T
433 let add_lower_bound ?union
env name ty
=
434 env_with_tpenv env (TPEnv.add_lower_bound ?union
(get_tpenv env) name ty
)
436 (* Add type parameters to environment, initially with no bounds.
437 * Existing type parameters with the same name will be overridden. *)
438 let add_generic_parameters env tparaml
=
439 env_with_tpenv env (TPEnv.add_generic_parameters (get_tpenv env) tparaml
)
441 let is_generic_parameter env name
=
442 TPEnv.mem name
(get_tpenv env) || SSet.mem name
env.fresh_typarams
444 let get_generic_parameters env =
445 TPEnv.get_names
(TPEnv.union
(get_tpenv env) env.global_tpenv
)
447 let get_tpenv_size env =
448 TPEnv.size
(get_tpenv env) + TPEnv.size
env.global_tpenv
450 let is_consistent env = TPEnv.is_consistent (get_tpenv env)
452 let mark_inconsistent env =
453 env_with_tpenv env (TPEnv.mark_inconsistent (get_tpenv env))
455 (* Generate a fresh generic parameter with a specified prefix but distinct
456 * from all generic parameters in the environment *)
457 let add_fresh_generic_parameter_by_kind env prefix kind
=
459 let name = Printf.sprintf
"%s#%d" prefix i
in
460 if is_generic_parameter env name then
465 let name = iterate 1 in
466 let env = { env with fresh_typarams
= SSet.add name env.fresh_typarams
} in
468 env_with_tpenv env (TPEnv.add ~def_pos
:Pos.none
name kind
(get_tpenv env))
472 let add_fresh_generic_parameter env prefix ~reified ~enforceable ~newable
=
476 lower_bounds
= empty_bounds;
477 upper_bounds
= empty_bounds;
484 add_fresh_generic_parameter_by_kind env prefix
kind
486 let is_fresh_generic_parameter name =
487 String.contains
name '#'
&& not
(DependentKind.is_generic_dep_ty
name)
489 let tparams_visitor env =
491 inherit [SSet.t
] Type_visitor.locl_type_visitor
493 method! on_tgeneric acc _ s _
=
494 (* as for tnewtype: not traversing args, although they may contain Tgenerics *)
497 (* Perserving behavior but this seems incorrect to me since a newtype may
498 * contain type arguments with generics
500 method! on_tdependent acc _ _ _
= acc
502 method! on_tnewtype acc _ _ _ _
= acc
504 method! on_tvar acc r ix
=
505 let (_env
, ty
) = expand_var env r ix
in
506 match get_node ty
with
508 | _
-> this#on_type acc ty
511 let get_tparams_aux env acc ty
= (tparams_visitor env)#on_type acc ty
513 let get_tparams env ty
= get_tparams_aux env SSet.empty ty
515 let get_tpenv_tparams env =
526 (* FIXME what to do here? it seems dangerous to just traverse *)
531 let (_env
, ty
) = expand_type env ty
in
532 match get_node ty
with
534 | _
-> get_tparams_aux env acc ty
536 TySet.fold
folder lower_bounds
@@ TySet.fold
folder upper_bounds acc
541 (* Replace types for locals with empty environment *)
542 let env_with_locals env locals
=
543 { env with lenv
= { env.lenv
with per_cont_env
= locals
} }
545 (* This is used whenever we start checking a method. Retain tpenv from the class type parameters *)
546 let reinitialize_locals env =
549 LEnvC.(initial_locals
{ empty_entry
with tpenv = get_tpenv env })
551 let initial_local tpenv local_reactive
=
553 per_cont_env
= LEnvC.(initial_locals
{ empty_entry
with tpenv });
554 local_using_vars
= LID.Set.empty
;
555 local_mutability
= LID.Map.empty
;
559 let empty ?origin ?
(mode
= FileInfo.Mstrict
) ctx file ~droot
=
561 function_pos
= Pos.none
;
562 fresh_typarams
= SSet.empty;
563 lenv
= initial_local TPEnv.empty Nonreactive
;
567 in_expr_tree
= false;
568 inside_constructor
= false;
569 decl_env
= { mode
; droot
; ctx
};
571 Option.map origin ~f
:(fun origin
-> { Decl_counters.origin
; file
});
574 tcopt = Provider_context.get_tcopt ctx
;
577 (* Actually should get set straight away anyway *)
579 { et_type
= mk
(Reason.Rnone
, Tunion
[]); et_enforced
= false };
580 return_disposable
= false;
581 return_mutable
= false;
582 return_explicit
= false;
583 return_void_to_rx
= false;
584 return_dynamically_callable
= false;
586 params
= LID.Map.empty;
587 condition_types
= SMap.empty;
592 fun_kind
= Ast_defs.FSync
;
596 global_tpenv
= TPEnv.empty;
597 log_levels
= TypecheckerOptions.log_levels
(Provider_context.get_tcopt ctx
);
598 inference_env
= Inf.empty_inference_env
;
599 allow_wildcards
= false;
604 let set_env_reactive env reactive
=
605 { env with lenv
= { env.lenv
with local_reactive
= reactive
} }
607 let set_env_pessimize env =
608 let pessimize_coefficient =
609 TypecheckerOptions.simple_pessimize
(get_tcopt env)
612 Pos.pessimize_enabled
env.function_pos
pessimize_coefficient
614 { env with pessimize }
616 let set_env_function_pos env function_pos
= { env with function_pos
}
618 let set_condition_type env n ty
=
622 { env.genv with condition_types
= SMap.add n ty
env.genv.condition_types
};
625 let get_condition_type env n
= SMap.find_opt n
env.genv.condition_types
627 (* Some form (strict/shallow/local) of reactivity *)
628 let env_local_reactive env =
629 not
(equal_reactivity
(env_reactivity
env) Nonreactive
)
631 let function_is_mutable env = env.genv.fun_mutable
633 let set_fun_mutable env mut
=
634 { env with genv = { env.genv with fun_mutable
= mut
} }
636 let error_if_reactive_context env f
=
637 if env_local_reactive env && not
(TypecheckerOptions.unsafe_rx
env.genv.tcopt)
641 let make_depend_on_class env class_name
=
642 let dep = Dep.Class class_name
in
643 Option.iter
env.decl_env
.droot
(fun root
->
644 Typing_deps.add_idep
(get_deps_mode env) root
dep);
647 let make_depend_on_constructor env class_name
=
648 make_depend_on_class env class_name
;
649 let dep = Dep.Cstr class_name
in
650 Option.iter
env.decl_env
.droot
(fun root
->
651 Typing_deps.add_idep
(get_deps_mode env) root
dep);
654 let make_depend_on_class_def env x cd
=
656 | Some cd
when Pos.is_hhi
(Cls.pos cd
) -> ()
657 | _
-> make_depend_on_class env x
659 let print_size _kind _name obj
=
667 (Obj.reachable_words (Obj.repr r) * (Sys.word_size / 8));*)
670 let get_typedef env x
=
675 (Decl_provider.get_typedef
676 ?tracing_info
:(get_tracing_info env)
681 | Some td
when Pos.is_hhi td
.td_pos
-> res
683 make_depend_on_class env x
;
686 let is_typedef env x
=
687 match Naming_provider.get_type_kind
(get_ctx env) x
with
688 | Some
Naming_types.TTypedef
-> true
691 let get_class (env : env) (name : string) : Cls.t
option =
696 (Decl_provider.get_class
697 ?tracing_info
:(get_tracing_info env)
701 make_depend_on_class_def env name res;
704 let get_class_or_typedef env x
=
705 if is_typedef env x
then
706 match get_typedef env x
with
708 | Some td
-> Some
(TypedefResult td
)
710 match get_class env x
with
712 | Some cd
-> Some
(ClassResult cd
)
714 let get_class_dep env x
=
715 let res = get_class env x
in
717 | Some cd
when Pos.is_hhi
(Cls.pos cd
) -> res
719 Decl_env.add_extends_dependency
env.decl_env x
;
727 (Decl_provider.get_fun
728 ?tracing_info
:(get_tracing_info env)
733 | Some fd
when Pos.is_hhi fd
.fe_pos
-> res
735 let dep = Typing_deps.Dep.Fun x
in
736 Option.iter
env.decl_env
.Decl_env.droot
(fun root
->
737 Typing_deps.add_idep
(get_deps_mode env) root
dep);
740 let get_enum_constraint env x
=
741 match get_class env x
with
744 (match Cls.enum_type tc
with
746 | Some e
-> e
.te_constraint
)
748 let env_with_mut env local_mutability
=
749 { env with lenv
= { env.lenv
with local_mutability
} }
751 let get_env_mutability env = env.lenv
.local_mutability
754 match get_class_or_typedef env x
with
755 | Some
(ClassResult tc
) when Option.is_some
(Cls.enum_type tc
) -> Some tc
759 match get_enum env x
with
761 (match Cls.enum_type cls
with
762 | Some enum_type
-> not enum_type
.te_enum_class
763 | None
-> false (* we know this is impossible due to get_enum *))
766 let is_enum_class env x
=
767 match get_enum env x
with
769 (match Cls.enum_type cls
with
770 | Some enum_type
-> enum_type
.te_enum_class
771 | None
-> false (* we know this is impossible due to get_enum *))
774 let get_typeconst env class_ mid
=
775 if not
(Pos.is_hhi
(Cls.pos class_
)) then begin
776 let dep = Dep.Const
(Cls.name class_
, mid
) in
777 make_depend_on_class env (Cls.name class_
);
778 Option.iter
env.decl_env
.droot
(fun root
->
779 Typing_deps.add_idep
(get_deps_mode env) root
dep)
781 Cls.get_typeconst class_ mid
783 (* Used to access class constants. *)
784 let get_const env class_ mid
=
785 if not
(Pos.is_hhi
(Cls.pos class_
)) then begin
786 let dep = Dep.Const
(Cls.name class_
, mid
) in
787 make_depend_on_class env (Cls.name class_
);
788 Option.iter
env.decl_env
.droot
(fun root
->
789 Typing_deps.add_idep
(get_deps_mode env) root
dep)
791 Cls.get_const class_ mid
793 (* Used to access "global constants". That is constants that were
794 * introduced with "const X = ...;" at topelevel, or "define('X', ...);"
796 let get_gconst env cst_name
=
798 Decl_provider.get_gconst
799 ?tracing_info
:(get_tracing_info env)
804 | Some cst
when Pos.is_hhi cst
.cd_pos
-> res
806 let dep = Dep.GConst cst_name
in
807 Option.iter
env.decl_env
.droot
(fun root
->
808 Typing_deps.add_idep
(get_deps_mode env) root
dep);
811 let get_static_member is_method
env class_ mid
=
812 (* The type of a member is stored separately in the heap. This means that
813 * any user of the member also has a dependency on the class where the member
818 Cls.get_smethod class_ mid
820 Cls.get_sprop class_ mid
822 if not
(Pos.is_hhi
(Cls.pos class_
)) then begin
823 make_depend_on_class env (Cls.name class_
);
831 Option.iter
env.decl_env
.droot
(fun root
->
832 Typing_deps.add_idep
(get_deps_mode env) root
dep)
834 add_dep (Cls.name class_
);
835 Option.iter
ce_opt (fun ce
-> add_dep ce
.ce_origin
)
840 (* Given a list of things whose name we can extract with `f`, return
841 the item whose name is closest to `name`. *)
842 let most_similar (name : string) (possibilities
: 'a list
) (f
: 'a
-> string) :
844 let distance = String_utils.levenshtein_distance
in
845 let choose_closest x y
=
846 if distance (f x
) name < distance (f y
) name then
851 List.fold possibilities ~init
:None ~f
:(fun acc possibility
->
853 | None
-> Some possibility
854 | Some current_best
-> Some
(choose_closest current_best possibility
))
856 let suggest_member members mid
=
858 List.map members ~f
:(fun (x
, { ce_type
= (lazy ty
); _
}) -> (get_pos ty
, x
))
860 most_similar mid
pairs snd
862 let suggest_static_member is_method class_ mid
=
863 let mid = String.lowercase
mid in
870 suggest_member members mid
872 let get_member is_method
env class_
mid =
880 Option.iter
env.decl_env
.droot
(fun root
->
881 Typing_deps.add_idep
(get_deps_mode env) root
dep)
883 (* The type of a member is stored separately in the heap. This means that
884 * any user of the member also has a dependency on the class where the member
889 Cls.get_method class_
mid
891 Cls.get_prop class_
mid
893 if not
(Pos.is_hhi
(Cls.pos class_
)) then
894 make_depend_on_class env (Cls.name class_
);
895 Option.iter
ce_opt (fun ce
->
896 add_dep (Cls.name class_
);
897 add_dep ce
.ce_origin
);
900 let suggest_member is_method class_
mid =
901 let mid = String.lowercase
mid in
908 suggest_member members mid
910 let get_construct env class_
=
911 if not
(Pos.is_hhi
(Cls.pos class_
)) then begin
912 make_depend_on_constructor env (Cls.name class_
);
914 (fst
(Cls.construct class_
))
915 (fun ce
-> make_depend_on_constructor env ce
.ce_origin
)
919 let get_return env = env.genv.return
921 let set_return env x
=
922 let genv = env.genv in
923 let genv = { genv with return
= x
} in
926 let get_params env = env.genv.params
928 let set_params env params
= { env with genv = { env.genv with params
} }
930 let set_param env x param
=
931 let params = get_params env in
932 let params = LID.Map.add x param
params in
933 set_params env params
935 let clear_params env = set_params env LID.Map.empty
938 let ret = get_return env in
939 let params = get_params env in
940 let (env, result
) = f
env in
941 let env = set_params env params in
942 let env = set_return env ret in
945 let with_origin env origin f
=
946 let ti1 = env.tracing_info
in
947 let ti2 = Option.map
ti1 ~f
:(fun ti
-> { ti
with Decl_counters.origin
}) in
948 let env = { env with tracing_info
= ti2 } in
949 let (env, result
) = f
env in
950 let env = { env with tracing_info
= ti1 } in
953 let with_origin2 env origin f
=
954 let ti1 = env.tracing_info
in
955 let ti2 = Option.map
ti1 ~f
:(fun ti
-> { ti
with Decl_counters.origin
}) in
956 let env = { env with tracing_info
= ti2 } in
957 let (env, r1
, r2
) = f
env in
958 let env = { env with tracing_info
= ti1 } in
961 let is_static env = env.genv.static
963 let get_val_kind env = env.genv.val_kind
965 let get_self_ty env = Option.map
env.genv.self ~f
:snd
967 let get_self_class_type env =
968 match get_self_ty env with
971 match get_node self
with
972 | Tclass
(id
, exact
, tys
) -> Some
(id
, exact
, tys
)
977 let get_self_id env = Option.map
env.genv.self ~f
:fst
979 let get_self_class env =
981 get_self_id env >>= get_class env
983 let get_parent_ty env = Option.map
env.genv.parent ~f
:snd
985 let get_parent_id env = Option.map
env.genv.parent ~f
:fst
987 let get_parent_class env =
989 get_parent_id env >>= get_class_dep env
991 let get_fn_kind env = env.genv.fun_kind
993 let set_fn_kind env fn_type
=
994 let genv = env.genv in
995 let genv = { genv with fun_kind
= fn_type
} in
998 let set_self env self_id self_ty
=
999 let genv = env.genv in
1000 let genv = { genv with self
= Some
(self_id
, self_ty
) } in
1003 let set_parent env parent_id parent_ty
=
1004 let genv = env.genv in
1005 let genv = { genv with parent
= Some
(parent_id
, parent_ty
) } in
1008 let set_static env =
1009 let genv = env.genv in
1010 let genv = { genv with static
= true } in
1013 let set_val_kind env x
=
1014 let genv = env.genv in
1015 let genv = { genv with val_kind
= x
} in
1018 let set_mode env mode
=
1019 let decl_env = env.decl_env in
1020 let decl_env = { decl_env with mode
} in
1021 { env with decl_env }
1023 let get_mode env = env.decl_env.mode
1025 let is_strict env = FileInfo.is_strict (get_mode env)
1027 let is_hhi env = FileInfo.(equal_mode
(get_mode env) Mhhi
)
1029 let get_allow_solve_globals env =
1030 wrap_inference_env_call_res env Inf.get_allow_solve_globals
1032 let set_allow_solve_globals env flag
=
1033 wrap_inference_env_call_env env (fun env ->
1034 Inf.set_allow_solve_globals env flag
)
1036 (*****************************************************************************)
1038 (*****************************************************************************)
1040 let set_local_ env x ty
=
1041 let per_cont_env = LEnvC.add_to_cont
C.Next x ty
env.lenv
.per_cont_env in
1042 { env with lenv
= { env.lenv
with per_cont_env } }
1044 (* We maintain 2 states for a local: the type
1045 * that the local currently has, and an expression_id generated from
1046 * the last assignment to this local.
1048 let set_local ?
(immutable
= false) env x new_type
pos =
1050 match get_node
new_type with
1054 match next_cont_opt env with
1058 match LID.Map.find_opt x next_cont
.LEnvC.local_types
with
1059 | None
-> Ident.tmp
()
1060 | Some
(_
, _
, y
) -> y
1064 LID.make_immutable
expr_id
1068 let local = (new_type, pos, expr_id) in
1069 set_local_ env x
local
1071 let is_using_var env x
= LID.Set.mem x
env.lenv
.local_using_vars
1073 let set_using_var env x
=
1079 local_using_vars
= LID.Set.add x
env.lenv
.local_using_vars
;
1083 let unset_local env local =
1084 let { per_cont_env; local_using_vars
; local_mutability
; local_reactive
} =
1088 LEnvC.remove_from_cont
C.Next
local
1089 @@ LEnvC.remove_from_cont
C.Catch
local
1092 let local_using_vars = LID.Set.remove
local local_using_vars in
1093 let local_mutability = LID.Map.remove
local local_mutability in
1098 { per_cont_env; local_using_vars; local_mutability; local_reactive
};
1103 let add_mutable_var env local mutability_type
=
1104 env_with_mut env (LID.Map.add local mutability_type
env.lenv
.local_mutability)
1106 let local_is_mutable ~include_borrowed
env id
=
1107 let module TME
= Typing_mutability_env
in
1108 match LID.Map.find_opt id
(get_env_mutability env) with
1109 | Some
(_
, TME.Mutable
) -> true
1110 | Some
(_
, TME.Borrowed
) -> include_borrowed
1114 let dynamic_view_enabled = TypecheckerOptions.dynamic_view
(get_tcopt env) in
1115 if dynamic_view_enabled then
1118 Typing_defs.make_tany
()
1120 let get_local_in_ctx env ?error_if_undef_at_pos
:p x ctx_opt
=
1121 let not_found_is_ok x ctx
=
1122 let xstr = LID.to_string x
in
1123 (String.equal
xstr SG.globals
|| SG.is_superglobal
xstr)
1124 && not
(is_strict env)
1125 || Fake.is_valid ctx
.LEnvC.fake_members x
1127 let error_if_pos_provided posopt ctx
=
1130 let in_rx_scope = env_local_reactive env in
1131 let lid = LID.to_string x
in
1132 let suggest_most_similar lid =
1133 (* Ignore fake locals *)
1137 if String.is_prefix ~prefix
:"$#" (LID.to_string k
) then
1141 ctx
.LEnvC.local_types
1144 let var_name (k
, _
) = LID.to_string k
in
1145 match most_similar lid all_locals var_name with
1146 | Some
(k
, (_
, pos, _
)) -> Some
(LID.to_string k
, pos)
1149 Errors.undefined ~
in_rx_scope p
lid (suggest_most_similar lid)
1154 (* If the continuation is absent, we are in dead code so the variable should
1155 have type nothing. *)
1156 Some
(Typing_make_type.nothing
Reason.Rnone
, Pos.none
, 0)
1158 let lcl = LID.Map.find_opt x ctx
.LEnvC.local_types
in
1162 if not_found_is_ok x ctx
then
1165 error_if_pos_provided p ctx
1170 let get_local_ty_in_ctx env ?error_if_undef_at_pos x ctx_opt
=
1171 match get_local_in_ctx env ?error_if_undef_at_pos x ctx_opt
with
1172 | None
-> (false, mk
(Reason.Rnone
, tany env), Pos.none
)
1173 | Some
(x
, pos, _
) -> (true, x
, pos)
1175 let get_local_in_next_continuation ?error_if_undef_at_pos
:p
env x
=
1176 let next_cont = next_cont_opt env in
1177 get_local_ty_in_ctx env ?error_if_undef_at_pos
:p x
next_cont
1179 let get_local_ ?error_if_undef_at_pos
:p
env x
=
1181 get_local_in_next_continuation ?error_if_undef_at_pos
:p
env x
1185 let get_local env x
= snd
(get_local_ env x
)
1187 let get_local_pos env x
=
1188 let (_
, ty
, pos) = get_local_in_next_continuation env x
in
1191 let get_locals env plids
=
1192 let next_cont = next_cont_opt env in
1193 List.fold plids ~init
:LID.Map.empty ~f
:(fun locals
(p
, lid) ->
1194 match get_local_in_ctx env ~error_if_undef_at_pos
:p
lid next_cont with
1196 | Some ty_eid
-> LID.Map.add lid ty_eid locals
)
1198 let set_locals env locals
=
1199 LID.Map.fold
(fun lid ty
env -> set_local_ env lid ty
) locals
env
1201 let is_local_defined env x
=
1202 let next_cont = next_cont_opt env in
1203 Option.is_some
next_cont && fst
(get_local_ env x
)
1205 let get_local_check_defined env (p
, x
) =
1206 snd
(get_local_ ~error_if_undef_at_pos
:p
env x
)
1208 let set_local_expr_id env x new_eid
=
1209 let per_cont_env = env.lenv
.per_cont_env in
1210 match LEnvC.get_cont_option
C.Next
per_cont_env with
1214 match LID.Map.find_opt x
next_cont.LEnvC.local_types
with
1215 | Some
(type_
, pos, eid
)
1216 when not
(Typing_local_types.equal_expression_id eid new_eid
) ->
1217 if LID.is_immutable eid
then Errors.immutable_local
pos;
1218 let local = (type_
, pos, new_eid
) in
1219 let per_cont_env = LEnvC.add_to_cont
C.Next x
local per_cont_env in
1220 let env = { env with lenv
= { env.lenv
with per_cont_env } } in
1225 let get_local_expr_id env x
=
1226 match next_cont_opt env with
1227 | None
-> (* dead code *) None
1229 let lcl = LID.Map.find_opt x
next_cont.LEnvC.local_types
in
1230 Option.map
lcl ~f
:(fun (_
, _
, x
) -> x
)
1232 let set_fake_members env fake_members
=
1234 LEnvC.update_cont_entry
C.Next
env.lenv
.per_cont_env (fun entry
->
1235 { entry
with LEnvC.fake_members
})
1237 { env with lenv
= { env.lenv
with per_cont_env } }
1239 let get_fake_members env =
1240 match LEnvC.get_cont_option
C.Next
env.lenv
.per_cont_env with
1241 | None
-> Fake.empty
1242 | Some
next_cont -> next_cont.LEnvC.fake_members
1244 let update_lost_info name blame
env ty
=
1245 let info r
= Reason.Rlost_info
(name, r
, blame
) in
1246 let rec update_ty (env, seen_tyvars) ty
=
1247 let (env, ty
) = expand_type env ty
in
1250 if ISet.mem v
seen_tyvars then
1251 ((env, seen_tyvars), ty
)
1253 let seen_tyvars = ISet.add v
seen_tyvars in
1254 let bs = get_tyvar_lower_bounds env v
in
1255 let ((env, seen_tyvars), bs) =
1256 ITySet.fold_map
bs ~init
:(env, seen_tyvars) ~f
:update_ty_i
1258 let env = set_tyvar_lower_bounds env v
bs in
1259 let bs = get_tyvar_upper_bounds env v
in
1260 let ((env, seen_tyvars), bs) =
1261 ITySet.fold_map
bs ~init
:(env, seen_tyvars) ~f
:update_ty_i
1263 let env = set_tyvar_upper_bounds env v
bs in
1264 ((env, seen_tyvars), ty
)
1265 | (r
, Toption ty
) ->
1266 let ((env, seen_tyvars), ty
) = update_ty (env, seen_tyvars) ty
in
1267 ((env, seen_tyvars), mk
(info r
, Toption ty
))
1268 | (r
, Tunion tyl
) ->
1269 let ((env, seen_tyvars), tyl
) =
1270 List.fold_map tyl ~init
:(env, seen_tyvars) ~f
:update_ty
1272 ((env, seen_tyvars), mk
(info r
, Tunion tyl
))
1273 | _
-> ((env, seen_tyvars), map_reason ty ~f
:info)
1274 and update_ty_i
(env, seen_tyvars) ty
=
1277 let ((env, seen_tyvars), ty
) = update_ty (env, seen_tyvars) ty
in
1278 ((env, seen_tyvars), LoclType ty
)
1279 | ConstraintType ty
->
1280 let (r
, ty
) = deref_constraint_type ty
in
1281 ((env, seen_tyvars), ConstraintType
(mk_constraint_type
(info r
, ty
)))
1283 let ((env, _seen_tyvars
), ty
) = update_ty (env, ISet.empty) ty
in
1286 let forget_generic forget
env blame
=
1287 let fake_members = get_fake_members env in
1288 let fake_members = forget
fake_members blame
in
1289 set_fake_members env fake_members
1291 let forget_members = forget_generic Fake.forget
1293 let forget_prefixed_members env lid =
1294 forget_generic (fun fake_members -> Fake.forget_prefixed
fake_members lid) env
1296 let forget_suffixed_members env suffix
=
1298 (fun fake_members -> Fake.forget_suffixed
fake_members suffix
)
1301 module FakeMembers
= struct
1302 let update_fake_members env fake_members =
1304 LEnvC.update_cont_entry
C.Next
env.lenv
.per_cont_env (fun entry
->
1305 LEnvC.{ entry
with fake_members })
1307 { env with lenv
= { env.lenv
with per_cont_env } }
1309 let is_valid env obj member_name
=
1313 let fake_members = get_fake_members env in
1314 let id = Fake.make_id obj member_name
in
1315 Fake.is_valid fake_members id
1318 let is_valid_static env cid member_name
=
1319 let name = Fake.make_static_id cid member_name
in
1320 let fake_members = get_fake_members env in
1321 Fake.is_valid fake_members name
1323 let check_static_invalid env cid member_name ty
=
1324 let fake_members = get_fake_members env in
1325 let fake_id = Fake.make_static_id cid member_name
in
1326 match Fake.is_invalid
fake_members fake_id with
1328 | Some blame
-> update_lost_info (Local_id.to_string
fake_id) blame
env ty
1330 let check_instance_invalid env obj member_name ty
=
1334 let fake_members = get_fake_members env in
1335 let fake_id = Fake.make_id obj member_name
in
1337 match Fake.is_invalid
fake_members fake_id with
1340 update_lost_info (Local_id.to_string
fake_id) blame
env ty
1344 let add_member env fake_id pos =
1345 let fake_members = get_fake_members env in
1346 let fake_members = Fake.add fake_members fake_id pos in
1347 set_fake_members env fake_members
1349 let make env obj_name member_name
pos =
1350 let my_fake_local_id = Fake.make_id obj_name member_name
in
1351 let env = add_member env my_fake_local_id pos in
1352 (env, my_fake_local_id)
1354 let make_static env class_name member_name
pos =
1355 let my_fake_local_id = Fake.make_static_id class_name member_name
in
1356 let env = add_member env my_fake_local_id pos in
1357 (env, my_fake_local_id)
1360 (*****************************************************************************)
1361 (* Sets up/cleans up the environment when typing anonymous function / lambda *)
1362 (*****************************************************************************)
1364 let closure lenv
env f
=
1365 (* Setting up the environment. *)
1366 let old_lenv = env.lenv
in
1367 let old_return = get_return env in
1368 let old_params = get_params env in
1369 let outer_fun_kind = get_fn_kind env in
1370 let env = { env with lenv
} in
1372 let (env, ret) = f
env in
1373 (* Cleaning up the environment. *)
1374 let env = { env with lenv
= old_lenv } in
1375 let env = set_params env old_params in
1376 let env = set_return env old_return in
1377 let env = set_fn_kind env outer_fun_kind in
1381 let old_in_try = env.in_try in
1382 let env = { env with in_try = true } in
1383 let (env, result
) = f
env in
1384 ({ env with in_try = old_in_try }, result
)
1387 let old_in_case = env.in_case in
1388 let env = { env with in_case = true } in
1389 let (env, result
) = f
env in
1390 ({ env with in_case = old_in_case }, result
)
1392 (* Return the subset of env which is saved in the Typed AST's EnvAnnotation. *)
1393 let save local_tpenv
env =
1395 Tast.tcopt = get_tcopt env;
1396 Tast.inference_env
= env.inference_env
;
1397 Tast.tpenv = TPEnv.union local_tpenv
env.global_tpenv
;
1398 Tast.reactivity
= env_reactivity
env;
1399 Tast.local_mutability = get_env_mutability env;
1400 Tast.fun_mutable
= function_is_mutable env;
1401 Tast.condition_types
= env.genv.condition_types
;
1402 Tast.pessimize = env.pessimize;
1405 (* Compute the type variables appearing covariantly (positively)
1406 * resp. contravariantly (negatively) in a given type ty.
1407 * Return a pair of sets of positive and negative type variables
1408 * (as well as an updated environment).
1410 let rec get_tyvars env (ty
: locl_ty
) = get_tyvars_i
env (LoclType ty
)
1412 and get_tyvars_i
env (ty
: internal_type
) =
1413 let get_tyvars_union (env, acc_positive
, acc_negative
) ty
=
1414 let (env, positive
, negative
) = get_tyvars env ty
in
1415 (env, ISet.union acc_positive positive
, ISet.union acc_negative negative
)
1417 let get_tyvars_param (env, acc_positive
, acc_negative
) fp
=
1418 let (env, positive
, negative
) = get_tyvars env fp
.fp_type
.et_type
in
1419 match get_fp_mode fp
with
1420 (* Parameters are treated contravariantly *)
1422 (env, ISet.union negative acc_positive
, ISet.union positive acc_negative
)
1423 (* Inout parameters are both co- and contra-variant *)
1425 let tyvars = ISet.union negative positive
in
1426 (env, ISet.union
tyvars acc_positive
, ISet.union
tyvars acc_negative
)
1428 let (env, ety
) = expand_internal_type env ty
in
1431 (match get_node ety
with
1432 | Tvar v
-> (env, ISet.singleton v
, ISet.empty)
1439 (env, ISet.empty, ISet.empty)
1440 | Toption ty
-> get_tyvars env ty
1443 | Tintersection tyl
->
1444 List.fold_left tyl ~init
:(env, ISet.empty, ISet.empty) ~f
:get_tyvars_union
1447 (fun _
{ sft_ty
; _
} res -> get_tyvars_union res sft_ty
)
1449 (env, ISet.empty, ISet.empty)
1451 let (env, params_positive
, params_negative
) =
1452 match ft
.ft_arity
with
1453 | Fstandard
-> (env, ISet.empty, ISet.empty)
1454 | Fvariadic fp
-> get_tyvars_param (env, ISet.empty, ISet.empty) fp
1456 let (env, params_positive
, params_negative
) =
1459 ~init
:(env, params_positive
, params_negative
)
1462 let (env, ret_positive
, ret_negative
) =
1463 get_tyvars env ft
.ft_ret
.et_type
1466 ISet.union ret_positive params_positive
,
1467 ISet.union ret_negative params_negative
)
1468 | Tnewtype
(name, tyl
, _
) ->
1469 if List.is_empty tyl
then
1470 (env, ISet.empty, ISet.empty)
1472 match get_typedef env name with
1473 | Some
{ td_tparams
; _
} ->
1474 let variancel = List.map td_tparams
(fun t
-> t
.tp_variance
) in
1475 get_tyvars_variance_list
(env, ISet.empty, ISet.empty) variancel tyl
1476 | None
-> (env, ISet.empty, ISet.empty)
1478 | Tdependent
(_
, ty
) -> get_tyvars env ty
1479 | Tgeneric
(_
, tyl
) ->
1480 (* TODO(T69931993) Once implementing variance support for HK types, query
1481 tyvar env here for list of variances *)
1482 let variancel = List.replicate
(List.length tyl
) Ast_defs.Invariant
in
1483 get_tyvars_variance_list
(env, ISet.empty, ISet.empty) variancel tyl
1484 | Tclass
((_
, cid
), _
, tyl
) ->
1485 if List.is_empty tyl
then
1486 (env, ISet.empty, ISet.empty)
1488 match get_class env cid
with
1490 let variancel = List.map
(Cls.tparams cls
) (fun t
-> t
.tp_variance
) in
1491 get_tyvars_variance_list
(env, ISet.empty, ISet.empty) variancel tyl
1492 | None
-> (env, ISet.empty, ISet.empty)
1494 | Tvarray ty
-> get_tyvars env ty
1495 | Tdarray
(ty1
, ty2
) ->
1496 let (env, positive1
, negative1
) = get_tyvars env ty1
in
1497 let (env, positive2
, negative2
) = get_tyvars env ty2
in
1498 (env, ISet.union positive1 positive2
, ISet.union negative1 negative2
)
1499 | Tvec_or_dict
(ty1
, ty2
)
1500 | Tvarray_or_darray
(ty1
, ty2
) ->
1501 let (env, positive1
, negative1
) = get_tyvars env ty1
in
1502 let (env, positive2
, negative2
) = get_tyvars env ty2
in
1503 (env, ISet.union positive1 positive2
, ISet.union negative1 negative2
)
1504 | Tunapplied_alias _
-> (env, ISet.empty, ISet.empty)
1505 | Taccess
(ty
, _ids
) -> get_tyvars env ty
)
1506 | ConstraintType ty
->
1507 (match deref_constraint_type ty
with
1508 | (_
, Tdestructure
{ d_required
; d_optional
; d_variadic
; d_kind
= _
}) ->
1509 let (env, positive1
, negative1
) =
1512 ~init
:(env, ISet.empty, ISet.empty)
1515 let (env, positive2
, negative2
) =
1518 ~init
:(env, ISet.empty, ISet.empty)
1521 let (env, positive3
, negative3
) =
1522 match d_variadic
with
1523 | Some ty
-> get_tyvars env ty
1524 | None
-> (env, ISet.empty, ISet.empty)
1527 ISet.union
(ISet.union positive1 positive2
) positive3
,
1528 ISet.union
(ISet.union negative1 negative2
) negative3
)
1529 | (_
, Thas_member hm
) ->
1530 let { hm_type
; hm_name
= _
; hm_class_id
= _
; hm_explicit_targs
= _
} =
1533 get_tyvars env hm_type
1534 | (_
, TCunion
(lty
, cty
))
1535 | (_
, TCintersection
(lty
, cty
)) ->
1536 let (env, positive1
, negative1
) = get_tyvars env lty
in
1537 let (env, positive2
, negative2
) = get_tyvars_i
env (ConstraintType cty
) in
1538 (env, ISet.union positive1 positive2
, ISet.union negative1 negative2
))
1540 and get_tyvars_variance_list
(env, acc_positive
, acc_negative
) variancel tyl
=
1541 match (variancel, tyl
) with
1542 | (variance
:: variancel, ty
:: tyl
) ->
1543 let (env, positive
, negative
) = get_tyvars env ty
in
1544 let (acc_positive
, acc_negative
) =
1546 | Ast_defs.Covariant
->
1547 (ISet.union acc_positive positive
, ISet.union acc_negative negative
)
1548 | Ast_defs.Contravariant
->
1549 (ISet.union acc_positive negative
, ISet.union acc_negative positive
)
1550 | Ast_defs.Invariant
->
1551 let positive_or_negative = ISet.union positive negative
in
1552 ( ISet.union acc_positive
positive_or_negative,
1553 ISet.union acc_negative
positive_or_negative )
1555 get_tyvars_variance_list
(env, acc_positive
, acc_negative
) variancel tyl
1556 | _
-> (env, acc_positive
, acc_negative
)
1558 let rec set_tyvar_appears_covariantly_and_propagate env var
=
1559 if get_tyvar_appears_covariantly env var
then
1562 let env = set_tyvar_appears_covariantly env var
in
1563 let lower_bounds = get_tyvar_lower_bounds env var
in
1564 update_variance_of_tyvars_occurring_in_lower_bounds
env lower_bounds
1566 and set_tyvar_appears_contravariantly_and_propagate
env var
=
1567 if get_tyvar_appears_contravariantly env var
then
1570 let env = set_tyvar_appears_contravariantly env var
in
1571 let upper_bounds = get_tyvar_upper_bounds env var
in
1572 update_variance_of_tyvars_occurring_in_upper_bounds
env upper_bounds
1574 and update_variance_of_tyvars_occurring_in_lower_bounds
env tys
=
1576 (fun ty
env -> update_variance_of_tyvars_occurring_in_lower_bound
env ty
)
1580 and update_variance_of_tyvars_occurring_in_upper_bounds
env tys
=
1582 (fun ty
env -> update_variance_of_tyvars_occurring_in_upper_bound
env ty
)
1586 and update_variance_of_tyvars_occurring_in_lower_bound
env ty
=
1587 let (env, ety
) = expand_internal_type env ty
in
1589 | LoclType ty
when is_tyvar ty
-> env
1591 let (env, positive
, negative
) = get_tyvars_i
env ty
in
1594 (fun var
env -> set_tyvar_appears_covariantly env var
)
1600 (fun var
env -> set_tyvar_appears_contravariantly env var
)
1606 and update_variance_of_tyvars_occurring_in_upper_bound
env ty
=
1607 let (env, ety
) = expand_internal_type env ty
in
1609 | LoclType ty
when is_tyvar ty
-> env
1611 let (env, positive
, negative
) = get_tyvars_i
env ty
in
1614 (fun var
env -> set_tyvar_appears_contravariantly env var
)
1620 (fun var
env -> set_tyvar_appears_covariantly env var
)
1626 let set_tyvar_appears_covariantly = set_tyvar_appears_covariantly_and_propagate
1628 let set_tyvar_appears_contravariantly =
1629 set_tyvar_appears_contravariantly_and_propagate
1631 (* After a type variable var has been "solved", or bound to a type ty, we need
1632 * to update the variance of type variables occurring in ty. Suppose that
1633 * variable var is marked "appears covariantly", i.e. it appears (at least) in
1634 * positive positions in the type of an expression. Then when we substitute ty
1635 * for var, variables that appear positively in ty must now be marked as
1636 * appearing covariantly; variables that appear negatively in ty must now be
1637 * marked as appearing contravariantly. And the dual, if the variable var is marked
1638 * "appears contravariantly".
1640 let update_variance_after_bind env var ty
=
1641 let appears_contravariantly = get_tyvar_appears_contravariantly env var
in
1642 let appears_covariantly = get_tyvar_appears_covariantly env var
in
1643 let (env, positive
, negative
) = get_tyvars env ty
in
1648 if appears_contravariantly then
1649 set_tyvar_appears_contravariantly env var
1653 if appears_covariantly then
1654 set_tyvar_appears_covariantly env var
1664 if appears_contravariantly then
1665 set_tyvar_appears_covariantly env var
1669 if appears_covariantly then
1670 set_tyvar_appears_contravariantly env var
1678 let set_tyvar_variance_i env ?
(flip
= false) ?
(for_all_vars
= false) ty
=
1679 log_env_change "set_tyvar_variance" env
1681 let (env, positive
, negative
) = get_tyvars_i
env ty
in
1682 let (positive
, negative
) =
1684 (negative
, positive
)
1686 (positive
, negative
)
1689 if for_all_vars
then
1690 ISet.union positive negative
|> ISet.elements
1692 get_current_tyvars env
1694 List.fold_left
tyvars ~init
:env ~f
:(fun env var
->
1696 if ISet.mem var positive
then
1697 set_tyvar_appears_covariantly env var
1702 if ISet.mem var negative
then
1703 set_tyvar_appears_contravariantly env var
1709 let set_tyvar_variance env ?
(flip
= false) ?
(for_all_vars
= false) ty
=
1710 set_tyvar_variance_i env ~flip ~for_all_vars
(LoclType ty
)
1712 let add_tyvar_upper_bound ?intersect
env var
(ty
: internal_type
) =
1713 log_env_change "add_tyvar_upper_bound" env
1714 @@ wrap_inference_env_call_env env (fun env ->
1715 Inf.add_tyvar_upper_bound ?intersect
env var ty
)
1717 (* Add a single new upper bound [ty] to type variable [var] in [env.inference_env].
1718 * If the optional [intersect] operation is supplied, then use this to avoid
1719 * adding redundant bounds by merging the type with existing bounds. This makes
1720 * sense because a conjunction of upper bounds
1721 * (v <: t1) /\ ... /\ (v <: tn)
1722 * is equivalent to a single upper bound
1723 * v <: (t1 & ... & tn)
1725 let add_tyvar_upper_bound_and_update_variances
1726 ?intersect
env var
(ty
: internal_type
) =
1727 log_env_change "add_tyvar_upper_bound" env
1729 let env = add_tyvar_upper_bound ?intersect
env var ty
in
1730 if get_tyvar_appears_contravariantly env var
then
1731 update_variance_of_tyvars_occurring_in_upper_bound
env ty
1735 (* Remove type variable `upper_var` from the upper bounds on `var`, if it exists
1737 let remove_tyvar_upper_bound env var upper_var
=
1738 log_env_change "remove_tyvar_upper_bound" env
1739 @@ wrap_inference_env_call_env env (fun env ->
1740 Inf.remove_tyvar_upper_bound env var upper_var
)
1742 (* Remove type variable `lower_var` from the lower bounds on `var`, if it exists
1744 let remove_tyvar_lower_bound env var lower_var
=
1745 log_env_change "remove_tyvar_lower_bound var" env
1746 @@ wrap_inference_env_call_env env (fun env ->
1747 Inf.remove_tyvar_lower_bound env var lower_var
)
1749 let add_tyvar_lower_bound ?union
env var ty
=
1750 log_env_change "add_tyvar_lower_bound" env
1751 @@ wrap_inference_env_call_env env (fun env ->
1752 Inf.add_tyvar_lower_bound ?union
env var ty
)
1754 (* Add a single new lower bound [ty] to type variable [var] in [env.tvenv].
1755 * If the optional [union] operation is supplied, then use this to avoid
1756 * adding redundant bounds by merging the type with existing bounds. This makes
1757 * sense because a conjunction of lower bounds
1758 * (t1 <: v) /\ ... /\ (tn <: v)
1759 * is equivalent to a single lower bound
1760 * (t1 | ... | tn) <: v
1762 let add_tyvar_lower_bound_and_update_variances ?union
env var ty
=
1763 log_env_change "add_tyvar_lower_bound" env
1765 let env = add_tyvar_lower_bound ?union
env var ty
in
1766 if get_tyvar_appears_covariantly env var
then
1767 update_variance_of_tyvars_occurring_in_lower_bound
env ty
1771 let initialize_tyvar_as_in ~as_in
:genv env v
=
1772 log_env_change "initialize_tyvar_as_in" env
1773 @@ wrap_inference_env_call_env env (fun env ->
1774 Inf.initialize_tyvar_as_in ~as_in
:genv env v
)
1776 let copy_tyvar_from_genv_to_env var ~to_
:env ~from
:genv =
1777 log_env_change_ "copy_tyvar_from_genv_to_env" env
1778 @@ wrap_inference_env_call env (fun env ->
1779 Inf.copy_tyvar_from_genv_to_env var ~to_
:env ~from
:genv)
1781 let get_all_tyvars env =
1782 wrap_inference_env_call_res env (fun env -> Inf.get_vars
env)
1784 let remove_var env var ~search_in_upper_bounds_of ~search_in_lower_bounds_of
=
1785 log_env_change "remove_var" env
1786 @@ wrap_inference_env_call_env env (fun env ->
1790 ~search_in_upper_bounds_of
1791 ~search_in_lower_bounds_of
)
1794 wrap_inference_env_call_env env (fun env -> Inf.unsolve env v
)
1797 (** Convert a type variable from an environment into json *)
1799 (p_locl_ty
: locl_ty
-> string)
1800 (p_internal_type
: internal_type
-> string)
1803 wrap_inference_env_call_res env (fun env ->
1804 Inf.Log.tyvar_to_json p_locl_ty p_internal_type
env v
)