Posted
over 3 years
ago
by
Bo Yang
HHVM 4.151 is released! This release marks the end of support of 4.145; 4.146 -
4.150 remain supported, as do the 4.102 and 4.128 LTS releases.
Highlights
Added IDE hover information for class constants when the type is inferred.
hphpd_break
... [More]
and hphp_debug_break are now marked as pure.
Add an IDE quickfix for non-existent type names.
Adds a new constant (HHVM_COMPILER_TIMESTAMP) and read-only ini setting
(ini_get('hphp.compiler_timestamp')) that contain the timestamp to build
hhvm (which is itself part of the HHVM_COMPILER_ID and hphp.compiler_id
constant and ini setting).
abstract enum class is not considered an experimental feature any more.
Breaking Changes
The key type of a dict or a keyset is now always inferred as a subtype of
arraykey even when used with dynamic. For example, previously the key type
could be inferred as types like int|dynamic and now it would be
int|(dynamic&arraykey) in that case.
[Less]
|
Posted
over 3 years
ago
by
Fred Emmott
HHVM 4.150 is released! This release marks the end of support of 4.144;
4.145 - 4.149 remain supported, as do the 4.102 and 4.128 LTS releases.
Highlights
The ENT_HTML5 constant is now recognized by the typechecker
Added getSslCertCn()
... [More]
, getSslCertSan(), getSslCertExtensions(), and
isSslCertValidationEnforced() to AsyncMysqlResult and
AsyncMysqlConnection
Added $server_cert_values parameter to AsyncMysqlClient::connect(), which
contains comma separated values that are matched against the existing
$cserver_cert_extensions parameter when verifying the certificate.
class_implements(), class_parents(), and class_uses() are now marked
as pure
If a function is marked as returning mixed but returns without a value,
LSP-based IDEs such as VSCode will now suggest void or Awaitable
return types
LSP-based IDEs will now show Vector/Map/Set documentation comments on hover
for literals, not just the types
LSP-based IDE hover information for shape elements will now show information
type information the specific element, not the shape as a whole
HH\Readonly\Shapes now includes typechecker definitions
Breaking Changes
AsyncMysqlClient::adoptConnection() has been removed.
It is now a type error to use meth_caller() on methods that return a
readonly object; previously, this would be a runtime error. This is due to
technical limitations of the current implementation.
If a memoized function is called from a context that does not have the
write_globals capability, a more specific error is raised based on the write
or passing of the return value (if mutable), instead of always when the
function is called. This may change necessary fixme codes from 4461 (“a
memoized function is called”) to 4459 (“A global variable is written”).
Removed `HH\class_get_class_name()
[Less]
|
Posted
over 3 years
ago
by
James Wu
As of HHVM version 4.139, we’ve released a new keyword called readonly in Hack. readonly is a new feature in Hack for restricting the mutability of object properties. It’s designed for use cases that require performant, runtime-enforced mutability
... [More]
control.
readonly has two main principles: readonlyness and deepness.
Readonlyness: Object properties of any readonly value cannot be modified (i.e. mutated).
Deepness: All nested properties of a readonly value are readonly.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Bar {
public function __construct(
public Foo $foo,
){}
}
class Foo {
public function __construct(
public int $prop,
) {}
}
function test(readonly Foo $foo, readonly Bar $bar) : void {
$foo->prop = 5; // error, $foo is readonly
// Deepness: $x is also readonly
$x = $bar->foo;
$x->prop = 3; // error, $x is readonly
}
The readonly keyword can be used in many places in Hack.
Readonly expressions: Any expression can be marked readonly with the readonly keyword.
Readonly parameters: A parameter marked readonly signal that a function or method can take in a readonly value, and does not modify it.
Readonly return types: A function can return readonly, which allows it to return a readonly reference.
Readonly properties: A property can be marked readonly, which allows you to assign a readonly value to it. Note that readonly properties can have their values replaced, as readonly is a modifier on the value of the property, not the property definition itself.
Readonly methods: An instance method can be marked readonly. Instance methods that are readonly treat $this as readonly. Readonly values can only call readonly methods.
Readonly closures: A readonly closure captures external variables as readonly.
You can see some examples of the readonly keyword in this code snippet:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
class Bar {
public int $prop = 0;
}
class Foo {
public function __construct(public Bar $bar, public readonly Bar $ro_bar) {}
// This method promises not to modify $this
public readonly function getBar(): readonly Bar {
// note that $this is readonly, so $this->prop is readonly, which is why
// this method must return readonly
return $this->bar;
}
public static function takesReadonlyExample(readonly Foo $x): void {
$x->bar = new Bar(); // error, $x is readonly here!
}
public static function readonlyClosureExample(): void {
$x = new Bar();
$readonly_f = readonly (): void ==> {
$x->prop = 5; // error, $x is captured as readonly since $readonly_f is a readonly function
};
$x->prop = 4; // $x is still mutable out here, so this is okay!
}
public function readonlyPropExample(Foo $foo): void {
$x = readonly new Bar();
$foo->bar = $x; // error, $x is readonly but bar is a regular property
$foo->ro_bar = $x; // ok!
}
}
Some function calls and property accesses require explicitly annotating the result of the call as readonly:
If you call a function that returns a readonly value, you must annotate the call with the readonly keyword.
If you access a class’s readonly property, you must annotate the access with the readonly keyword.
1
2
3
4
5
6
function testExplicitReadonly(readonly Foo $foo): void {
// vvvvvvvv This keyword is required here since getBar returns readonly
$bar = readonly $foo->getBar();
// vvvvvvvv This keyword is required here since $ro_bar is a readonly property
$ro_bar_prop = readonly $foo->ro_bar;
}
For a full guide and specification to using readonly, you can check our full documentation on the feature.
[Less]
|
Posted
over 3 years
ago
by
Bo Yang
HHVM 4.149 is released! This release marks the end of support of 4.143;
4.144 - 4.148 remain supported, as do the 4.102 and 4.128 LTS releases.
Highlights
__clone is now able to write to its own properties even when the capability set is
... [More]
specified as pure.
Add coeffects to the following builtin APIs:
class_*
dyncall_*_force
ReflectionProperty::{get,set}Value
Reflection{Method,Property}::setAccessible
thrift_protocol_set_compact_version
mb_*
Fix segment fault when the locale specified in $LANG is not found.
[Less]
|
Posted
over 3 years
ago
by
Fred Emmott
HHVM 4.148 is released! This release marks the end of support of 4.140;
4.143 - 4.147 remain supported, as do the 4.102 and 4.128 LTS releases.
Highlights
Fixed error where libelf may not be found
Autocomplete now suggests enum values for
... [More]
function parameters
Added HH\Readonly\Shapes class, partially mirroring the Shapes class
HH\Lib\Str\length() now takes advantage of JIT optimizations that were
previously exclusive to \strlen()
Breaking Changes
function bodies are now required for non-builtin functions.
[Less]
|
Posted
over 3 years
ago
by
Fred Emmott
HHVM 4.148 is released! This release marks the end of support of 4.140;
4.143 - 4.146 remain supported, as do the 4.102 and 4.128 LTS releases.
Highlights
Fixed error where libelf may not be found
Autocomplete now suggests enum values for
... [More]
function parameters
Added HH\Readonly\Shapes class, partially mirroring the Shapes class
HH\Lib\Str\length() now takes advantage of JIT optimizations that were
previously exclusive to \strlen()
Breaking Changes
function bodies are now required for non-builtin functions.
[Less]
|
Posted
over 3 years
ago
by
Bo Yang
HHVM 4.147 is released! This release marks the end of support of 4.139;
4.140, and 4.143 - 4.146 remain supported, as do the 4.102 and 4.128 LTS releases.
4.141 and 4.142 were cancelled due to the holiday season.
Highlights
Add coeffects to
... [More]
thrift_protocol_set_compact_version, DateTime and mbstring functions.
Support hover and go-to-definition on type parameters in an IDE.
Support hover and go-to-definition on the abstract keyword in an IDE.
Breaking Changes
The result of HH\FIXME\UNSAFE_CAST is now considered readonly if the input is readonly.
Always raise an error when inheriting members that differ only by case (previously the error would be raised only if case_sensitive_inheritance option is enabled)
[Less]
|
Posted
over 3 years
ago
by
Fred Emmott
HHVM 4.146 is released! This release marks the end of support of 4.138;
4.139, 4.140, and 4.143 - 4.145 remain supported, as do the 4.102 and 4.128 LTS releases.
4.141 and 4.142 were cancelled due to the holiday season.
Highlights
If options to
... [More]
log or forbid dynamic calls to class (static) methods are enabled, logging/errors will no longer be raised by calls to static methods on reified generics, e.g. T::foo();.
Breaking Changes
Coeffect violations now throw a CoeffectViolationException instead of a
BadMethodCallException; both extend LogicException.
It is now a parse error to declare a lambda/method/fuction parameter called
$this; previously, any attempts to use it would be treated as references to
the current object instance, not the parameter.
ob_get_contents(), ob_get_length(), ob_get_level(), ob_get_status,
ob_list_handlers(), hphp_get_stats(), hphp_get_status(),
hphp_get_io_status(), hphp_get_timers(), hphp_instruction_counter(),
and hphp_get_hardware_counters() are now marked as [read_globals], so can
no longer be called from ‘pure’ functions.
diamond hierarchies of traits (traits with a shared parent trait) are banned if the traits define generic properties as it can be unsound.
[Less]
|
Posted
over 3 years
ago
by
Bo Yang
HHVM 4.145 is released! This release marks the end of support of 4.137;
4.138, 4.139, 4.140, 4.143, 4.144 remain supported, as do the 4.102 and 4.128 LTS releases.
4.141 and 4.142 were cancelled due to the holiday season.
Highlights
Support
... [More]
throw on dynamic, e.g. function foo(dynamic $d): void { throw $d; }
Attributes on class constants do not result errors any more (assessing the attributes via runtime reflection is still not yet supported)
The built-in function gethostname is now a pure function.
Breaking Changes
Raise the typing error 4068 on ?mixed and similar if they’re in a type hint position, including f() or new C().
Reject calls in l-value position, such as (foo($x))[3] = 'a' or (bar($y))[] = 45.
The built-in function curl_multi_exec now requires int as the second parameter.
[Less]
|
Posted
over 3 years
ago
by
Bo Yang
HHAST is a toolkit for for analyzing the structure of Hack files. It includes a linting and migration framework to find and automatically fix problems in your code. The lint errors and migration suggestions can be accessed from Hack API, command line
... [More]
interface or IDEs.
HHAST also ships with many built-in lint rules and migration rules. However, the HHAST built-in lint rules have limited access to the type checker, therefore, it is difficult to create a lint rule that needs to determine questions like “is this type a subtype of that type?” or “is this expression compatible with that function signature?”.
Recently, we released HHAST v4.139.0. The new version brings a proxy to run the linter from the Hack compiler written in OCaml, which includes more powerful lint rules that need the access to the type checker 1. Note that type checker based lint rules cannot be user-defined, as they must be written in OCaml, built in to the HHVM repository.
How to enable type checker based lint rules?
Firstly, follow the User Documentation to set up the linters for IDEs and command line tools.
The lint rules from the Hack compiler are not enabled by default, to enable them, put the following settings into your hhast-lint.json:
1
2
3
"extraLinters": [
"Facebook\\HHAST\\HHClientLinter"
],
HHClientLinter is the special linter as a proxy to run linters from the Hack compiler. Similar to the Hack typing errors, these lint rules report lint errors with 4-digit numeric codes. To avoid conflicts, the 5xxx range is reserved for Hack compiler lint rules.
Run HHClientLinter for particular error codes
HHClientLinter can be configured to not report particular error codes by adding the following settings into your hhast-lint.json
1
2
3
4
5
"linterConfigs": {
"Facebook\\HHAST\\HHClientLinter": {
"ignore": [5624, 5639]
}
}
or if you are interested in only particular error codes:
1
2
3
4
5
"linterConfigs": {
"Facebook\\HHAST\\HHClientLinter": {
"ignore_except": [5624, 5639]
}
}
The definition of error codes can be found at lints_codes.ml.
Suppressing error codes in a file
Each lint error can be suppressed separately with the help of HHAST_IGNORE_ERROR markers.
For example, suppose you are generating a file including some unnecessary null checks, which triggers the error code 5611, putting the HHAST_IGNORE_ERROR[5611] marker at the previous line of each lint error position could prevent HHAST from reporting it.
1
2
3
4
5
6
7
8
9
10
11
class Diagnosis {
public function __construct(shape('file' => string, 'position' => ?int, 'reason' => string) $data) {}
public function hasFile(): bool {
// HHAST_IGNORE_ERROR[5611]
return $this->data['file'] is nonnull;
}
public function getFile(): string {
return $this->data['file'];
}
}
HHAST_IGNORE_ALL is also supported for suppressing an error code in the whole file:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// HHAST_IGNORE_ALL[5611] because this file is generated.
// It is expected to include some correct but unnecessary null checks.
class Diagnosis {
public function __construct(shape('file' => string, 'position' => ?int, 'reason' => string) $data) {}
public function hasFile(): bool {
return $this->data['file'] is nonnull;
}
public function getFile(): string {
return $this->data['file'];
}
public function hasPosition(): bool {
return $this->data['position'] is nonnull;
}
public function getPosition(): ?int {
return $this->data['position'];
}
public function hasReason(): bool {
return $this->data['reason'] is nonnull;
}
public function getReason(): string {
return $this->data['reason'];
}
}
HHAST_IGNORE_ALL is not encouraged because, unlike HHAST_IGNORE_ERROR, HHAST_IGNORE_ALL would silently skip newly introduced errors and you would miss the opportunity to review them.
References
HHAST Github Project
HHAST User Documentation
HHAST 4.139.0 Release Note
Lint Error Code Definition
HHAST v4.139.0 requires HHVM 4.126 or newer version. ↩
[Less]
|