Revert visibility of class/type constants.
[hiphop-php.git] / hphp / hack / src / typing / typing_defs.ml
blob85bf9e48cd18436980e622d8af28c39311e86702
1 (*
2 * Copyright (c) 2015, Facebook, Inc.
3 * All rights reserved.
5 * This source code is licensed under the MIT license found in the
6 * LICENSE file in the "hack" directory of this source tree.
8 *)
10 open Core_kernel
11 module Reason = Typing_reason
12 module SN = Naming_special_names
14 type visibility =
15 | Vpublic
16 | Vprivate of string
17 | Vprotected of string
18 [@@deriving show]
20 type exact =
21 | Exact
22 | Nonexact
24 (* All the possible types, reason is a trace of why a type
25 was inferred in a certain way.
27 Types exists in two phases. Phase one is 'decl', meaning it is a type that
28 was declared in user code. Phase two is 'locl', meaning it is a type that is
29 inferred via local inference.
31 (* create private types to represent the different type phases *)
32 type decl_phase = private DeclPhase
34 type locl_phase = private LoclPhase
36 (* This abstract type allows us to guard the construction of Tany to the
37 * make_tany function in this module. *)
38 module TanySentinel : sig
39 type t
41 val value : t
42 end = struct
43 type t = ()
45 let value : t = ()
46 end
48 let show_phase_ty _ = "<phase_ty>"
50 let pp_phase_ty _ _ = Printf.printf "%s\n" "<phase_ty>"
52 type pu_kind =
53 (* all atoms of an enumeration *)
54 | Pu_plain
55 (* single atom of an enumeration *)
56 | Pu_atom of string
58 type 'phase ty = Reason.t * 'phase ty_
60 and decl_ty = decl_phase ty
62 and locl_ty = locl_phase ty
64 (* A shape may specify whether or not fields are required. For example, consider
65 this typedef:
67 type ShapeWithOptionalField = shape(?'a' => ?int);
69 With this definition, the field 'a' may be unprovided in a shape. In this
70 case, the field 'a' would have sf_optional set to true.
72 and 'phase shape_field_type = {
73 sft_optional: bool;
74 sft_ty: 'phase ty;
77 and _ ty_ =
78 (*========== Following Types Exist Only in the Declared Phase ==========*)
79 (* The late static bound type of a class *)
80 | Tthis : decl_phase ty_
81 (* Either an object type or a type alias, ty list are the arguments *)
82 | Tapply : Nast.sid * decl_ty list -> decl_phase ty_
83 (* The type of a generic parameter. The constraints on a generic parameter
84 * are accessed through the lenv.tpenv component of the environment, which
85 * is set up when checking the body of a function or method. See uses of
86 * Typing_phase.localize_generic_parameters_with_bounds.
88 | Tgeneric : string -> decl_phase ty_
89 (* Name of class, name of type const, remaining names of type consts *)
90 | Taccess : taccess_type -> decl_phase ty_
91 (* The type of the various forms of "array":
92 * Tarray (None, None) => "array"
93 * Tarray (Some ty, None) => "array<ty>"
94 * Tarray (Some ty1, Some ty2) => "array<ty1, ty2>"
95 * Tarray (None, Some ty) => [invalid]
97 | Tarray : decl_ty option * decl_ty option -> decl_phase ty_
98 (* Tdarray (ty1, ty2) => "darray<ty1, ty2>" *)
99 | Tdarray : decl_ty * decl_ty -> decl_phase ty_
100 (* Tvarray (ty) => "varray<ty>" *)
101 | Tvarray : decl_ty -> decl_phase ty_
102 (* Tvarray_or_darray (ty) => "varray_or_darray<ty>" *)
103 | Tvarray_or_darray : decl_ty -> decl_phase ty_
104 (* "Any" is the type of a variable with a missing annotation, and "mixed" is
105 * the type of a variable annotated as "mixed". THESE TWO ARE VERY DIFFERENT!
106 * Any unifies with anything, i.e., it is both a supertype and subtype of any
107 * other type. You can do literally anything to it; it's the "trust me" type.
108 * Mixed, on the other hand, is only a supertype of everything. You need to do
109 * a case analysis to figure out what it is (i.e., its elimination form).
111 * Here's an example to demonstrate:
113 * function f($x): int {
114 * return $x + 1;
117 * In that example, $x has type Tany. This unifies with anything, so adding
118 * one to it is allowed, and returning that as int is allowed.
120 * In contrast, if $x were annotated as mixed, adding one to that would be
121 * a type error -- mixed is not a subtype of int, and you must be a subtype
122 * of int to take part in addition. (The converse is true though -- int is a
123 * subtype of mixed.) A case analysis would need to be done on $x, via
124 * is_int or similar.
126 * mixed exists only in the decl_phase phase because it is desugared into ?nonnull
127 * during the localization phase.
129 | Tmixed : decl_phase ty_
130 | Tnothing : decl_phase ty_
131 | Tlike : decl_ty -> decl_phase ty_
132 (*========== Following Types Exist in Both Phases ==========*)
133 | Tany : TanySentinel.t -> 'phase ty_
134 | Terr
135 | Tnonnull
136 (* A dynamic type is a special type which sometimes behaves as if it were a
137 * top type; roughly speaking, where a specific value of a particular type is
138 * expected and that type is dynamic, anything can be given. We call this
139 * behaviour "coercion", in that the types "coerce" to dynamic. In other ways it
140 * behaves like a bottom type; it can be used in any sort of binary expression
141 * or even have object methods called from it. However, it is in fact neither.
143 * it captures dynamicism within function scope.
144 * See tests in typecheck/dynamic/ for more examples.
146 | Tdynamic
147 (* Nullable, called "option" in the ML parlance. *)
148 | Toption : 'phase ty -> 'phase ty_
149 (* All the primitive types: int, string, void, etc. *)
150 | Tprim : Aast.tprim -> 'phase ty_
151 (* A wrapper around fun_type, which contains the full type information for a
152 * function, method, lambda, etc. Note that lambdas have an additional layer
153 * of indirection before you get to Tfun -- see Tanon below. *)
154 | Tfun : 'phase ty fun_type -> 'phase ty_
155 (* Tuple, with ordered list of the types of the elements of the tuple. *)
156 | Ttuple : 'phase ty list -> 'phase ty_
157 (* Whether all fields of this shape are known, types of each of the
158 * known arms.
160 | Tshape : shape_kind * 'phase shape_field_type Nast.ShapeMap.t -> 'phase ty_
161 (* Access to a Pocket Universe Expression or Atom, denoted by
162 * Foo:@Bar or Foo:@Bar:@X.
163 * It might be unresolved at first (e.g. if Foo is a generic variable).
164 * Will be refined to Tpu once typechecking is successful
166 | Tpu_access : 'phase ty * Nast.sid -> 'phase ty_
167 (* A type variable (not to be confused with a type parameter).
168 * It represents a type that is "unknown" and must be inferred by Hack's
169 * constraint-based type inference engine.
171 | Tvar : Ident.t -> 'phase ty_
172 (*========== Below Are Types That Cannot Be Declared In User Code ==========*)
174 (* The type of an opaque type (e.g. a "newtype" outside of the file where it
175 * was defined). They are "opaque", which means that they only unify with
176 * themselves. However, it is possible to have a constraint that allows us to
177 * relax this. For example:
179 * newtype my_type as int = ...
181 * Outside of the file where the type was defined, this translates to:
183 * Tabstract (AKnewtype (pos, "my_type", []), Some (Tprim Tint))
185 * Which means that my_type is abstract, but is subtype of int as well.
187 * We also create abstract types for generic parameters of a function, i.e.
189 * function foo<T>(T $x): void {
190 * // Body
193 * The type 'T' will be represented as an abstract type when type checking
194 * the body of 'foo'.
196 * Finally abstract types are also derived from the 'this' type and
197 * accessing type constants on it, resulting in a dependent type.
199 | Tabstract : abstract_kind * locl_ty option -> locl_phase ty_
200 (* An anonymous function, including the fun arity, and the identifier to
201 * type the body of the function. (The actual closure is stored in
202 * Typing_env.env.genv.anons) *)
203 | Tanon : locl_fun_arity * Ident.t -> locl_phase ty_
204 (* Union type.
205 * The values that are members of this type are the union of the values
206 * that are members of the components of the union.
207 * Some examples (writing | for binary union)
208 * Tunion [] is the "nothing" type, with no values
209 * Tunion [int;float] is the same as num
210 * Tunion [null;t] is the same as Toption t
212 | Tunion : locl_ty list -> locl_phase ty_
213 | Tintersection : locl_ty list -> locl_phase ty_
214 (* Tobject is an object type compatible with all objects. This type is also
215 * compatible with some string operations (since a class might implement
216 * __toString), but not with string type hints. In a similar way, Tobject
217 * is compatible with some array operations (since a class might implement
218 * ArrayAccess), but not with array type hints.
220 * Tobject is currently used to type code like:
221 * ../test/typecheck/return_unknown_class.php
223 | Tobject : locl_phase ty_
224 (* An instance of a class or interface, ty list are the arguments
225 * If exact=Exact, then this represents instances of *exactly* this class
226 * If exact=Nonexact, this also includes subclasses
228 | Tclass : Nast.sid * exact * locl_ty list -> locl_phase ty_
229 (* Localized version of Tarray *)
230 | Tarraykind : array_kind -> locl_phase ty_
231 (* The type of a list destructructuring assignment.
232 * Implements valid destructuring operations via subtyping *)
233 | Tdestructure : locl_ty list -> locl_phase ty_
234 (* Typing of Pocket Universe Expressions
235 * - first parameter is the enclosing class
236 * - second parameter is the name of the Pocket Universe Enumeration
237 * - third parameter is either Pu_plain (the enumeration as the set of
238 * all its atoms) or Pu_atom (a specific atom in the enumeration)
240 | Tpu : locl_ty * Nast.sid * pu_kind -> locl_phase ty_
242 and array_kind =
243 (* Those three types directly correspond to their decl_phase level counterparts:
244 * array, array<_> and array<_, _> *)
245 | AKany
246 (* An array declared as a varray. *)
247 | AKvarray of locl_ty
248 (* An array declared as a darray. *)
249 | AKdarray of locl_ty * locl_ty
250 (* An array annotated as a varray_or_darray. *)
251 | AKvarray_or_darray of locl_ty
252 (* An array "used like a vec".
253 * /!\ An actual `vec` is represented as a `Tclass ("\\vec", [...])`
255 | AKvec of locl_ty
256 (* An array "used like a map or dict".
257 * /!\ An actual `dict` is represented as a `Tclass ("\\dict", [...])`
259 | AKmap of locl_ty * locl_ty
260 (* This is a type created when we see array() literal *)
261 | AKempty
263 (* An abstract type derived from either a newtype, a type parameter, or some
264 * dependent type
266 and abstract_kind =
267 (* newtype foo<T1, T2> ...
268 * or
269 * enum foo ... *)
270 | AKnewtype of string * locl_ty list
271 (* <T super C> ; None if 'as' constrained *)
272 | AKgeneric of string
273 (* see dependent_type *)
274 | AKdependent of dependent_type
276 (* A dependent type consists of a base kind which indicates what the type is
277 * dependent on. It is either dependent on:
278 * - The type 'this'
279 * - A class
280 * - An expression
282 * Dependent types also have a path component (derived from accessing a type
283 * constant). Thus the dependent type (`expr 0, ['A', 'B', 'C']) roughly means
284 * "The type resulting from accessing the type constant A then the type constant
285 * B and then the type constant C on the expression reference by 0"
287 and dependent_type =
288 (* Type that is the subtype of the late bound type within a class. *)
289 | DTthis
290 (* A class name, new type, or generic, i.e.
292 * abstract class C { abstract const type T }
294 * The type C::T is (`cls '\C', ['T'])
296 | DTcls of string
297 (* A reference to some expression. For example:
299 * $x->foo()
301 * The expression $x would have a reference Ident.t
302 * The expression $x->foo() would have a different one
304 | DTexpr of Ident.t
306 and taccess_type = decl_ty * Nast.sid list
308 and shape_kind =
309 | Closed_shape
310 | Open_shape
312 (* represents reactivity of function
313 - None corresponds to non-reactive function
314 - Some reactivity - to reactive function with specified reactivity flavor
316 Nonreactive <: Local -t <: Shallow -t <: Reactive -t
318 MaybeReactive represents conditional reactivity of function that depends on
319 reactivity of function arguments
320 <<__Rx>>
321 function f(<<__MaybeRx>> $g) { ... }
322 call to function f will be treated as reactive only if $g is reactive
324 and reactivity =
325 | Nonreactive
326 | Local of decl_ty option
327 | Shallow of decl_ty option
328 | Reactive of decl_ty option
329 | MaybeReactive of reactivity
330 | RxVar of reactivity option
332 and val_kind =
333 | Lval
334 | LvalSubexpr
335 | Other
337 and param_mutability =
338 | Param_owned_mutable
339 | Param_borrowed_mutable
340 | Param_maybe_mutable
342 and fun_tparams_kind =
343 | FTKtparams
344 (** If ft_tparams is empty, the containing fun_type is a concrete function type.
345 Otherwise, it is a generic function and ft_tparams specifies its type parameters. *)
346 | FTKinstantiated_targs
347 (** The containing fun_type is a concrete function type which is an
348 instantiation of a generic function with at least one reified type
349 parameter. This means that the function requires explicit type arguments
350 at every invocation, and ft_tparams specifies the type arguments with
351 which the generic function was instantiated, as well as whether each
352 explicit type argument must be reified. *)
354 (* The type of a function AND a method.
355 * A function has a min and max arity because of optional arguments *)
356 and 'ty fun_type = {
357 ft_pos: Pos.t;
358 ft_deprecated: string option;
359 ft_is_coroutine: bool;
360 ft_arity: 'ty fun_arity;
361 ft_tparams: 'ty tparam list * fun_tparams_kind;
362 ft_where_constraints: 'ty where_constraint list;
363 ft_params: 'ty fun_params;
364 ft_ret: 'ty possibly_enforced_ty;
365 (* Carries through the sync/async information from the aast *)
366 ft_fun_kind: Ast_defs.fun_kind;
367 ft_reactive: reactivity;
368 ft_return_disposable: bool;
369 (* mutability of the receiver *)
370 ft_mutability: param_mutability option;
371 ft_returns_mutable: bool;
372 ft_decl_errors: Errors.t option;
373 ft_returns_void_to_rx: bool;
376 and decl_fun_type = decl_ty fun_type
378 and locl_fun_type = locl_ty fun_type
380 (* Arity information for a fun_type; indicating the minimum number of
381 * args expected by the function and the maximum number of args for
382 * standard, non-variadic functions or the type of variadic argument taken *)
383 and 'ty fun_arity =
384 (* min ; max *)
385 | Fstandard of int * int
386 (* PHP5.6-style ...$args finishes the func declaration.
387 min ; variadic param type *)
388 | Fvariadic of int * 'ty fun_param
389 (* HH-style ... anonymous variadic arg; body presumably uses func_get_args.
390 min ; position of ... *)
391 | Fellipsis of int * Pos.t
393 and decl_fun_arity = decl_ty fun_arity
395 and locl_fun_arity = locl_ty fun_arity
397 and param_mode =
398 | FPnormal
399 | FPref
400 | FPinout
402 and param_rx_annotation =
403 | Param_rx_var
404 | Param_rx_if_impl of decl_ty
406 and 'ty possibly_enforced_ty = {
407 (* True if consumer of this type enforces it at runtime *)
408 et_enforced: bool;
409 et_type: 'ty;
412 and decl_possibly_enforced_ty = decl_ty possibly_enforced_ty
414 and locl_possibly_enforced_ty = locl_ty possibly_enforced_ty
416 and 'ty fun_param = {
417 fp_pos: Pos.t;
418 fp_name: string option;
419 fp_type: 'ty possibly_enforced_ty;
420 fp_kind: param_mode;
421 fp_accept_disposable: bool;
422 fp_mutability: param_mutability option;
423 fp_rx_annotation: param_rx_annotation option;
426 and decl_fun_param = decl_ty fun_param
428 and locl_fun_param = locl_ty fun_param
430 and 'ty fun_params = 'ty fun_param list
432 and decl_fun_params = decl_ty fun_params
434 and locl_fun_params = locl_ty fun_params
436 and xhp_attr_tag =
437 | Required
438 | Lateinit
440 and xhp_attr = {
441 xa_tag: xhp_attr_tag option;
442 xa_has_default: bool;
445 and class_elt = {
446 ce_abstract: bool;
447 ce_final: bool;
448 ce_xhp_attr: xhp_attr option;
449 (* This field has different meanings in shallow mode and eager mode:
450 * In shallow mode, true if this method has attribute __Override.
451 * In eager mode, true if this method is originally defined in a trait,
452 * AND has the override attribute, AND the trait does not inherit any
453 * other method of that name. *)
454 ce_override: bool;
455 (* true if this static property has attribute __LSB *)
456 ce_lsb: bool;
457 (* true if this method has attribute __MemoizeLSB *)
458 ce_memoizelsb: bool;
459 (* true if this elt arose from require-extends or other mechanisms
460 of hack "synthesizing" methods that were not written by the
461 programmer. The eventual purpose of this is to make sure that
462 elts that *are* written by the programmer take precedence over
463 synthesized elts. *)
464 ce_synthesized: bool;
465 ce_visibility: visibility;
466 ce_const: bool;
467 ce_lateinit: bool;
468 ce_type: decl_ty Lazy.t;
469 (* identifies the class from which this elt originates *)
470 ce_origin: string;
473 and class_const = {
474 cc_synthesized: bool;
475 cc_abstract: bool;
476 cc_pos: Pos.t;
477 cc_type: decl_ty;
478 cc_expr: Nast.expr option;
479 (* identifies the class from which this const originates *)
480 cc_origin: string;
483 (* The position is that of the hint in the `use` / `implements` AST node
484 * that causes a class to have this requirement applied to it. E.g.
486 * class Foo {}
488 * interface Bar {
489 * require extends Foo; <- position of the decl_phase ty
492 * class Baz extends Foo implements Bar { <- position of the `implements`
495 and requirement = Pos.t * decl_ty
497 (* In the default case, we use Inconsistent. If a class has <<__ConsistentConstruct>>,
498 * or if it inherits a class that has <<__ConsistentConstruct>>, we use inherited.
499 * If we have a new final class that doesn't extend from <<__ConsistentConstruct>>,
500 * then we use Final. Only classes that are Inconsistent or Final can have reified
501 * generics. *)
502 and consistent_kind =
503 | Inconsistent
504 | ConsistentConstruct
505 | FinalClass
507 and class_type = {
508 tc_need_init: bool;
509 (* Whether the typechecker knows of all (non-interface) ancestors
510 * and thus known all accessible members of this class *)
511 tc_members_fully_known: bool;
512 tc_abstract: bool;
513 tc_final: bool;
514 tc_const: bool;
515 (* True when the class is annotated with the __PPL attribute. *)
516 tc_ppl: bool;
517 (* When a class is abstract (or in a trait) the initialization of
518 * a protected member can be delayed *)
519 tc_deferred_init_members: SSet.t;
520 tc_kind: Ast_defs.class_kind;
521 tc_is_xhp: bool;
522 tc_is_disposable: bool;
523 tc_name: string;
524 tc_pos: Pos.t;
525 tc_tparams: decl_tparam list;
526 tc_where_constraints: decl_where_constraint list;
527 tc_consts: class_const SMap.t;
528 tc_typeconsts: typeconst_type SMap.t;
529 tc_pu_enums: pu_enum_type SMap.t;
530 tc_props: class_elt SMap.t;
531 tc_sprops: class_elt SMap.t;
532 tc_methods: class_elt SMap.t;
533 tc_smethods: class_elt SMap.t;
534 (* the bool represents final constructor or __ConsistentConstruct *)
535 tc_construct: class_elt option * consistent_kind;
536 (* This includes all the classes, interfaces and traits this class is
537 * using. *)
538 tc_ancestors: decl_ty SMap.t;
539 tc_req_ancestors: requirement list;
540 tc_req_ancestors_extends: SSet.t;
541 (* the extends of req_ancestors *)
542 tc_extends: SSet.t;
543 tc_enum_type: enum_type option;
544 tc_sealed_whitelist: SSet.t option;
545 tc_decl_errors: Errors.t option;
548 and typeconst_abstract_kind =
549 | TCAbstract of decl_ty option
550 | TCPartiallyAbstract
551 | TCConcrete
553 and typeconst_type = {
554 ttc_abstract: typeconst_abstract_kind;
555 ttc_name: Nast.sid;
556 ttc_constraint: decl_ty option;
557 ttc_type: decl_ty option;
558 ttc_origin: string;
559 ttc_enforceable: Pos.t * bool;
560 ttc_reifiable: Pos.t option;
563 and pu_enum_type = {
564 tpu_name: Nast.sid;
565 tpu_is_final: bool;
566 tpu_case_types: Nast.sid SMap.t;
567 tpu_case_values: (Nast.sid * decl_ty) SMap.t;
568 tpu_members: pu_member_type SMap.t;
571 and pu_member_type = {
572 tpum_atom: Nast.sid;
573 tpum_types: (Nast.sid * decl_ty) SMap.t;
574 tpum_exprs: Nast.sid SMap.t;
577 and enum_type = {
578 te_base: decl_ty;
579 te_constraint: decl_ty option;
582 and record_def_type = {
583 rdt_name: Nast.sid;
584 rdt_pos: Pos.t;
585 rdt_errors: Errors.t option;
588 and typedef_type = {
589 td_pos: Pos.t;
590 td_vis: Aast.typedef_visibility;
591 td_tparams: decl_tparam list;
592 td_constraint: decl_ty option;
593 td_type: decl_ty;
594 td_decl_errors: Errors.t option;
597 and 'ty tparam = {
598 tp_variance: Ast_defs.variance;
599 tp_name: Ast_defs.id;
600 tp_constraints: (Ast_defs.constraint_kind * 'ty) list;
601 tp_reified: Aast.reify_kind;
602 tp_user_attributes: Nast.user_attribute list;
605 and decl_tparam = decl_ty tparam
607 and locl_tparam = locl_ty tparam
609 and 'ty where_constraint = 'ty * Ast_defs.constraint_kind * 'ty
611 and decl_where_constraint = decl_ty where_constraint
613 and locl_where_constraint = locl_ty where_constraint
615 type phase_ty =
616 | DeclTy of decl_ty
617 | LoclTy of locl_ty
619 type deserialization_error =
620 (* The type was valid, but some component thereof was a decl_ty when we
621 expected a locl_phase ty, or vice versa. *)
622 | Wrong_phase of string
623 (* The specific type or some component thereof is not one that we support
624 deserializing, usually because not enough information was serialized to be
625 able to deserialize it again. For example, lambda types (`Tanon`) contain a
626 reference to an identifier (`Ident.t`), which is not serialized. *)
627 | Not_supported of string
628 (* The input JSON was invalid for some reason. *)
629 | Deserialization_error of string
631 (* Tracks information about how a type was expanded *)
632 type expand_env = {
633 (* A list of the type defs and type access we have expanded thus far. Used
634 * to prevent entering into a cycle when expanding these types
636 type_expansions: (Pos.t * string) list;
637 substs: locl_ty SMap.t;
638 this_ty: locl_ty;
639 (* The class that the type is extracted from. Used for creating expression
640 * dependent types for type constants.
642 from_class: Nast.class_id_ option;
645 let is_type_no_return ty = ty = Tprim Aast.Tnoreturn
647 let has_expanded { type_expansions; _ } x =
648 List.exists type_expansions (function
649 | (_, x') when x = x' -> true
650 | _ -> false)
652 (* The identifier for this *)
653 let this = Local_id.make_scoped "$this"
655 (* This should be the ONLY way that Tany is constructed anywhere in the
656 * codebase. *)
657 let make_tany () = Tany TanySentinel.value
659 let arity_min ft_arity : int =
660 match ft_arity with
661 | Fstandard (min, _)
662 | Fvariadic (min, _)
663 | Fellipsis (min, _) ->
666 let get_param_mode ~is_ref callconv =
667 (* If a param has both & and inout, this should have errored in parsing. *)
668 match callconv with
669 | Some Ast_defs.Pinout -> FPinout
670 | None when is_ref -> FPref
671 | None -> FPnormal
673 module AbstractKind = struct
674 let to_string = function
675 | AKnewtype (name, _) -> name
676 | AKgeneric name -> name
677 | AKdependent dt ->
678 let dt =
679 match dt with
680 | DTthis -> SN.Typehints.this
681 | DTcls c -> c
682 | DTexpr i ->
683 let display_id = Reason.get_expr_display_id i in
684 "<expr#" ^ string_of_int display_id ^ ">"
688 let is_generic_dep_ty s = String_utils.is_substring "::" s
691 module ShapeFieldMap = struct
692 include Nast.ShapeMap
694 let map_and_rekey shape_map key_f value_f =
695 let f_over_shape_field_type ({ sft_ty; _ } as shape_field_type) =
696 { shape_field_type with sft_ty = value_f sft_ty }
698 Nast.ShapeMap.map_and_rekey shape_map key_f f_over_shape_field_type
700 let map_env f env shape_map =
701 let f_over_shape_field_type env _key ({ sft_ty; _ } as shape_field_type) =
702 let (env, sft_ty) = f env sft_ty in
703 (env, { shape_field_type with sft_ty })
705 Nast.ShapeMap.map_env f_over_shape_field_type env shape_map
707 let map f shape_map = map_and_rekey shape_map (fun x -> x) f
709 let iter f shape_map =
710 let f_over_shape_field_type shape_map_key { sft_ty; _ } =
711 f shape_map_key sft_ty
713 Nast.ShapeMap.iter f_over_shape_field_type shape_map
715 let iter_values f = iter (fun _ -> f)
718 module ShapeFieldList = struct
719 include Hh_core.List
721 let map_env env xs ~f =
722 let f_over_shape_field_type env ({ sft_ty; _ } as shape_field_type) =
723 let (env, sft_ty) = f env sft_ty in
724 (env, { shape_field_type with sft_ty })
726 Hh_core.List.map_env env xs ~f:f_over_shape_field_type
729 (*****************************************************************************)
730 (* Suggest mode *)
731 (*****************************************************************************)
733 (* Set to true when we are trying to infer the missing type hints. *)
734 let is_suggest_mode = ref false
736 (* Ordinal value for type constructor, for localized types *)
737 let ty_con_ordinal ty =
738 match snd ty with
739 | Tany _
740 | Terr ->
742 | Toption (_, Tnonnull) -> 1
743 | Tnonnull -> 2
744 | Tdynamic -> 3
745 | Toption _ -> 4
746 | Tprim _ -> 5
747 | Tfun _ -> 6
748 | Ttuple _ -> 7
749 | Tshape _ -> 8
750 | Tvar _ -> 9
751 | Tabstract _ -> 10
752 | Tanon _ -> 11
753 | Tunion _ -> 12
754 | Tintersection _ -> 13
755 | Tobject -> 14
756 | Tclass _ -> 15
757 | Tarraykind _ -> 16
758 | Tdestructure _ -> 17
759 | Tpu _ -> 18
760 | Tpu_access _ -> 19
762 let array_kind_con_ordinal ak =
763 match ak with
764 | AKany -> 0
765 | AKvarray _ -> 1
766 | AKvec _ -> 2
767 | AKdarray _ -> 3
768 | AKvarray_or_darray _ -> 4
769 | AKmap _ -> 5
770 | AKempty -> 6
772 let abstract_kind_con_ordinal ak =
773 match ak with
774 | AKnewtype _ -> 0
775 | AKgeneric _ -> 1
776 | AKdependent _ -> 2
778 (* Compare two types syntactically, ignoring reason information and other
779 * small differences that do not affect type inference behaviour. This
780 * comparison function can be used to construct tree-based sets of types,
781 * or to compare two types for "exact" equality.
782 * Note that this function does *not* expand type variables, or type
783 * aliases.
784 * But if ty_compare ty1 ty2 = 0, then the types must not be distinguishable
785 * by any typing rules.
787 * TODO(T52611361): Make this comparison exhaustive on ty1 to remove the _ catchall
789 let rec ty_compare ?(normalize_lists = false) ty1 ty2 =
790 let rec ty_compare ty1 ty2 =
791 let (ty_1, ty_2) = (snd ty1, snd ty2) in
792 match (ty_1, ty_2) with
793 | (Tprim ty1, Tprim ty2) -> compare ty1 ty2
794 | (Toption ty, Toption ty2) -> ty_compare ty ty2
795 | (Tfun fty, Tfun fty2) -> tfun_compare fty fty2
796 | (Tdestructure tyl1, Tdestructure tyl2) ->
797 tyl_compare ~sort:false tyl1 tyl2
798 | (Tunion tyl1, Tunion tyl2)
799 | (Tintersection tyl1, Tintersection tyl2) ->
800 tyl_compare ~sort:normalize_lists ~normalize_lists tyl1 tyl2
801 | (Ttuple tyl1, Ttuple tyl2) ->
802 tyl_compare ~sort:normalize_lists ~normalize_lists tyl1 tyl2
803 | (Tabstract (ak1, opt_cstr1), Tabstract (ak2, opt_cstr2)) ->
804 begin
805 match abstract_kind_compare ak1 ak2 with
806 | 0 -> opt_ty_compare opt_cstr1 opt_cstr2
807 | n -> n
809 (* An instance of a class or interface, ty list are the arguments *)
810 | (Tclass (id, exact, tyl), Tclass (id2, exact2, tyl2)) ->
811 begin
812 match String.compare (snd id) (snd id2) with
813 | 0 ->
814 begin
815 match tyl_compare ~sort:false tyl tyl2 with
816 | 0 ->
817 begin
818 match (exact, exact2) with
819 | (Exact, Exact) -> 0
820 | (Nonexact, Nonexact) -> 0
821 | (Nonexact, Exact) -> -1
822 | (Exact, Nonexact) -> 1
824 | n -> n
826 | n -> n
828 | (Tarraykind ak1, Tarraykind ak2) -> array_kind_compare ak1 ak2
829 | (Tshape (shape_kind1, fields1), Tshape (shape_kind2, fields2)) ->
830 begin
831 match shape_kind_compare shape_kind1 shape_kind2 with
832 | 0 ->
833 List.compare
834 (fun (k1, v1) (k2, v2) ->
835 match Ast_defs.ShapeField.compare k1 k2 with
836 | 0 -> shape_field_type_compare v1 v2
837 | n -> n)
838 (Nast.ShapeMap.elements fields1)
839 (Nast.ShapeMap.elements fields2)
840 | n -> n
842 | (Tvar v1, Tvar v2) -> compare v1 v2
843 | (Tanon (_, id1), Tanon (_, id2)) -> compare id1 id2
844 | _ -> ty_con_ordinal ty1 - ty_con_ordinal ty2
845 and shape_kind_compare sk1 sk2 =
846 match (sk1, sk2) with
847 | (Closed_shape, Closed_shape)
848 | (Open_shape, Open_shape) ->
850 | (Closed_shape, Open_shape) -> -1
851 | (Open_shape, Closed_shape) -> 1
852 and shape_field_type_compare sft1 sft2 =
853 match ty_compare sft1.sft_ty sft2.sft_ty with
854 | 0 -> compare sft1.sft_optional sft2.sft_optional
855 | n -> n
856 and tfun_compare fty1 fty2 =
857 match possibly_enforced_ty_compare fty1.ft_ret fty2.ft_ret with
858 | 0 ->
859 begin
860 match ft_params_compare fty1.ft_params fty2.ft_params with
861 | 0 ->
862 compare
863 ( fty1.ft_is_coroutine,
864 fty1.ft_arity,
865 fty1.ft_reactive,
866 fty1.ft_return_disposable,
867 fty1.ft_mutability,
868 fty1.ft_returns_mutable )
869 ( fty2.ft_is_coroutine,
870 fty2.ft_arity,
871 fty2.ft_reactive,
872 fty2.ft_return_disposable,
873 fty2.ft_mutability,
874 fty2.ft_returns_mutable )
875 | n -> n
877 | n -> n
878 and opt_ty_compare opt_ty1 opt_ty2 =
879 match (opt_ty1, opt_ty2) with
880 | (None, None) -> 0
881 | (Some _, None) -> 1
882 | (None, Some _) -> -1
883 | (Some ty1, Some ty2) -> ty_compare ty1 ty2
884 and array_kind_compare ak1 ak2 =
885 match (ak1, ak2) with
886 | (AKmap (ty1, ty2), AKmap (ty3, ty4))
887 | (AKdarray (ty1, ty2), AKdarray (ty3, ty4)) ->
888 tyl_compare ~sort:false [ty1; ty2] [ty3; ty4]
889 | (AKvarray ty1, AKvarray ty2)
890 | (AKvarray_or_darray ty1, AKvarray_or_darray ty2)
891 | (AKvec ty1, AKvec ty2) ->
892 ty_compare ty1 ty2
893 | _ -> array_kind_con_ordinal ak1 - array_kind_con_ordinal ak2
895 ty_compare ty1 ty2
897 and tyl_compare ~sort ?(normalize_lists = false) tyl1 tyl2 =
898 let (tyl1, tyl2) =
899 if sort then
900 (List.sort ty_compare tyl1, List.sort ty_compare tyl2)
901 else
902 (tyl1, tyl2)
904 List.compare (ty_compare ~normalize_lists) tyl1 tyl2
906 and possibly_enforced_ty_compare ?(normalize_lists = false) ety1 ety2 =
907 match ty_compare ~normalize_lists ety1.et_type ety2.et_type with
908 | 0 -> Bool.compare ety1.et_enforced ety2.et_enforced
909 | n -> n
911 and ft_params_compare ?(normalize_lists = false) params1 params2 =
912 let rec ft_params_compare params1 params2 =
913 List.compare ft_param_compare params1 params2
914 and ft_param_compare param1 param2 =
915 match
916 possibly_enforced_ty_compare
917 ~normalize_lists
918 param1.fp_type
919 param2.fp_type
920 with
921 | 0 ->
922 compare
923 (param1.fp_kind, param1.fp_accept_disposable, param1.fp_mutability)
924 (param2.fp_kind, param2.fp_accept_disposable, param2.fp_mutability)
925 | n -> n
927 ft_params_compare params1 params2
929 and abstract_kind_compare ?(normalize_lists = false) t1 t2 =
930 let tyl_compare = tyl_compare ~normalize_lists in
931 match (t1, t2) with
932 | (AKnewtype (id, tyl), AKnewtype (id2, tyl2)) ->
933 begin
934 match String.compare id id2 with
935 | 0 -> tyl_compare ~sort:false tyl tyl2
936 | n -> n
938 | (AKgeneric id1, AKgeneric id2) -> String.compare id1 id2
939 | (AKdependent d1, AKdependent d2) -> compare d1 d2
940 | _ -> abstract_kind_con_ordinal t1 - abstract_kind_con_ordinal t2
942 let ty_equal ?(normalize_lists = false) ty1 ty2 =
943 ty_compare ~normalize_lists ty1 ty2 = 0
945 let make_function_type_rxvar param_ty =
946 match param_ty with
947 | (r, Tfun tfun) -> (r, Tfun { tfun with ft_reactive = RxVar None })
948 | (r, Toption (r1, Tfun tfun)) ->
949 (r, Toption (r1, Tfun { tfun with ft_reactive = RxVar None }))
950 | _ -> param_ty