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
darrayvalue tois_array, the type-checker no longer rewrites$value’s type tovarray_or_darraybut 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-posnow 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
switchstatements 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=trueoption in.hhconfigenables this behavior.
- In previous HHVM versions, the
array_key_exists()now throws anInvalidArgumentExceptionif the provided key isnull.- In HHVM 4.44, the
hhvm.hack_arr_compat_check_null_hack_array_key=trueandhhvm.hack_arr_compat_notices=trueINI options can be used to raise a notice.
- In HHVM 4.44, the
- The
ArrayAccessinterface 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
finalmethod, 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_FIXMEs 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
thisas 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/keysetinstead if possible, otherwisevarrayordarray.- 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
switchstatements where none of the cases matched the provided value.- A
defaultbranch should be added to anyswitchstatements that intentionally don’t cover all possible cases. - Use the
hhvm.throw_on_non_exhaustive_switch=2INI option to enable this behavior now (or set the value to1to raise a warning instead of throwing an exception).
- A
- Upper bounds on generic type parameters will be enforced at runtime. For
example, passing
trueto 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=truewithhhvm.enforce_generics_ub=2to enable this behavior now (or set the latter value to1to raise a warning instead of a fatal error).
- The behavior of
is_array()will likely be changed to also returntruefor Hack arrays (vec,dictandkeyset).- Currently it only returns
truefor legacy arrays (array,varrayanddarray). 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 returnstruefor 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,dictandkeyset) with boolean values using the “fuzzy” comparison operators==and!=will be changed to consider empty arrays equal tofalseand 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 tofalsewhen 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=1INI 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 (