HHVM 4.45
HHVM 4.45 is released! This release marks the end of support for 4.38 and 4.39 (some versions were supported for longer than usual because 4.37 was skipped); HHVM 4.40–4.44 remain supported, as do the 4.8 and 4.32 LTS releases.
Highlights
- Fixed the type refinement done by
is_array($value)
to be less restrictive. The type-checker now understands the refined type to be the intersection of$value
’s original type andvarray_or_darray
, instead of always rewriting the type tovarray_or_darray
.- For example, after passing a
darray
value tois_array
, the type-checker no longer rewrites$value
’s type tovarray_or_darray
but keeps treating it as adarray
.
- For example, after passing a
- New built-in functions
HH\autoload_type_to_path()
,HH\autoload_function_to_path()
andHH\autoload_constant_to_path()
can be used to look up entries in the autoload map (e.g. for debugging). hh_client --type-at-pos
now returns additional information about how the type was determined.- Various small clarifications in type-checker error messages (e.g. “missing property” instead of “missing member”).
Breaking Changes
- Empty
switch
statements are no longer allowed. They now produce a type-checker error as well as a fatal error at runtime, and in the future will be treated as a parsing error. - The type-checker now raises an error for any lambda functions whose types
cannot be inferred. This can reveal
previously hidden type errors.
- In previous HHVM versions, the
new_inference_lambda=true
option in.hhconfig
enables this behavior.
- In previous HHVM versions, the
array_key_exists()
now throws anInvalidArgumentException
if the provided key isnull
.- In HHVM 4.44, the
hhvm.hack_arr_compat_check_null_hack_array_key=true
andhhvm.hack_arr_compat_notices=true
INI options can be used to raise a notice.
- In HHVM 4.44, the
- The
ArrayAccess
interface no longer provides its “magic” behavior. The interface still exists but its methods now need to be called directly (e.g.$stack->push(42)
instead of$stack[] = 42;
). - When attempting to override a
final
method, the type-checker now raises an error in the child class instead of the parent class. This doesn’t introduce any new errors but may require someHH_FIXME
s to be moved.- The same change was made for class properties declared with
<<__Const>>
or<<__LateInit>>
.
- The same change was made for class properties declared with
- Using a type constant via
this
as a reified generic type parameter in a type annotation (e.g.ClassWithReifiedGeneric<this::T> $arg
) is now a type-checker error.- It is still allowed in function calls (
foo<this::T>()
) including constructor calls (new ClassWithReifiedGeneric<this::T>()
).
- It is still allowed in function calls (
- We no longer build packages for Ubuntu 18.10 (its official support ended in July 2019).
Future Changes
array()
literals will be removed; usevec
/dict
/keyset
instead if possible, otherwisevarray
ordarray
.- Automated migration is available in
HHAST 4.33.6:
hhast-migrate --php-arrays
- Automated migration is available in
HHAST 4.33.6:
- The runtime will be changed to throw an exception for any
switch
statements where none of the cases matched the provided value.- A
default
branch should be added to anyswitch
statements that intentionally don’t cover all possible cases. - Use the
hhvm.throw_on_non_exhaustive_switch=2
INI option to enable this behavior now (or set the value to1
to raise a warning instead of throwing an exception).
- A
- Upper bounds on generic type parameters will be enforced at runtime. For
example, passing
true
to a function declared asfunction takes_arraykey<T as arraykey>(T $arg)
will be a runtime error in the future.- Any such violations already raise type-checker errors, but this could reveal new errors in code without full type coverage.
- It is enforced regardless of where the generic parameter appears (function parameter and return types, class properties, etc).
- Use the INI options
hhvm.emit_generics_ub=true
withhhvm.enforce_generics_ub=2
to enable this behavior now (or set the latter value to1
to raise a warning instead of a fatal error).
- The behavior of
is_array()
will likely be changed to also returntrue
for Hack arrays (vec
,dict
andkeyset
).- Currently it only returns
true
for legacy arrays (array
,varray
anddarray
). This change should make it easier to migrate from legacy arrays to Hack arrays. - New built-in function
HH\is_php_array()
was added in this release, which only returnstrue
for legacy arrays (the current behavior ofis_array()
). You can replace any calls tois_array()
with this function to guarantee no behavior changes in the future. - You can use
HH\is_any_array()
to preemptively migrate anyis_array()
calls to the future behavior.
- Currently it only returns
- Comparing Hack arrays (
vec
,dict
andkeyset
) with boolean values using the “fuzzy” comparison operators==
and!=
will be changed to consider empty arrays equal tofalse
and non-empty arrays totrue
.- This is consistent with how fuzzy comparisons work for other types,
including legacy arrays (
array
,varray
,darray
). It should make it easier to migrate from legacy arrays to Hack arrays. - Strict equality operators
===
and!==
are not affected, they will always evaluate tofalse
when comparing values of different types. It is highly recommended to use these strict operators for comparisons and useC\is_empty()
for checking the emptiness of arrays instead. - Use the
hhvm.hack_arr_compat_hack_arr_cmp_notices=1
INI option to raise a notice whenever Hack arrays are compared with boolean values, and therefore the result may be affected by this future change.
- This is consistent with how fuzzy comparisons work for other types,
including legacy arrays (