Make ExprTree's TInfer type param covariant
[hiphop-php.git] / hphp / hack / test / typecheck / expression_trees / splice_state4.php
blobdb4ebb53ce593cee639aa8b1434c375c85aa4f5c
1 <?hh
3 <<file:__EnableUnstableFeatures('expression_trees')>>
5 class Foo {
6 public ?int $x;
7 public function reset(): int {
8 return 1;
12 function lift<T>(T $_): ExprTree<Code, Code::TAst, T> {
13 throw new Exception();
16 function test(): void {
17 $x = new Foo();
19 if ($x->x !== null) {
20 $_ = Code`() ==> {
21 ${lift($x->reset())};
22 return;
23 }`;
25 // We should think that $x->x could be null
26 $x->x + 1;
30 //// BEGIN DEFS
31 // Placeholder definition so we don't get naming/typing errors.
32 class Code {
33 const type TAst = mixed;
34 // Lifting literals.
35 public static function intLiteral(
36 int $_,
37 ): ExprTree<Code, Code::TAst, ExampleInt> {
38 throw new Exception();
40 public static function floatLiteral(
41 float $_,
42 ): ExprTree<Code, Code::TAst, ExampleFloat> {
43 throw new Exception();
45 public static function boolLiteral(bool $_):
46 ExprTree<Code, Code::TAst, ExampleBool>
48 throw new Exception();
50 public static function stringLiteral(string $_):
51 ExprTree<Code, Code::TAst, ExampleString>
53 throw new Exception();
55 public static function nullLiteral(): ExprTree<Code, Code::TAst, null> {
56 throw new Exception();
59 // Symbols
60 public static function symbol<T>(
61 string $_,
62 (function(ExampleContext): ExprTree<Code, Code::TAst, T>) $_,
63 ): ExprTree<Code, Code::TAst, T> {
64 throw new Exception();
67 // Expressions
68 public function localVar(?ExprPos $_, string $_): Code::TAst {
69 throw new Exception();
71 public function lambdaLiteral(
72 ?ExprPos $_,
73 vec<string> $_args,
74 vec<Code::TAst> $_body,
75 ): Code::TAst {
76 throw new Exception();
79 // Operators
80 public function methCall(
81 ?ExprPos $_,
82 Code::TAst $_,
83 string $_,
84 vec<Code::TAst> $_,
85 ): Code::TAst {
86 throw new Exception();
89 // Old style operators
90 public function call<T>(
91 ?ExprPos $_,
92 Code::TAst $_callee,
93 vec<Code::TAst> $_args,
94 ): Code::TAst {
95 throw new Exception();
98 public function assign(
99 ?ExprPos $_,
100 Code::TAst $_,
101 Code::TAst $_,
102 ): Code::TAst {
103 throw new Exception();
106 public function ternary(
107 ?ExprPos $_,
108 Code::TAst $_condition,
109 ?Code::TAst $_truthy,
110 Code::TAst $_falsy,
111 ): Code::TAst {
112 throw new Exception();
115 // Statements.
116 public function ifStatement(
117 ?ExprPos $_,
118 Code::TAst $_cond,
119 vec<Code::TAst> $_then_body,
120 vec<Code::TAst> $_else_body,
121 ): Code::TAst {
122 throw new Exception();
124 public function whileStatement(
125 ?ExprPos $_,
126 Code::TAst $_cond,
127 vec<Code::TAst> $_body,
128 ): Code::TAst {
129 throw new Exception();
131 public function returnStatement(
132 ?ExprPos $_,
133 ?Code::TAst $_,
134 ): Code::TAst {
135 throw new Exception();
137 public function forStatement(
138 ?ExprPos $_,
139 vec<Code::TAst> $_,
140 Code::TAst $_,
141 vec<Code::TAst> $_,
142 vec<Code::TAst> $_,
143 ): Code::TAst {
144 throw new Exception();
146 public function breakStatement(?ExprPos $_): Code::TAst {
147 throw new Exception();
149 public function continueStatement(?ExprPos $_,): Code::TAst {
150 throw new Exception();
153 // Splice
154 public function splice<T>(
155 ?ExprPos $_,
156 string $_key,
157 ExprTree<Code, Code::TAst, T> $_,
158 ): Code::TAst {
159 throw new Exception();
162 // TODO: Discard unsupported syntax nodes while lowering
163 public function unsupportedSyntax(string $msg): Code::TAst {
164 throw new Exception($msg);
168 final class ExprTree<TVisitor, TResult, +TInfer>{
169 public function __construct(
170 private ?ExprPos $pos,
171 private string $filepath,
172 private dict<string, mixed> $spliced_values,
173 private (function(TVisitor): TResult) $x,
174 private (function(): TInfer) $err,
175 ) {}
178 final class ExprPos {
179 public function __construct(
180 private int $begin_line,
181 private int $begin_col,
182 private int $end_line,
183 private int $end_col,
184 ) {}
187 final class ExampleInt {
188 public function __plus(ExampleInt $_): ExampleInt {
189 throw new Exception();
191 public function __minus(ExampleInt $_): ExampleInt {
192 throw new Exception();
194 public function __star(ExampleInt $_): ExampleInt {
195 throw new Exception();
197 public function __slash(ExampleInt $_): ExampleInt {
198 throw new Exception();
201 public function __lessThan(ExampleInt $_): ExampleBool {
202 throw new Exception();
205 public function __lessThanEqual(ExampleInt $_): ExampleBool {
206 throw new Exception();
209 public function __greaterThan(ExampleInt $_): ExampleBool {
210 throw new Exception();
213 public function __greaterThanEqual(ExampleInt $_): ExampleBool {
214 throw new Exception();
217 public function __tripleEquals(ExampleInt $_): ExampleBool {
218 throw new Exception();
221 public function __notTripleEquals(ExampleInt $_): ExampleBool {
222 throw new Exception();
226 final class ExampleBool {
227 public function __ampamp(ExampleBool $_): ExampleBool {
228 throw new Exception();
231 public function __barbar(ExampleBool $_): ExampleBool {
232 throw new Exception();
235 public function __bool(): bool {
236 throw new Exception();
239 public function __exclamationMark(): ExampleBool {
240 throw new Exception();
244 final class ExampleString {}
246 final class ExampleContext {}
248 final class ExampleFloat {}
250 //// END DEFS