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

Commit 264e2b3

Browse files
committed
Support varray/darray/varray_or_darray in type structures/reified
1 parent 9182b9e commit 264e2b3

File tree

3 files changed

+62
-21
lines changed

3 files changed

+62
-21
lines changed

src/TypeSpec/__Private/from_type_structure.hack

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,28 @@ function from_type_structure<T>(TypeStructure<T> $ts): TypeSpec<T> {
8686
default:
8787
invariant_violation('OF_ARRAY with > 2 generics');
8888
}
89+
case TypeStructureKind::OF_VARRAY:
90+
$generics = $ts['generic_types'] as nonnull;
91+
invariant(C\count($generics) === 1, 'got varray with multiple generics');
92+
/* HH_IGNORE_ERROR[4110] */
93+
return TypeSpec\varray(from_type_structure($generics[0]));
94+
case TypeStructureKind::OF_DARRAY:
95+
$generics = $ts['generic_types'] as nonnull;
96+
invariant(
97+
C\count($generics) === 2,
98+
'darrays must have exactly 2 generics',
99+
);
100+
/* HH_IGNORE_ERROR[4110] */
101+
return TypeSpec\darray(from_type_structure($generics[0]), from_type_structure($generics[1]));
102+
case TypeStructureKind::OF_VARRAY_OR_DARRAY:
103+
$generics = $ts['generic_types'] as nonnull;
104+
invariant(
105+
C\count($generics) === 1,
106+
'got varray_or_darray with multiple generics',
107+
);
108+
/* HH_IGNORE_ERROR[4110] */
109+
return TypeSpec\varray_or_darray(from_type_structure($generics[0]));
110+
89111
case TypeStructureKind::OF_DICT:
90112
$generics = TypeAssert\not_null($ts['generic_types']);
91113
invariant(C\count($generics) === 2, 'dicts must have 2 generics');

tests/TypeStructureTest.hack

Lines changed: 37 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,10 @@ final class TypeStructureTest extends \Facebook\HackTest\HackTest {
4646
/* HHAST_IGNORE_ERROR[NoPHPArrayLiterals] */
4747
['123', '456'],
4848
),
49+
'varray<string>' => tuple(
50+
type_structure(TypeConstants::class, 'TStringVArray'),
51+
varray['123', '456'],
52+
),
4953
'empty array<string, string>' => tuple(
5054
type_structure(TypeConstants::class, 'TStringStringArray'),
5155
/* HHAST_IGNORE_ERROR[NoPHPArrayLiterals] */
@@ -56,6 +60,10 @@ final class TypeStructureTest extends \Facebook\HackTest\HackTest {
5660
/* HHAST_IGNORE_ERROR[NoPHPArrayLiterals] */
5761
['foo' => 'bar', 'herp' => 'derp'],
5862
),
63+
'darray<string, string>' => tuple(
64+
type_structure(TypeConstants::class, 'TStringStringDArray'),
65+
darray['foo' => 'bar', 'herp' => 'derp'],
66+
),
5967
'string as ?string' => tuple(
6068
type_structure(TypeConstants::class, 'TNullableString'),
6169
'hello, world',
@@ -70,11 +78,11 @@ final class TypeStructureTest extends \Facebook\HackTest\HackTest {
7078
tuple(type_structure(TypeConstants::class, 'TStringVector'), Vector {}),
7179
'Vector<string>' => tuple(
7280
type_structure(TypeConstants::class, 'TStringVector'),
73-
Vector { 'foo', 'bar' },
81+
Vector {'foo', 'bar'},
7482
),
7583
'Traversable<int>' => tuple(
7684
type_structure(TypeConstants::class, 'TIntTraversable'),
77-
Vector { 123, 456 },
85+
Vector {123, 456},
7886
),
7987
'array as Container<int>' => tuple(
8088
type_structure(TypeConstants::class, 'TIntContainer'),
@@ -83,15 +91,15 @@ final class TypeStructureTest extends \Facebook\HackTest\HackTest {
8391
),
8492
'Container<int>' => tuple(
8593
type_structure(TypeConstants::class, 'TIntContainer'),
86-
Vector { 123, 456 },
94+
Vector {123, 456},
8795
),
8896
'KeyedTraversable<string, int>' => tuple(
8997
type_structure(TypeConstants::class, 'TStringIntKeyedTraversable'),
90-
Map { 'foo' => 123 },
98+
Map {'foo' => 123},
9199
),
92100
'KeyedContainer<string, int>' => tuple(
93101
type_structure(TypeConstants::class, 'TStringIntKeyedContainer'),
94-
Map { 'foo' => 123 },
102+
Map {'foo' => 123},
95103
),
96104
'PHP array as KeyedContainer<string, int>' => tuple(
97105
type_structure(TypeConstants::class, 'TStringIntKeyedContainer'),
@@ -102,19 +110,19 @@ final class TypeStructureTest extends \Facebook\HackTest\HackTest {
102110
tuple(type_structure(TypeConstants::class, 'TStringStringMap'), Map {}),
103111
'Map<string, string>' => tuple(
104112
type_structure(TypeConstants::class, 'TStringStringMap'),
105-
Map { 'foo' => 'bar', 'herp' => 'derp' },
113+
Map {'foo' => 'bar', 'herp' => 'derp'},
106114
),
107115
'Vector<Vector<string>>' => tuple(
108116
type_structure(TypeConstants::class, 'TStringVectorVector'),
109-
Vector { Vector { 'foo' } },
117+
Vector {Vector {'foo'}},
110118
),
111119
'Vector<Vector<string>> with no outer elems' => tuple(
112120
type_structure(TypeConstants::class, 'TStringVectorVector'),
113121
Vector {},
114122
),
115123
'Vector<Vector<string>> with no inner elems' => tuple(
116124
type_structure(TypeConstants::class, 'TStringVectorVector'),
117-
Vector { Vector {} },
125+
Vector {Vector {}},
118126
),
119127
'shape with missing string ?field' => tuple(
120128
type_structure(TypeConstants::class, 'TFlatShape'),
@@ -162,7 +170,7 @@ final class TypeStructureTest extends \Facebook\HackTest\HackTest {
162170
'shape with non-empty container' => tuple(
163171
type_structure(TypeConstants::class, 'TShapeWithContainer'),
164172
/* HHAST_IGNORE_ERROR[NoPHPArrayLiterals] */
165-
array('container' => Vector { 'foo' }),
173+
array('container' => Vector {'foo'}),
166174
),
167175
'enum' =>
168176
tuple(type_structure(TypeConstants::class, 'TEnum'), ExampleEnum::DERP),
@@ -209,6 +217,14 @@ final class TypeStructureTest extends \Facebook\HackTest\HackTest {
209217
/* HHAST_IGNORE_ERROR[NoPHPArrayLiterals] */
210218
['foo' => 'bar'],
211219
),
220+
'varray<int> as varray_or_darray<int>' => tuple(
221+
type_structure(TypeConstants::class, 'TVArrayOrDArray'),
222+
varray[123],
223+
),
224+
'darray<int> as varray_or_darray<int>' => tuple(
225+
type_structure(TypeConstants::class, 'TVArrayOrDArray'),
226+
darray['foo' => 123],
227+
),
212228
'empty array in array<> shape field' => tuple(
213229
type_structure(TypeConstants::class, 'TShapeWithArrayWithoutGenerics'),
214230
shape(
@@ -306,17 +322,17 @@ final class TypeStructureTest extends \Facebook\HackTest\HackTest {
306322
),
307323
'ints in Vector<string>' => tuple(
308324
type_structure(TypeConstants::class, 'TStringVector'),
309-
Vector { 'foo', 123 },
325+
Vector {'foo', 123},
310326
vec['HH\\Vector<T>'],
311327
),
312328
'int keys in Map<string, string>' => tuple(
313329
type_structure(TypeConstants::class, 'TStringStringMap'),
314-
Map { 123 => 'foo' },
330+
Map {123 => 'foo'},
315331
vec['HH\\Map<Tk, _>'],
316332
),
317333
'int values in Map<string, string>' => tuple(
318334
type_structure(TypeConstants::class, 'TStringStringMap'),
319-
Map { 'foo' => 'bar', 'herp' => 123 },
335+
Map {'foo' => 'bar', 'herp' => 123},
320336
vec['HH\\Map<_, Tv>'],
321337
),
322338
'shape with missing field' => tuple(
@@ -363,42 +379,42 @@ final class TypeStructureTest extends \Facebook\HackTest\HackTest {
363379
),
364380
'string in Traversable<int>' => tuple(
365381
type_structure(TypeConstants::class, 'TIntTraversable'),
366-
Vector { 123, '456' },
382+
Vector {123, '456'},
367383
vec['HH\\Traversable<T>'],
368384
),
369385
'string in Container<int>' => tuple(
370386
type_structure(TypeConstants::class, 'TIntContainer'),
371-
Vector { 123, '456' },
387+
Vector {123, '456'},
372388
vec['HH\\Container<T>'],
373389
),
374390
'string value in KeyedTraversable<string, int>' => tuple(
375391
type_structure(TypeConstants::class, 'TStringIntKeyedTraversable'),
376-
Map { 'foo' => 'bar' },
392+
Map {'foo' => 'bar'},
377393
vec['HH\\KeyedTraversable<_, Tv>'],
378394
),
379395
'int key in KeyedTraversable<string, int>' => tuple(
380396
type_structure(TypeConstants::class, 'TStringIntKeyedTraversable'),
381-
Map { 123 => 456 },
397+
Map {123 => 456},
382398
vec['HH\\KeyedTraversable<Tk, _>'],
383399
),
384400
'string value in KeyedContainer<string, int>' => tuple(
385401
type_structure(TypeConstants::class, 'TStringIntKeyedContainer'),
386-
Map { 'foo' => 'bar' },
402+
Map {'foo' => 'bar'},
387403
vec['HH\\KeyedContainer<_, Tv>'],
388404
),
389405
'int key in KeyedContainer<string, int>' => tuple(
390406
type_structure(TypeConstants::class, 'TStringIntKeyedContainer'),
391-
Map { 123 => 456 },
407+
Map {123 => 456},
392408
vec['HH\\KeyedContainer<Tk, _>'],
393409
),
394410
'Vector<Vector<string>> with non-container child' => tuple(
395411
type_structure(TypeConstants::class, 'TStringVectorVector'),
396-
Vector { 'foo' },
412+
Vector {'foo'},
397413
vec['HH\\Vector<T>'],
398414
),
399415
'Vector<Vector<string>> with incorrect container child' => tuple(
400416
type_structure(TypeConstants::class, 'TStringVectorVector'),
401-
Vector { ImmVector { 'foo' } },
417+
Vector {ImmVector {'foo'}},
402418
vec['HH\\Vector<T>'],
403419
),
404420
'nested shape with missing field' => tuple(
@@ -426,7 +442,7 @@ final class TypeStructureTest extends \Facebook\HackTest\HackTest {
426442
'shape with container of wrong kind' => tuple(
427443
type_structure(TypeConstants::class, 'TShapeWithContainer'),
428444
/* HHAST_IGNORE_ERROR[NoPHPArrayLiterals] */
429-
array('container' => Vector { 123 }),
445+
array('container' => Vector {123}),
430446
vec['shape[container]', 'HH\\Vector<T>'],
431447
),
432448
'enum' => tuple(

tests/fixtures/TypeConstants.hack

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@ class TypeConstants {
1919
const type TArrayKey = arraykey;
2020
const type TTuple = (string, int);
2121
const type TStringArray = array<string>;
22+
const type TStringVArray = varray<string>;
2223
const type TStringStringArray = array<string, string>;
24+
const type TStringStringDArray = darray<string, string>;
2325

2426
const type TNullableString = ?string;
2527

@@ -71,4 +73,5 @@ class TypeConstants {
7173
/* HH_IGNORE_ERROR[4045] array without generics */
7274
'two' => array,
7375
);
76+
const type TVArrayOrDArray = varray_or_darray<int>;
7477
}

0 commit comments

Comments
 (0)