Introduce __ReturnsVoidToRx
[hiphop-php.git] / hphp / hack / src / typing / typing_defs.ml
blob9c5c3699710b116a1d27507d46c47ddfe3f9cc5d
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 Hh_core
12 module Reason = Typing_reason
13 module SN = Naming_special_names
15 type visibility =
16 | Vpublic
17 | Vprivate of string
18 | Vprotected of string [@@deriving show]
20 (* All the possible types, reason is a trace of why a type
21 was inferred in a certain way.
23 Types exists in two phases. Phase one is 'decl', meaning it is a type that
24 was declared in user code. Phase two is 'locl', meaning it is a type that is
25 inferred via local inference.
27 (* create private types to represent the different type phases *)
28 type decl = private DeclPhase
29 type locl = private LoclPhase
31 let show_phase_ty _ = "<phase_ty>"
32 let pp_phase_ty _ _ = Printf.printf "%s\n" "<phase_ty>"
34 type 'phase ty = ( Reason.t * 'phase ty_ )
36 (* A shape may specify whether or not fields are required. For example, consider
37 this typedef:
39 type ShapeWithOptionalField = shape(?'a' => ?int);
41 With this definition, the field 'a' may be unprovided in a shape. In this
42 case, the field 'a' would have sf_optional set to true.
44 and 'phase shape_field_type = {
45 sft_optional : bool;
46 sft_ty : 'phase ty;
49 and _ ty_ =
50 (*========== Following Types Exist Only in the Declared Phase ==========*)
51 (* The late static bound type of a class *)
52 | Tthis : decl ty_
54 (* Either an object type or a type alias, ty list are the arguments *)
55 | Tapply : Nast.sid * decl ty list -> decl ty_
57 (* The type of a generic parameter. The constraints on a generic parameter
58 * are accessed through the lenv.tpenv component of the environment, which
59 * is set up when checking the body of a function or method. See uses of
60 * Typing_phase.localize_generic_parameters_with_bounds.
62 | Tgeneric : string -> decl ty_
64 (* Name of class, name of type const, remaining names of type consts *)
65 | Taccess : taccess_type -> decl ty_
67 (* The type of the various forms of "array":
68 * Tarray (None, None) => "array"
69 * Tarray (Some ty, None) => "array<ty>"
70 * Tarray (Some ty1, Some ty2) => "array<ty1, ty2>"
71 * Tarray (None, Some ty) => [invalid]
73 | Tarray : decl ty option * decl ty option -> decl ty_
75 (* Tdarray (ty1, ty2) => "darray<ty1, ty2>" *)
76 | Tdarray : decl ty * decl ty -> decl ty_
78 (* Tvarray (ty) => "varray<ty>" *)
79 | Tvarray : decl ty -> decl ty_
81 (* Tvarray_or_darray (ty) => "varray_or_darray<ty>" *)
82 | Tvarray_or_darray : decl ty -> decl ty_
84 (*========== Following Types Exist in Both Phases ==========*)
85 (* "Any" is the type of a variable with a missing annotation, and "mixed" is
86 * the type of a variable annotated as "mixed". THESE TWO ARE VERY DIFFERENT!
87 * Any unifies with anything, i.e., it is both a supertype and subtype of any
88 * other type. You can do literally anything to it; it's the "trust me" type.
89 * Mixed, on the other hand, is only a supertype of everything. You need to do
90 * a case analysis to figure out what it is (i.e., its elimination form).
92 * Here's an example to demonstrate:
94 * function f($x): int {
95 * return $x + 1;
96 * }
98 * In that example, $x has type Tany. This unifies with anything, so adding
99 * one to it is allowed, and returning that as int is allowed.
101 * In contrast, if $x were annotated as mixed, adding one to that would be
102 * a type error -- mixed is not a subtype of int, and you must be a subtype
103 * of int to take part in addition. (The converse is true though -- int is a
104 * subtype of mixed.) A case analysis would need to be done on $x, via
105 * is_int or similar.
107 | Tany
108 | Tmixed
109 | Tnonnull
110 (* A dynamic type is a special type which, similar to mixed, is considered the
111 * supertype of all types (except mixed), can be used in any operation like
112 * TAny, but, unlike TAny, does not subtype or unify with regular types:
113 * it captures dynamicism within function scope.
114 * See tests in typecheck/dynamic/ for more examples.
116 | Tdynamic
117 | Terr
119 (* Nullable, called "option" in the ML parlance. *)
120 | Toption : 'phase ty -> 'phase ty_
122 (* All the primitive types: int, string, void, etc. *)
123 | Tprim : Nast.tprim -> 'phase ty_
125 (* A wrapper around fun_type, which contains the full type information for a
126 * function, method, lambda, etc. Note that lambdas have an additional layer
127 * of indirection before you get to Tfun -- see Tanon below. *)
128 | Tfun : 'phase fun_type -> 'phase ty_
131 (* Tuple, with ordered list of the types of the elements of the tuple. *)
132 | Ttuple : 'phase ty list -> 'phase ty_
134 (* Whether all fields of this shape are known, types of each of the
135 * known arms.
137 | Tshape
138 : shape_fields_known * ('phase shape_field_type Nast.ShapeMap.t)
139 -> 'phase ty_
141 (*========== Below Are Types That Cannot Be Declared In User Code ==========*)
143 (* A type variable (not to be confused with a type parameter). This is the
144 * core of how type inference works. If you aren't familiar with it, a
145 * suitable explanation couldn't possibly fit here; terms to google for
146 * include "Hindley-Milner type inference", "unification", and "algorithm W".
148 | Tvar : Ident.t -> locl ty_
150 (* The type of an opaque type (e.g. a "newtype" outside of the file where it
151 * was defined). They are "opaque", which means that they only unify with
152 * themselves. However, it is possible to have a constraint that allows us to
153 * relax this. For example:
155 * newtype my_type as int = ...
157 * Outside of the file where the type was defined, this translates to:
159 * Tabstract (AKnewtype (pos, "my_type", []), Some (Tprim Tint))
161 * Which means that my_type is abstract, but is subtype of int as well.
163 * We also create abstract types for generic parameters of a function, i.e.
165 * function foo<T>(T $x): void {
166 * // Body
169 * The type 'T' will be represented as an abstract type when type checking
170 * the body of 'foo'.
172 * Finally abstract types are also derived from the 'this' type and
173 * accessing type constants on it, resulting in a dependent type.
175 | Tabstract : abstract_kind * locl ty option -> locl ty_
177 (* An anonymous function, including the fun arity, and the identifier to
178 * type the body of the function. (The actual closure is stored in
179 * Typing_env.env.genv.anons) *)
180 | Tanon : locl fun_arity * Ident.t -> locl ty_
182 (* This is a kinda-union-type we use in order to defer picking which common
183 * ancestor for a type we should use until we hit a type annotation.
184 * For example:
186 * interface I {}
187 * class C implements I {}
188 * class D extends C {}
189 * function f(): I {
190 * if (...) {
191 * $x = new C();
192 * } else {
193 * $x = new D();
195 * return $x;
198 * What is the type of $x? We need to pick some common ancestor, but which
199 * one? Both C and I would be acceptable, which do we mean? This is where
200 * Tunresolved comes in -- after the if/else, the type of $x is
201 * Unresolved[C, D] -- it could be *either one*, and we defer the check until
202 * we hit an annotation. In particular, when we hit the "return", we make sure
203 * that it is compatible with both C and D, and then we know we've found the
204 * right supertype. Since we don't do global inference, we'll always either
205 * hit an annotation to check, or hit a place an annotation is missing in
206 * which case we can just throw away the type.
208 * Note that this is *not* really a union type -- most notably, it's allowed
209 * to grow as inference goes on, which union types don't. For example:
211 * function f(): Vector<num> {
212 * $v = Vector {};
213 * $v[] = 1;
214 * $v[] = 3.14;
215 * return $v;
218 * (Eliding some Tvar for clarity) On the first line, $v is
219 * Vector<Unresolved[]>. On the second, Vector<Unresolved[int]>. On the third,
220 * Vector<Unresolved[int,float]> -- it grows! Then when we finally return $v,
221 * we see that int and float are both compatible with num, and we have found
222 * our suitable supertype.
224 * One final implication of this growing is that if an unresolved is used in
225 * a contravariant position, we must collapse it down to whatever is annotated
226 * right then, in order to be sound.
228 | Tunresolved : locl ty list -> locl ty_
230 (* Tobject is an object type compatible with all objects. This type is also
231 * compatible with some string operations (since a class might implement
232 * __toString), but not with string type hints. In a similar way, Tobject
233 * is compatible with some array operations (since a class might implement
234 * ArrayAccess), but not with array type hints.
236 * Tobject is currently used to type code like:
237 * ../test/typecheck/return_unknown_class.php
239 | Tobject : locl ty_
241 (* An instance of a class or interface, ty list are the arguments *)
242 | Tclass : Nast.sid * locl ty list -> locl ty_
244 (* Localized version of Tarray *)
245 | Tarraykind : array_kind -> locl ty_
247 and array_kind =
248 (* Those three types directly correspond to their decl level counterparts:
249 * array, array<_> and array<_, _> *)
250 | AKany
251 (* An array declared as a varray. *)
252 | AKvarray of locl ty
253 | AKvec of locl ty
254 (* An array declared as a darray. *)
255 | AKdarray of locl ty * locl ty
256 (* An array annotated as a varray_or_darray. *)
257 | AKvarray_or_darray of locl ty
258 | AKmap of locl ty * locl ty
259 (* This is a type created when we see array() literal *)
260 | AKempty
261 (* Array "used like a shape" - initialized and indexed with keys that are
262 * only string/class constants *)
263 | AKshape of (locl ty * locl ty) Nast.ShapeMap.t
264 (* Array "used like a tuple" - initialized without keys and indexed with
265 * integers that are within initialized range *)
266 | AKtuple of (locl ty) IMap.t
268 (* An abstract type derived from either a newtype, a type parameter, or some
269 * dependent type
271 and abstract_kind =
272 (* newtype foo<T1, T2> ... *)
273 | AKnewtype of string * locl ty list
274 (* enum foo ... *)
275 | AKenum of string
276 (* <T super C> ; None if 'as' constrained *)
277 | AKgeneric of string
278 (* see dependent_type *)
279 | AKdependent of dependent_type
281 (* A dependent type consists of a base kind which indicates what the type is
282 * dependent on. It is either dependent on:
283 * - The type 'this'
284 * - The class context (what 'static' is resolved to in a class)
285 * - A class
286 * - An expression
288 * Dependent types also have a path component (derived from accessing a type
289 * constant). Thus the dependent type (`expr 0, ['A', 'B', 'C']) roughly means
290 * "The type resulting from accessing the type constant A then the type constant
291 * B and then the type constant C on the expression reference by 0"
293 and dependent_type =
294 (* Type that is the subtype of the late bound type within a class. *)
295 [ `this
296 (* The late bound type within a class. It is the type of 'new static()' and
297 * '$this'. This is different from the 'this' type. The 'this' type isn't
298 * quite strong enough in some cases. It means you are a subtype of the late
299 * bound class, but there are instances where you need the exact type.
300 * We may not need both since the only way to make something of type 'this'
301 * that is not 'static' is with 'instanceof static'.
303 | `static
304 (* A class name, new type, or generic, i.e.
306 * abstract class C { abstract const type T }
308 * The type C::T is (`cls '\C', ['T'])
310 | `cls of string
311 (* A reference to some expression. For example:
313 * $x->foo()
315 * The expression $x would have a reference Ident.t
316 * The expression $x->foo() would have a different one
318 | `expr of Ident.t
319 ] * string list
321 and taccess_type = decl ty * Nast.sid list
323 (* Local shape constructed using "shape" keyword has all the fields
324 * known:
326 * $s = shape('x' => 4, 'y' => 4);
328 * It has fields 'x' and 'y' and definitely no other fields. On the other
329 * hand, shape types that come from typehints may (due to structural
330 * subtyping of shapes) have some other, unlisted fields:
332 * type s = shape('x' => int);
334 * function f(s $s) {
337 * f(shape('x' => 4, 'y' => 5));
339 * The call to f is valid because of structural subtyping - shapes are
340 * permitted to "forget" fields. But the 'y' field still exists at runtime,
341 * and we cannot say inside the body of $f that we know that 'x' is the only
342 * field. This is relevant when deciding if it's safe to omit optional fields
343 * - if shape fields are not fully known, even optional fields have to be
344 * explicitly set/unset.
346 * We also track in additional map of FieldsPartiallyKnown names of fields
347 * that are known to not exist (because they were explicitly unset).
349 and shape_fields_known =
350 | FieldsFullyKnown
351 | FieldsPartiallyKnown of Pos.t Nast.ShapeMap.t
353 (* represents reactivity of function
354 - None corresponds to non-reactive function
355 - Some reactivity - to reactive function with specified reactivity flavor
357 Nonreactive <: Local -t <: Shallow -t <: Reactive -t
359 MaybeReactive represents conditional reactivity of function that depends on
360 reactivity of function arguments
361 <<__Rx>>
362 function f(<<__MaybeRx>> $g) { ... }
363 call to function f will be treated as reactive only if $g is reactive
365 and reactivity =
366 | Nonreactive
367 | Local of decl ty option
368 | Shallow of decl ty option
369 | Reactive of decl ty option
370 | MaybeReactive of reactivity
372 (* The type of a function AND a method.
373 * A function has a min and max arity because of optional arguments *)
374 and 'phase fun_type = {
375 ft_pos : Pos.t ;
376 ft_deprecated : string option ;
377 ft_abstract : bool ;
378 ft_is_coroutine : bool ;
379 ft_arity : 'phase fun_arity ;
380 ft_tparams : 'phase tparam list ;
381 ft_where_constraints : 'phase where_constraint list ;
382 ft_params : 'phase fun_params ;
383 ft_ret : 'phase ty ;
384 ft_ret_by_ref : bool ;
385 ft_reactive : reactivity ;
386 ft_return_disposable : bool ;
387 ft_mutable : bool ;
388 ft_returns_mutable : bool ;
389 ft_decl_errors : Errors.t option ;
390 ft_returns_void_to_rx: bool ;
393 (* Arity information for a fun_type; indicating the minimum number of
394 * args expected by the function and the maximum number of args for
395 * standard, non-variadic functions or the type of variadic argument taken *)
396 and 'phase fun_arity =
397 | Fstandard of int * int (* min ; max *)
398 (* PHP5.6-style ...$args finishes the func declaration *)
399 | Fvariadic of int * 'phase fun_param (* min ; variadic param type *)
400 (* HH-style ... anonymous variadic arg; body presumably uses func_get_args *)
401 | Fellipsis of int (* min *)
403 and param_mode =
404 | FPnormal
405 | FPref
406 | FPinout
408 and param_rx_condition =
409 | Param_rxfunc
410 | Param_rx_if_impl of decl ty
412 and 'phase fun_param = {
413 fp_pos : Pos.t;
414 fp_name : string option;
415 fp_type : 'phase ty;
416 fp_kind : param_mode;
417 fp_accept_disposable : bool;
418 fp_mutable : bool;
419 fp_rx_condition: param_rx_condition option;
422 and 'phase fun_params = 'phase fun_param list
424 and class_elt = {
425 ce_final : bool;
426 ce_is_xhp_attr : bool;
427 ce_override : bool;
428 (* true if this elt arose from require-extends or other mechanisms
429 of hack "synthesizing" methods that were not written by the
430 programmer. The eventual purpose of this is to make sure that
431 elts that *are* written by the programmer take precedence over
432 synthesized elts. *)
433 ce_synthesized : bool;
434 ce_visibility : visibility;
435 ce_const : bool;
436 ce_type : decl ty Lazy.t;
437 (* identifies the class from which this elt originates *)
438 ce_origin : string;
441 and class_const = {
442 cc_synthesized : bool;
443 cc_abstract : bool;
444 cc_pos : Pos.t;
445 cc_type : decl ty;
446 cc_expr : Nast.expr option;
447 (* identifies the class from which this const originates *)
448 cc_origin : string;
451 (* The position is that of the hint in the `use` / `implements` AST node
452 * that causes a class to have this requirement applied to it. E.g.
454 * class Foo {}
456 * interface Bar {
457 * require extends Foo; <- position of the decl ty
460 * class Baz extends Foo implements Bar { <- position of the `implements`
463 and requirement = Pos.t * decl ty
465 and class_type = {
466 tc_need_init : bool;
467 (* Whether the typechecker knows of all (non-interface) ancestors
468 * and thus known all accessible members of this class *)
469 tc_members_fully_known : bool;
470 tc_abstract : bool;
471 tc_final : bool;
472 tc_const : bool;
473 (* When a class is abstract (or in a trait) the initialization of
474 * a protected member can be delayed *)
475 tc_deferred_init_members : SSet.t;
476 tc_kind : Ast.class_kind;
477 tc_is_xhp : bool;
478 tc_is_disposable : bool;
479 tc_name : string ;
480 tc_pos : Pos.t ;
481 tc_tparams : decl tparam list ;
482 tc_consts : class_const SMap.t;
483 tc_typeconsts : typeconst_type SMap.t;
484 tc_props : class_elt SMap.t;
485 tc_sprops : class_elt SMap.t;
486 tc_methods : class_elt SMap.t;
487 tc_smethods : class_elt SMap.t;
488 tc_construct : class_elt option * bool;
489 (* This includes all the classes, interfaces and traits this class is
490 * using. *)
491 tc_ancestors : decl ty SMap.t ;
492 tc_req_ancestors : requirement list;
493 tc_req_ancestors_extends : SSet.t; (* the extends of req_ancestors *)
494 tc_extends : SSet.t;
495 tc_enum_type : enum_type option;
496 tc_decl_errors : Errors.t option;
499 and typeconst_type = {
500 ttc_name : Nast.sid;
501 ttc_constraint : decl ty option;
502 ttc_type : decl ty option;
503 ttc_origin : string;
506 and enum_type = {
507 te_base : decl ty;
508 te_constraint : decl ty option;
511 and typedef_type = {
512 td_pos: Pos.t;
513 td_vis: Nast.typedef_visibility;
514 td_tparams: decl tparam list;
515 td_constraint: decl ty option;
516 td_type: decl ty;
517 td_decl_errors: Errors.t option;
520 and 'phase tparam =
521 Ast.variance * Ast.id * (Ast.constraint_kind * 'phase ty) list
523 and 'phase where_constraint =
524 'phase ty * Ast.constraint_kind * 'phase ty
526 type phase_ty =
527 | DeclTy of decl ty
528 | LoclTy of locl ty
530 (* Tracks information about how a type was expanded *)
531 type expand_env = {
532 (* A list of the type defs and type access we have expanded thus far. Used
533 * to prevent entering into a cycle when expanding these types
535 type_expansions : (Pos.t * string) list;
536 substs : locl ty SMap.t;
537 this_ty : locl ty;
538 (* The class that the type is extracted from. Used for creating expression
539 * dependent types for type constants.
541 from_class : Nast.class_id_ option;
544 type ety = expand_env * locl ty
546 let has_expanded {type_expansions; _} x =
547 List.exists type_expansions begin function
548 | (_, x') when x = x' -> true
549 | _ -> false
552 (* The identifier for this *)
553 let this = Local_id.make "$this"
555 let arity_min ft_arity : int = match ft_arity with
556 | Fstandard (min, _) | Fvariadic (min, _) | Fellipsis min -> min
558 let get_param_mode ~is_ref callconv =
559 (* If a param has both & and inout, this should have errored in parsing. *)
560 match callconv with
561 | Some Ast.Pinout -> FPinout
562 | None when is_ref -> FPref
563 | None -> FPnormal
565 module AbstractKind = struct
566 let to_string = function
567 | AKnewtype (name, _) -> name
568 | AKgeneric name -> name
569 | AKenum name -> "enum "^(Utils.strip_ns name)
570 | AKdependent (dt, ids) ->
571 let dt =
572 match dt with
573 | `this -> SN.Typehints.this
574 | `static -> "<"^SN.Classes.cStatic^">"
575 | `cls c -> c
576 | `expr i ->
577 let display_id = Reason.get_expr_display_id i in
578 "<expr#"^string_of_int display_id^">" in
579 String.concat "::" (dt::ids)
581 let is_generic_dep_ty s = String_utils.is_substring "::" s
584 module ShapeFieldMap = struct
585 include Nast.ShapeMap
587 let map_and_rekey shape_map key_f value_f =
588 let f_over_shape_field_type ({ sft_ty; _ } as shape_field_type) =
589 { shape_field_type with sft_ty = value_f sft_ty } in
590 Nast.ShapeMap.map_and_rekey
591 shape_map
592 key_f
593 f_over_shape_field_type
595 let map_env f env shape_map =
596 let f_over_shape_field_type env ({ sft_ty; _ } as shape_field_type) =
597 let env, sft_ty = f env sft_ty in
598 env, { shape_field_type with sft_ty } in
599 Nast.ShapeMap.map_env f_over_shape_field_type env shape_map
601 let map f shape_map = map_and_rekey shape_map (fun x -> x) f
603 let iter f shape_map =
604 let f_over_shape_field_type shape_map_key { sft_ty; _ } =
605 f shape_map_key sft_ty in
606 Nast.ShapeMap.iter f_over_shape_field_type shape_map
608 let iter_values f = iter (fun _ -> f)
611 module ShapeFieldList = struct
612 include Hh_core.List
614 let map_env env xs ~f =
615 let f_over_shape_field_type env ({ sft_ty; _ } as shape_field_type) =
616 let env, sft_ty = f env sft_ty in
617 env, { shape_field_type with sft_ty } in
618 Hh_core.List.map_env env xs ~f:f_over_shape_field_type
621 (*****************************************************************************)
622 (* Suggest mode *)
623 (*****************************************************************************)
625 (* Set to true when we are trying to infer the missing type hints. *)
626 let is_suggest_mode = ref false
628 (* Ordinal value for type constructor, for localized types *)
629 let ty_con_ordinal ty =
630 match snd ty with
631 | Tany -> 0
632 | Tmixed -> 1
633 | Tnonnull -> 2
634 | Tdynamic -> 3
635 | Terr -> 4
636 | Toption _ -> 5
637 | Tprim _ -> 6
638 | Tfun _ -> 7
639 | Ttuple _ -> 8
640 | Tshape _ -> 9
641 | Tvar _ -> 10
642 | Tabstract _ -> 11
643 | Tanon _ -> 12
644 | Tunresolved _ -> 13
645 | Tobject -> 14
646 | Tclass _ -> 15
647 | Tarraykind _ -> 16
649 let array_kind_con_ordinal ak =
650 match ak with
651 | AKany -> 0
652 | AKvarray _ -> 1
653 | AKvec _ -> 2
654 | AKdarray _ -> 3
655 | AKvarray_or_darray _ -> 4
656 | AKmap _ -> 5
657 | AKempty -> 6
658 | AKshape _ -> 7
659 | AKtuple _ -> 8
661 let abstract_kind_con_ordinal ak =
662 match ak with
663 | AKnewtype _ -> 0
664 | AKenum _ -> 1
665 | AKgeneric _ -> 2
666 | AKdependent _ -> 3
668 (* Compare two types syntactically, ignoring reason information and other
669 * small differences that do not affect type inference behaviour. This
670 * comparison function can be used to construct tree-based sets of types,
671 * or to compare two types for "exact" equality.
672 * Note that this function does *not* expand type variables, or type
673 * aliases.
674 * But if ty_compare ty1 ty2 = 0, then the types must not be distinguishable
675 * by any typing rules.
677 let rec ty_compare ty1 ty2 =
678 let ty_1, ty_2 = (snd ty1, snd ty2) in
679 match ty_1, ty_2 with
680 | Tprim ty1, Tprim ty2 ->
681 compare ty1 ty2
682 | Toption ty, Toption ty2 ->
683 ty_compare ty ty2
684 | Tfun fty, Tfun fty2 ->
685 tfun_compare fty fty2
686 | Tunresolved tyl1, Tunresolved tyl2
687 | Ttuple tyl1, Ttuple tyl2 ->
688 tyl_compare tyl1 tyl2
689 | Tabstract (ak1, opt_cstr1), Tabstract (ak2, opt_cstr2) ->
690 begin match abstract_kind_compare ak1 ak2 with
691 | 0 -> opt_ty_compare opt_cstr1 opt_cstr2
692 | n -> n
694 (* An instance of a class or interface, ty list are the arguments *)
695 | Tclass (id, tyl), Tclass(id2, tyl2) ->
696 begin match String.compare (snd id) (snd id2) with
697 | 0 -> tyl_compare tyl tyl2
698 | n -> n
700 | Tarraykind ak1, Tarraykind ak2 ->
701 array_kind_compare ak1 ak2
702 | Tshape (known1, fields1), Tshape (known2, fields2) ->
703 begin match shape_fields_known_compare known1 known2 with
704 | 0 ->
705 List.compare ~cmp:(fun (k1,v1) (k2,v2) ->
706 match compare k1 k2 with
707 | 0 -> shape_field_type_compare v1 v2
708 | n -> n)
709 (Nast.ShapeMap.elements fields1) (Nast.ShapeMap.elements fields2)
710 | n -> n
712 | Tvar v1, Tvar v2 ->
713 compare v1 v2
714 | Tanon (_, id1), Tanon (_, id2) ->
715 compare id1 id2
716 | _ ->
717 ty_con_ordinal ty1 - ty_con_ordinal ty2
719 and shape_fields_known_compare sfk1 sfk2 =
720 match sfk1, sfk2 with
721 | FieldsFullyKnown, FieldsFullyKnown -> 0
722 | FieldsFullyKnown, FieldsPartiallyKnown _ -> -1
723 | FieldsPartiallyKnown _, FieldsFullyKnown -> 1
724 | FieldsPartiallyKnown f1, FieldsPartiallyKnown f2 ->
725 compare (Nast.ShapeMap.keys f1) (Nast.ShapeMap.keys f2)
727 and shape_field_type_compare sft1 sft2 =
728 match ty_compare sft1.sft_ty sft2.sft_ty with
729 | 0 -> compare sft1.sft_optional sft2.sft_optional
730 | n -> n
732 and tfun_compare fty1 fty2 =
733 begin match ty_compare fty1.ft_ret fty2.ft_ret with
734 | 0 ->
735 begin match ft_params_compare fty1.ft_params fty2.ft_params with
736 | 0 ->
737 compare
738 (fty1.ft_is_coroutine, fty1.ft_arity, fty1.ft_ret_by_ref, fty1.ft_reactive,
739 fty1.ft_return_disposable, fty1.ft_mutable, fty1.ft_returns_mutable)
740 (fty2.ft_is_coroutine, fty2.ft_arity, fty2.ft_ret_by_ref, fty2.ft_reactive,
741 fty2.ft_return_disposable, fty2.ft_mutable, fty2.ft_returns_mutable)
742 | n -> n
744 | n -> n
747 and ft_params_compare params1 params2 =
748 List.compare ~cmp:ft_param_compare params1 params2
750 and ft_param_compare param1 param2 =
751 match ty_compare param1.fp_type param2.fp_type with
752 | 0 ->
753 compare
754 (param1.fp_kind, param1.fp_accept_disposable, param1.fp_mutable)
755 (param2.fp_kind, param2.fp_accept_disposable, param2.fp_mutable)
756 | n -> n
758 and tyl_compare tyl1 tyl2 =
759 List.compare ~cmp:ty_compare tyl1 tyl2
761 and opt_ty_compare opt_ty1 opt_ty2 =
762 match opt_ty1, opt_ty2 with
763 | None, None -> 0
764 | Some _, None -> 1
765 | None, Some _ -> -1
766 | Some ty1, Some ty2 -> ty_compare ty1 ty2
768 and array_kind_compare ak1 ak2 =
769 match ak1, ak2 with
770 | AKmap (ty1, ty2), AKmap (ty3, ty4)
771 | AKdarray (ty1, ty2), AKdarray (ty3, ty4) ->
772 tyl_compare [ty1; ty2] [ty3; ty4]
773 | AKvarray ty1, AKvarray ty2
774 | AKvarray_or_darray ty1, AKvarray_or_darray ty2
775 | AKvec ty1, AKvec ty2 ->
776 ty_compare ty1 ty2
777 | _ ->
778 array_kind_con_ordinal ak1 - array_kind_con_ordinal ak2
780 and abstract_kind_compare t1 t2 =
781 match t1, t2 with
782 | AKnewtype (id, tyl), AKnewtype (id2, tyl2) ->
783 begin match String.compare id id2 with
784 | 0 -> tyl_compare tyl tyl2
785 | n -> n
787 | AKgeneric id1, AKgeneric id2
788 | AKenum id1, AKenum id2 ->
789 String.compare id1 id2
790 | AKdependent d1, AKdependent d2 ->
791 compare d1 d2
792 | _ ->
793 abstract_kind_con_ordinal t1 - abstract_kind_con_ordinal t2
795 let ty_equal ty1 ty2 = ty_compare ty1 ty2 = 0