Skip to content

Commit 5d8eb83

Browse files
viratyosinmeta-codesync[bot]
authored andcommitted
Update and extract examples for case type docs
Summary: ``` buck run fbcode//hphp/hack/src/hh_manual:hh_manual extract hphp/hack/manual/hack/ ``` Reviewed By: enetsee Differential Revision: D90035371 fbshipit-source-id: c56194495315e40787aca06fefb311f09237cd7e
1 parent 06fd254 commit 5d8eb83

11 files changed

Lines changed: 142 additions & 75 deletions

File tree

hphp/hack/manual/hack/10-types/80-case-types.md

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ Case types are a special kind of type alias that enable declaration of runtime-d
44

55
## Basic Syntax
66

7-
```hack
7+
```
88
case type Name = Variant1 | Variant2 | ... ;
99
case type Name<T1, T2> as UpperBound = Variant1 | Variant2 | ... ;
1010
```
@@ -18,6 +18,8 @@ case type Name<T1, T2> as UpperBound = Variant1 | Variant2 | ... ;
1818
### Examples
1919

2020
```hack
21+
class MyClass {}
22+
2123
case type SimpleCaseType = int | MyClass;
2224
2325
case type BoundedAndGenericCaseType<+Tk as arraykey> as nonnull =
@@ -102,8 +104,10 @@ case type CT = int | string;
102104
// When CT is expected (super side), we can pass int or string
103105
function accept_ct(CT $x): void {}
104106
105-
accept_ct(42); // OK: int <: (int | string)
106-
accept_ct("hello"); // OK: string <: (int | string)
107+
function f(): void {
108+
accept_ct(42); // OK: int <: (int | string)
109+
accept_ct("hello"); // OK: string <: (int | string)
110+
}
107111
```
108112

109113
### When Case Type is on the Sub Side (Left Side)
@@ -134,6 +138,8 @@ function test(CT_Bounded $bounded, CT_No_Bounds $unbounded): void {
134138
Case types can be decomposed using `is` runtime type checks:
135139

136140
```hack
141+
final class MyClass {}
142+
137143
case type MyCaseType = int | string | MyClass;
138144
139145
function takes_case_type(MyCaseType $x): void {

hphp/hack/src/hh_manual/src/main.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ fn looks_like_toplevel_code(src: &str) -> bool {
100100
// Type aliases
101101
"type",
102102
"newtype",
103+
"case",
103104
// Constants
104105
"const",
105106
// Modules
Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
// @generated by hh_manual from manual/hack/10-types/80-case-types.md
22
// @codegen-command : buck run fbcode//hphp/hack/src/hh_manual:hh_manual extract fbcode/hphp/hack/manual/hack/
3-
async function example_snippet_wrapper(): Awaitable<void> {
4-
case type Name = Variant1 | Variant2 | ... ;
5-
case type Name<T1, T2> as UpperBound = Variant1 | Variant2 | ... ;
6-
}
3+
class MyClass {}
4+
5+
case type SimpleCaseType = int | MyClass;
6+
7+
case type BoundedAndGenericCaseType<+Tk as arraykey> as nonnull =
8+
keyset<Tk> | int;
Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,18 @@
11
// @generated by hh_manual from manual/hack/10-types/80-case-types.md
22
// @codegen-command : buck run fbcode//hphp/hack/src/hh_manual:hh_manual extract fbcode/hphp/hack/manual/hack/
3-
async function example_snippet_wrapper(): Awaitable<void> {
4-
case type SimpleCaseType = int | MyClass;
5-
6-
case type BoundedAndGenericCaseType<+Tk as arraykey> as nonnull =
7-
keyset<Tk> | int;
8-
}
3+
// Different primitives
4+
case type Good1 = int | string | bool;
5+
6+
// Different array kinds
7+
case type Good2 = vec<int> | dict<int, int>;
8+
9+
// vec vs shape
10+
case type Good3 = vec<int> | shape('x' => int);
11+
12+
// Final class vs interface - it is known that C does not implement I2
13+
final class C {}
14+
interface I2<T> {}
15+
case type Good4 = C | I2<int>;
16+
17+
// due to the `as arraykey` bound, we know that `T` is disjoint from `float`
18+
case type GenericCaseType<T as arraykey> = T | float;
Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,20 @@
11
// @generated by hh_manual from manual/hack/10-types/80-case-types.md
22
// @codegen-command : buck run fbcode//hphp/hack/src/hh_manual:hh_manual extract fbcode/hphp/hack/manual/hack/
3-
// Different primitives
4-
case type Good1 = int | string | bool;
3+
// vec and Traversable overlap (vec implements Traversable)
4+
case type Bad1 = vec<int> | Traversable<string>;
55

6-
// Different array kinds
7-
case type Good2 = vec<int> | dict<int, int>;
6+
// Two interfaces can overlap (a class could implement both)
7+
interface I1 {}
8+
interface I2 {}
9+
case type Bad2 = I1 | I2;
810

9-
// vec vs shape
10-
case type Good3 = vec<int> | shape('x' => int);
11+
// vec and tuple have overlapping runtime representation
12+
case type Bad3 = vec<int> | (int, int);
1113

12-
// Final class vs interface - it is known that C does not implement I2
13-
final class C {}
14-
interface I2<T> {}
15-
case type Good4 = C | I2<int>;
14+
// shape fields are not considered
15+
case type Bad4 = shape('x' => int) | shape('y' => string);
1616

17-
// due to the `as arraykey` bound, we know that `T` is disjoint from `float`
18-
case type GenericCaseType<T as arraykey> = T | float;
17+
// E is a subtype of C, so they overlap
18+
class C {}
19+
class E extends C {}
20+
case type Bad5 = C | E;
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
ERROR: File "80-case-types-03.hack", line 4, characters 11-14:
2+
Invalid case type declaration. More than one variant of `Bad1` could contain values with the same runtime tag (Typing[4475])
3+
File "80-case-types-03.hack", line 4, characters 18-25:
4+
This is the type `vec<int>`, which includes **vecs**
5+
File "80-case-types-03.hack", line 4, characters 29-47:
6+
It overlaps with `Traversable<string>`, which also includes **vecs** because `Traversable` is a special interface that includes non-object values
7+
ERROR: File "80-case-types-03.hack", line 9, characters 11-14:
8+
Invalid case type declaration. More than one variant of `Bad2` could contain values with the same runtime tag (Typing[4475])
9+
File "80-case-types-03.hack", line 9, characters 18-19:
10+
This is the type `I1`, which includes **instances of the interface I1**
11+
File "80-case-types-03.hack", line 9, characters 23-24:
12+
It may overlap with `I2`, which includes **instances of the interface I2**
13+
File "80-case-types-03.hack", line 9, characters 11-14:
14+
Because it is possible for values to be both **instances of the interface I1** and **instances of the interface I2**, `I1` and `I2` cannot be in the same case type
15+
ERROR: File "80-case-types-03.hack", line 12, characters 11-14:
16+
Invalid case type declaration. More than one variant of `Bad3` could contain values with the same runtime tag (Typing[4475])
17+
File "80-case-types-03.hack", line 12, characters 18-25:
18+
This is the type `vec<int>`, which includes **vecs**
19+
File "80-case-types-03.hack", line 12, characters 29-38:
20+
It may overlap with `(int, int)`, which includes **tuples** because tuples are vecs at runtime
21+
File "80-case-types-03.hack", line 12, characters 11-14:
22+
Because it is possible for values to be both **vecs** and **tuples**, `vec<int>` and `(int, int)` cannot be in the same case type
23+
ERROR: File "80-case-types-03.hack", line 15, characters 11-14:
24+
Invalid case type declaration. More than one variant of `Bad4` could contain values with the same runtime tag (Typing[4475])
25+
File "80-case-types-03.hack", line 15, characters 18-34:
26+
This is the type `shape('x' => int)`, which includes **shapes** because shapes are dicts at runtime
27+
File "80-case-types-03.hack", line 15, characters 38-57:
28+
It may overlap with `shape('y' => string)`, which includes **shapes** because shapes are dicts at runtime
29+
File "80-case-types-03.hack", line 15, characters 11-14:
30+
Because it is possible for values to be both **shapes** and **shapes**, `shape('x' => int)` and `shape('y' => string)` cannot be in the same case type
31+
ERROR: File "80-case-types-03.hack", line 20, characters 11-14:
32+
Invalid case type declaration. More than one variant of `Bad5` could contain values with the same runtime tag (Typing[4475])
33+
File "80-case-types-03.hack", line 20, characters 18-18:
34+
This is the type `C`, which includes **instances of the class C**
35+
File "80-case-types-03.hack", line 20, characters 22-22:
36+
It overlaps with `E`, which includes **instances of the class E**
37+
File "80-case-types-03.hack", line 20, characters 11-14:
38+
Because **instances of the class C** contains **instances of the class E**, `C` and `E` cannot be in the same case type
Lines changed: 7 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,11 @@
11
// @generated by hh_manual from manual/hack/10-types/80-case-types.md
22
// @codegen-command : buck run fbcode//hphp/hack/src/hh_manual:hh_manual extract fbcode/hphp/hack/manual/hack/
3-
// vec and Traversable overlap (vec implements Traversable)
4-
case type Bad1 = vec<int> | Traversable<string>;
3+
case type CT = int | string;
54

6-
// Two interfaces can overlap (a class could implement both)
7-
interface I1 {}
8-
interface I2 {}
9-
case type Bad2 = I1 | I2;
5+
// When CT is expected (super side), we can pass int or string
6+
function accept_ct(CT $x): void {}
107

11-
// vec and tuple have overlapping runtime representation
12-
case type Bad3 = vec<int> | (int, int);
13-
14-
// shape fields are not considered
15-
case type Bad4 = shape('x' => int) | shape('y' => string);
16-
17-
// E is a subtype of C, so they overlap
18-
class C {}
19-
class E extends C {}
20-
case type Bad5 = C | E;
8+
function f(): void {
9+
accept_ct(42); // OK: int <: (int | string)
10+
accept_ct("hello"); // OK: string <: (int | string)
11+
}
Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,18 @@
11
// @generated by hh_manual from manual/hack/10-types/80-case-types.md
22
// @codegen-command : buck run fbcode//hphp/hack/src/hh_manual:hh_manual extract fbcode/hphp/hack/manual/hack/
3-
case type CT = int | string;
3+
case type CT_Bounded as arraykey = int;
4+
case type CT_No_Bounds = int;
45

5-
// When CT is expected (super side), we can pass int or string
6-
function accept_ct(CT $x): void {}
6+
function expect_int(int $x): void {}
7+
function expect_arraykey(arraykey $x): void {}
8+
function expect_mixed(mixed $x): void {}
79

8-
accept_ct(42); // OK: int <: (int | string)
9-
accept_ct("hello"); // OK: string <: (int | string)
10+
function test(CT_Bounded $bounded, CT_No_Bounds $unbounded): void {
11+
expect_int($bounded); // ERROR: arraykey </: int
12+
expect_arraykey($bounded); // OK: arraykey <: arraykey
13+
expect_mixed($bounded); // OK: arraykey <: mixed
14+
15+
expect_int($unbounded); // ERROR: mixed </: int
16+
expect_arraykey($unbounded);// ERROR: mixed </: arraykey
17+
expect_mixed($unbounded); // OK: mixed <: mixed
18+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
ERROR: File "80-case-types-05.hack", line 11, characters 14-21:
2+
Invalid argument (Typing[4110])
3+
File "80-case-types-05.hack", line 6, characters 21-23:
4+
Expected `int`
5+
File "80-case-types-05.hack", line 10, characters 15-24:
6+
But got `arraykey`
7+
File "80-case-types-05.hack", line 3, characters 25-32:
8+
by the definition of `CT_Bounded`
9+
ERROR: File "80-case-types-05.hack", line 15, characters 14-23:
10+
Invalid argument (Typing[4110])
11+
File "80-case-types-05.hack", line 6, characters 21-23:
12+
Expected `int`
13+
File "80-case-types-05.hack", line 10, characters 36-47:
14+
But got `mixed`
15+
File "80-case-types-05.hack", line 4, characters 11-22:
16+
by the definition of `CT_No_Bounds`
17+
ERROR: File "80-case-types-05.hack", line 16, characters 19-28:
18+
Invalid argument (Typing[4110])
19+
File "80-case-types-05.hack", line 7, characters 26-33:
20+
Expected `arraykey`
21+
File "80-case-types-05.hack", line 10, characters 36-47:
22+
But got `mixed`
23+
File "80-case-types-05.hack", line 4, characters 11-22:
24+
by the definition of `CT_No_Bounds`
Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
11
// @generated by hh_manual from manual/hack/10-types/80-case-types.md
22
// @codegen-command : buck run fbcode//hphp/hack/src/hh_manual:hh_manual extract fbcode/hphp/hack/manual/hack/
3-
case type CT_Bounded as arraykey = int;
4-
case type CT_No_Bounds = int;
3+
final class MyClass {}
54

6-
function expect_int(int $x): void {}
7-
function expect_arraykey(arraykey $x): void {}
8-
function expect_mixed(mixed $x): void {}
5+
case type MyCaseType = int | string | MyClass;
96

10-
function test(CT_Bounded $bounded, CT_No_Bounds $unbounded): void {
11-
expect_int($bounded); // ERROR: arraykey </: int
12-
expect_arraykey($bounded); // OK: arraykey <: arraykey
13-
expect_mixed($bounded); // OK: arraykey <: mixed
14-
15-
expect_int($unbounded); // ERROR: mixed </: int
16-
expect_arraykey($unbounded);// ERROR: mixed </: arraykey
17-
expect_mixed($unbounded); // OK: mixed <: mixed
7+
function takes_case_type(MyCaseType $x): void {
8+
if ($x is int) {
9+
// $x : int
10+
} else {
11+
// $x : string | MyClass
12+
if ($x is string) {
13+
// $x : string
14+
} else {
15+
// $x : MyClass
16+
}
17+
}
1818
}

0 commit comments

Comments
 (0)