Make ExprTree's TInfer type param covariant
[hiphop-php.git] / hphp / hack / test / typecheck / expression_trees / loop.php
blob952bbb8c9888c9f84213785310d498cb86dbd4d4
1 <?hh
3 <<file:__EnableUnstableFeatures('expression_trees')>>
5 function bar(
6 ExampleContext $_,
7 ): ExprTree<Code, Code::TAst, (function(): void)> {
8 throw new Exception();
10 function baz(
11 ExampleContext $_,
12 ): ExprTree<Code, Code::TAst, (function(ExampleInt): void)> {
13 throw new Exception();
16 function foo(): void {
17 $loop = Code`() ==> { while(true) { bar(); } }`;
18 $for = Code`() ==> { for($x = 0; true; $x = $x + 1) { baz($x); } }`;
21 //// BEGIN DEFS
22 // Placeholder definition so we don't get naming/typing errors.
23 class Code {
24 const type TAst = mixed;
25 // Lifting literals.
26 public static function intLiteral(
27 int $_,
28 ): ExprTree<Code, Code::TAst, ExampleInt> {
29 throw new Exception();
31 public static function floatLiteral(
32 float $_,
33 ): ExprTree<Code, Code::TAst, ExampleFloat> {
34 throw new Exception();
36 public static function boolLiteral(bool $_):
37 ExprTree<Code, Code::TAst, ExampleBool>
39 throw new Exception();
41 public static function stringLiteral(string $_):
42 ExprTree<Code, Code::TAst, ExampleString>
44 throw new Exception();
46 public static function nullLiteral(): ExprTree<Code, Code::TAst, null> {
47 throw new Exception();
50 // Symbols
51 public static function symbol<T>(
52 string $_,
53 (function(ExampleContext): ExprTree<Code, Code::TAst, T>) $_,
54 ): ExprTree<Code, Code::TAst, T> {
55 throw new Exception();
58 // Expressions
59 public function localVar(?ExprPos $_, string $_): Code::TAst {
60 throw new Exception();
62 public function lambdaLiteral(
63 ?ExprPos $_,
64 vec<string> $_args,
65 vec<Code::TAst> $_body,
66 ): Code::TAst {
67 throw new Exception();
70 // Operators
71 public function methCall(
72 ?ExprPos $_,
73 Code::TAst $_,
74 string $_,
75 vec<Code::TAst> $_,
76 ): Code::TAst {
77 throw new Exception();
80 // Old style operators
81 public function call<T>(
82 ?ExprPos $_,
83 Code::TAst $_callee,
84 vec<Code::TAst> $_args,
85 ): Code::TAst {
86 throw new Exception();
89 public function assign(
90 ?ExprPos $_,
91 Code::TAst $_,
92 Code::TAst $_,
93 ): Code::TAst {
94 throw new Exception();
97 public function ternary(
98 ?ExprPos $_,
99 Code::TAst $_condition,
100 ?Code::TAst $_truthy,
101 Code::TAst $_falsy,
102 ): Code::TAst {
103 throw new Exception();
106 // Statements.
107 public function ifStatement(
108 ?ExprPos $_,
109 Code::TAst $_cond,
110 vec<Code::TAst> $_then_body,
111 vec<Code::TAst> $_else_body,
112 ): Code::TAst {
113 throw new Exception();
115 public function whileStatement(
116 ?ExprPos $_,
117 Code::TAst $_cond,
118 vec<Code::TAst> $_body,
119 ): Code::TAst {
120 throw new Exception();
122 public function returnStatement(
123 ?ExprPos $_,
124 ?Code::TAst $_,
125 ): Code::TAst {
126 throw new Exception();
128 public function forStatement(
129 ?ExprPos $_,
130 vec<Code::TAst> $_,
131 Code::TAst $_,
132 vec<Code::TAst> $_,
133 vec<Code::TAst> $_,
134 ): Code::TAst {
135 throw new Exception();
137 public function breakStatement(?ExprPos $_): Code::TAst {
138 throw new Exception();
140 public function continueStatement(?ExprPos $_,): Code::TAst {
141 throw new Exception();
144 // Splice
145 public function splice<T>(
146 ?ExprPos $_,
147 string $_key,
148 ExprTree<Code, Code::TAst, T> $_,
149 ): Code::TAst {
150 throw new Exception();
153 // TODO: Discard unsupported syntax nodes while lowering
154 public function unsupportedSyntax(string $msg): Code::TAst {
155 throw new Exception($msg);
159 final class ExprTree<TVisitor, TResult, +TInfer>{
160 public function __construct(
161 private ?ExprPos $pos,
162 private string $filepath,
163 private dict<string, mixed> $spliced_values,
164 private (function(TVisitor): TResult) $x,
165 private (function(): TInfer) $err,
166 ) {}
169 final class ExprPos {
170 public function __construct(
171 private int $begin_line,
172 private int $begin_col,
173 private int $end_line,
174 private int $end_col,
175 ) {}
178 final class ExampleInt {
179 public function __plus(ExampleInt $_): ExampleInt {
180 throw new Exception();
182 public function __minus(ExampleInt $_): ExampleInt {
183 throw new Exception();
185 public function __star(ExampleInt $_): ExampleInt {
186 throw new Exception();
188 public function __slash(ExampleInt $_): ExampleInt {
189 throw new Exception();
192 public function __lessThan(ExampleInt $_): ExampleBool {
193 throw new Exception();
196 public function __lessThanEqual(ExampleInt $_): ExampleBool {
197 throw new Exception();
200 public function __greaterThan(ExampleInt $_): ExampleBool {
201 throw new Exception();
204 public function __greaterThanEqual(ExampleInt $_): ExampleBool {
205 throw new Exception();
208 public function __tripleEquals(ExampleInt $_): ExampleBool {
209 throw new Exception();
212 public function __notTripleEquals(ExampleInt $_): ExampleBool {
213 throw new Exception();
217 final class ExampleBool {
218 public function __ampamp(ExampleBool $_): ExampleBool {
219 throw new Exception();
222 public function __barbar(ExampleBool $_): ExampleBool {
223 throw new Exception();
226 public function __bool(): bool {
227 throw new Exception();
230 public function __exclamationMark(): ExampleBool {
231 throw new Exception();
235 final class ExampleString {}
237 final class ExampleContext {}
239 final class ExampleFloat {}
241 //// END DEFS