Introduce StringishObject, Have HHVM magically generate StringishObject instead of...
[hiphop-php.git] / hphp / hack / src / naming / naming_special_names.ml
blob32bdab890c1674957d3b754fc03c471bb04ffe42
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
12 (** Module consisting of the special names known to the typechecker *)
14 module Classes = struct
15 let cParent = "parent"
17 let cStatic = "static"
19 let cSelf = "self"
21 let cUnknown = "\\*Unknown*"
23 (* Used for dynamic classnames, e.g. new $foo(); *)
25 let cAwaitable = "\\HH\\Awaitable"
27 let cGenerator = "\\Generator"
29 let cAsyncGenerator = "\\HH\\AsyncGenerator"
31 let cHHFormatString = "\\HH\\FormatString"
33 let is_format_string x = String.equal x cHHFormatString
35 let cHH_BuiltinEnum = "\\HH\\BuiltinEnum"
37 let cHH_BuiltinEnumClass = "\\HH\\BuiltinEnumClass"
39 let cThrowable = "\\Throwable"
41 let cStdClass = "\\stdClass"
43 let cDateTime = "\\DateTime"
45 let cDateTimeImmutable = "\\DateTimeImmutable"
47 let cAsyncIterator = "\\HH\\AsyncIterator"
49 let cAsyncKeyedIterator = "\\HH\\AsyncKeyedIterator"
51 let cStringish = "\\Stringish"
53 let cStringishObject = "\\StringishObject"
55 let cXHPChild = "\\XHPChild"
57 let cIMemoizeParam = "\\HH\\IMemoizeParam"
59 let cClassname = "\\HH\\classname"
61 let cTypename = "\\HH\\typename"
63 let cIDisposable = "\\IDisposable"
65 let cIAsyncDisposable = "\\IAsyncDisposable"
67 let cMemberOf = "\\HH\\MemberOf"
69 let cEnumClassLabel = "\\HH\\EnumClass\\Label"
71 (* Classes that can be spliced into ExpressionTrees *)
72 let cSpliceable = "\\Spliceable"
73 end
75 module Collections = struct
76 (* concrete classes *)
77 let cVector = "\\HH\\Vector"
79 let cMutableVector = "\\HH\\MutableVector"
81 let cImmVector = "\\HH\\ImmVector"
83 let cSet = "\\HH\\Set"
85 let cMutableSet = "\\HH\\MutableSet"
87 let cImmSet = "\\HH\\ImmSet"
89 let cMap = "\\HH\\Map"
91 let cMutableMap = "\\HH\\MutableMap"
93 let cImmMap = "\\HH\\ImmMap"
95 let cPair = "\\HH\\Pair"
97 (* interfaces *)
98 let cContainer = "\\HH\\Container"
100 let cKeyedContainer = "\\HH\\KeyedContainer"
102 let cTraversable = "\\HH\\Traversable"
104 let cKeyedTraversable = "\\HH\\KeyedTraversable"
106 let cCollection = "\\Collection"
108 let cConstVector = "\\ConstVector"
110 let cConstMap = "\\ConstMap"
112 let cConstCollection = "\\ConstCollection"
114 let cAnyArray = "\\HH\\AnyArray"
116 let cDict = "\\HH\\dict"
118 let cVec = "\\HH\\vec"
120 let cKeyset = "\\HH\\keyset"
123 module Members = struct
124 let mGetInstanceKey = "getInstanceKey"
126 let mClass = "class"
128 let __construct = "__construct"
130 let __destruct = "__destruct"
132 let __call = "__call"
134 let __callStatic = "__callStatic"
136 let __clone = "__clone"
138 let __debugInfo = "__debugInfo"
140 let __dispose = "__dispose"
142 let __disposeAsync = "__disposeAsync"
144 let __get = "__get"
146 let __invoke = "__invoke"
148 let __isset = "__isset"
150 let __set = "__set"
152 let __set_state = "__set_state"
154 let __sleep = "__sleep"
156 let __toString = "__toString"
158 let __unset = "__unset"
160 let __wakeup = "__wakeup"
162 let as_set =
163 List.fold_right
164 ~f:SSet.add
165 ~init:SSet.empty
167 __construct;
168 __destruct;
169 __call;
170 __callStatic;
171 __clone;
172 __debugInfo;
173 __dispose;
174 __disposeAsync;
175 __get;
176 __invoke;
177 __isset;
178 __set;
179 __set_state;
180 __sleep;
181 __toString;
182 __unset;
183 __wakeup;
186 let as_lowercase_set = SSet.map String.lowercase as_set
188 (* Any data- or aria- attribute is always valid, even if it is not declared
189 * for a given XHP element *)
190 let is_special_xhp_attribute s =
191 String_utils.string_starts_with s ":data-"
192 || String_utils.string_starts_with s ":aria-"
195 module AttributeKinds = struct
196 let cls = "\\HH\\ClassAttribute"
198 let enum = "\\HH\\EnumAttribute"
200 let typealias = "\\HH\\TypeAliasAttribute"
202 let fn = "\\HH\\FunctionAttribute"
204 let mthd = "\\HH\\MethodAttribute"
206 let instProperty = "\\HH\\InstancePropertyAttribute"
208 let staticProperty = "\\HH\\StaticPropertyAttribute"
210 let parameter = "\\HH\\ParameterAttribute"
212 let typeparam = "\\HH\\TypeParameterAttribute"
214 let file = "\\HH\\FileAttribute"
216 let typeconst = "\\HH\\TypeConstantAttribute"
218 let lambda = "\\HH\\LambdaAttribute"
220 let enumcls = "\\HH\\EnumClassAttribute"
222 let plain_english_map =
223 List.fold_left
224 ~init:SMap.empty
225 ~f:(fun acc (k, v) -> SMap.add k v acc)
227 (cls, "a class");
228 (enum, "an enum");
229 (typealias, "a typealias");
230 (fn, "a function");
231 (mthd, "a method");
232 (instProperty, "an instance property");
233 (staticProperty, "a static property");
234 (parameter, "a parameter");
235 (typeparam, "a type parameter");
236 (file, "a file");
237 (typeconst, "a type constant");
238 (lambda, "a lambda expression");
239 (enumcls, "an enum class");
243 module UserAttributes = struct
244 let uaOverride = "__Override"
246 let uaConsistentConstruct = "__ConsistentConstruct"
248 let uaConst = "__Const"
250 let uaDeprecated = "__Deprecated"
252 let uaEntryPoint = "__EntryPoint"
254 let uaMemoize = "__Memoize"
256 let uaMemoizeLSB = "__MemoizeLSB"
258 let uaPolicyShardedMemoize = "__PolicyShardedMemoize"
260 let uaPHPStdLib = "__PHPStdLib"
262 let uaAcceptDisposable = "__AcceptDisposable"
264 let uaReturnDisposable = "__ReturnDisposable"
266 let uaLSB = "__LSB"
268 let uaSealed = "__Sealed"
270 let uaLateInit = "__LateInit"
272 let uaNewable = "__Newable"
274 let uaEnforceable = "__Enforceable"
276 let uaExplicit = "__Explicit"
278 let uaSoft = "__Soft"
280 let uaWarn = "__Warn"
282 let uaMockClass = "__MockClass"
284 let uaProvenanceSkipFrame = "__ProvenanceSkipFrame"
286 let uaDynamicallyCallable = "__DynamicallyCallable"
288 let uaDynamicallyConstructible = "__DynamicallyConstructible"
290 let uaReifiable = "__Reifiable"
292 let uaNeverInline = "__NEVER_INLINE"
294 let uaDisableTypecheckerInternal = "__DisableTypecheckerInternal"
296 let uaHasTopLevelCode = "__HasTopLevelCode"
298 let uaIsFoldable = "__IsFoldable"
300 let uaNative = "__Native"
302 let uaOutOnly = "__OutOnly"
304 let uaAlwaysInline = "__ALWAYS_INLINE"
306 let uaEnableUnstableFeatures = "__EnableUnstableFeatures"
308 let uaEnumClass = "__EnumClass"
310 let uaPolicied = "__Policied"
312 let uaInferFlows = "__InferFlows"
314 let uaExternal = "__External"
316 let uaCanCall = "__CanCall"
318 let uaViaLabel = "__ViaLabel"
320 let uaSupportDynamicType = "__SupportDynamicType"
322 let uaNoRequireDynamic = "__NoRequireDynamic"
324 let uaModule = "__Module"
326 let uaInternal = "__Internal"
328 let as_map =
329 AttributeKinds.(
330 SMap.of_list
332 (uaOverride, [mthd]);
333 (uaConsistentConstruct, [cls]);
334 (uaConst, [cls; instProperty; parameter; staticProperty]);
335 (uaDeprecated, [fn; mthd]);
336 (uaEntryPoint, [fn]);
337 (uaMemoize, [fn; mthd]);
338 (uaMemoizeLSB, [mthd]);
339 (uaPolicyShardedMemoize, [fn; mthd]);
340 (uaPHPStdLib, [cls; fn; mthd]);
341 (uaAcceptDisposable, [parameter]);
342 (uaReturnDisposable, [fn; mthd; lambda]);
343 (uaLSB, [staticProperty]);
344 (uaSealed, [cls; enumcls; enum]);
345 (uaLateInit, [instProperty; staticProperty]);
346 (uaNewable, [typeparam]);
347 (uaEnforceable, [typeconst; typeparam]);
348 (uaExplicit, [typeparam]);
349 (uaSoft, [instProperty; parameter; staticProperty; typeparam]);
350 (uaWarn, [typeparam]);
351 (uaMockClass, [cls]);
352 (uaProvenanceSkipFrame, [fn; mthd; lambda]);
353 (uaDynamicallyCallable, [fn; mthd]);
354 (uaDynamicallyConstructible, [cls]);
355 (uaReifiable, [typeconst]);
356 (uaNeverInline, [fn; mthd]);
357 (uaDisableTypecheckerInternal, [fn; mthd]);
358 (uaEnableUnstableFeatures, [file]);
359 (uaEnumClass, [cls; enumcls]);
360 (uaPolicied, [fn; mthd; instProperty; parameter]);
361 (uaInferFlows, [fn; mthd]);
362 (uaExternal, [parameter]);
363 (uaCanCall, [parameter]);
364 (uaViaLabel, [parameter]);
365 (uaSupportDynamicType, [fn; cls; mthd]);
366 (uaNoRequireDynamic, [typeparam]);
367 (uaModule, [fn; cls; file; typealias; enum; enumcls]);
368 (uaInternal, [fn; mthd; cls; instProperty; staticProperty]);
371 (* These are names which are allowed in the systemlib but not in normal programs *)
372 let systemlib_map =
373 AttributeKinds.(
374 SMap.of_list
376 (uaAlwaysInline, [fn; mthd]);
377 (uaIsFoldable, [fn; mthd]);
378 (uaNative, [fn; mthd]);
379 (uaOutOnly, [parameter]);
382 let is_reserved name = String.is_prefix name ~prefix:"__"
385 (* Tested before \\-prepending name-canonicalization *)
386 module SpecialFunctions = struct
387 let echo = "echo" (* pseudo-function *)
389 let hhas_adata = "__hhas_adata"
391 let is_special_function =
392 let all_special_functions = HashSet.of_list [echo; hhas_adata] in
393 (fun x -> HashSet.mem all_special_functions x)
396 (* There are a number of functions that are automatically imported into the
397 * namespace. The full list can be found in hh_autoimport.ml.
399 module AutoimportedFunctions = struct
400 let invariant_violation = "\\HH\\invariant_violation"
402 let invariant = "\\HH\\invariant"
404 let fun_ = "\\HH\\fun"
406 let inst_meth = "\\HH\\inst_meth"
408 let class_meth = "\\HH\\class_meth"
410 let meth_caller = "\\HH\\meth_caller"
413 module SpecialIdents = struct
414 let this = "$this"
416 let placeholder = "$_"
418 let dollardollar = "$$"
420 (* Intentionally using an invalid variable name to ensure it's translated *)
421 let tmp_var_prefix = "__tmp$"
423 let is_tmp_var name =
424 String.length name > 6 && String.(sub name ~pos:0 ~len:6 = tmp_var_prefix)
426 let assert_tmp_var name = assert (is_tmp_var name)
429 (* PseudoFunctions are functions (or items that are parsed like functions)
430 * that are treated like builtins that do not have a public HHI or interface.
432 module PseudoFunctions = struct
433 let isset = "\\isset"
435 let unset = "\\unset"
437 let hh_show = "\\hh_show"
439 let hh_show_env = "\\hh_show_env"
441 let hh_log_level = "\\hh_log_level"
443 let hh_force_solve = "\\hh_force_solve"
445 let hh_loop_forever = "\\hh_loop_forever"
447 let echo = "\\echo"
449 let empty = "\\empty"
451 let exit = "\\exit"
453 let die = "\\die"
455 let unsafe_cast = "\\unsafe_cast"
457 let all_pseudo_functions =
458 HashSet.of_list
460 isset;
461 unset;
462 hh_show;
463 hh_show_env;
464 hh_log_level;
465 hh_force_solve;
466 hh_loop_forever;
467 echo;
468 empty;
469 exit;
470 die;
471 unsafe_cast;
474 let is_pseudo_function x = HashSet.mem all_pseudo_functions x
477 module StdlibFunctions = struct
478 let is_null = "\\is_null"
480 let get_class = "\\get_class"
482 let array_filter = "\\array_filter"
484 let array_map = "\\array_map"
486 let call_user_func = "\\call_user_func"
488 let type_structure = "\\HH\\type_structure"
490 let array_mark_legacy = "\\HH\\array_mark_legacy"
492 let array_unmark_legacy = "\\HH\\array_unmark_legacy"
494 let is_php_array = "\\HH\\is_php_array"
496 let is_any_array = "\\HH\\is_any_array"
498 let is_dict_or_darray = "\\HH\\is_dict_or_darray"
500 let is_vec_or_varray = "\\HH\\is_vec_or_varray"
502 (* All Id funcions that Typing.dispatch_call handles specially *)
503 let special_dispatch =
504 String.Hash_set.of_list
505 ~growth_allowed:false
507 SpecialFunctions.echo;
508 PseudoFunctions.isset;
509 PseudoFunctions.unset;
510 array_filter;
511 type_structure;
512 array_map;
513 PseudoFunctions.unsafe_cast;
516 let needs_special_dispatch x = Hash_set.mem special_dispatch x
519 module Typehints = struct
520 let null = "null"
522 let void = "void"
524 let resource = "resource"
526 let num = "num"
528 let arraykey = "arraykey"
530 let noreturn = "noreturn"
532 let mixed = "mixed"
534 let nonnull = "nonnull"
536 let this = "this"
538 let dynamic = "dynamic"
540 let nothing = "nothing"
542 let int = "int"
544 let bool = "bool"
546 let float = "float"
548 let string = "string"
550 let darray = "darray"
552 let varray = "varray"
554 let varray_or_darray = "varray_or_darray"
556 let vec_or_dict = "vec_or_dict"
558 let callable = "callable"
560 let wildcard = "_"
562 let is_reserved_type_hint =
563 let reserved_typehints =
564 HashSet.of_list
566 null;
567 void;
568 resource;
569 num;
570 arraykey;
571 noreturn;
572 mixed;
573 nonnull;
574 this;
575 dynamic;
576 nothing;
577 int;
578 bool;
579 float;
580 string;
581 darray;
582 varray;
583 varray_or_darray;
584 vec_or_dict;
585 callable;
586 wildcard;
589 (fun x -> HashSet.mem reserved_typehints x)
591 let is_reserved_global_name x =
592 String.equal x callable
593 || String.equal x Classes.cSelf
594 || String.equal x Classes.cParent
596 let is_reserved_hh_name x =
597 String.equal x void
598 || String.equal x noreturn
599 || String.equal x int
600 || String.equal x bool
601 || String.equal x float
602 || String.equal x num
603 || String.equal x string
604 || String.equal x resource
605 || String.equal x mixed
606 || String.equal x arraykey
607 || String.equal x dynamic
608 || String.equal x wildcard
609 || String.equal x null
610 || String.equal x nonnull
611 || String.equal x nothing
612 || String.equal x this
614 let is_namespace_with_reserved_hh_name x =
615 let unqualify qualified_name =
616 let as_list = Str.split (Str.regexp "\\") qualified_name in
617 let as_list = List.filter as_list ~f:(fun s -> not (phys_equal s "")) in
618 match List.rev as_list with
619 | name :: qualifiers -> (List.rev qualifiers, name)
620 | [] -> ([], qualified_name)
622 let is_HH qualifier =
623 match qualifier with
624 | [qual] -> String.equal qual "HH"
625 | _ -> false
627 let (qualifier, name) = unqualify x in
628 name |> is_reserved_hh_name
629 && (not (List.is_empty qualifier))
630 && not (qualifier |> is_HH)
633 module PseudoConsts = struct
634 let g__LINE__ = "\\__LINE__"
636 let g__CLASS__ = "\\__CLASS__"
638 let g__TRAIT__ = "\\__TRAIT__"
640 let g__FILE__ = "\\__FILE__"
642 let g__DIR__ = "\\__DIR__"
644 let g__FUNCTION__ = "\\__FUNCTION__"
646 let g__METHOD__ = "\\__METHOD__"
648 let g__NAMESPACE__ = "\\__NAMESPACE__"
650 let g__COMPILER_FRONTEND__ = "\\__COMPILER_FRONTEND__"
652 let g__FUNCTION_CREDENTIAL__ = "\\__FUNCTION_CREDENTIAL__"
654 (* exit and die are not pseudo consts, but they are currently parsed as such.
655 * Would be more correct to parse them as special statements like return
657 let exit = "\\exit"
659 let die = "\\die"
661 let all_pseudo_consts =
662 HashSet.of_list
664 g__LINE__;
665 g__CLASS__;
666 g__TRAIT__;
667 g__FILE__;
668 g__DIR__;
669 g__FUNCTION__;
670 g__METHOD__;
671 g__NAMESPACE__;
672 g__COMPILER_FRONTEND__;
673 g__FUNCTION_CREDENTIAL__;
674 exit;
675 die;
678 let is_pseudo_const x = HashSet.mem all_pseudo_consts x
681 module FB = struct
682 let cEnum = "\\Enum"
684 let tInner = "TInner"
686 let idx = "\\HH\\idx"
688 let cTypeStructure = "\\HH\\TypeStructure"
690 let cIncorrectType = "\\HH\\INCORRECT_TYPE"
693 module HH = struct
694 let contains = "\\HH\\Lib\\C\\contains"
696 let contains_key = "\\HH\\Lib\\C\\contains_key"
699 module Rx = struct
700 let is_enabled = "\\HH\\Rx\\IS_ENABLED"
703 module Shapes = struct
704 let cShapes = "\\HH\\Shapes"
706 let idx = "idx"
708 let at = "at"
710 let keyExists = "keyExists"
712 let removeKey = "removeKey"
714 let toArray = "toArray"
716 let toDict = "toDict"
719 module Superglobals = struct
720 let globals = "$GLOBALS"
722 let is_superglobal =
723 let superglobals =
724 HashSet.of_list
726 "$_SERVER";
727 "$_GET";
728 "$_POST";
729 "$_FILES";
730 "$_COOKIE";
731 "$_REQUEST";
732 "$_ENV";
735 (fun x -> HashSet.mem superglobals x)
738 module Regex = struct
739 let tPattern = "\\HH\\Lib\\Regex\\Pattern"
742 (* These are functions treated by the emitter specially. They are not
743 * autoimported (see hh_autoimport.ml) nor are they consider PseudoFunctions
744 * so they can be overridden by namespacing (at least currently)
746 module EmitterSpecialFunctions = struct
747 let eval = "\\eval"
749 let set_frame_metadata = "\\HH\\set_frame_metadata"
751 let systemlib_reified_generics = "\\__systemlib_reified_generics"
754 module XHP = struct
755 let pcdata = "pcdata"
757 let any = "any"
759 let empty = "empty"
761 let is_reserved name =
762 String.equal name pcdata || String.equal name any || String.equal name empty
764 let is_xhp_category name = String_utils.string_starts_with name "%"
767 (* This should be a subset of rust_parser_errors::UnstableFeatures that is relevant
768 * to the typechecker *)
769 module UnstableFeatures = struct
770 let coeffects_provisional = "coeffects_provisional"
772 let ifc = "ifc"
774 let readonly = "readonly"
776 let expression_trees = "expression_trees"
778 let modules = "modules"
781 module Coeffects = struct
782 let capability = "$#capability"
784 let local_capability = "$#local_capability"
786 let contexts = "\\HH\\Contexts"
788 let unsafe_contexts = contexts ^ "\\Unsafe"
791 module Readonly = struct
792 let prefix = "\\HH\\Readonly\\"
794 let as_mut = prefix ^ "as_mut"
797 module Capabilities = struct
798 let defaults = Coeffects.contexts ^ "\\defaults"
800 let prefix = "\\HH\\Capabilities\\"
802 let writeProperty = prefix ^ "WriteProperty"
804 let accessGlobals = prefix ^ "AccessGlobals"
806 let readGlobals = prefix ^ "ReadGlobals"
808 let io = prefix ^ "IO"
810 let rx = prefix ^ "Rx"