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.
11 module Reason
= Typing_reason
12 module SN
= Naming_special_names
17 | Vprotected
of string
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
48 let show_phase_ty _
= "<phase_ty>"
50 let pp_phase_ty _ _
= Printf.printf
"%s\n" "<phase_ty>"
53 (* all atoms of an enumeration *)
55 (* single atom of an enumeration *)
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
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
= {
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 {
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
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_
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.
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
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 {
193 * The type 'T' will be represented as an abstract type when type checking
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_
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_
243 (* Those three types directly correspond to their decl_phase level counterparts:
244 * array, array<_> and array<_, _> *)
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", [...])`
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 *)
263 (* An abstract type derived from either a newtype, a type parameter, or some
267 (* newtype foo<T1, T2> ...
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:
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"
288 (* Type that is the subtype of the late bound type within a class. *)
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'])
297 (* A reference to some expression. For example:
301 * The expression $x would have a reference Ident.t
302 * The expression $x->foo() would have a different one
306 and taccess_type
= decl_ty
* Nast.sid list
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
321 function f(<<__MaybeRx>> $g) { ... }
322 call to function f will be treated as reactive only if $g is reactive
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
337 and param_mutability
=
338 | Param_owned_mutable
339 | Param_borrowed_mutable
340 | Param_maybe_mutable
342 and fun_tparams_kind
=
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 *)
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 *)
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
402 and param_rx_annotation
=
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 *)
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
= {
418 fp_name
: string option;
419 fp_type
: 'ty possibly_enforced_ty
;
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
441 xa_tag
: xhp_attr_tag
option;
442 xa_has_default
: 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. *)
455 (* true if this static property has attribute __LSB *)
457 (* true if this method has attribute __MemoizeLSB *)
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
464 ce_synthesized
: bool;
465 ce_visibility
: visibility
;
468 ce_type
: decl_ty
Lazy.t
;
469 (* identifies the class from which this elt originates *)
474 cc_synthesized
: bool;
478 cc_expr
: Nast.expr
option;
479 (* identifies the class from which this const originates *)
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.
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
502 and consistent_kind
=
504 | ConsistentConstruct
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;
515 (* True when the class is annotated with the __PPL attribute. *)
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
;
522 tc_is_disposable
: bool;
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
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 *)
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
553 and typeconst_type
= {
554 ttc_abstract
: typeconst_abstract_kind
;
556 ttc_constraint
: decl_ty
option;
557 ttc_type
: decl_ty
option;
559 ttc_enforceable
: Pos.t
* bool;
560 ttc_reifiable
: Pos.t
option;
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
= {
573 tpum_types
: (Nast.sid
* decl_ty
) SMap.t
;
574 tpum_exprs
: Nast.sid
SMap.t
;
579 te_constraint
: decl_ty
option;
582 and record_def_type
= {
585 rdt_errors
: Errors.t
option;
590 td_vis
: Aast.typedef_visibility
;
591 td_tparams
: decl_tparam list
;
592 td_constraint
: decl_ty
option;
594 td_decl_errors
: Errors.t
option;
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
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 *)
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
;
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
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
657 let make_tany () = Tany
TanySentinel.value
659 let arity_min ft_arity
: int =
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. *)
669 | Some
Ast_defs.Pinout
-> FPinout
670 | None
when is_ref
-> FPref
673 module AbstractKind
= struct
674 let to_string = function
675 | AKnewtype
(name
, _
) -> name
676 | AKgeneric name
-> name
680 | DTthis
-> SN.Typehints.this
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
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 (*****************************************************************************)
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
=
742 | Toption
(_
, Tnonnull
) -> 1
754 | Tintersection _
-> 13
758 | Tdestructure _
-> 17
762 let array_kind_con_ordinal ak
=
768 | AKvarray_or_darray _
-> 4
772 let abstract_kind_con_ordinal ak
=
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
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
)) ->
805 match abstract_kind_compare ak1 ak2
with
806 | 0 -> opt_ty_compare opt_cstr1 opt_cstr2
809 (* An instance of a class or interface, ty list are the arguments *)
810 | (Tclass
(id
, exact
, tyl
), Tclass
(id2
, exact2
, tyl2
)) ->
812 match String.compare
(snd id
) (snd id2
) with
815 match tyl_compare ~sort
:false tyl tyl2
with
818 match (exact
, exact2
) with
819 | (Exact
, Exact
) -> 0
820 | (Nonexact
, Nonexact
) -> 0
821 | (Nonexact
, Exact
) -> -1
822 | (Exact
, Nonexact
) -> 1
828 | (Tarraykind ak1
, Tarraykind ak2
) -> array_kind_compare ak1 ak2
829 | (Tshape
(shape_kind1
, fields1
), Tshape
(shape_kind2
, fields2
)) ->
831 match shape_kind_compare shape_kind1 shape_kind2
with
834 (fun (k1
, v1
) (k2
, v2
) ->
835 match Ast_defs.ShapeField.compare k1 k2
with
836 | 0 -> shape_field_type_compare v1 v2
838 (Nast.ShapeMap.elements fields1
)
839 (Nast.ShapeMap.elements fields2
)
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
856 and tfun_compare fty1 fty2
=
857 match possibly_enforced_ty_compare fty1
.ft_ret fty2
.ft_ret
with
860 match ft_params_compare fty1
.ft_params fty2
.ft_params
with
863 ( fty1
.ft_is_coroutine
,
866 fty1
.ft_return_disposable
,
868 fty1
.ft_returns_mutable
)
869 ( fty2
.ft_is_coroutine
,
872 fty2
.ft_return_disposable
,
874 fty2
.ft_returns_mutable
)
878 and opt_ty_compare opt_ty1 opt_ty2
=
879 match (opt_ty1
, opt_ty2
) with
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
) ->
893 | _
-> array_kind_con_ordinal ak1
- array_kind_con_ordinal ak2
897 and tyl_compare ~sort ?
(normalize_lists
= false) tyl1 tyl2
=
900 (List.sort
ty_compare tyl1
, List.sort
ty_compare 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
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
=
916 possibly_enforced_ty_compare
923 (param1
.fp_kind
, param1
.fp_accept_disposable
, param1
.fp_mutability
)
924 (param2
.fp_kind
, param2
.fp_accept_disposable
, param2
.fp_mutability
)
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
932 | (AKnewtype
(id
, tyl
), AKnewtype
(id2
, tyl2
)) ->
934 match String.compare id id2
with
935 | 0 -> tyl_compare ~sort
:false tyl tyl2
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
=
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
}))