From 016483cade9eaf61bb607ee99726614c6d539e1d Mon Sep 17 00:00:00 2001 From: Eugene Letuchy Date: Thu, 6 Nov 2014 11:04:54 -0800 Subject: [PATCH] typechecker: support stdClass Summary: stdClass is a special builtin in that it's basically designed for dynamic properties. So, special case 'stdClass' in to bypass the declaration check for non-static members. Reviewed By: @int3 Differential Revision: D1664175 Signature: t1:1664175:1415309554:52fc0b92cf403d8a158d8eec62fe0c5a011752f1 --- hphp/hack/hhi/classes.hhi | 9 ++++++++- hphp/hack/src/hh_single_type_check.ml | 3 ++- hphp/hack/src/naming/naming_special_names.ml | 1 + hphp/hack/src/typing/typing.ml | 6 +++++- hphp/hack/test/typecheck/array_map.php.exp | 2 +- hphp/hack/test/typecheck/instanceof_static_with_reqs.php.exp | 4 ++-- hphp/hack/test/typecheck/stdclass_final.php | 3 +++ hphp/hack/test/typecheck/stdclass_final.php.exp | 2 ++ hphp/hack/test/typecheck/stdclass_members.php | 6 ++++++ hphp/hack/test/typecheck/stdclass_members.php.exp | 1 + hphp/hack/test/typecheck/stdclass_static_members.php | 5 +++++ hphp/hack/test/typecheck/stdclass_static_members.php.exp | 4 ++++ 12 files changed, 40 insertions(+), 6 deletions(-) create mode 100644 hphp/hack/test/typecheck/stdclass_final.php create mode 100644 hphp/hack/test/typecheck/stdclass_final.php.exp create mode 100644 hphp/hack/test/typecheck/stdclass_members.php create mode 100644 hphp/hack/test/typecheck/stdclass_members.php.exp create mode 100644 hphp/hack/test/typecheck/stdclass_static_members.php create mode 100644 hphp/hack/test/typecheck/stdclass_static_members.php.exp diff --git a/hphp/hack/hhi/classes.hhi b/hphp/hack/hhi/classes.hhi index 29fba9ce3b2..90308d31fd0 100644 --- a/hphp/hack/hhi/classes.hhi +++ b/hphp/hack/hhi/classes.hhi @@ -1,4 +1,4 @@ - extends WaitableWaitHandle { public static function setOnSuccessCallback(?(function(ExternalThreadEventWaitHandle, mixed): void) $callback) {} public static function setOnFailCallback(?(function(ExternalThreadEventWaitHandle, Exception): void) $callback) {} } + +/* + * stdClass is not really final. However, because stdClass has no + * properties of its own and is the result of casting an array to an + * object, it is exempt from 'property must exist' checks. + */ +final class stdClass {} diff --git a/hphp/hack/src/hh_single_type_check.ml b/hphp/hack/src/hh_single_type_check.ml index a629df9195a..740ec09a7e0 100644 --- a/hphp/hack/src/hh_single_type_check.ml +++ b/hphp/hack/src/hh_single_type_check.ml @@ -89,7 +89,8 @@ let builtins = "(?Indexish $c, $i, $d = null) {}\n" + "function idx(?Indexish $c, $i, $d = null) {}\n"^ + "final class stdClass {}\n" (*****************************************************************************) (* Helpers *) diff --git a/hphp/hack/src/naming/naming_special_names.ml b/hphp/hack/src/naming/naming_special_names.ml index e120b54d222..fe5f190ff85 100644 --- a/hphp/hack/src/naming/naming_special_names.ml +++ b/hphp/hack/src/naming/naming_special_names.ml @@ -26,6 +26,7 @@ module Classes = struct let cHH_BuiltinEnum = "\\HH\\BuiltinEnum" let cException = "\\Exception" + let cStdClass = "\\stdClass" let cAsyncIterator = "\\AsyncIterator" let cAsyncKeyedIterator = "\\AsyncKeyedIterator" diff --git a/hphp/hack/src/typing/typing.ml b/hphp/hack/src/typing/typing.ml index 8b6a9120849..bbaaa4d4c64 100644 --- a/hphp/hack/src/typing/typing.ml +++ b/hphp/hack/src/typing/typing.ml @@ -2350,7 +2350,11 @@ and obj_get_ ~is_method:is_method ~nullsafe:nullsafe env ty1 (p, s as id) | Tapply (x, paraml) -> let env, class_ = Env.get_class env (snd x) in (match class_ with - | None -> env, (Reason.Rnone, Tany), None + | None -> + env, (Reason.Rnone, Tany), None + | Some class_ when not is_method + && class_.tc_name = SN.Classes.cStdClass -> + env, (Reason.Rnone, Tany), None | Some class_ -> let paraml = if List.length paraml = 0 diff --git a/hphp/hack/test/typecheck/array_map.php.exp b/hphp/hack/test/typecheck/array_map.php.exp index e83460e39dd..4189cf10a58 100644 --- a/hphp/hack/test/typecheck/array_map.php.exp +++ b/hphp/hack/test/typecheck/array_map.php.exp @@ -1,2 +1,2 @@ -array<[153]Tbool> +array<[155]Tbool> No errors diff --git a/hphp/hack/test/typecheck/instanceof_static_with_reqs.php.exp b/hphp/hack/test/typecheck/instanceof_static_with_reqs.php.exp index 829dfb3a53d..a8b2059c00f 100644 --- a/hphp/hack/test/typecheck/instanceof_static_with_reqs.php.exp +++ b/hphp/hack/test/typecheck/instanceof_static_with_reqs.php.exp @@ -1,7 +1,7 @@ object this> -App \INeedsFoo<[187]intersect(), > -[216]intersect(App \INeedsFoo<[196]intersect(X), >, this>) +App \INeedsFoo<[190]intersect(), > +[219]intersect(App \INeedsFoo<[199]intersect(X), >, this>) File "instanceof_static_with_reqs.php", line 31, characters 12-17: Invalid return type (Typing[4110]) File "instanceof_static_with_reqs.php", line 7, characters 49-52: diff --git a/hphp/hack/test/typecheck/stdclass_final.php b/hphp/hack/test/typecheck/stdclass_final.php new file mode 100644 index 00000000000..48403b608e4 --- /dev/null +++ b/hphp/hack/test/typecheck/stdclass_final.php @@ -0,0 +1,3 @@ +prop = 10; +} diff --git a/hphp/hack/test/typecheck/stdclass_members.php.exp b/hphp/hack/test/typecheck/stdclass_members.php.exp new file mode 100644 index 00000000000..4269126fceb --- /dev/null +++ b/hphp/hack/test/typecheck/stdclass_members.php.exp @@ -0,0 +1 @@ +No errors diff --git a/hphp/hack/test/typecheck/stdclass_static_members.php b/hphp/hack/test/typecheck/stdclass_static_members.php new file mode 100644 index 00000000000..0faf277900d --- /dev/null +++ b/hphp/hack/test/typecheck/stdclass_static_members.php @@ -0,0 +1,5 @@ +