Remove Tarray from the typechecker
[hiphop-php.git] / hphp / hack / src / typing / typing_defs.ml
bloba4ddea14d55998530375c8f34bff5f8bf08adf39
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_prelude
11 open Typing_defs_flags
12 include Typing_defs_core
14 type const_decl = {
15 cd_pos: Pos.t;
16 cd_type: decl_ty;
18 [@@deriving show]
20 type class_elt = {
21 ce_visibility: ce_visibility;
22 ce_type: decl_ty Lazy.t;
23 ce_origin: string; (** identifies the class from which this elt originates *)
24 ce_deprecated: string option;
25 ce_pos: Pos.t Lazy.t; (** pos of the type of the elt *)
26 ce_flags: int;
28 [@@deriving show]
30 type fun_elt = {
31 fe_deprecated: string option;
32 fe_type: decl_ty;
33 fe_pos: Pos.t;
34 fe_php_std_lib: bool;
36 [@@deriving show]
38 type class_const = {
39 cc_synthesized: bool;
40 cc_abstract: bool;
41 cc_pos: Pos.t;
42 cc_type: decl_ty;
43 cc_origin: string;
44 (** identifies the class from which this const originates *)
46 [@@deriving show]
48 type record_field_req =
49 | ValueRequired
50 | HasDefaultValue
51 [@@deriving show]
53 type record_def_type = {
54 rdt_name: Nast.sid;
55 rdt_extends: Nast.sid option;
56 rdt_fields: (Nast.sid * record_field_req) list;
57 rdt_abstract: bool;
58 rdt_pos: Pos.t;
60 [@@deriving show]
62 (** The position is that of the hint in the `use` / `implements` AST node
63 * that causes a class to have this requirement applied to it. E.g.
65 * ```
66 * class Foo {}
68 * interface Bar {
69 * require extends Foo; <- position of the decl_phase ty
70 * }
72 * class Baz extends Foo implements Bar { <- position of the `implements`
73 * }
74 * ```
76 type requirement = Pos.t * decl_ty
78 and class_type = {
79 tc_need_init: bool;
80 tc_members_fully_known: bool;
81 (** Whether the typechecker knows of all (non-interface) ancestors
82 * and thus known all accessible members of this class *)
83 tc_abstract: bool;
84 tc_final: bool;
85 tc_const: bool;
86 tc_deferred_init_members: SSet.t;
87 (** When a class is abstract (or in a trait) the initialization of
88 * a protected member can be delayed *)
89 tc_kind: Ast_defs.class_kind;
90 tc_is_xhp: bool;
91 tc_has_xhp_keyword: bool;
92 tc_is_disposable: bool;
93 tc_name: string;
94 tc_pos: Pos.t;
95 tc_tparams: decl_tparam list;
96 tc_where_constraints: decl_where_constraint list;
97 tc_consts: class_const SMap.t;
98 tc_typeconsts: typeconst_type SMap.t;
99 tc_props: class_elt SMap.t;
100 tc_sprops: class_elt SMap.t;
101 tc_methods: class_elt SMap.t;
102 tc_smethods: class_elt SMap.t;
103 tc_construct: class_elt option * consistent_kind;
104 (** the consistent_kind represents final constructor or __ConsistentConstruct *)
105 tc_ancestors: decl_ty SMap.t;
106 (** This includes all the classes, interfaces and traits this class is
107 * using. *)
108 tc_implements_dynamic: bool; (** Whether the class is coercible to dynamic *)
109 tc_req_ancestors: requirement list;
110 tc_req_ancestors_extends: SSet.t; (** the extends of req_ancestors *)
111 tc_extends: SSet.t;
112 tc_enum_type: enum_type option;
113 tc_sealed_whitelist: SSet.t option;
114 tc_decl_errors: Errors.t option; [@opaque]
117 and typeconst_abstract_kind =
118 | TCAbstract of decl_ty option
119 | TCPartiallyAbstract
120 | TCConcrete
122 and typeconst_type = {
123 ttc_abstract: typeconst_abstract_kind;
124 ttc_name: Nast.sid;
125 ttc_constraint: decl_ty option;
126 ttc_type: decl_ty option;
127 ttc_origin: string;
128 ttc_enforceable: Pos.t * bool;
129 ttc_reifiable: Pos.t option;
132 and enum_type = {
133 te_base: decl_ty;
134 te_constraint: decl_ty option;
135 te_includes: decl_ty list;
136 te_enum_class: bool;
138 [@@deriving show]
140 type typedef_type = {
141 td_pos: Pos.t;
142 td_vis: Aast.typedef_visibility;
143 td_tparams: decl_tparam list;
144 td_constraint: decl_ty option;
145 td_type: decl_ty;
147 [@@deriving show]
149 let is_enum_class = function
150 | None -> false
151 | Some info -> info.te_enum_class
153 type phase_ty =
154 | DeclTy of decl_ty
155 | LoclTy of locl_ty
157 type deserialization_error =
158 | Wrong_phase of string
159 (** The type was valid, but some component thereof was a decl_ty when we
160 expected a locl_phase ty, or vice versa. *)
161 | Not_supported of string
162 (** The specific type or some component thereof is not one that we support
163 deserializing, usually because not enough information was serialized to be
164 able to deserialize it again. *)
165 | Deserialization_error of string
166 (** The input JSON was invalid for some reason. *)
168 (** Tracks information about how a type was expanded *)
169 type expand_env = {
170 type_expansions: (bool * Pos.t * string) list;
171 (** A list of the type defs and type access we have expanded thus far. Used
172 * to prevent entering into a cycle when expanding these types.
173 * If the boolean is set, then emit an error because we were checking the
174 * definition of a type (by type, or newtype, or a type constant)
176 substs: locl_ty SMap.t;
177 this_ty: locl_ty;
178 (** The type that is substituted for `this` in signatures. It should be
179 * set to an expression dependent type if appropraite
181 quiet: bool;
182 (** If set to true, do not report errors, just return Terr or equivalent *)
183 on_error: Errors.typing_error_callback;
184 (** If what we are localizing or expanding comes from the decl heap for
185 example, then some errors must be silenced since they must have already been
186 raised when first typechecking whatever we have fetched from the heap.
187 Setting {!quiet} to true will silence those errors.
188 T54121530 aims at offering a better mechanism. *)
191 let get_var t =
192 match get_node t with
193 | Tvar v -> Some v
194 | _ -> None
196 let get_class_type t =
197 match get_node t with
198 | Tclass (id, exact, tyl) -> Some (id, exact, tyl)
199 | _ -> None
201 let get_var_i t =
202 match t with
203 | LoclType t -> get_var t
204 | ConstraintType _ -> None
206 let is_tyvar t = Option.is_some (get_var t)
208 let is_var_v t v =
209 match get_node t with
210 | Tvar v' when Ident.equal v v' -> true
211 | _ -> false
213 let is_generic t =
214 match get_node t with
215 | Tgeneric _ -> true
216 | _ -> false
218 let is_dynamic t =
219 match get_node t with
220 | Tdynamic -> true
221 | _ -> false
223 let is_nonnull t =
224 match get_node t with
225 | Tnonnull -> true
226 | _ -> false
228 let is_fun t =
229 match get_node t with
230 | Tfun _ -> true
231 | _ -> false
233 let is_any t =
234 match get_node t with
235 | Tany _ -> true
236 | _ -> false
238 let is_generic_equal_to n t =
239 (* TODO(T69551141) handle type arguments *)
240 match get_node t with
241 | Tgeneric (n', _tyargs) when String.equal n n' -> true
242 | _ -> false
244 let is_prim p t =
245 match get_node t with
246 | Tprim p' when Aast.equal_tprim p p' -> true
247 | _ -> false
249 let is_union t =
250 match get_node t with
251 | Tunion _ -> true
252 | _ -> false
254 let is_constraint_type_union t =
255 match deref_constraint_type t with
256 | (_, TCunion _) -> true
257 | _ -> false
259 let is_has_member t =
260 match deref_constraint_type t with
261 | (_, Thas_member _) -> true
262 | _ -> false
264 let show_phase_ty _ = "<phase_ty>"
266 let pp_phase_ty _ _ = Printf.printf "%s\n" "<phase_ty>"
268 let is_locl_type = function
269 | LoclType _ -> true
270 | _ -> false
272 let has_expanded { type_expansions; _ } x =
273 List.find_map type_expansions (function
274 | (report, _, x') when String.equal x x' -> Some report
275 | _ -> None)
277 let reason = function
278 | LoclType t -> get_reason t
279 | ConstraintType t -> fst (deref_constraint_type t)
281 let is_constraint_type = function
282 | ConstraintType _ -> true
283 | LoclType _ -> false
285 let is_union_or_inter_type (ty : locl_ty) =
286 (* do not expand type here! *)
287 match get_node ty with
288 | Toption _
289 | Tunion _
290 | Tintersection _ ->
291 true
292 | Terr
293 | Tnonnull
294 | Tdynamic
295 | Tobject
296 | Tany _
297 | Tprim _
298 | Tfun _
299 | Ttuple _
300 | Tshape _
301 | Tvar _
302 | Tnewtype _
303 | Tdependent _
304 | Tgeneric _
305 | Tclass _
306 | Tvarray _
307 | Tdarray _
308 | Tunapplied_alias _
309 | Tvarray_or_darray _
310 | Taccess _ ->
311 false
313 module InternalType = struct
314 let get_var t =
315 match t with
316 | LoclType t -> get_var t
317 | ConstraintType _ -> None
319 let is_var_v t ~v =
320 match t with
321 | LoclType t -> is_var_v t v
322 | ConstraintType _ -> false
324 let is_not_var_v t ~v = not @@ is_var_v t ~v
327 (* The identifier for this *)
328 let this = Local_id.make_scoped "$this"
330 (* This should be the ONLY way that Tany is constructed anywhere in the
331 * codebase. *)
332 let make_tany () = Tany TanySentinel.value
334 let arity_min ft : int =
335 List.count ~f:(fun fp -> not (get_fp_has_default fp)) ft.ft_params
337 let get_param_mode callconv =
338 match callconv with
339 | Some Ast_defs.Pinout -> FPinout
340 | None -> FPnormal
342 module DependentKind = struct
343 let to_string = function
344 | DTthis -> SN.Typehints.this
345 | DTexpr i ->
346 let display_id = Reason.get_expr_display_id i in
347 "<expr#" ^ string_of_int display_id ^ ">"
349 let is_generic_dep_ty s = String_utils.is_substring "::" s
352 module ShapeFieldMap = struct
353 include Nast.ShapeMap
355 let map_and_rekey shape_map key_f value_f =
356 let f_over_shape_field_type ({ sft_ty; _ } as shape_field_type) =
357 { shape_field_type with sft_ty = value_f sft_ty }
359 Nast.ShapeMap.map_and_rekey shape_map key_f f_over_shape_field_type
361 let map_env f env shape_map =
362 let f_over_shape_field_type env _key ({ sft_ty; _ } as shape_field_type) =
363 let (env, sft_ty) = f env sft_ty in
364 (env, { shape_field_type with sft_ty })
366 Nast.ShapeMap.map_env f_over_shape_field_type env shape_map
368 let map f shape_map = map_and_rekey shape_map (fun x -> x) f
370 let iter f shape_map =
371 let f_over_shape_field_type shape_map_key { sft_ty; _ } =
372 f shape_map_key sft_ty
374 Nast.ShapeMap.iter f_over_shape_field_type shape_map
376 let iter_values f = iter (fun _ -> f)
379 module ShapeFieldList = struct
380 include Common.List
382 let map_env env xs ~f =
383 let f_over_shape_field_type env ({ sft_ty; _ } as shape_field_type) =
384 let (env, sft_ty) = f env sft_ty in
385 (env, { shape_field_type with sft_ty })
387 Common.List.map_env env xs ~f:f_over_shape_field_type
390 (*****************************************************************************)
391 (* Suggest mode *)
392 (*****************************************************************************)
394 (* Set to true when we are trying to infer the missing type hints. *)
395 let is_suggest_mode = ref false
397 (* Ordinal value for type constructor, for localized types *)
398 let ty_con_ordinal ty_ =
399 match ty_ with
400 | Tany _
401 | Terr ->
403 | Toption t ->
404 begin
405 match get_node t with
406 | Tnonnull -> 1
407 | _ -> 4
409 | Tnonnull -> 2
410 | Tdynamic -> 3
411 | Tprim _ -> 5
412 | Tfun _ -> 6
413 | Ttuple _ -> 7
414 | Tshape _ -> 8
415 | Tvar _ -> 9
416 | Tnewtype _ -> 10
417 | Tgeneric _ -> 11
418 | Tdependent _ -> 12
419 | Tunion _ -> 13
420 | Tintersection _ -> 14
421 | Tobject -> 15
422 | Tclass _ -> 16
423 | Tvarray _ -> 20
424 | Tdarray _ -> 21
425 | Tvarray_or_darray _ -> 22
426 | Tunapplied_alias _ -> 23
427 | Taccess _ -> 24
429 (* Ordinal value for type constructor, for decl types *)
430 let decl_ty_con_ordinal ty_ =
431 match ty_ with
432 | Tany _
433 | Terr ->
435 | Tthis -> 1
436 | Tapply _ -> 2
437 | Tgeneric _ -> 3
438 | Taccess _ -> 4
439 | Tdarray _ -> 6
440 | Tvarray _ -> 7
441 | Tvarray_or_darray _ -> 8
442 | Tmixed -> 9
443 | Tlike _ -> 10
444 | Tnonnull -> 11
445 | Tdynamic -> 12
446 | Toption _ -> 13
447 | Tprim _ -> 14
448 | Tfun _ -> 15
449 | Ttuple _ -> 16
450 | Tshape _ -> 17
451 | Tvar _ -> 19
452 | Tunion _ -> 20
453 | Tintersection _ -> 21
455 let reactivity_ordinal r =
456 match r with
457 | Nonreactive -> 0
458 | CippGlobal -> 1
459 | CippRx -> 2
460 | Local _ -> 3
461 | Shallow _ -> 4
462 | Reactive _ -> 5
463 | Pure _ -> 6
464 | MaybeReactive _ -> 7
465 | RxVar _ -> 8
466 | Cipp _ -> 9
467 | CippLocal _ -> 10
469 (* Compare two types syntactically, ignoring reason information and other
470 * small differences that do not affect type inference behaviour. This
471 * comparison function can be used to construct tree-based sets of types,
472 * or to compare two types for "exact" equality.
473 * Note that this function does *not* expand type variables, or type
474 * aliases.
475 * But if ty_compare ty1 ty2 = 0, then the types must not be distinguishable
476 * by any typing rules.
478 let rec ty__compare ?(normalize_lists = false) ty_1 ty_2 =
479 let rec ty__compare ty_1 ty_2 =
480 match (ty_1, ty_2) with
481 | (Tprim ty1, Tprim ty2) -> Aast_defs.compare_tprim ty1 ty2
482 | (Toption ty, Toption ty2)
483 | (Tvarray ty, Tvarray ty2) ->
484 ty_compare ty ty2
485 | (Tdarray (tk, tv), Tdarray (tk2, tv2))
486 | (Tvarray_or_darray (tk, tv), Tvarray_or_darray (tk2, tv2)) ->
487 begin
488 match ty_compare tk tk2 with
489 | 0 -> ty_compare tv tv2
490 | n -> n
492 | (Tfun fty, Tfun fty2) -> tfun_compare fty fty2
493 | (Tunion tyl1, Tunion tyl2)
494 | (Tintersection tyl1, Tintersection tyl2)
495 | (Ttuple tyl1, Ttuple tyl2) ->
496 tyl_compare ~sort:normalize_lists ~normalize_lists tyl1 tyl2
497 | (Tgeneric (n1, args1), Tgeneric (n2, args2)) ->
498 begin
499 match String.compare n1 n2 with
500 | 0 -> tyl_compare ~sort:false ~normalize_lists args1 args2
501 | n -> n
503 | (Tnewtype (id, tyl, cstr1), Tnewtype (id2, tyl2, cstr2)) ->
504 begin
505 match String.compare id id2 with
506 | 0 ->
507 (match tyl_compare ~sort:false tyl tyl2 with
508 | 0 -> ty_compare cstr1 cstr2
509 | n -> n)
510 | n -> n
512 | (Tdependent (d1, cstr1), Tdependent (d2, cstr2)) ->
513 begin
514 match compare_dependent_type d1 d2 with
515 | 0 -> ty_compare cstr1 cstr2
516 | n -> n
518 (* An instance of a class or interface, ty list are the arguments *)
519 | (Tclass (id, exact, tyl), Tclass (id2, exact2, tyl2)) ->
520 begin
521 match String.compare (snd id) (snd id2) with
522 | 0 ->
523 begin
524 match tyl_compare ~sort:false tyl tyl2 with
525 | 0 -> compare_exact exact exact2
526 | n -> n
528 | n -> n
530 | (Tshape (shape_kind1, fields1), Tshape (shape_kind2, fields2)) ->
531 begin
532 match compare_shape_kind shape_kind1 shape_kind2 with
533 | 0 ->
534 List.compare
535 (fun (k1, v1) (k2, v2) ->
536 match Ast_defs.ShapeField.compare k1 k2 with
537 | 0 -> shape_field_type_compare v1 v2
538 | n -> n)
539 (Nast.ShapeMap.elements fields1)
540 (Nast.ShapeMap.elements fields2)
541 | n -> n
543 | (Tvar v1, Tvar v2) -> compare v1 v2
544 | (Tunapplied_alias n1, Tunapplied_alias n2) -> String.compare n1 n2
545 | (Taccess (ty1, id1), Taccess (ty2, id2)) ->
546 begin
547 match ty_compare ty1 ty2 with
548 | 0 -> String.compare (snd id1) (snd id2)
549 | n -> n
551 | (Tnonnull, Tnonnull) -> 0
552 | (Tdynamic, Tdynamic) -> 0
553 | (Tobject, Tobject) -> 0
554 | (Terr, Terr) -> 0
555 | ( ( Tprim _ | Toption _ | Tvarray _ | Tdarray _ | Tvarray_or_darray _
556 | Tfun _ | Tintersection _ | Tunion _ | Ttuple _ | Tgeneric _
557 | Tnewtype _ | Tdependent _ | Tclass _ | Tshape _ | Tvar _
558 | Tunapplied_alias _ | Tnonnull | Tdynamic | Terr | Tobject | Taccess _
559 | Tany _ ),
561 | ( _,
562 ( Tprim _ | Toption _ | Tvarray _ | Tdarray _ | Tvarray_or_darray _
563 | Tfun _ | Tintersection _ | Tunion _ | Ttuple _ | Tgeneric _
564 | Tnewtype _ | Tdependent _ | Tclass _ | Tshape _ | Tvar _
565 | Tunapplied_alias _ | Tnonnull | Tdynamic | Terr | Tobject | Taccess _
566 | Tany _ ) ) ->
567 ty_con_ordinal ty_1 - ty_con_ordinal ty_2
568 and shape_field_type_compare sft1 sft2 =
569 let { sft_ty = ty1; sft_optional = optional1 } = sft1 in
570 let { sft_ty = ty2; sft_optional = optional2 } = sft2 in
571 match ty_compare ty1 ty2 with
572 | 0 -> Bool.compare optional1 optional2
573 | n -> n
574 and user_attribute_compare ua1 ua2 =
575 let { ua_name = name1; ua_classname_params = classname_params1 } = ua1 in
576 let { ua_name = name2; ua_classname_params = classname_params2 } = ua2 in
577 match String.compare (snd name1) (snd name2) with
578 | 0 -> List.compare String.compare classname_params1 classname_params2
579 | n -> n
580 and user_attributes_compare ual1 ual2 =
581 List.compare user_attribute_compare ual1 ual2
582 and tparam_compare tp1 tp2 =
583 let {
584 (* Type parameters on functions are always marked invariant *)
585 tp_variance = _;
586 tp_name = name1;
587 tp_tparams = tparams1;
588 tp_constraints = constraints1;
589 tp_reified = reified1;
590 tp_user_attributes = user_attributes1;
594 let {
595 tp_variance = _;
596 tp_name = name2;
597 tp_tparams = tparams2;
598 tp_constraints = constraints2;
599 tp_reified = reified2;
600 tp_user_attributes = user_attributes2;
604 match String.compare (snd name1) (snd name2) with
605 | 0 ->
606 begin
607 match tparams_compare tparams1 tparams2 with
608 | 0 ->
609 begin
610 match constraints_compare constraints1 constraints2 with
611 | 0 ->
612 begin
613 match
614 user_attributes_compare user_attributes1 user_attributes2
615 with
616 | 0 -> Aast_defs.compare_reify_kind reified1 reified2
617 | n -> n
619 | n -> n
621 | n -> n
623 | n -> n
624 and tparams_compare tpl1 tpl2 = List.compare tparam_compare tpl1 tpl2
625 and constraints_compare cl1 cl2 = List.compare constraint_compare cl1 cl2
626 and constraint_compare (ck1, ty1) (ck2, ty2) =
627 match Ast_defs.compare_constraint_kind ck1 ck2 with
628 | 0 -> ty_compare ty1 ty2
629 | n -> n
630 and where_constraint_compare (ty1a, ck1, ty1b) (ty2a, ck2, ty2b) =
631 match Ast_defs.compare_constraint_kind ck1 ck2 with
632 | 0 ->
633 begin
634 match ty_compare ty1a ty2a with
635 | 0 -> ty_compare ty1b ty2b
636 | n -> n
638 | n -> n
639 and where_constraints_compare cl1 cl2 =
640 List.compare where_constraint_compare cl1 cl2
641 (* We match every field rather than using field selection syntax. This guards against future additions to function type elements *)
642 and tfun_compare fty1 fty2 =
643 let {
644 ft_ret = ret1;
645 ft_params = params1;
646 ft_arity = arity1;
647 ft_reactive = reactive1;
648 ft_flags = flags1;
649 ft_implicit_params = implicit_params1;
650 ft_ifc_decl = ifc_decl1;
651 ft_tparams = tparams1;
652 ft_where_constraints = where_constraints1;
654 fty1
656 let {
657 ft_ret = ret2;
658 ft_params = params2;
659 ft_arity = arity2;
660 ft_reactive = reactive2;
661 ft_flags = flags2;
662 ft_implicit_params = implicit_params2;
663 ft_ifc_decl = ifc_decl2;
664 ft_tparams = tparams2;
665 ft_where_constraints = where_constraints2;
667 fty2
669 match possibly_enforced_ty_compare ret1 ret2 with
670 | 0 ->
671 begin
672 match ft_params_compare params1 params2 with
673 | 0 ->
674 (* Explicit polymorphic equality. Need to write equality on
675 * locl_ty by hand if we want to make a specialized one
677 begin
678 match ft_arity_compare arity1 arity2 with
679 | 0 ->
680 begin
681 match tparams_compare tparams1 tparams2 with
682 | 0 ->
683 begin
684 match
685 where_constraints_compare
686 where_constraints1
687 where_constraints2
688 with
689 | 0 ->
690 begin
691 match Int.compare flags1 flags2 with
692 | 0 ->
693 let { capability = capability1 } = implicit_params1 in
694 let { capability = capability2 } = implicit_params2 in
695 begin
696 match
697 capability_compare capability1 capability2
698 with
699 | 0 ->
700 begin
701 match
702 compare_ifc_fun_decl ifc_decl1 ifc_decl2
703 with
704 | 0 -> reactivity_compare reactive1 reactive2
705 | n -> n
707 | n -> n
709 | n -> n
711 | n -> n
713 | n -> n
715 | n -> n
717 | n -> n
719 | n -> n
720 and ft_arity_compare a1 a2 =
721 match (a1, a2) with
722 | (Fstandard, Fstandard) -> 0
723 | (Fstandard, Fvariadic _) -> -1
724 | (Fvariadic _, Fstandard) -> 1
725 | (Fvariadic p1, Fvariadic p2) -> ft_param_compare ~normalize_lists p1 p2
726 and capability_compare cap1 cap2 =
727 match (cap1, cap2) with
728 | (CapDefaults _, CapDefaults _) -> 0
729 | (CapDefaults _, CapTy _) -> -1
730 | (CapTy _, CapDefaults _) -> 1
731 | (CapTy ty1, CapTy ty2) -> ty_compare ty1 ty2
732 and reactivity_compare r1 r2 =
733 match (r1, r2) with
734 | (Nonreactive, Nonreactive)
735 | (CippGlobal, CippGlobal)
736 | (CippRx, CippRx) ->
738 | (Local opt_ty1, Local opt_ty2)
739 | (Shallow opt_ty1, Shallow opt_ty2)
740 | (Reactive opt_ty1, Reactive opt_ty2)
741 | (Pure opt_ty1, Pure opt_ty2) ->
742 (* TODO T82455489: proper decl compare. Poly.compare will be position sensitive *)
743 Option.compare Poly.compare opt_ty1 opt_ty2
744 | (MaybeReactive r1, MaybeReactive r2) -> reactivity_compare r1 r2
745 | (RxVar opt_r1, RxVar opt_r2) ->
746 Option.compare reactivity_compare opt_r1 opt_r2
747 | (Cipp opt_s1, Cipp opt_s2)
748 | (CippLocal opt_s1, CippLocal opt_s2) ->
749 Option.compare String.compare opt_s1 opt_s2
750 | ( ( Nonreactive | CippGlobal | CippRx | Local _ | Shallow _ | Reactive _
751 | Pure _ | MaybeReactive _ | RxVar _ | Cipp _ | CippLocal _ ),
752 ( Nonreactive | CippGlobal | CippRx | Local _ | Shallow _ | Reactive _
753 | Pure _ | MaybeReactive _ | RxVar _ | Cipp _ | CippLocal _ ) ) ->
754 reactivity_ordinal r1 - reactivity_ordinal r2
755 and ty_compare ty1 ty2 = ty__compare (get_node ty1) (get_node ty2) in
756 ty__compare ty_1 ty_2
758 and ty_compare ?(normalize_lists = false) ty1 ty2 =
759 ty__compare ~normalize_lists (get_node ty1) (get_node ty2)
761 and tyl_compare ~sort ?(normalize_lists = false) tyl1 tyl2 =
762 let (tyl1, tyl2) =
763 if sort then
764 (List.sort ~compare:ty_compare tyl1, List.sort ~compare:ty_compare tyl2)
765 else
766 (tyl1, tyl2)
768 List.compare (ty_compare ~normalize_lists) tyl1 tyl2
770 and possibly_enforced_ty_compare ?(normalize_lists = false) ety1 ety2 =
771 match ty_compare ~normalize_lists ety1.et_type ety2.et_type with
772 | 0 -> Bool.compare ety1.et_enforced ety2.et_enforced
773 | n -> n
775 and ft_param_compare ?(normalize_lists = false) param1 param2 =
776 match
777 possibly_enforced_ty_compare ~normalize_lists param1.fp_type param2.fp_type
778 with
779 | 0 -> Int.compare param1.fp_flags param2.fp_flags
780 | n -> n
782 and ft_params_compare ?(normalize_lists = false) params1 params2 =
783 List.compare (ft_param_compare ~normalize_lists) params1 params2
785 let tyl_equal tyl1 tyl2 = Int.equal 0 @@ tyl_compare ~sort:false tyl1 tyl2
787 let class_id_con_ordinal cid =
788 match cid with
789 | Aast.CIparent -> 0
790 | Aast.CIself -> 1
791 | Aast.CIstatic -> 2
792 | Aast.CIexpr _ -> 3
793 | Aast.CI _ -> 4
795 let class_id_compare cid1 cid2 =
796 match (cid1, cid2) with
797 | (Aast.CIexpr _e1, Aast.CIexpr _e2) -> 0
798 | (Aast.CI (_, id1), Aast.CI (_, id2)) -> String.compare id1 id2
799 | _ -> class_id_con_ordinal cid2 - class_id_con_ordinal cid1
801 let class_id_equal cid1 cid2 = Int.equal (class_id_compare cid1 cid2) 0
803 let has_member_compare ~normalize_lists hm1 hm2 =
804 let ty_compare = ty_compare ~normalize_lists in
805 let {
806 hm_name = (_, m1);
807 hm_type = ty1;
808 hm_class_id = cid1;
809 hm_explicit_targs = targs1;
813 let {
814 hm_name = (_, m2);
815 hm_type = ty2;
816 hm_class_id = cid2;
817 hm_explicit_targs = targs2;
821 let targ_compare (_, (_, hint1)) (_, (_, hint2)) =
822 Aast_defs.compare_hint_ hint1 hint2
824 match String.compare m1 m2 with
825 | 0 ->
826 (match ty_compare ty1 ty2 with
827 | 0 ->
828 (match class_id_compare cid1 cid2 with
829 | 0 -> Option.compare (List.compare targ_compare) targs1 targs2
830 | comp -> comp)
831 | comp -> comp)
832 | comp -> comp
834 let destructure_compare ~normalize_lists d1 d2 =
835 let {
836 d_required = tyl1;
837 d_optional = tyl_opt1;
838 d_variadic = ty_opt1;
839 d_kind = e1;
843 let {
844 d_required = tyl2;
845 d_optional = tyl_opt2;
846 d_variadic = ty_opt2;
847 d_kind = e2;
851 match tyl_compare ~normalize_lists ~sort:false tyl1 tyl2 with
852 | 0 ->
853 (match tyl_compare ~normalize_lists ~sort:false tyl_opt1 tyl_opt2 with
854 | 0 ->
855 (match Option.compare ty_compare ty_opt1 ty_opt2 with
856 | 0 -> compare_destructure_kind e1 e2
857 | comp -> comp)
858 | comp -> comp)
859 | comp -> comp
861 let constraint_ty_con_ordinal cty =
862 match cty with
863 | Thas_member _ -> 0
864 | Tdestructure _ -> 1
865 | TCunion _ -> 2
866 | TCintersection _ -> 3
868 let rec constraint_ty_compare ?(normalize_lists = false) ty1 ty2 =
869 let (_, ty1) = deref_constraint_type ty1 in
870 let (_, ty2) = deref_constraint_type ty2 in
871 match (ty1, ty2) with
872 | (Thas_member hm1, Thas_member hm2) ->
873 has_member_compare ~normalize_lists hm1 hm2
874 | (Tdestructure d1, Tdestructure d2) ->
875 destructure_compare ~normalize_lists d1 d2
876 | (TCunion (lty1, cty1), TCunion (lty2, cty2))
877 | (TCintersection (lty1, cty1), TCintersection (lty2, cty2)) ->
878 let comp1 = ty_compare ~normalize_lists lty1 lty2 in
879 if not @@ Int.equal comp1 0 then
880 comp1
881 else
882 constraint_ty_compare ~normalize_lists cty1 cty2
883 | (_, (Thas_member _ | Tdestructure _ | TCunion _ | TCintersection _)) ->
884 constraint_ty_con_ordinal ty2 - constraint_ty_con_ordinal ty1
886 let constraint_ty_equal ?(normalize_lists = false) ty1 ty2 =
887 Int.equal (constraint_ty_compare ~normalize_lists ty1 ty2) 0
889 let ty_equal ?(normalize_lists = false) ty1 ty2 =
890 Int.equal 0 (ty_compare ~normalize_lists ty1 ty2)
892 let equal_internal_type ty1 ty2 =
893 match (ty1, ty2) with
894 | (LoclType ty1, LoclType ty2) -> ty_equal ~normalize_lists:true ty1 ty2
895 | (ConstraintType ty1, ConstraintType ty2) ->
896 constraint_ty_equal ~normalize_lists:true ty1 ty2
897 | (_, (LoclType _ | ConstraintType _)) -> false
899 let equal_locl_ty ty1 ty2 = ty_equal ty1 ty2
901 let equal_locl_ty_ ty_1 ty_2 = Int.equal 0 (ty__compare ty_1 ty_2)
903 let equal_locl_fun_arity ft1 ft2 =
904 match (ft1.ft_arity, ft2.ft_arity) with
905 | (Fstandard, Fstandard) ->
906 Int.equal (List.length ft1.ft_params) (List.length ft2.ft_params)
907 | (Fvariadic param1, Fvariadic param2) ->
908 Int.equal 0 (ft_params_compare [param1] [param2])
909 | (Fstandard, Fvariadic _)
910 | (Fvariadic _, Fstandard) ->
911 false
913 let is_type_no_return = equal_locl_ty_ (Tprim Aast.Tnoreturn)
915 let make_function_type_rxvar param_ty =
916 match deref param_ty with
917 | (r, Tfun tfun) -> mk (r, Tfun { tfun with ft_reactive = RxVar None })
918 | (r, Toption t) ->
919 begin
920 match deref t with
921 | (r1, Tfun tfun) ->
922 mk (r, Toption (mk (r1, Tfun { tfun with ft_reactive = RxVar None })))
923 | _ -> param_ty
925 | _ -> param_ty
927 let rec equal_decl_ty_ ty_1 ty_2 =
928 match (ty_1, ty_2) with
929 | (Tany _, Tany _) -> true
930 | (Terr, Terr) -> true
931 | (Tthis, Tthis) -> true
932 | (Tmixed, Tmixed) -> true
933 | (Tnonnull, Tnonnull) -> true
934 | (Tdynamic, Tdynamic) -> true
935 | (Tapply ((_, s1), tyl1), Tapply ((_, s2), tyl2)) ->
936 String.equal s1 s2 && equal_decl_tyl tyl1 tyl2
937 | (Tgeneric (s1, argl1), Tgeneric (s2, argl2)) ->
938 String.equal s1 s2 && equal_decl_tyl argl1 argl2
939 | (Taccess (ty1, (_, s1)), Taccess (ty2, (_, s2))) ->
940 equal_decl_ty ty1 ty2 && String.equal s1 s2
941 | (Tdarray (tk1, tv1), Tdarray (tk2, tv2)) ->
942 equal_decl_ty tk1 tk2 && equal_decl_ty tv1 tv2
943 | (Tvarray ty1, Tvarray ty2) -> equal_decl_ty ty1 ty2
944 | (Tvarray_or_darray (tk1, tv1), Tvarray_or_darray (tk2, tv2)) ->
945 equal_decl_ty tk1 tk2 && equal_decl_ty tv1 tv2
946 | (Tlike ty1, Tlike ty2) -> equal_decl_ty ty1 ty2
947 | (Tprim ty1, Tprim ty2) -> Aast.equal_tprim ty1 ty2
948 | (Toption ty, Toption ty2) -> equal_decl_ty ty ty2
949 | (Tfun fty1, Tfun fty2) -> equal_decl_fun_type fty1 fty2
950 | (Tunion tyl1, Tunion tyl2)
951 | (Tintersection tyl1, Tintersection tyl2)
952 | (Ttuple tyl1, Ttuple tyl2) ->
953 equal_decl_tyl tyl1 tyl2
954 | (Tshape (shape_kind1, fields1), Tshape (shape_kind2, fields2)) ->
955 equal_shape_kind shape_kind1 shape_kind2
956 && List.equal
957 (fun (k1, v1) (k2, v2) ->
958 Ast_defs.ShapeField.equal k1 k2 && equal_shape_field_type v1 v2)
959 (Nast.ShapeMap.elements fields1)
960 (Nast.ShapeMap.elements fields2)
961 | (Tvar v1, Tvar v2) -> Ident.equal v1 v2
962 | (Tany _, _)
963 | (Terr, _)
964 | (Tthis, _)
965 | (Tapply _, _)
966 | (Tgeneric _, _)
967 | (Taccess _, _)
968 | (Tdarray _, _)
969 | (Tvarray _, _)
970 | (Tvarray_or_darray _, _)
971 | (Tmixed, _)
972 | (Tlike _, _)
973 | (Tnonnull, _)
974 | (Tdynamic, _)
975 | (Toption _, _)
976 | (Tprim _, _)
977 | (Tfun _, _)
978 | (Ttuple _, _)
979 | (Tshape _, _)
980 | (Tvar _, _)
981 | (Tunion _, _)
982 | (Tintersection _, _) ->
983 false
985 and equal_decl_ty ty1 ty2 = equal_decl_ty_ (get_node ty1) (get_node ty2)
987 and equal_shape_field_type sft1 sft2 =
988 equal_decl_ty sft1.sft_ty sft2.sft_ty
989 && Bool.equal sft1.sft_optional sft2.sft_optional
991 and equal_decl_fun_arity ft1 ft2 =
992 match (ft1.ft_arity, ft2.ft_arity) with
993 | (Fstandard, Fstandard) ->
994 Int.equal (List.length ft1.ft_params) (List.length ft2.ft_params)
995 | (Fvariadic param1, Fvariadic param2) ->
996 equal_decl_ft_params [param1] [param2]
997 | (Fstandard, Fvariadic _)
998 | (Fvariadic _, Fstandard) ->
999 false
1001 and equal_decl_fun_type fty1 fty2 =
1002 equal_decl_possibly_enforced_ty fty1.ft_ret fty2.ft_ret
1003 && equal_decl_ft_params fty1.ft_params fty2.ft_params
1004 && equal_decl_ft_implicit_params
1005 fty1.ft_implicit_params
1006 fty2.ft_implicit_params
1007 && equal_decl_fun_arity fty1 fty2
1008 && equal_reactivity fty1.ft_reactive fty2.ft_reactive
1009 && Int.equal fty1.ft_flags fty2.ft_flags
1011 and equal_reactivity r1 r2 =
1012 match (r1, r2) with
1013 | (Nonreactive, Nonreactive) -> true
1014 | (Local ty1, Local ty2)
1015 | (Shallow ty1, Shallow ty2)
1016 | (Reactive ty1, Reactive ty2)
1017 | (Pure ty1, Pure ty2) ->
1018 Option.equal equal_decl_ty ty1 ty2
1019 | (MaybeReactive r1, MaybeReactive r2) -> equal_reactivity r1 r2
1020 | (RxVar r1, RxVar r2) -> Option.equal equal_reactivity r1 r2
1021 | (Cipp s1, Cipp s2) -> Option.equal String.equal s1 s2
1022 | (CippLocal s1, CippLocal s2) -> Option.equal String.equal s1 s2
1023 | (CippGlobal, CippGlobal) -> true
1024 | (CippRx, CippRx) -> true
1025 | _ -> false
1027 and any_reactive r =
1028 match r with
1029 | Local _
1030 | Shallow _
1031 | Reactive _
1032 | Pure _
1033 | MaybeReactive _
1034 | RxVar _
1035 | CippRx ->
1036 true
1037 | Nonreactive
1038 | Cipp _
1039 | CippLocal _
1040 | CippGlobal ->
1041 false
1043 and non_public_ifc ifc =
1044 match ifc with
1045 | FDPolicied (Some "PUBLIC") -> false
1046 | _ -> true
1048 and equal_param_rx_annotation pa1 pa2 =
1049 match (pa1, pa2) with
1050 | (Param_rx_var, Param_rx_var) -> true
1051 | (Param_rx_if_impl ty1, Param_rx_if_impl ty2) -> equal_decl_ty ty1 ty2
1052 | (Param_rx_var, Param_rx_if_impl _)
1053 | (Param_rx_if_impl _, Param_rx_var) ->
1054 false
1056 and equal_decl_tyl tyl1 tyl2 = List.equal equal_decl_ty tyl1 tyl2
1058 and equal_decl_possibly_enforced_ty ety1 ety2 =
1059 equal_decl_ty ety1.et_type ety2.et_type
1060 && Bool.equal ety1.et_enforced ety2.et_enforced
1062 and equal_decl_fun_param param1 param2 =
1063 equal_decl_possibly_enforced_ty param1.fp_type param2.fp_type
1064 && Int.equal param1.fp_flags param2.fp_flags
1066 and equal_decl_ft_params params1 params2 =
1067 List.equal equal_decl_fun_param params1 params2
1069 and equal_decl_ft_implicit_params { capability = cap1 } { capability = cap2 } =
1070 (* TODO(coeffects): could rework this so that implicit defaults and explicit
1071 * [defaults] are considered equal *)
1072 match (cap1, cap2) with
1073 | (CapDefaults p1, CapDefaults p2) -> Pos.equal p1 p2
1074 | (CapTy c1, CapTy c2) -> equal_decl_ty c1 c2
1075 | (CapDefaults _, CapTy _)
1076 | (CapTy _, CapDefaults _) ->
1077 false
1079 let equal_typeconst_abstract_kind ak1 ak2 =
1080 match (ak1, ak2) with
1081 | (TCAbstract ty1, TCAbstract ty2) -> Option.equal equal_decl_ty ty1 ty2
1082 | (TCPartiallyAbstract, TCPartiallyAbstract) -> true
1083 | (TCConcrete, TCConcrete) -> true
1084 | (TCAbstract _, _)
1085 | (TCPartiallyAbstract, _)
1086 | (TCConcrete, _) ->
1087 false
1089 let equal_enum_type et1 et2 =
1090 equal_decl_ty et1.te_base et2.te_base
1091 && Option.equal equal_decl_ty et1.te_constraint et2.te_constraint
1093 let equal_decl_where_constraint c1 c2 =
1094 let (tya1, ck1, tyb1) = c1 in
1095 let (tya2, ck2, tyb2) = c2 in
1096 equal_decl_ty tya1 tya2
1097 && Ast_defs.equal_constraint_kind ck1 ck2
1098 && equal_decl_ty tyb1 tyb2
1100 let equal_decl_tparam tp1 tp2 =
1101 Ast_defs.equal_variance tp1.tp_variance tp2.tp_variance
1102 && Ast_defs.equal_id tp1.tp_name tp2.tp_name
1103 && List.equal
1104 (Tuple.T2.equal ~eq1:Ast_defs.equal_constraint_kind ~eq2:equal_decl_ty)
1105 tp1.tp_constraints
1106 tp2.tp_constraints
1107 && Aast.equal_reify_kind tp1.tp_reified tp2.tp_reified
1108 && List.equal
1109 equal_user_attribute
1110 tp1.tp_user_attributes
1111 tp2.tp_user_attributes
1113 let equal_typedef_type tt1 tt2 =
1114 Pos.equal tt1.td_pos tt2.td_pos
1115 && Aast.equal_typedef_visibility tt1.td_vis tt2.td_vis
1116 && List.equal equal_decl_tparam tt1.td_tparams tt2.td_tparams
1117 && Option.equal equal_decl_ty tt1.td_constraint tt2.td_constraint
1118 && equal_decl_ty tt1.td_type tt2.td_type
1120 let equal_fun_elt fe1 fe2 =
1121 Option.equal String.equal fe1.fe_deprecated fe2.fe_deprecated
1122 && equal_decl_ty fe1.fe_type fe2.fe_type
1123 && Pos.equal fe1.fe_pos fe2.fe_pos
1125 let equal_const_decl cd1 cd2 =
1126 Pos.equal cd1.cd_pos cd2.cd_pos && equal_decl_ty cd1.cd_type cd2.cd_type
1128 let get_ce_abstract ce = is_set ce_flags_abstract ce.ce_flags
1130 let get_ce_final ce = is_set ce_flags_final ce.ce_flags
1132 let get_ce_override ce = is_set ce_flags_override ce.ce_flags
1134 let get_ce_lsb ce = is_set ce_flags_lsb ce.ce_flags
1136 let get_ce_synthesized ce = is_set ce_flags_synthesized ce.ce_flags
1138 let get_ce_const ce = is_set ce_flags_const ce.ce_flags
1140 let get_ce_lateinit ce = is_set ce_flags_lateinit ce.ce_flags
1142 let get_ce_dynamicallycallable ce =
1143 is_set ce_flags_dynamicallycallable ce.ce_flags
1145 let xhp_attr_to_ce_flags xa =
1146 match xa with
1147 | None -> 0x0
1148 | Some { xa_tag; xa_has_default } ->
1149 Int.bit_or
1150 ( if xa_has_default then
1151 ce_flags_xa_has_default
1152 else
1153 0x0 )
1155 (match xa_tag with
1156 | None -> ce_flags_xa_tag_none
1157 | Some Required -> ce_flags_xa_tag_required
1158 | Some Lateinit -> ce_flags_xa_tag_lateinit)
1160 let flags_to_xhp_attr flags =
1161 let tag_flags = Int.bit_and ce_flags_xa_tag_mask flags in
1162 if Int.equal tag_flags 0 then
1163 None
1164 else
1165 Some
1167 xa_has_default = is_set ce_flags_xa_has_default flags;
1168 xa_tag =
1169 ( if Int.equal tag_flags ce_flags_xa_tag_none then
1170 None
1171 else if Int.equal tag_flags ce_flags_xa_tag_required then
1172 Some Required
1173 else
1174 Some Lateinit );
1177 let get_ce_xhp_attr ce = flags_to_xhp_attr ce.ce_flags
1179 let make_ce_flags
1180 ~xhp_attr
1181 ~abstract
1182 ~final
1183 ~override
1184 ~lsb
1185 ~synthesized
1186 ~const
1187 ~lateinit
1188 ~dynamicallycallable =
1189 let flags = 0 in
1190 let flags = set_bit ce_flags_abstract abstract flags in
1191 let flags = set_bit ce_flags_final final flags in
1192 let flags = set_bit ce_flags_override override flags in
1193 let flags = set_bit ce_flags_lsb lsb flags in
1194 let flags = set_bit ce_flags_synthesized synthesized flags in
1195 let flags = set_bit ce_flags_const const flags in
1196 let flags = set_bit ce_flags_lateinit lateinit flags in
1197 let flags = set_bit ce_flags_dynamicallycallable dynamicallycallable flags in
1198 let flags = Int.bit_or flags (xhp_attr_to_ce_flags xhp_attr) in
1199 flags
1201 (** Tunapplied_alias is a locl phase constructor that always stands for a higher-kinded type.
1202 We use this function in cases where Tunapplied_alias appears in a context where we expect
1203 a fully applied type, rather than a type constructor. Seeing Tunapplied_alias in such a context
1204 always indicates a kinding error, which means that during localization, we should have
1205 created Terr rather than Tunapplied_alias. Hence, this is an *internal* error, because
1206 something went wrong during localization. Kind mismatches in code are reported to users
1207 elsewhere. *)
1208 let error_Tunapplied_alias_in_illegal_context () =
1209 failwith "Found Tunapplied_alias in a context where it must not occur"
1211 module Attributes = struct
1212 let mem x xs =
1213 List.exists xs (fun { ua_name; _ } -> String.equal x (snd ua_name))
1215 let find x xs =
1216 List.find xs (fun { ua_name; _ } -> String.equal x (snd ua_name))