Skip to content
This repository was archived by the owner on Sep 1, 2023. It is now read-only.

Commit 0eb8276

Browse files
fredemmottlexidor
andauthored
Compatibility with 4.62 and current nightlies (#54)
* Add allowed fixmes for hhvm 4.62 Running Fred's jq script Co-authored-by: Fred Emmott <fe@fb.com> * Bump hhvm version to hhvm 4.56 to avoid conflicts * Remove support for PHP arrays, make VarrayOrDarraySpec use varray more often - at runtime, PHP arrays, varrays, and darrays are now distinct types; this makes keeping PHP arrays impractical, and it seems unnecessary now that `unserialize()` will return `darray`s instead - previously, VarrayOrDarraySpec would fall back to `darray` if unclear what type should be used. The result is no longer usable as a varray if unclear, so make it look at the input type to guess what the output should be. * add another fixme to whitelist needed for 4.62 * Require HHVM 4.60 Needed for testing, so that the newer hacktest can be used * Use ConstVector instead of Vector + ImmVector Also matches Pair, so add test * fixme constmap/constvector references Co-authored-by: Lexidor Digital <31805625+lexidor@users.noreply.github.com>
1 parent cb61020 commit 0eb8276

12 files changed

+53
-126
lines changed

.hhconfig

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,5 @@ disallow_invalid_arraykey = true
88
disallow_stringish_magic = true
99
user_attributes=
1010
error_php_lambdas = true
11+
allowed_decl_fixme_codes=2053,4045
12+
allowed_fixme_codes_strict=2011,2049,2050,2053,4027,4045,4106,4107,4108,4110,4128,4135,4188,4240,4323

.travis.yml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,7 @@ sudo: required
22
language: generic
33
services: docker
44
env:
5-
- HHVM_VERSION=4.30-latest
6-
- HHVM_VERSION=4.32-latest
5+
- HHVM_VERSION=4.60-latest
76
- HHVM_VERSION=latest
87
- HHVM_VERSION=nightly
98
install:

composer.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22
"name": "hhvm/type-assert",
33
"description": "Convert untyped data to typed data",
44
"license": "MIT",
5-
"keywords": ["hack", "TypeAssert" ],
5+
"keywords": ["hack", "TypeAssert"],
66
"require": {
7-
"hhvm": "^4.30",
7+
"hhvm": "^4.60",
88
"hhvm/hsl": "^4.0"
99
},
1010
"extra": {

src/TypeSpec.hack

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -151,11 +151,6 @@ function string(): TypeSpec<string> {
151151
return new __Private\StringSpec();
152152
}
153153

154-
/* HH_IGNORE_ERROR[4045] untyped array */
155-
function untyped_array(): TypeSpec<array> {
156-
return new __Private\UntypedArraySpec();
157-
}
158-
159154
function varray<Tv>(TypeSpec<Tv> $tsv): TypeSpec<varray<Tv>> {
160155
return new __Private\VarraySpec($tsv);
161156
}

src/TypeSpec/__Private/DarraySpec.hack

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ final class DarraySpec<Tk as arraykey, Tv>
4646

4747
<<__Override>>
4848
public function assertType(mixed $value): darray<Tk, Tv> {
49-
if (!\is_array($value)) {
49+
if (/* HH_FIXME[2049] */ /* HH_FIXME[4107] */ !is_darray($value)) {
5050
throw IncorrectTypeException::withValue(
5151
$this->getTrace(),
5252
$this->toString(),
@@ -58,7 +58,7 @@ final class DarraySpec<Tk as arraykey, Tv>
5858
$vt = $this->getTrace()->withFrame('darray<_, Tv>');
5959

6060
return Dict\pull_with_key(
61-
$value,
61+
$value as KeyedTraversable<_, _>,
6262
($_k, $v) ==> $this->tsv->withTrace($vt)->assertType($v),
6363
($k, $_v) ==> $this->tsk->withTrace($kt)->assertType($k),
6464
)

src/TypeSpec/__Private/UnionSpec.hack

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ abstract class UnionSpec<+T> extends TypeSpec<T> {
2020
}
2121

2222
<<__Override>>
23-
final public function coerceType(mixed $value): T {
23+
public function coerceType(mixed $value): T {
2424
try {
2525
return $this->assertType($value);
2626
} catch (IncorrectTypeException $_) {

src/TypeSpec/__Private/VArrayOrDArraySpec.hack

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,19 +10,51 @@
1010

1111
namespace Facebook\TypeSpec\__Private;
1212

13+
use namespace HH\Lib\{C, Vec};
1314
use namespace Facebook\TypeSpec;
1415

1516
final class VArrayOrDArraySpec<T> extends UnionSpec<varray_or_darray<T>> {
17+
private TypeSpec\TypeSpec<darray<arraykey, T>> $darraySpec;
18+
private TypeSpec\TypeSpec<varray<T>> $varraySpec;
19+
1620
public function __construct(private TypeSpec\TypeSpec<T> $inner) {
21+
$this->darraySpec = TypeSpec\darray(TypeSpec\arraykey(), $inner);
22+
$this->varraySpec = TypeSpec\varray($inner);
1723
parent::__construct(
1824
'varray_or_darray',
19-
TypeSpec\darray(TypeSpec\arraykey(), $inner),
20-
TypeSpec\varray($inner),
25+
$this->darraySpec,
26+
$this->varraySpec,
2127
);
2228
}
2329

2430
<<__Override>>
2531
public function toString(): string {
2632
return 'varray_or_darray<'.$this->inner->toString().'>';
2733
}
34+
35+
<<__Override>>
36+
public function coerceType(mixed $value): varray_or_darray<T> {
37+
try {
38+
return $this->assertType($value);
39+
} catch (\Throwable $_) {
40+
}
41+
42+
if ($value is vec<_> || $value is /* HH_FIXME[2049] */ ConstVector<_>) {
43+
return $this->varraySpec->coerceType($value);
44+
}
45+
46+
if ($value is dict<_, _> || $value is /* HH_FIXME[2049] */ ConstMap<_, _>) {
47+
return $this->darraySpec->coerceType($value);
48+
}
49+
50+
$new = $this->darraySpec->coerceType($value);
51+
if ($new === darray[]) {
52+
return $new;
53+
}
54+
55+
if (Vec\keys($new) === Vec\range(0, C\count($new) - 1)) {
56+
return varray($new);
57+
}
58+
return $new;
59+
}
2860
}

src/TypeSpec/__Private/VarraySpec.hack

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,12 @@ final class VarraySpec<T> extends TypeSpec<varray<T>> {
3131
}
3232

3333
return Vec\map($value, $inner ==> $this->inner->coerceType($inner))
34-
|> \array_values($$);
34+
|> varray($$);
3535
}
3636

3737
<<__Override>>
3838
public function assertType(mixed $value): varray<T> {
39-
if (!\is_array($value)) {
39+
if (/* HH_FIXME[2049] */ /* HH_FIXME[4107] */ !is_varray($value)) {
4040
throw IncorrectTypeException::withValue(
4141
$this->getTrace(),
4242
'varray<T>',
@@ -53,7 +53,7 @@ final class VarraySpec<T> extends TypeSpec<varray<T>> {
5353
)();
5454

5555
return Vec\map_with_key(
56-
$value,
56+
$value as KeyedTraversable<_, _>,
5757
($k, $inner) ==> {
5858
$counter->next();
5959
$i = $counter->current();

src/TypeSpec/__Private/from_type_structure.hack

Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -68,23 +68,7 @@ function from_type_structure<T>(TypeStructure<T> $ts): TypeSpec<T> {
6868
case TypeStructureKind::OF_FUNCTION:
6969
throw new UnsupportedTypeException('OF_FUNCTION');
7070
case TypeStructureKind::OF_ARRAY:
71-
$generics = $ts['generic_types'] ?? vec[];
72-
switch (C\count($generics)) {
73-
case 0:
74-
/* HH_IGNORE_ERROR[4110] */
75-
return new UntypedArraySpec();
76-
case 1:
77-
/* HH_IGNORE_ERROR[4110] */
78-
return new VarraySpec(from_type_structure($generics[0]));
79-
case 2:
80-
/* HH_IGNORE_ERROR[4110] */
81-
return new DarraySpec(
82-
from_type_structure($generics[0]),
83-
from_type_structure($generics[1]),
84-
);
85-
default:
86-
invariant_violation('OF_ARRAY with > 2 generics');
87-
}
71+
throw new UnsupportedTypeException('OF_ARRAY');
8872
case TypeStructureKind::OF_VARRAY:
8973
$generics = $ts['generic_types'] as nonnull;
9074
invariant(C\count($generics) === 1, 'got varray with multiple generics');

tests/TypeStructureTest.hack

Lines changed: 4 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -36,30 +36,10 @@ final class TypeStructureTest extends \Facebook\HackTest\HackTest {
3636
type_structure(TypeConstants::class, 'TTuple'),
3737
tuple('foo', 123),
3838
),
39-
'empty array<string>' => tuple(
40-
type_structure(TypeConstants::class, 'TStringArray'),
41-
/* HHAST_IGNORE_ERROR[NoPHPArrayLiterals] */
42-
array(),
43-
),
44-
'array<string>' => tuple(
45-
type_structure(TypeConstants::class, 'TStringArray'),
46-
/* HHAST_IGNORE_ERROR[NoPHPArrayLiterals] */
47-
array('123', '456'),
48-
),
4939
'varray<string>' => tuple(
5040
type_structure(TypeConstants::class, 'TStringVArray'),
5141
varray['123', '456'],
5242
),
53-
'empty array<string, string>' => tuple(
54-
type_structure(TypeConstants::class, 'TStringStringArray'),
55-
/* HHAST_IGNORE_ERROR[NoPHPArrayLiterals] */
56-
array(),
57-
),
58-
'array<string, string>' => tuple(
59-
type_structure(TypeConstants::class, 'TStringStringArray'),
60-
/* HHAST_IGNORE_ERROR[NoPHPArrayLiterals] */
61-
array('foo' => 'bar', 'herp' => 'derp'),
62-
),
6343
'darray<string, string>' => tuple(
6444
type_structure(TypeConstants::class, 'TStringStringDArray'),
6545
darray['foo' => 'bar', 'herp' => 'derp'],
@@ -164,13 +144,11 @@ final class TypeStructureTest extends \Facebook\HackTest\HackTest {
164144
),
165145
'shape with empty container' => tuple(
166146
type_structure(TypeConstants::class, 'TShapeWithContainer'),
167-
/* HHAST_IGNORE_ERROR[NoPHPArrayLiterals] */
168-
array('container' => Vector {}),
147+
darray['container' => Vector {}],
169148
),
170149
'shape with non-empty container' => tuple(
171150
type_structure(TypeConstants::class, 'TShapeWithContainer'),
172-
/* HHAST_IGNORE_ERROR[NoPHPArrayLiterals] */
173-
array('container' => Vector {'foo'}),
151+
darray['container' => Vector {'foo'}],
174152
),
175153
'enum' =>
176154
tuple(type_structure(TypeConstants::class, 'TEnum'), ExampleEnum::DERP),
@@ -202,21 +180,6 @@ final class TypeStructureTest extends \Facebook\HackTest\HackTest {
202180
type_structure(TypeConstants::class, 'TStringKeyset'),
203181
keyset['foo', 'bar', 'baz', 'herp', 'derp'],
204182
),
205-
'empty array as array<>' => tuple(
206-
type_structure(TypeConstants::class, 'TArrayWithoutGenerics'),
207-
/* HHAST_IGNORE_ERROR[NoPHPArrayLiterals] */
208-
array(),
209-
),
210-
'vec-like array as array<>' => tuple(
211-
type_structure(TypeConstants::class, 'TArrayWithoutGenerics'),
212-
/* HHAST_IGNORE_ERROR[NoPHPArrayLiterals] */
213-
array('foo', 'bar'),
214-
),
215-
'dict-like array as array<>' => tuple(
216-
type_structure(TypeConstants::class, 'TArrayWithoutGenerics'),
217-
/* HHAST_IGNORE_ERROR[NoPHPArrayLiterals] */
218-
array('foo' => 'bar'),
219-
),
220183
'varray<int> as varray_or_darray<int>' => tuple(
221184
type_structure(TypeConstants::class, 'TVArrayOrDArray'),
222185
varray[123],
@@ -225,29 +188,6 @@ final class TypeStructureTest extends \Facebook\HackTest\HackTest {
225188
type_structure(TypeConstants::class, 'TVArrayOrDArray'),
226189
darray['foo' => 123],
227190
),
228-
'empty array in array<> shape field' => tuple(
229-
type_structure(TypeConstants::class, 'TShapeWithArrayWithoutGenerics'),
230-
shape(
231-
'one' => true,
232-
'two' => /* HHAST_IGNORE_ERROR[NoPHPArrayLiterals] */ array(),
233-
),
234-
),
235-
'vec-like array in array<> shape field' => tuple(
236-
type_structure(TypeConstants::class, 'TShapeWithArrayWithoutGenerics'),
237-
shape(
238-
'one' => true,
239-
'two' =>
240-
/* HHAST_IGNORE_ERROR[NoPHPArrayLiterals] */ array('foo', 'bar'),
241-
),
242-
),
243-
'dict-like array in array<> shape field' => tuple(
244-
type_structure(TypeConstants::class, 'TShapeWithArrayWithoutGenerics'),
245-
shape(
246-
'one' => true,
247-
'two' =>
248-
/* HHAST_IGNORE_ERROR[NoPHPArrayLiterals] */ array('foo' => 'bar'),
249-
),
250-
),
251191
];
252192
}
253193

@@ -293,24 +233,6 @@ final class TypeStructureTest extends \Facebook\HackTest\HackTest {
293233
tuple('foo', 123, 456),
294234
vec[],
295235
),
296-
'int in array<string>' => tuple(
297-
type_structure(TypeConstants::class, 'TStringArray'),
298-
/* HHAST_IGNORE_ERROR[NoPHPArrayLiterals] */
299-
array(123),
300-
vec['varray[0]'],
301-
),
302-
'int keys in array<string, string>' => tuple(
303-
type_structure(TypeConstants::class, 'TStringStringArray'),
304-
/* HHAST_IGNORE_ERROR[NoPHPArrayLiterals] */
305-
array(123 => 'bar', 123 => 'derp'),
306-
vec['darray<Tk, _>'],
307-
),
308-
'int values in array<string, string>' => tuple(
309-
type_structure(TypeConstants::class, 'TStringStringArray'),
310-
/* HHAST_IGNORE_ERROR[NoPHPArrayLiterals] */
311-
array('foo' => 123, 'bar' => 456),
312-
vec['darray<_, Tv>'],
313-
),
314236
'0 as ?string' => tuple(
315237
type_structure(TypeConstants::class, 'TNullableString'),
316238
0,
@@ -508,11 +430,10 @@ final class TypeStructureTest extends \Facebook\HackTest\HackTest {
508430
);
509431
}
510432

433+
const type TUnsupported = array<string>;
511434
public function testUnsupportedType(): void {
512-
$ts = type_structure(TypeConstants::class, 'TStringArray');
513-
$ts['kind'] = TypeStructureKind::OF_GENERIC;
435+
$ts = type_structure(self::class, 'TUnsupported');
514436

515-
/* HH_IGNORE_ERROR[4110] */
516437
expect(() ==> TypeAssert\matches_type_structure($ts, null))->toThrow(
517438
UnsupportedTypeException::class,
518439
);

tests/VArrayOrDArraySpecTest.hack

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,14 @@ final class VArrayOrDArraySpecTest
2525
public function getValidCoercions(): vec<(mixed, varray_or_darray<int>)> {
2626
return vec[
2727
tuple(vec[], varray[]),
28+
tuple(dict[], darray[]),
29+
tuple(keyset[], darray[]),
2830
tuple(vec['123'], varray[123]),
2931
tuple(varray['123'], varray[123]),
3032
tuple(varray[123], varray[123]),
3133
tuple(dict['foo' => '456'], darray['foo' => 456]),
3234
tuple(Vector {123}, varray[123]),
35+
tuple(Pair {123, 456}, varray[123, 456]),
3336
tuple(darray['foo' => 123], darray['foo' => 123]),
3437
tuple(keyset['123'], darray['123' => 123]),
3538
];

tests/fixtures/TypeConstants.hack

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,7 @@ class TypeConstants {
1818
const type TNum = num;
1919
const type TArrayKey = arraykey;
2020
const type TTuple = (string, int);
21-
const type TStringArray = array<string>;
2221
const type TStringVArray = varray<string>;
23-
const type TStringStringArray = array<string, string>;
2422
const type TStringStringDArray = darray<string, string>;
2523

2624
const type TNullableString = ?string;
@@ -66,12 +64,5 @@ class TypeConstants {
6664
const type TStringStringVecDict = dict<string, vec<string>>;
6765
const type TStringKeyset = keyset<string>;
6866

69-
/* HH_IGNORE_ERROR[4045] array without generics */
70-
const type TArrayWithoutGenerics = array;
71-
const type TShapeWithArrayWithoutGenerics = shape(
72-
'one' => bool,
73-
/* HH_IGNORE_ERROR[4045] array without generics */
74-
'two' => array,
75-
);
7667
const type TVArrayOrDArray = varray_or_darray<int>;
7768
}

0 commit comments

Comments
 (0)