Ban globals in default args if ctx lacks AccessGlobals [1/2]
commitcc31f0b8c1d0d194740640f1d52a3c53754f9835
authorLeo Osvald <leoo@fb.com>
Tue, 14 Sep 2021 19:38:26 +0000 (14 12:38 -0700)
committerFacebook GitHub Bot <facebook-github-bot@users.noreply.github.com>
Tue, 14 Sep 2021 19:39:50 +0000 (14 12:39 -0700)
treee73e0ab61f033a109d3c213fab14472e93c9859f
parent570b0b227148e2a3b4062c9a9f190b4606a3d496
Ban globals in default args if ctx lacks AccessGlobals [1/2]

Summary:
Fixes the unsoundness by not introducing the AccessGlobals out of thin air
when a `function`'s context would not otherwise give this capability, e.g.:

  function f(int $x = AnotherClass::$staticInt)[]

should _not_ be allowed (at the very least when called from a pure context),
but the typechecker previously allowed it.  Therefore, check if `AccessGlobals`
is present before type-checking the parameter list and the matching arguments,
and _only then_ reintroduce the capability the `AcceessGlobals`. E.g.,

  function g(int $x = Another::$staticInt)[defaults]

is sound to allow because `AccessGlobals` is contained in `defaults`.

 ---

However, this is still too conservative, since the above startegy rejects:

  function h(int $x = readonly Another::$staticInt)[read_globals]

The extra precision comes at the cost of doing additional subtyping check:

  ReadGlobals <: FUN_CTX

and if so, introducing `ReadGlobals` instead of `AccessGlobals` when
type-checking argument binding for a function call.  As an optimization,
we could check that the default argument is marked `readonly` and then
only do the latter subtyping check but not the former.
This optimized approach will be considered as a separate change.

Reviewed By: vassilmladenov

Differential Revision: D30547750

fbshipit-source-id: 8b3952e8d8db612684bb3f11bc5cf479301ef0d4
12 files changed:
hphp/hack/src/typing/typing.ml
hphp/hack/src/typing/typing.mli
hphp/hack/src/typing/typing_make_type.ml
hphp/hack/src/typing/typing_toplevel.ml
hphp/hack/test/deps/circular_type_method_deps.php.exp
hphp/hack/test/deps/static_method_function_deps.php.exp
hphp/hack/test/enum_class/typing/access_in_default_arg_pure.bad.php.exp
hphp/hack/test/enum_class/typing/access_in_default_arg_write_props.bad.php.exp
hphp/hack/test/typecheck/coeffects/default-arg/static_prop.php
hphp/hack/test/typecheck/coeffects/default-arg/static_prop.php.exp
hphp/hack/test/typecheck/coeffects/parameter_default.php.exp
hphp/hack/test/unit/server_tests.ml