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.
14 module Env
= Typing_env
15 module TUtils
= Typing_utils
16 module TGenConstraint
= Typing_generic_constraint
17 module Subst
= Decl_subst
18 module MakeType
= Typing_make_type
19 module Cls
= Folded_class
20 module KindDefs
= Typing_kinding_defs
21 module TIntegrity
= Typing_type_integrity
22 module SN
= Naming_special_names
24 (* Here is the general problem the delayed application of the phase solves.
25 * Let's say you have a function that you want to operate generically across
26 * phases. In most cases when you do this you can use the 'ty' GADT and locally
27 * abstract types to write code in a phase agonistic way.
29 * let yell_any: type a. a ty -> string = fun ty ->
34 * Now let's add a function that works for all phases, but whose logic is phase
35 * dependent. For this we can use 'phase_ty' ADT:
37 * let yell_locl phase_ty =
40 * | LoclTy ty -> "Locl"
42 * Let's say you want to write a function that has behavior that works across
43 * phases, but needs to invoke a function that is phase dependent. Our options
46 * let yell_any_or_locl phase_ty =
47 * let ans = yell_locl phase_ty in
49 * | DeclTy ty -> ans ^ (yell_any ty)
50 * | LoclTy ty -> ans ^ (yell_any ty)
52 * This would lead to code duplication since we can't generically operate on the
53 * underlying 'ty' GADT. If we want to eliminate this code duplication there are
56 * let generic_ty: type a. phase_ty -> a ty = function
60 * let yell_any_or_locl phase_ty =
61 * let ans = yell_locl phase_ty in
62 * ans ^ (yell_any (generic_ty phase_ty))
64 * generic_ty allows us to extract a generic value which we can use. This
65 * approach is limiting because we lose all information about what phase 'a ty
68 * The other approach is to pass in a function that goes from 'a ty -> phase_ty'
70 * let yell_any_or_locl phase ty =
71 * let ans = yell_locl (phase ty) in
74 * Here we can use 'ty' generically (without losing information about what phase
75 * 'a ty' is), and we rely on the caller passing in an appropriate function that
76 * converts into the 'phase_ty' when we need to hop into phase specific code.
78 let decl ty
= DeclTy ty
80 let locl ty
= LoclTy ty
82 type method_instantiation
= {
85 explicit_targs
: Tast.targ list
;
88 (*****************************************************************************)
89 (* Localization caching. *)
90 (*****************************************************************************)
92 module type CACHESETTINGS
= sig
95 val node_count_threshold
: int
98 module MakeTyCache
(Settings
: CACHESETTINGS
) : sig
99 val add
: env
-> string -> locl_ty
-> unit
101 val get
: env
-> string -> locl_ty
option
112 let cache = create
Settings.capacity
114 let should_cache_type lty
=
115 let exception NodeLimitReached
in
118 inherit [int] Type_visitor.locl_type_visitor
as super
120 method! on_type acc ty
=
121 if acc
>= Settings.node_count_threshold
then raise NodeLimitReached
;
122 super#on_type
(acc
+ 1) ty
125 match size_visitor#on_type
0 lty
with
127 | exception NodeLimitReached
-> true
130 (* The only reliable way to empty the LRU cache. *)
133 resize
Settings.capacity
cache;
134 assert (is_empty
cache)
136 let active_context = ref (Relative_path.default
, None
)
138 (* We invalidate the cache as soon as we are processing a new file or
139 * module because those affect how types are expanded (e.g., newtypes
140 * are unfolded only in the file that defines them). *)
141 let maybe_invalidate env
=
142 let context = (Env.get_file env
, Env.get_current_module env
) in
144 [%eq
: Relative_path.t
* string option] !active_context context
146 if not
valid then begin
147 active_context := context;
151 let add env alias lty
=
152 let () = maybe_invalidate env
in
153 if should_cache_type lty
then begin
159 let () = maybe_invalidate env
in
164 (* Since the typechecker options defining the cache parameters will be
165 * available only when we have an environment, the add/get functions are
166 * stored in references initially set to stubs that update themselves
167 * during their first call. *)
168 let rec locl_cache_add =
178 and setup_cache env
=
179 let tcopts = Env.get_tcopt env
in
180 let module Settings
= struct
181 let capacity = TypecheckerOptions.locl_cache_capacity
tcopts
183 let node_count_threshold =
184 TypecheckerOptions.locl_cache_node_threshold
tcopts
186 let module Cache
= MakeTyCache
(Settings
) in
187 locl_cache_add := Cache.add;
188 locl_cache_get
:= Cache.get
190 (*****************************************************************************)
191 (* Transforms a declaration phase type into a localized type. This performs
192 * common operations that are necessary for this operation, specifically:
193 * > Expand newtype/types
194 * > Resolves the "this" type
195 * > Instantiate generics
198 * When keep track of additional information while localizing a type such as
199 * what type defs were expanded to detect potentially recursive definitions..
201 (*****************************************************************************)
203 let rec localize ~
(ety_env
: expand_env
) env
(dty
: decl_ty
) =
204 (fun ((env
, ty_err_opt
), ty
) ->
205 let (env
, ty
) = Typing_log.log_localize ~level
:1 ety_env dty
(env
, ty
) in
206 ((env
, ty_err_opt
), ty
))
208 let rec find_origin dty
=
209 match get_node dty
with
210 | Taccess
(root_ty
, (_pos
, id
)) ->
211 Option.map ~f
:(fun orig
-> orig ^
"::" ^ id
) (find_origin root_ty
)
212 | Tapply
((_pos
, cid
), []) -> Some cid
215 let set_origin_and_cache origin_opt final_env ty_err_opt lty decl_pos_opt
=
216 (* When the type resulting from the localize call originates from a
217 * decl type with a succinct unambiguous form (e.g., Cls or Cls::T) we
218 * store a serialized version of the decl alias in an *origin* field
219 * of the locl type returned. Currently, only shape types have an
221 let cache_result () =
222 (* Under the following conditions we may cache the localized
225 * 1/ We did not encounter cycles during expansion,
226 * 2/ localization was error-free,
227 * 3/ we are expanding under regular assumptions (local
228 * newtypes are visible), and
229 * 4/ the expansion has not created new global type params.
231 * Case 4 happens when we bogusly create type params for
232 * abstract type constants.
233 * Cycles are not reported systematically as errors, so we
234 * track them separately with a reference in ety_env. *)
235 let no_new_global_type_params =
236 Type_parameter_env.size final_env
.tpenv
237 <= Type_parameter_env.size env
.tpenv
239 (not
(Typing_defs.cyclic_expansion ety_env
))
240 && Option.is_none ty_err_opt
241 && ety_env
.expand_visible_newtype
242 && ety_env
.make_internal_opaque
243 && no_new_global_type_params
250 s_unknown_value
= shape_kind
;
251 s_fields
= shape_fields
;
253 match origin_opt
with
261 s_origin
= From_alias
(origin
, decl_pos_opt
);
262 s_unknown_value
= shape_kind
;
263 s_fields
= shape_fields
;
266 if cache_result () then !locl_cache_add env origin
lty;
271 let push_supportdyn_into_shape lty =
272 let (is_supportdyn
, _env
, stripped_lty
) = TUtils.strip_supportdyn env
lty in
273 match deref stripped_lty
with
276 { s_origin
= origin
; s_unknown_value
= ty
; s_fields
= shape_fields
}
278 when is_supportdyn
->
286 s_unknown_value
= MakeType.supportdyn r ty
;
287 s_fields
= shape_fields
;
291 let r = get_reason dty
|> Typing_reason.localize in
292 match get_node dty
with
293 | Trefinement
(root
, cr
) -> localize_refinement ~ety_env env
r root cr
294 | (Tnonnull
| Tprim _
| Tdynamic
| Tany _
) as x
-> ((env
, None
), mk
(r, x
))
295 | Tmixed
-> ((env
, None
), MakeType.mixed
r)
298 map_reason ety_env
.this_ty ~f
:(function reason
->
299 if Reason.Predicates.is_none reason
then
302 match Reason.Predicates.unpack_expr_dep_type_opt reason
with
303 | Some
(_
, pos
, s
) -> Reason.expr_dep_type
(r, pos
, s
)
304 | None
-> Reason.instantiate
(reason
, SN.Typehints.this
, r)
307 (* When refining `as this`, insert a like type for generic or non-final
308 * classes, because generics are not checked at runtime *)
310 if ety_env
.ish_weakening
then
311 match Env.get_self_class env
with
312 | Decl_entry.Found tc
->
313 if Cls.final tc
&& List.is_empty
(Cls.tparams tc
) then
316 MakeType.locl_like
(Reason.pessimised_this
(Reason.to_pos
r)) ty
322 | Tvec_or_dict
(tk
, tv
) ->
323 let ((env
, e1
), tk
) = localize ~ety_env env tk
in
324 let ((env
, e2
), tv
) = localize ~ety_env env tv
in
325 let ty = Tvec_or_dict
(tk
, tv
) in
326 let ty_err_opt = Option.merge e1 e2 ~f
:Typing_error.both
in
327 ((env
, ty_err_opt), mk
(r, ty))
328 | Tgeneric
(x
, targs
) ->
329 let localize_tgeneric ?replace_with name
r =
330 match (targs
, replace_with
, Env.get_pos_and_kind_of_generic env name
) with
331 | (_
, _
, Some
(_def_pos
, kind
)) ->
332 let arg_kinds : KindDefs.Simple.named_kind list
=
333 KindDefs.Simple.from_full_kind kind
334 |> KindDefs.Simple.get_named_parameter_kinds
338 ( localize_targs_by_kind
339 ~ety_env
:{ ety_env
with expand_visible_newtype
= true }
345 | ((env
, _
), Some repl_ty
) -> (env
, mk
(r, repl_ty
))
346 | ((env
, locl_tyargs
), None
) ->
347 (env
, mk
(r, Tgeneric
(name
, locl_tyargs
)))
349 | ([], None
, None
) ->
350 (* No kinding info, but also no type arguments. Just return Tgeneric *)
351 ((env
, None
), mk
(r, Tgeneric
(x
, [])))
352 | ([], Some repl_ty
, None
) -> ((env
, None
), mk
(r, repl_ty
))
353 | (_
:: _
, _
, None
) ->
354 (* No kinding info, but type arguments given. We don't know the kinds of the arguments,
355 so we can't localize them. Not much we can do. *)
356 let (env
, ty) = Env.fresh_type_error env
Pos.none
in
360 match SMap.find_opt x ety_env
.substs
with
362 let (env
, x_ty
) = Env.expand_type env x_ty
in
364 let rp = get_reason x_ty
in
365 if not
@@ TypecheckerOptions.using_extended_reasons env
.genv
.tcopt
367 Reason.instantiate
(rp, x
, r)
372 match (targs
, get_node x_ty
) with
373 | (_
:: _
, Tclass
(((_
, name
) as id
), _
, [])) ->
374 let class_info = Env.get_class env name
in
375 localize_class_instantiation
381 (Decl_entry.to_option
class_info)
382 | (_
:: _
, Tnewtype
(id
, [], _
))
383 | (_
:: _
, Tunapplied_alias id
) ->
384 localize_typedef_instantiation
390 (Env.get_typedef env id
|> Decl_entry.to_option
)
391 | (_
:: _
, Tgeneric
(x'
, [])) -> localize_tgeneric x'
r_inst
392 | (_
, ty_
) -> ((env
, None
), mk
(r_inst, ty_
))
394 | None
-> localize_tgeneric x
r
397 let ((env
, ty_err_opt), ty) = localize ~ety_env env
ty in
398 (* Calling into the union module here would cost 2% perf regression on a full init,
399 * so we use this lightweight version instead. *)
400 let union_null env
ty =
401 let rec null_is_subtype_of ty =
402 match get_node
ty with
404 | Tprim
Aast.Tnull
->
406 | Tunion tyl
-> List.exists tyl ~f
:null_is_subtype_of
407 | Tintersection tyl
-> List.for_all tyl ~f
:null_is_subtype_of
410 if null_is_subtype_of ty then
413 MakeType.nullable
r ty |> TUtils.wrap_union_inter_ty_in_var env
r
415 let (env
, ty) = union_null env
ty in
416 ((env
, ty_err_opt), ty)
418 let ((env
, ty_err_opt), ty) = localize ~ety_env env
ty in
419 let lty = MakeType.locl_like
r ty in
420 ((env
, ty_err_opt), lty)
422 let pos = Reason.to_pos
r in
423 let (env
, ft
) = localize_ft ~ety_env ~def_pos
:pos env ft
in
424 (env
, mk
(r, Tfun ft
))
425 | Tapply
((_
, x
), [arg
]) when String.equal x
SN.HH.FIXME.tPoisonMarker
->
427 if TypecheckerOptions.enable_sound_dynamic
(Env.get_tcopt env
) then
428 mk
(get_reason dty
, Tlike arg
)
432 localize ~ety_env env
decl_ty
434 match ety_env
.wildcard_action
with
435 (* Generate a fresh type variable *)
436 | Wildcard_fresh_tyvar
->
438 Env.fresh_type env
(Pos_or_decl.unsafe_to_raw_pos
(Reason.to_pos
r))
441 (* Produce an error: wildcard is not allowed in this position *)
442 | Wildcard_require_explicit tparam
->
443 let (decl_pos
, param_name
) = tparam
.tp_name
in
448 @@ Primary.Require_generic_explicit
452 pos = Pos_or_decl.unsafe_to_raw_pos
(Reason.to_pos
r);
458 (Pos_or_decl.unsafe_to_raw_pos
(Reason.to_pos
r))
461 (* All should have been dealt with already:
462 * (1) Wildcard_fresh_generic and Wildcard_fresh_generic_type_argument, in localize_targ_by_kind.
463 * (2) Wildcard_illegal, in the naming phase.
464 * (3) Wildcard_higher_kinded_placeholder, in Typing_type_integrity.ml
466 | Wildcard_fresh_generic
468 | Wildcard_higher_kinded_placeholder
->
472 (Pos_or_decl.unsafe_to_raw_pos
(Reason.to_pos
r))
476 | Tapply
(((_p
, cid
) as cls
), argl
) ->
478 match Env.get_class_or_typedef env cid
with
479 | Decl_entry.Found
(Env.ClassResult
class_info) ->
480 localize_class_instantiation ~ety_env env
r cls argl
(Some
class_info)
481 | Decl_entry.Found
(Env.TypedefResult typedef_info
) ->
482 let origin_opt = find_origin dty
in
483 let ((env
, ty_err_opt), lty) =
484 match Option.bind
origin_opt ~f
:(!locl_cache_get env
) with
485 | Some
lty -> ((env
, None
), with_reason
lty r)
487 localize_typedef_instantiation
496 Reason.to_pos
@@ Typing_defs.get_reason typedef_info
.td_type
499 set_origin_and_cache origin_opt env
ty_err_opt lty (Some
shp_def_pos)
502 Typing_env.update_reason env
lty ~f
:(fun r ->
503 Typing_reason.(definition typedef_info
.td_pos
r))
505 ((env
, ty_err_opt), lty)
506 | Decl_entry.DoesNotExist
507 | Decl_entry.NotYetAvailable
->
508 localize_class_instantiation ~ety_env env
r cls argl None
511 (* If we have supportdyn<t> then push supportdyn into open shape fields *)
512 if String.equal cid
SN.Classes.cSupportDyn
then
513 push_supportdyn_into_shape lty
520 List.map_env_ty_err_opt
523 ~f
:(localize ~ety_env
)
524 ~combine_ty_errs
:Typing_error.multiple_opt
526 (env
, mk
(r, Ttuple tyl
))
528 let ((env
, ty_err_opt), tyl
) =
529 List.map_env_ty_err_opt
532 ~f
:(localize ~ety_env
)
533 ~combine_ty_errs
:Typing_error.union_opt
535 let (env
, ty) = Typing_union.union_list env
r tyl
in
536 ((env
, ty_err_opt), ty)
537 | Tintersection tyl
->
538 let ((env
, ty_err_opt), tyl
) =
539 List.map_env_ty_err_opt
542 ~f
:(localize ~ety_env
)
543 ~combine_ty_errs
:Typing_error.multiple_opt
545 let (env
, ty) = Typing_intersection.intersect_list env
r tyl
in
546 ((env
, ty_err_opt), ty)
547 | Taccess
(root_ty
, id
) ->
548 let origin_opt = find_origin dty
in
549 (match Option.bind
origin_opt ~f
:(!locl_cache_get env
) with
550 | Some
lty -> ((env
, None
), with_reason
lty r)
552 let rec allow_abstract_tconst ty =
553 match get_node
ty with
557 * When the root of an access is 'this', abstract type constants
558 * are allowed and localized as rigid type variables (Tgeneric).
559 * This happens when typing generic code in an abstract class
560 * that deals with data whose type is going to be set later in
563 * In case the root is a generic, we also accept accesses to
564 * abstract constant to type check the dangerous and ubiquitous
567 * function get<TBox as Box, T>(TBox $foo) : T where T = TBox::T
571 | Taccess
(ty, _
) -> allow_abstract_tconst ty
574 let allow_abstract_tconst = allow_abstract_tconst root_ty
in
575 let ((env
, e1
), root_ty
) =
576 (* We don't want to put `~` on this::TC, so set ish_weakening to false *)
577 localize ~ety_env
:{ ety_env
with ish_weakening
= false } env root_ty
579 let ((env
, e2
), ty) =
580 TUtils.expand_typeconst ety_env env root_ty id ~
allow_abstract_tconst
582 (* Elaborate reason with information about expression dependent types and
583 * the original location of the Taccess type
585 let ty_err_opt = Option.merge e1 e2 ~f
:Typing_error.both
in
586 let ty = set_origin_and_cache origin_opt env
ty_err_opt ty None
in
587 let elaborate_reason expand_reason
=
589 lazy (Typing_print.full_strip_ns env root_ty ^
"::" ^ snd id
)
591 (* If the root is an expression dependent type, change the primary
592 * reason to be for the full Taccess type to preserve the position where
593 * the expression dependent type was derived from.
597 Reason.Predicates.unpack_expr_dep_type_opt
(get_reason root_ty
)
599 | Some
(_
, p
, e
) -> Reason.expr_dep_type
(r, p
, e
)
602 Reason.type_access
(expand_reason
, [(reason, taccess_string)])
604 let ty = map_reason
ty ~f
:elaborate_reason in
605 ((env
, ty_err_opt), ty))
606 | Tshape
{ s_origin
= _
; s_unknown_value
= shape_kind
; s_fields
= tym
} ->
607 let ((env
, ty_err_opt1
), tym
) =
608 ShapeFieldMap.map_env_ty_err_opt
612 ~combine_ty_errs
:Typing_error.multiple_opt
614 let ((env
, ty_err_opt2
), shape_kind
) = localize ~ety_env env shape_kind
in
616 Option.merge ty_err_opt1 ty_err_opt2 ~f
:Typing_error.both
623 s_origin
= Missing_origin
;
624 s_unknown_value
= shape_kind
;
627 | Tnewtype
(name
, tyl
, ty) ->
629 Decl_provider.get_typedef
(Env.get_ctx env
) name
630 |> Decl_entry.to_option
634 Env.is_typedef_visible
636 ~expand_visible_newtype
:ety_env
.expand_visible_newtype
640 if should_expand then
641 let decl_pos = Reason.to_pos
r in
642 let (ety_env
, has_cycle
) =
643 Typing_defs.add_type_expansion_check_cycles ety_env
(decl_pos, name
)
646 | Some initial_taccess_pos_opt
->
648 Option.map initial_taccess_pos_opt ~f
:(fun initial_taccess_pos
->
651 @@ Primary.Cyclic_typedef
652 { def_pos
= initial_taccess_pos
; use_pos
= decl_pos }))
655 Env.fresh_type_error env
(Pos_or_decl.unsafe_to_raw_pos
decl_pos)
657 ((env
, ty_err_opt), ty)
659 Decl_typedef_expand.expand_typedef
665 |> localize ~ety_env env
667 let ((env
, e1
), ty) = localize ~ety_env env
ty in
668 let ((env
, e2
), tyl
) =
669 List.map_env_ty_err_opt
672 ~f
:(localize ~ety_env
)
673 ~combine_ty_errs
:Typing_error.multiple_opt
675 let ty_err_opt = Option.merge e1 e2 ~f
:Typing_error.both
in
676 ((env
, ty_err_opt), mk
(r, Tnewtype
(name
, tyl
, ty)))
678 (* Localize type arguments for something whose kinds is [kind] *)
679 and localize_targs_by_kind
682 (tyargs
: decl_ty list
)
683 (nkinds
: KindDefs.Simple.named_kind list
) =
684 let exp_len = List.length nkinds
in
685 let act_len = List.length tyargs
in
686 let length = min
exp_len act_len in
687 let (tyargs
, nkinds
) = (List.take tyargs
length, List.take nkinds
length) in
688 let ((env
, ty_errs
, _
), tyl
) =
693 ~f
:(fun (env
, ty_errs
, ety_env
) x y
->
694 let ((env
, ty_err_opt, ety_env
), res
) =
695 localize_targ_by_kind
(env
, ety_env
) x y
698 Option.value_map
ty_err_opt ~default
:ty_errs ~f
:(fun e
->
701 ((env
, ty_errs, ety_env
), res
))
703 let ty_err_opt = Typing_error.multiple_opt
ty_errs in
704 (* Note that we removed superfluous type arguments, because we don't have a kind to localize
706 It would also be useful to fill in Terr for missing type arguments, but this breaks some
707 checks on built-in collections that check the number of type arguments *after* localization. *)
708 ((env
, ty_err_opt), tyl
)
710 and localize_targ_by_kind
(env
, ety_env
) ty (nkind
: KindDefs.Simple.named_kind
)
712 match (get_node
ty, ety_env
.wildcard_action
) with
713 | (Twildcard
, Wildcard_fresh_generic
) ->
714 let r = get_reason
ty in
715 let pos = get_pos
ty in
716 let r = Typing_reason.localize r in
717 let (name
, kind
) = nkind
in
718 let is_higher_kinded = KindDefs.Simple.get_arity kind
> 0 in
719 if is_higher_kinded then
720 let (env
, ty) = Env.fresh_type_error env
Pos.none
in
721 (* We don't support wildcards in place of HK type arguments *)
722 ((env
, None
, ety_env
), ty)
724 let full_kind_without_bounds =
725 KindDefs.Simple.to_full_kind_without_bounds kind
727 let (env
, new_name
) =
728 (* add without bounds, because we need to substitute inside them first,
730 Env.add_fresh_generic_parameter_by_kind
734 full_kind_without_bounds
736 let ty_fresh = mk
(r, Tgeneric
(new_name
, [])) in
737 (* Substitute fresh type parameters for original formals in constraint *)
738 let substs = SMap.add (snd name
) ty_fresh ety_env
.substs in
739 let ety_env = { ety_env with substs } in
740 let subst_and_add_localized_constraints env ck cstr_tys
=
743 let cstr_ty = TIntegrity.Locl_Inst.instantiate
substs cstr_ty in
744 TUtils.add_constraint env ck
ty_fresh cstr_ty ety_env.on_error
)
749 match KindDefs.Simple.get_wilcard_bounds kind
with
750 | KindDefs.Simple.NonLocalized decl_cstrs
->
754 ~f
:(fun (env
, ty_errs) (ck
, ty) ->
755 let ((env
, ty_err_opt), ty) = localize ~
ety_env env
ty in
759 ~f
:(fun e
-> e
:: ty_errs)
763 TUtils.add_constraint
env ck
ty_fresh ty ety_env.on_error
766 | KindDefs.Simple.Localized
{ wc_lower
; wc_upper
} ->
768 subst_and_add_localized_constraints
770 Ast_defs.Constraint_as
774 subst_and_add_localized_constraints
776 Ast_defs.Constraint_super
781 let ty_err_opt = Typing_error.multiple_opt
ty_errs in
782 ((env, ty_err_opt, ety_env), ty_fresh)
784 let ((env, ty_err_opt), ty) = localize_with_kind ~
ety_env env ty nkind
in
785 ((env, ty_err_opt, ety_env), ty)
787 and localize_class_instantiation
788 ~
ety_env env r sid tyargs
(class_info : _
option) =
789 let (pos, name
) = sid
in
790 match class_info with
792 (* Without class info, we don't know the kinds of the arguments.
793 We assume they are non-HK types. *)
795 List.map_env_ty_err_opt
798 ~f
:(localize ~
ety_env:{ ety_env with expand_visible_newtype
= true })
799 ~combine_ty_errs
:Typing_error.multiple_opt
801 (env, mk
(r, Tclass
(sid
, nonexact
, tyl
)))
803 if Option.is_some
(Cls.enum_type
class_info) then
804 let (ety_env, has_cycle
) =
805 Typing_defs.add_type_expansion_check_cycles
ety_env (pos, name
)
815 apply_reasons ~on_error
816 @@ Secondary.Cyclic_enum_constraint
pos)
819 Env.fresh_type_error
env (Pos_or_decl.unsafe_to_raw_pos
pos)
821 ((env, ty_err_opt), ty)
823 if Ast_defs.is_c_enum_class
(Cls.kind
class_info) then
824 (* Enum classes no longer has the ambiguity between the type of
825 * the enum set and the type of elements, so the enum class
826 * itself is seen as a Tclass
828 ((env, None
), mk
(r, Tclass
(sid
, nonexact
, [])))
831 match Env.get_enum_constraint
env name
with
832 (* If not specified, default bound is arraykey *)
833 | Decl_entry.DoesNotExist
834 | Decl_entry.NotYetAvailable
835 | Decl_entry.Found None
->
838 (Reason.implicit_upper_bound
(pos, "arraykey")) )
839 | Decl_entry.Found
(Some
ty) -> localize ~
ety_env env ty
841 let enum_ty = mk
(r, Tnewtype
(name
, [], cstr
)) in
844 if ety_env.ish_weakening
then
845 MakeType.intersection
847 [MakeType.locl_like
r_dyn enum_ty; MakeType.arraykey
r_dyn]
853 let tparams = Cls.tparams class_info in
854 let nkinds = KindDefs.Simple.named_kinds_of_decl_tparams
tparams in
855 let ((env, err
), tyl
) =
856 localize_targs_by_kind
857 ~
ety_env:{ ety_env with expand_visible_newtype
= true }
862 (* Hide the class type if its internal and outside of the module *)
864 (not
ety_env.make_internal_opaque
)
865 || Typing_modules.is_class_visible
env class_info
868 if TypecheckerOptions.using_extended_reasons
env.genv
.tcopt
then
869 Typing_reason.(definition
(Folded_class.pos class_info) r)
873 ((env, err
), mk
(r, Tclass
(sid
, nonexact
, tyl
)))
876 match Cls.get_module
class_info with
880 "Internal error: module must exist for class to be not visible"
883 Reason.opaque_type_from_module
(Cls.pos class_info, callee_module, r)
885 let cstr = MakeType.mixed
new_r in
886 (* If the class supports dynamic, reveal this in the newtype *)
888 if Cls.get_support_dynamic_type
class_info then
889 MakeType.supportdyn
new_r cstr
893 ((env, err
), mk
(new_r, Tnewtype
(name
, tyl
, cstr)))
895 and localize_typedef_instantiation
896 ~
ety_env env (r : Reason.t
) type_name tyargs
(typedef_info
: _
option) =
897 match typedef_info
with
898 | Some typedef_info
->
899 let tparams = typedef_info
.Typing_defs.td_tparams
in
900 let nkinds = KindDefs.Simple.named_kinds_of_decl_tparams
tparams in
901 let ((env, e1
), tyargs
) =
902 localize_targs_by_kind
903 ~
ety_env:{ ety_env with expand_visible_newtype
= true }
908 let ((env, e2
), lty) =
909 TUtils.expand_typedef
ety_env env r type_name tyargs
911 let ty_err_opt = Option.merge e1 e2 ~f
:Typing_error.both
in
912 ((env, ty_err_opt), lty)
914 (* This must be unreachable. We only call localize_typedef_instantiation if we *know* that
915 we have a typedef with typedef info at hand. *)
916 failwith
"Internal error: No info about typedef"
918 (* Localize a type with the given expected kind, which
919 may either indicate a higher-kinded or fully applied type.
921 and localize_with_kind
925 (expected_named_kind
: KindDefs.Simple.named_kind
) =
926 let expected_kind = snd expected_named_kind
in
927 let (r, dty_
) = deref dty
in
928 let r = Typing_reason.localize r in
929 let arity = KindDefs.Simple.get_arity
expected_kind in
930 if Int.( = ) arity 0 then
931 (* Not higher-kinded *)
932 localize ~
ety_env env dty
935 | Tapply
(((_pos
, name
) as id
), []) -> begin
936 match Env.get_class_or_typedef
env name
with
937 | Decl_entry.Found
(Env.ClassResult
class_info) ->
938 let tparams = Cls.tparams class_info in
940 KindDefs.Simple.type_with_params_to_simple_kind
tparams
943 TIntegrity.Simple.is_subkind
env ~sub
:classish_kind ~sup
:expected_kind
945 ((env, None
), mk
(r, Tclass
(id
, nonexact
, [])))
947 let (env, ty) = Env.fresh_type_error
env Pos.none
in
949 | Decl_entry.Found
(Env.TypedefResult typedef
) ->
950 if Env.is_typedef_visible
env ~name typedef
then
951 ((env, None
), mk
(r, Tunapplied_alias name
))
953 (* The bound is unused until the newtype is fully applied *)
954 let (env, ty) = Env.fresh_type_error
env Pos.none
in
955 ((env, None
), mk
(r, Tnewtype
(name
, [], ty)))
956 | Decl_entry.NotYetAvailable
957 | Decl_entry.DoesNotExist
->
958 (* We are expected to localize a higher-kinded type, but are given an unknown class name.
959 Not much we can do. *)
960 let (env, ty) = Env.fresh_type_error
env Pos.none
in
963 | Tgeneric
(name
, []) -> begin
964 match Env.get_pos_and_kind_of_generic
env name
with
965 | Some
(_
, gen_kind
) ->
967 TIntegrity.Simple.is_subkind
969 ~sub
:(KindDefs.Simple.from_full_kind gen_kind
)
972 ((env, None
), mk
(r, Tgeneric
(name
, [])))
974 let (env, ty) = Env.fresh_type_error
env Pos.none
in
977 (* FIXME: Ideally, we would like to fail here, but sometimes we see type
978 parameters without an entry in the environment. *)
979 ((env, None
), mk
(r, Tgeneric
(name
, [])))
981 | Tgeneric
(_
, _targs
)
982 | Tapply
(_
, _targs
) ->
983 let (env, ty) = Env.fresh_type_error
env Pos.none
in
985 | Tany _
-> ((env, None
), mk
(r, make_tany
()))
987 let (env, ty) = Env.fresh_type_error
env Pos.none
in
990 and localize_cstr_ty ~
ety_env env ty tp_name
=
991 let (env, ty) = localize ~
ety_env env ty in
993 map_reason
ty ~f
:(fun r ->
994 Reason.cstr_on_generics
(Reason.to_pos
r, tp_name
))
998 (* For the majority of cases when we localize a function type we instantiate
999 * the function's type parameters to Tvars. There are two cases where we do not do this.
1001 * 1) In Typing_subtype.subtype_method. See the comment for that function for why
1002 * this is necessary.
1003 * 2) When the type arguments are explicitly specified, in which case we instantiate
1004 * the type parameters to the provided types.
1007 ?
(instantiation
: method_instantiation
option)
1011 (ft
: decl_ty fun_type
) =
1012 let ((env, arity_ty_err_opt
), substs) =
1013 match instantiation
with
1014 | Some
{ explicit_targs
; use_name
= _
; use_pos
} ->
1017 (not
(List.is_empty explicit_targs
))
1018 && Int.( <> ) (List.length explicit_targs
) (List.length ft
.ft_tparams
)
1023 @@ Primary.Expected_tparam
1027 n
= List.length ft
.ft_tparams
;
1032 let tvarl = List.map ~f
:fst explicit_targs
in
1033 let ft_subst = Subst.make_locl ft
.ft_tparams
tvarl in
1034 ((env, ty_err_opt), SMap.union
ft_subst ety_env.substs)
1035 | None
-> ((env, None
), ety_env.substs)
1037 let ety_env = { ety_env with substs } in
1038 (* Localize the constraints for a type parameter declaration *)
1039 let rec localize_tparam ~nested
env t
=
1040 let ((env, e1
), cstrl
) =
1042 For nested type parameters (i.e., type parameters of type parameters),
1043 we do not support constraints, yet. If nested type parameters do have
1044 constraints, this is reported earlier. We just throw them away here. *)
1048 List.map_env_ty_err_opt
1051 ~combine_ty_errs
:Typing_error.multiple_opt
1052 ~f
:(fun env (ck
, ty) ->
1053 let ((env, ty_err_opt), ty) =
1054 localize_cstr_ty ~
ety_env env ty t
.tp_name
1056 let name_str = snd t
.tp_name
in
1057 (* In order to access type constants on generics on where clauses,
1058 we need to add the constraints from the type parameters into the
1059 environment before localizing the where clauses with them. Temporarily
1060 add them to the environment here, and reset the environment later. *)
1063 | Ast_defs.Constraint_as
-> Env.add_upper_bound
env name_str ty
1064 | Ast_defs.Constraint_super
-> Env.add_lower_bound
env name_str ty
1065 | Ast_defs.Constraint_eq
->
1067 (Env.add_lower_bound
env name_str ty)
1071 ((env, ty_err_opt), (ck
, ty)))
1073 let ((env, e2
), tparams) =
1074 List.map_env_ty_err_opt
1077 ~f
:(localize_tparam ~nested
:true)
1078 ~combine_ty_errs
:Typing_error.multiple_opt
1080 let ty_err_opt = Option.merge e1 e2 ~f
:Typing_error.both
in
1081 ((env, ty_err_opt), { t
with tp_constraints
= cstrl
; tp_tparams
= tparams })
1083 let localize_where_constraint env (ty1
, ck
, ty2
) =
1084 let ((env, e1
), ty1
) = localize ~
ety_env env ty1
in
1085 let ((env, e2
), ty2
) = localize ~
ety_env env ty2
in
1086 let ty_err_opt = Option.merge e1 e2 ~f
:Typing_error.both
in
1087 ((env, ty_err_opt), (ty1
, ck
, ty2
))
1089 (* Grab and store the old tpenvs *)
1090 let old_tpenv = Env.get_tpenv
env in
1091 let old_global_tpenv = env.tpenv
in
1092 (* Always localize tparams so they are available for later Tast check *)
1093 let ((env, tparam_ty_err_opt
), tparams) =
1094 List.map_env_ty_err_opt
1097 ~f
:(localize_tparam ~nested
:false)
1098 ~combine_ty_errs
:Typing_error.multiple_opt
1100 (* Localize the 'where' constraints *)
1101 let ((env, where_cstr_ty_err_opt
), where_constraints
) =
1102 List.map_env_ty_err_opt
1104 ft
.ft_where_constraints
1105 ~f
:localize_where_constraint
1106 ~combine_ty_errs
:Typing_error.multiple_opt
1108 (* Remove the constraints we added for localizing where constraints *)
1109 let env = Env.env_with_tpenv
env old_tpenv in
1110 let env = Env.env_with_global_tpenv
env old_global_tpenv in
1111 (* If we're instantiating the generic parameters then add a deferred
1112 * check that constraints are satisfied under the
1113 * substitution [ety_env.substs].
1115 let (env, gen_param_ty_err_opt
) =
1116 match instantiation
with
1117 | Some
{ use_pos
; _
} ->
1119 check_tparams_constraints ~use_pos ~
ety_env env ft
.ft_tparams
1122 check_where_constraints
1125 ~definition_pos
:def_pos
1128 ft
.ft_where_constraints
1130 let ty_err_opt = Option.merge e1 e2 ~f
:Typing_error.both
in
1132 | None
-> (env, None
)
1134 let (((env, _
), variadic_params_ty_err_opt
), params
) =
1135 List.map_env_ty_err_opt
1138 ~f
:(fun (env, i
) param
->
1139 let ((env, ty_err_opt), ty) = localize ~
ety_env env param
.fp_type
in
1140 (((env, i
+ 1), ty_err_opt), { param
with fp_type
= ty }))
1141 ~combine_ty_errs
:Typing_error.multiple_opt
1143 let ((env, implicit_params_ty_err_opt
), implicit_params
) =
1144 let (env, capability
) =
1145 match ft
.ft_implicit_params
.capability
with
1147 let (env, ty) = localize ~
ety_env env c
in
1149 | CapDefaults p
-> ((env, None
), CapDefaults p
)
1151 (env, { capability
})
1153 let ((env, ret_ty_err_opt
), ret
) = localize ~
ety_env env ft
.ft_ret
in
1155 Typing_error.multiple_opt
1161 where_cstr_ty_err_opt
;
1162 gen_param_ty_err_opt
;
1163 variadic_params_ty_err_opt
;
1164 implicit_params_ty_err_opt
;
1168 ( (env, ty_err_opt),
1172 ft_implicit_params
= implicit_params
;
1174 ft_tparams
= tparams;
1175 ft_where_constraints
= where_constraints
;
1178 (* Given a list of generic parameters [tparams] and a substitution
1179 * in [ety_env.substs] whose domain is at least these generic parameters,
1180 * check that the types satisfy
1181 * the constraints on the corresponding generic parameter.
1183 * Note that the constraints may contain occurrences of the generic
1184 * parameters, but the subsitution will be applied to them. e.g. if tparams is
1185 * <Tu as MyCovariant<Tu>, Tv super Tu>
1186 * and ety_env.substs is
1190 * class C extends MyContravariant<I> implements I { ... }
1191 * Then the constraints are satisfied, because
1192 * C is a subtype of MyContravariant<C>
1193 * I is a supertype of C
1195 and check_tparams_constraints ~use_pos ~
ety_env env tparams =
1196 let check_tparam_constraints (env, ty_errs) t
=
1197 match SMap.find_opt
(snd t
.tp_name
) ety_env.substs with
1201 ~init
:(env, ty_errs)
1202 ~f
:(fun (env, ty_errs) (ck
, cstr_ty) ->
1203 let ((env, e1
), cstr_ty) =
1204 localize_cstr_ty ~
ety_env env cstr_ty t
.tp_name
1207 log_with_level
env "generics" ~level
:1 (fun () ->
1209 (Pos_or_decl.of_raw_pos use_pos
)
1213 ( "check_tparams_constraints: check_tparams_constraint",
1214 [Log_type
("cstr_ty", cstr_ty); Log_type
("ty", ty)] );
1217 TGenConstraint.check_tparams_constraint
env ~use_pos ck ~
cstr_ty ty
1219 let ty_err_opt = Option.merge e1 e2 ~f
:Typing_error.both
in
1223 ~f
:(fun e
-> e
:: ty_errs)
1227 | None
-> (env, ty_errs)
1229 let (env, ty_errs) =
1230 List.fold_left
tparams ~init
:(env, []) ~f
:check_tparam_constraints
1232 (env, Typing_error.multiple_opt
ty_errs)
1234 and check_where_constraints
1235 ~in_class ~use_pos ~
ety_env ~definition_pos
env cstrl
=
1239 (Typing_error.Reasons_callback.explain_where_constraint
1242 ~
decl_pos:definition_pos
)
1244 { ety_env with on_error }
1246 let (env, ty_errs) =
1250 ~f
:(fun (env, ty_errs) (ty, ck
, cstr_ty) ->
1251 let ((env, e1
), ty) = localize ~
ety_env env ty in
1252 let ((env, e2
), cstr_ty) = localize ~
ety_env env cstr_ty in
1254 TGenConstraint.check_where_constraint
1264 Typing_error.multiple_opt
@@ List.filter_map ~f
:Fn.id
[e1
; e2
; e3
]
1269 ~f
:(fun e
-> e
:: ty_errs)
1274 (env, Typing_error.multiple_opt
ty_errs)
1276 and localize_refinement ~
ety_env env r root decl_cr
=
1277 let mk_unsupported_err () =
1278 let pos = Reason.to_pos
r in
1279 Option.map
ety_env.on_error ~f
:(fun on_error ->
1281 apply_reasons ~
on_error (Secondary.Unsupported_refinement
pos)))
1283 let ((env, ty_err_opt), root
) = localize ~
ety_env env root
in
1284 match get_node root
with
1285 | Tclass
(cid
, Nonexact cr
, tyl
) ->
1286 let both_err e1 e2
= Option.merge e1 e2 ~f
:Typing_error.both
in
1287 let ((env, ty_err_opt), cr
) =
1288 Class_refinement.fold_refined_consts
1289 ~f
:(fun id
{ rc_bound
; rc_is_ctx
} ((env, ty_err_opt), cr
) ->
1290 let ((env, ty_err_opt'
), rc_bound
) =
1293 let (env_err
, ty) = localize ~
ety_env env ty in
1294 (env_err
, TRexact
ty)
1295 | TRloose
{ tr_lower
; tr_upper
} ->
1296 let localize_list env tyl
=
1297 List.map_env
(env, None
) tyl ~f
:(fun (env, ty_err_opt) ty ->
1298 let ((env, ty_err_opt'
), ty) = localize ~
ety_env env ty in
1299 ((env, both_err ty_err_opt ty_err_opt'
), ty))
1301 let ((env, ty_err_opt1
), tr_lower
) = localize_list env tr_lower
in
1302 let ((env, ty_err_opt2
), tr_upper
) = localize_list env tr_upper
in
1303 ( (env, both_err ty_err_opt1 ty_err_opt2
),
1304 TRloose
{ tr_lower
; tr_upper
} )
1307 Class_refinement.add_refined_const id
{ rc_bound
; rc_is_ctx
} cr
1309 ((env, both_err ty_err_opt ty_err_opt'
), cr))
1310 ~init
:((env, ty_err_opt), cr)
1313 ((env, ty_err_opt), mk
(r, Tclass
(cid
, Nonexact
cr, tyl
)))
1315 let (env, ty) = Env.fresh_type_error
env Pos.none
in
1316 ((env, mk_unsupported_err ()), ty)
1318 (* Like localize_no_subst, but uses the supplied kind, enabling support
1319 for higher-kinded types *)
1320 let localize_no_subst_and_kind env ~tparam ~
on_error ty nkind
=
1323 ~default
:empty_expand_env
1324 ~f
:empty_expand_env_with_on_error
1330 when Attributes.mem
SN.UserAttributes.uaExplicit tp
.tp_user_attributes
->
1331 { ety_env with wildcard_action
= Wildcard_require_explicit tp
}
1334 localize_with_kind ~
ety_env env ty nkind
1336 (** Localize an explicit type argument to a constructor or function. We
1337 support the use of wildcards at the top level only *)
1338 let localize_targ_with_kind
1339 ?tparam ~check_well_kinded
env hint
(nkind
: KindDefs.Simple.named_kind
) =
1340 (* For explicit type arguments we support a wildcard syntax `_` for which
1341 * Hack will generate a fresh type variable *)
1342 let kind = snd nkind
in
1344 | (p
, Aast.Hwildcard
) ->
1345 let is_higher_kinded = KindDefs.Simple.get_arity
kind > 0 in
1346 if is_higher_kinded then
1347 let ty_err = Typing_error.(primary
@@ Primary.HKT_wildcard
(fst hint
)) in
1348 let (env, ty) = Env.fresh_type_error
env p
in
1349 ((env, Some
ty_err), (ty, hint
))
1351 let (env, ty) = Env.fresh_type
env p
in
1352 ((env, None
), (ty, hint
))
1354 let ty = Decl_hint.hint
env.decl_env hint
in
1355 let full_kind = KindDefs.Simple.to_full_kind_without_bounds
kind in
1356 let in_non_reified_targ =
1357 Aast.is_erased
full_kind.Typing_kinding_defs.reified
1359 if check_well_kinded
then
1360 TIntegrity.Simple.check_well_kinded
1362 ~ignore_package_errors
:in_non_reified_targ
1367 localize_no_subst_and_kind
1371 (Some
(Typing_error.Reasons_callback.invalid_type_hint hint_pos
))
1377 let localize_targ ?tparam ~check_well_kinded
env hint
=
1379 KindDefs.Simple.with_dummy_name
(KindDefs.Simple.fully_applied_type
())
1381 localize_targ_with_kind ?tparam ~check_well_kinded
env hint
named_kind
1383 (* See signature in .mli file for details *)
1384 let localize_targs_with_kinds
1390 ?
(check_explicit_targs
= true)
1395 let targ_count = List.length targl
in
1396 let generated_tparam_count =
1398 ~f
:(fun t
-> SN.Coeffects.is_generated_generic
(snd t
.tp_name
))
1402 match List.length tparaml
with
1403 | 0 -> List.length named_kinds
1406 let explicit_tparam_count = tparam_count - generated_tparam_count in
1408 let checking_rewritten_call () =
1409 (* Typing_phase expands the case of targl=[] to a list of wildcards matching the
1410 * length of tparaml, but some `if` condition checks retype already typed
1411 * expressions, so we get the generated list instead of what the user wrote
1412 * TODO(coeffects) attempt to remove Tast.to_nast_expr calls *)
1413 generated_tparam_count > 0
1414 && targ_count = tparam_count
1415 && List.for_all ~f
:Aast_defs.is_wildcard_hint targl
1417 (* If there are explicit type arguments but too few or too many then
1418 * report an error *)
1419 let arity_ty_err_opt =
1424 || targ_count = explicit_tparam_count
1425 || checking_rewritten_call ())
1431 @@ Primary.Expected_tparam
1435 n
= explicit_tparam_count;
1441 @@ Primary.Type_arity_mismatch
1445 expected
= tparam_count;
1446 actual
= targ_count;
1452 (* Declare and localize the explicit type arguments *)
1453 let (targ_tparaml
, _
) = List.zip_with_remainder targl tparaml
in
1454 let ((env, ty_errs), explicit_targs
) =
1458 (List.take named_kinds
targ_count)
1459 ~f
:(fun (env, ty_errs) (targ
, tparam
) y
->
1460 let ((env, ty_err_opt), res
) =
1461 localize_targ_with_kind ~tparam ~check_well_kinded
env targ y
1464 Option.value_map
ty_err_opt ~default
:ty_errs ~f
:(fun e
->
1467 ((env, ty_errs), res
))
1469 let explicit_targ_ty_err_opt = Typing_error.multiple_opt
ty_errs in
1470 (* Generate fresh type variables for the remainder *)
1471 let ((env, implicit_targ_ty_err_opt
), implicit_targs
) =
1472 let mk_implicit_targ env (kind_name
, kind) =
1473 let wildcard_hint = (use_pos
, Aast.Hwildcard
) in
1476 && KindDefs.Simple.get_arity
kind > 0
1479 (* We only throw an error if the user didn't provide any type arguments at all.
1480 Otherwise, if they provided some, but not all of them, n arity mismatch
1481 triggers earlier in this function, independently from higher-kindedness *)
1485 @@ Primary.HKT_implicit_argument
1488 decl_pos = fst kind_name
;
1489 param_name
= snd kind_name
;
1492 let (env, ty) = Env.fresh_type_error
env use_pos
in
1493 ((env, Some
ty_err), (ty, wildcard_hint))
1496 Env.fresh_type_reason
1499 (Reason.type_variable_generics
(use_pos
, snd kind_name
, use_name
))
1501 Typing_log.log_tparam_instantiation
env use_pos
(snd kind_name
) tvar
;
1502 ((env, None
), (tvar
, wildcard_hint))
1504 List.map_env_ty_err_opt
1506 (List.drop named_kinds
targ_count)
1508 ~combine_ty_errs
:Typing_error.multiple_opt
1511 let check_for_explicit_user_attribute tparam
(_
, hint
) =
1513 Attributes.mem
SN.UserAttributes.uaExplicit tparam
.tp_user_attributes
1514 && Aast_defs.is_wildcard_hint hint
1516 let (decl_pos, param_name
) = tparam
.tp_name
in
1520 @@ Primary.Require_generic_explicit
1521 { decl_pos; param_name
; pos = fst hint
})
1527 if check_explicit_targs
then
1528 Typing_error.multiple_opt
1531 (explicit_targs
@ implicit_targs
)
1533 ~f
:(fun ty_errs tp targ
->
1534 Option.value_map ~default
:ty_errs ~f
:(fun e
-> e
:: ty_errs)
1535 @@ check_for_explicit_user_attribute tp targ
)
1540 Typing_error.multiple_opt
1545 explicit_targ_ty_err_opt;
1546 implicit_targ_ty_err_opt
;
1550 ((env, ty_err_opt), explicit_targs
@ implicit_targs
)
1558 ?
(check_explicit_targs
= true)
1562 let nkinds = KindDefs.Simple.named_kinds_of_decl_tparams tparaml
in
1563 localize_targs_with_kinds
1570 ~check_explicit_targs
1575 (* Performs no substitutions of generics and initializes Tthis to
1578 let localize_no_subst_
1579 env ~wildcard_action ~ish_weakening ~
on_error ?report_cycle
ty =
1582 empty_expand_env
with
1584 Typing_defs.Type_expansions.empty_w_cycle_report ~report_cycle
;
1590 localize env ty ~
ety_env
1592 let localize_hint_no_subst env ~ignore_errors ?report_cycle h
=
1594 let h = Decl_hint.hint
env.decl_env
h in
1598 (if ignore_errors
then
1601 Some
(Typing_error.Reasons_callback.invalid_type_hint
pos))
1602 ~wildcard_action
:Wildcard_illegal
1603 ~ish_weakening
:false
1607 let localize_hint_for_refinement env hint
=
1608 let (pos, _
) = hint
in
1609 let h = Decl_hint.hint
env.decl_env hint
in
1610 let ((env, ty_err_opt), hint_ty
) =
1613 ~
on_error:(Some
(Typing_error.Reasons_callback.invalid_type_hint
pos))
1614 ~wildcard_action
:Wildcard_fresh_generic
1615 ~ish_weakening
:(Env.get_tcopt
env |> TypecheckerOptions.pessimise_builtins
)
1618 ((env, ty_err_opt), hint_ty
)
1620 let localize_hint_for_lambda env h =
1622 let h = Decl_hint.hint
env.decl_env
h in
1625 ~
on_error:(Some
(Typing_error.Reasons_callback.invalid_type_hint
pos))
1626 ~wildcard_action
:Wildcard_fresh_tyvar
1627 ~ish_weakening
:false
1630 let localize_no_subst env ~ignore_errors
ty =
1634 (if ignore_errors
then
1638 (Typing_error.Reasons_callback.invalid_type_hint
1639 (Pos_or_decl.unsafe_to_raw_pos
@@ get_pos
ty)))
1640 ~wildcard_action
:Wildcard_illegal
1641 ~ish_weakening
:false
1644 let localize_targs_and_check_constraints
1649 ?
(check_explicit_targs
= true)
1655 let ((env, e1
), type_argl
) =
1661 ~use_name
:(Utils.strip_ns
(snd class_id
))
1662 ~check_explicit_targs
1667 let targs_tys = List.map ~f
:fst type_argl
in
1669 mk
(r, Tclass
(Positioned.of_raw_positioned class_id
, exact
, targs_tys))
1673 empty_expand_env
with
1675 substs = Subst.make_locl tparaml
targs_tys;
1676 on_error = Some
(Typing_error.Reasons_callback.unify_error_at use_pos
);
1679 let (env, e2
) = check_tparams_constraints ~use_pos ~
ety_env env tparaml
in
1680 let ty_err_opt = Option.merge e1 e2 ~f
:Typing_error.both
in
1681 ((env, ty_err_opt), this_ty, type_argl
)
1683 (* Add generic parameters to the environment, localize their bounds, and
1684 * transform these into a flat list of constraints of the form (ty1,ck,ty2)
1685 * where ck is as, super or =
1687 let localize_and_add_generic_parameters_with_bounds
1688 ~
ety_env (env : env) (tparams : decl_tparam list
) =
1689 let env = Env.add_generic_parameters
env tparams in
1691 env ({ tp_name
= (pos, name
); tp_constraints
= cstrl
; _
} : decl_tparam
) =
1692 (* TODO(T70068435) This may have to be touched when adding support for constraints on HK
1694 let tparam_ty = mk
(Reason.witness_from_decl
pos, Tgeneric
(name
, [])) in
1695 List.map_env_ty_err_opt
1698 ~f
:(fun env (ck
, cstr) ->
1699 let (env, ty) = localize env cstr ~
ety_env in
1700 (env, (tparam_ty, ck
, ty)))
1701 ~combine_ty_errs
:Typing_error.multiple_opt
1703 let ((env, ty_err_opt), cstrss
) =
1704 List.map_env_ty_err_opt
1708 ~combine_ty_errs
:Typing_error.multiple_opt
1710 let add_constraint env (ty1
, ck
, ty2
) =
1711 TUtils.add_constraint env ck ty1 ty2
ety_env.on_error
1713 let env = List.fold_left
(List.concat cstrss
) ~f
:add_constraint ~init
:env in
1716 let localize_and_add_where_constraints ~
ety_env (env : env) where_constraints
=
1717 let localize_and_add_constraint (env, ty_errs) (ty1
, ck
, ty2
) =
1718 let ((env, e1
), ty1
) = localize env ty1 ~
ety_env in
1719 let ((env, e2
), ty2
) = localize env ty2 ~
ety_env in
1720 let env = TUtils.add_constraint env ck ty1 ty2
ety_env.on_error in
1723 value_map ~default
:ty_errs ~f
:(fun e
-> e
:: ty_errs)
1724 @@ merge e1 e2 ~f
:Typing_error.both
)
1728 let (env, ty_errs) =
1731 ~f
:localize_and_add_constraint
1734 (env, Typing_error.multiple_opt
ty_errs)
1736 (* Helper functions *)
1738 let sub_type_decl env ty1 ty2
on_error =
1739 let ((env, e1
), ty1
) = localize_no_subst env ~ignore_errors
:true ty1
in
1740 let ((env, e2
), ty2
) = localize_no_subst env ~ignore_errors
:true ty2
in
1741 let (env, e3
) = TUtils.sub_type
env ty1 ty2
on_error in
1743 Typing_error.multiple_opt
@@ List.filter_map ~f
:Fn.id
[e1
; e2
; e3
]
1747 let is_sub_type_decl ?coerce
env ty1 ty2
=
1748 let ((env, e1
), ty1
) = localize_no_subst env ~ignore_errors
:true ty1
in
1749 let ((env, e2
), ty2
) = localize_no_subst env ~ignore_errors
:true ty2
in
1756 (Some
(Typing_error.Reasons_callback.unify_error_at
Pos.none
))
1758 Option.is_none e1
&& Option.is_none e2
&& Option.is_none e3
1760 let localize_and_add_generic_parameters_and_where_constraints
1761 ~
ety_env env tparams where_constraints
=
1763 localize_and_add_generic_parameters_with_bounds env tparams ~
ety_env
1766 localize_and_add_where_constraints env where_constraints ~
ety_env
1768 (env, Option.merge e1 e2 ~f
:Typing_error.both
)
1770 let localize_and_add_ast_generic_parameters_and_where_constraints
1773 (tparams : Nast.tparam list
)
1774 (where_constraints
: Aast_defs.where_constraint_hint list
) =
1775 let tparams : decl_tparam list
=
1776 List.map
tparams ~f
:(Decl_hint.aast_tparam_to_decl_tparam
env.decl_env
)
1778 let where_constraints : decl_where_constraint list
=
1779 List.map
where_constraints ~f
:(fun (h1
, ck
, h2
) ->
1780 (Decl_hint.hint
env.decl_env h1
, ck
, Decl_hint.hint
env.decl_env h2
))
1783 if ignore_errors
then
1786 empty_expand_env_with_on_error
1787 (Env.invalid_type_hint_assert_primary_pos_in_current_decl
env)
1789 localize_and_add_generic_parameters_and_where_constraints
1795 let () = TUtils.localize_no_subst_ref
:= localize_no_subst
1797 let () = TUtils.localize_ref
:= localize