1--TEST-- 2Computation of intersection types for typed reference to typed property assignments 3--FILE-- 4<?php 5 6class A {} 7class B extends A {} 8 9class Test { 10 public int $int; 11 public float $float; 12 public ?int $nint; 13 public ?string $nstring; 14 public array $array; 15 public object $object; 16 public iterable $iterable; 17 public Iterator $Iterator; 18 public A $A; 19 public B $B; 20} 21 22function invalid(Test $test, string $prop1, string $prop2, $value) { 23 try { 24 $test->$prop2 = $value; 25 $test->$prop1 =& $test->$prop2; 26 echo "Invalid assignment $prop1 =& $prop2 did not error\n"; 27 } catch (TypeError $e) {} 28 try { 29 $test->$prop1 = $value; 30 $test->$prop2 =& $test->$prop1; 31 echo "Invalid assignment $prop2 =& $prop1 did not error\n"; 32 } catch (TypeError $e) {} 33} 34 35function valid(Test $test, string $prop1, string $prop2, $value) { 36 try { 37 $test->$prop2 = $value; 38 $test->$prop1 =& $test->$prop2; 39 } catch (TypeError $e) { 40 echo "Valid assignment $prop1 =& $prop2 threw {$e->getMessage()}\n"; 41 } 42 try { 43 $test->$prop1 = $value; 44 $test->$prop2 =& $test->$prop1; 45 } catch (TypeError $e) { 46 echo "Valid assignment $prop2 =& $prop1 threw {$e->getMessage()}\n"; 47 } 48} 49 50$test = new Test; 51invalid($test, 'int', 'float', 42.0); 52valid($test, 'int', 'nint', 42); 53invalid($test, 'int', 'nint', null); 54valid($test, 'nint', 'nstring', null); 55invalid($test, 'nint', 'nstring', '42'); 56valid($test, 'A', 'A', new A); 57valid($test, 'A', 'B', new B); 58invalid($test, 'A', 'B', new A); 59valid($test, 'iterable', 'array', [1, 2, 3]); 60valid($test, 'A', 'object', new A); 61invalid($test, 'A', 'object', new Test); 62valid($test, 'iterable', 'Iterator', new ArrayIterator); 63invalid($test, 'Iterator', 'iterable', [1, 2, 3]); 64valid($test, 'object', 'iterable', new ArrayIterator); 65invalid($test, 'iterable', 'object', new stdClass); 66 67echo "Done\n"; 68 69?> 70--EXPECT-- 71Done 72