1 // RUN: %hackc compile-infer %s | FileCheck %s
3 // TEST-CHECK-BAL: type C$static
4 // CHECK: type C$static = .kind="class" .static {
5 // CHECK: prop3: .public *HackFloat;
6 // CHECK: prop4: .public .SomeAttribute *HackMixed
9 // TEST-CHECK-BAL: "type C "
10 // CHECK: type C = .kind="class" {
11 // CHECK: prop1: .public *HackInt;
12 // CHECK: prop2: .public *HackString;
13 // CHECK: type_: .public *HackInt
16 // TEST-CHECK-BAL: define C$static.$init_static
17 // CHECK: define C$static.$init_static() : void {
19 // CHECK: n0 = $builtins.alloc_words(0)
20 // CHECK: store &C$static::static_singleton <- n0: *C$static
21 // CHECK: store &C$static::MY_CONSTANT <- $builtins.hack_int(7): *HackMixed
25 <<__ConsistentConstruct>>
27 public int $prop1 = 42;
28 public string $prop2 = "hello";
29 public static float $prop3 = 3.14;
31 public static mixed $prop4 = null;
33 const int MY_CONSTANT = 7;
35 // Test reserved token.
38 // TEST-CHECK-BAL: define C$static.__factory
39 // CHECK: define C$static.__factory($this: *C$static, $a: *HackInt, $b: *HackString, $c: *HackInt) : *C {
41 // CHECK: n0: *HackInt = load &$a
42 // CHECK: n1: *HackString = load &$b
43 // CHECK: n2: *HackInt = load &$c
44 // CHECK: n3 = __sil_allocate(<C>)
45 // CHECK: n4 = C.__construct(n3, n0, n1, n2)
49 // TEST-CHECK-BAL: define C.__construct
50 // CHECK: define C.__construct($this: *C, $a: *HackInt, $b: *HackString, $c: *HackInt) : *HackMixed {
55 public function __construct(int $a, string $b, int $c) {
58 // TEST-CHECK-BAL: define C.cons_static
59 // CHECK: define C.cons_static($this: *C) : *void {
60 // CHECK: local $a: *void, $0: *void, $1: *void, $2: *void
64 // CHECK: n0: *C = load &$this
65 // CHECK: n1 = $builtins.hack_get_static_class(n0)
66 // CHECK: store &$0 <- n1: *HackMixed
67 // CHECK: n2: *C = load &$this
68 // CHECK: n3 = $builtins.hack_get_static_class(n2)
69 // CHECK: n4 = n3.HackMixed.__factory()
70 // CHECK: store &$2 <- n4: *HackMixed
71 // CHECK: n5: *HackMixed = load &$0
72 // CHECK: n6 = $builtins.hhbc_class_has_reified_generics(n5)
74 // CHECK: .handlers b17
76 // CHECK: prune ! $builtins.hack_is_true(n6)
79 // CHECK: prune $builtins.hack_is_true(n6)
80 // CHECK: n7: *HackMixed = load &$0
81 // CHECK: n8 = $builtins.hhbc_get_cls_rg_prop(n7)
82 // CHECK: store &$1 <- n8: *HackMixed
83 // CHECK: n9 = $builtins.hhbc_is_type_null(n8)
85 // CHECK: .handlers b17
87 // CHECK: prune $builtins.hack_is_true(n9)
90 // CHECK: prune ! $builtins.hack_is_true(n9)
91 // CHECK: n10: *HackMixed = load &$1
92 // CHECK: n11 = $root.count(null, n10)
93 // CHECK: n12 = $builtins.hhbc_cmp_eq(n11, $builtins.hack_int(0))
95 // CHECK: .handlers b17
97 // CHECK: prune $builtins.hack_is_true(n12)
100 // CHECK: n13: *HackMixed = load &$0
101 // CHECK: n14 = $builtins.hhbc_class_has_reified_generics(n13)
103 // CHECK: .handlers b17
105 // CHECK: prune ! $builtins.hack_is_true(n14)
108 // CHECK: prune $builtins.hack_is_true(n14)
109 // CHECK: n15: *HackMixed = load &$0
110 // CHECK: n16 = $builtins.hhbc_class_get_c(n15)
112 // CHECK: .handlers b17
114 // CHECK: prune ! $builtins.hack_is_true(n12)
115 // CHECK: n17: *HackMixed = load &$0
116 // CHECK: n18 = $builtins.hhbc_class_has_reified_generics(n17)
117 // CHECK: jmp b11, b15
118 // CHECK: .handlers b17
120 // CHECK: prune ! $builtins.hack_is_true(n18)
123 // CHECK: n19: *HackMixed = load &$0
124 // CHECK: n20 = $builtins.hhbc_has_reified_parent(n19)
125 // CHECK: jmp b13, b14
126 // CHECK: .handlers b17
128 // CHECK: prune ! $builtins.hack_is_true(n20)
131 // CHECK: prune $builtins.hack_is_true(n20)
132 // CHECK: n21: *HackMixed = load &$2
133 // CHECK: n22 = $builtins.hhbc_cast_vec($builtins.hhbc_new_col_vector())
134 // CHECK: n23 = n21.HackMixed._86reifiedinit(n22)
136 // CHECK: .handlers b17
138 // CHECK: prune $builtins.hack_is_true(n18)
139 // CHECK: n24: *HackMixed = load &$2
140 // CHECK: n25: *HackMixed = load &$1
141 // CHECK: n26 = n24.HackMixed._86reifiedinit(n25)
143 // CHECK: .handlers b17
145 // CHECK: n27: *HackMixed = load &$2
147 // CHECK: .handlers b17
148 // CHECK: #b17(n28: *HackMixed):
149 // CHECK: store &$0 <- null: *HackMixed
150 // CHECK: store &$1 <- null: *HackMixed
151 // CHECK: store &$2 <- null: *HackMixed
152 // CHECK: n29 = $builtins.hhbc_throw(n28)
153 // CHECK: unreachable
155 // CHECK: store &$0 <- null: *HackMixed
156 // CHECK: store &$1 <- null: *HackMixed
157 // CHECK: store &$2 <- null: *HackMixed
158 // CHECK: n30 = n27.HackMixed.__construct($builtins.hack_int(1), $builtins.hack_string("x"), $builtins.hack_int(3))
159 // CHECK: n31 = $builtins.hhbc_lock_obj(n27)
160 // CHECK: store &$a <- n27: *HackMixed
163 public function cons_static(): void {
164 $a = new static(1, "x", 3);
167 // TEST-CHECK-BAL: define C.cons_self
168 // CHECK: define C.cons_self($this: *C) : *void {
169 // CHECK: local $a: *void, $0: *void, $1: *void, $2: *void
173 // CHECK: n0: *C$static = load &C$static::static_singleton
174 // CHECK: n1 = $builtins.lazy_initialize(n0)
175 // CHECK: store &$0 <- n0: *HackMixed
176 // CHECK: n2: *C$static = load &C$static::static_singleton
177 // CHECK: n3 = $builtins.lazy_initialize(n2)
178 // CHECK: n4 = n2.HackMixed.__factory()
179 // CHECK: store &$2 <- n4: *HackMixed
180 // CHECK: n5: *HackMixed = load &$0
181 // CHECK: n6 = $builtins.hhbc_class_has_reified_generics(n5)
183 // CHECK: .handlers b7
185 // CHECK: prune ! $builtins.hack_is_true(n6)
186 // CHECK: n7: *HackMixed = load &$0
187 // CHECK: n8 = $builtins.hhbc_has_reified_parent(n7)
189 // CHECK: .handlers b7
191 // CHECK: prune ! $builtins.hack_is_true(n8)
194 // CHECK: prune $builtins.hack_is_true(n8)
195 // CHECK: n9: *HackMixed = load &$2
196 // CHECK: n10 = $builtins.hhbc_cast_vec($builtins.hhbc_new_col_vector())
197 // CHECK: n11 = n9.HackMixed._86reifiedinit(n10)
199 // CHECK: .handlers b7
201 // CHECK: prune $builtins.hack_is_true(n6)
202 // CHECK: n12: *HackMixed = load &$0
203 // CHECK: n13 = $builtins.hhbc_class_get_c(n12)
205 // CHECK: .handlers b7
207 // CHECK: n14: *HackMixed = load &$2
209 // CHECK: .handlers b7
210 // CHECK: #b7(n15: *HackMixed):
211 // CHECK: store &$0 <- null: *HackMixed
212 // CHECK: store &$1 <- null: *HackMixed
213 // CHECK: store &$2 <- null: *HackMixed
214 // CHECK: n16 = $builtins.hhbc_throw(n15)
215 // CHECK: unreachable
217 // CHECK: store &$0 <- null: *HackMixed
218 // CHECK: store &$1 <- null: *HackMixed
219 // CHECK: store &$2 <- null: *HackMixed
220 // CHECK: n17 = n14.HackMixed.__construct($builtins.hack_int(1), $builtins.hack_string("x"), $builtins.hack_int(3))
221 // CHECK: n18 = $builtins.hhbc_lock_obj(n14)
222 // CHECK: store &$a <- n14: *HackMixed
225 public function cons_self(): void {
226 $a = new self(1, "x", 3);
229 // TEST-CHECK-BAL: define C.cons_inst
230 // CHECK: define C.cons_inst($this: *C) : *void {
231 // CHECK: local $a: *void, $0: *void, $1: *void, $2: *void
235 // CHECK: n0: *C$static = load &C$static::static_singleton
236 // CHECK: n1 = $builtins.lazy_initialize(n0)
237 // CHECK: store &$0 <- n0: *HackMixed
238 // CHECK: n2: *C$static = load &C$static::static_singleton
239 // CHECK: n3 = $builtins.lazy_initialize(n2)
240 // CHECK: n4 = n2.HackMixed.__factory()
241 // CHECK: store &$2 <- n4: *HackMixed
242 // CHECK: n5: *HackMixed = load &$0
243 // CHECK: n6 = $builtins.hhbc_class_has_reified_generics(n5)
245 // CHECK: .handlers b7
247 // CHECK: prune ! $builtins.hack_is_true(n6)
248 // CHECK: n7: *HackMixed = load &$0
249 // CHECK: n8 = $builtins.hhbc_has_reified_parent(n7)
251 // CHECK: .handlers b7
253 // CHECK: prune ! $builtins.hack_is_true(n8)
256 // CHECK: prune $builtins.hack_is_true(n8)
257 // CHECK: n9: *HackMixed = load &$2
258 // CHECK: n10 = $builtins.hhbc_cast_vec($builtins.hhbc_new_col_vector())
259 // CHECK: n11 = n9.HackMixed._86reifiedinit(n10)
261 // CHECK: .handlers b7
263 // CHECK: prune $builtins.hack_is_true(n6)
264 // CHECK: n12: *HackMixed = load &$0
265 // CHECK: n13 = $builtins.hhbc_class_get_c(n12)
267 // CHECK: .handlers b7
269 // CHECK: n14: *HackMixed = load &$2
271 // CHECK: .handlers b7
272 // CHECK: #b7(n15: *HackMixed):
273 // CHECK: store &$0 <- null: *HackMixed
274 // CHECK: store &$1 <- null: *HackMixed
275 // CHECK: store &$2 <- null: *HackMixed
276 // CHECK: n16 = $builtins.hhbc_throw(n15)
277 // CHECK: unreachable
279 // CHECK: store &$0 <- null: *HackMixed
280 // CHECK: store &$1 <- null: *HackMixed
281 // CHECK: store &$2 <- null: *HackMixed
282 // CHECK: n17 = n14.HackMixed.__construct($builtins.hack_int(1), $builtins.hack_string("x"), $builtins.hack_int(3))
283 // CHECK: n18 = $builtins.hhbc_lock_obj(n14)
284 // CHECK: store &$a <- n14: *HackMixed
287 public function cons_inst(): void {
288 $a = new C(1, "x", 3);
291 // TEST-CHECK-BAL: define C$static.static_signature
292 // CHECK: define C$static.static_signature($this: *C$static, $a: *HackMixed, $b: *HackMixed) : *void {
294 // CHECK: n0: *HackMixed = load &$b
295 // CHECK: n1: *HackMixed = load &$a
296 // CHECK: n2 = $builtins.hhbc_cmp_eq(n1, n0)
299 // CHECK: prune ! $builtins.hack_is_true(n2)
300 // CHECK: n3 = $builtins.hhbc_print($builtins.hack_string("unequal"))
303 // CHECK: prune $builtins.hack_is_true(n2)
304 // CHECK: n4 = $builtins.hhbc_print($builtins.hack_string("equal"))
310 // TEST-CHECK-BAL: define C.static_signature
311 // CHECK: define C.static_signature($this: *C, $a: *HackMixed, $b: *HackMixed) : *void {
313 // CHECK: // forward to the static method
314 // CHECK: n0: *C = load &$this
315 // CHECK: n1 = $builtins.hack_get_static_class(n0)
316 // CHECK: n2: *HackMixed = load &$a
317 // CHECK: n3: *HackMixed = load &$b
318 // CHECK: n4 = C$static.static_signature(n1, n2, n3)
321 public static function static_signature(mixed $a, mixed $b): void {
329 // TEST-CHECK-BAL: define C.test_const
330 // CHECK: define C.test_const($this: *C) : *void {
331 // CHECK: local $x: *void
333 // CHECK: n0: *HackMixed = load &C$static::MY_CONSTANT
334 // CHECK: store &$x <- n0: *HackMixed
337 public function test_const(): void {
343 // TEST-CHECK-BAL: define T0.trait_parent_caller
344 // CHECK: define T0.trait_parent_caller($this: *T0) : *void {
346 // CHECK: n0: *T0 = load &$this
347 // CHECK: n1 = __parent__.test_const(n0)
350 public function trait_parent_caller(): void {
351 /* HH_FIXME[4074] This isn't valid Hack but actually occurs in www */
352 parent::test_const();
359 // TEST-CHECK-BAL: define T1.trait_parent_caller
360 // CHECK: define T1.trait_parent_caller($this: *T1) : *void {
362 // CHECK: n0: *T1 = load &$this
363 // CHECK: n1 = __parent__.test_const(n0)
366 public function trait_parent_caller(): void {
367 parent::test_const();
371 // TEST-CHECK-BAL: define $root.dynamic_const
372 // CHECK: define $root.dynamic_const($this: *void, $c: *C) : *void {
374 // CHECK: n0: *HackMixed = load &$c
375 // CHECK: n1 = $builtins.hhbc_class_get_c(n0)
376 // CHECK: n2 = $builtins.hhbc_cls_cns(n1, $builtins.hack_string("MY_CONSTANT"))
377 // CHECK: n3 = $builtins.hhbc_print(n2)
380 function dynamic_const(C $c): void {
381 echo $c::MY_CONSTANT;
384 // TEST-CHECK-BAL: global C$static::MY_CONSTANT
385 // CHECK: global C$static::MY_CONSTANT : *HackMixed
387 // TEST-CHECK-BAL: global C$static::static_singleton
388 // CHECK: global C$static::static_singleton : *C$static