commit
191361eb38
12 changed files with 243 additions and 9 deletions
@ -0,0 +1,8 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
function variable_variable_with_array_dim(): void |
||||||
|
{ |
||||||
|
$foo = ['bar' => 'hello']; |
||||||
|
${$foo['bar']} = 'world'; |
||||||
|
echo $hello; |
||||||
|
} |
||||||
@ -0,0 +1,12 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
function variable_name(): string |
||||||
|
{ |
||||||
|
return 'hello'; |
||||||
|
} |
||||||
|
|
||||||
|
function variable_variable_with_function_call(): void |
||||||
|
{ |
||||||
|
${variable_name()} = 'world'; |
||||||
|
echo $hello; |
||||||
|
} |
||||||
@ -0,0 +1,14 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
class VariableVariableTest extends \BaseTest |
||||||
|
{ |
||||||
|
public function testVariableVariableWithArrayDimThrowsUnsupportedError(): void |
||||||
|
{ |
||||||
|
$this->exec('The `$$` syntax is not supported', 'variable-variable-arraydim.php'); |
||||||
|
} |
||||||
|
|
||||||
|
public function testVariableVariableWithFunctionCallThrowsUnsupportedError(): void |
||||||
|
{ |
||||||
|
$this->exec('The `$$` syntax is not supported', 'variable-variable-function-call.php'); |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,42 @@ |
|||||||
|
--TEST-- |
||||||
|
interface method with `self` return type implemented by class (fluent interface), and namespace block containing comments |
||||||
|
--FILE-- |
||||||
|
<?php |
||||||
|
|
||||||
|
namespace { |
||||||
|
interface TestInterface |
||||||
|
{ |
||||||
|
public function get(): self; |
||||||
|
} |
||||||
|
|
||||||
|
class TestClass implements TestInterface |
||||||
|
{ |
||||||
|
public int $value = 0; |
||||||
|
|
||||||
|
public function get(): self |
||||||
|
{ |
||||||
|
return $this; |
||||||
|
} |
||||||
|
|
||||||
|
public function setValue(int $value): self |
||||||
|
{ |
||||||
|
$this->value = $value; |
||||||
|
return $this; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
function main() |
||||||
|
{ |
||||||
|
$test = new TestClass; |
||||||
|
// get() returns self, so the result still satisfies the interface |
||||||
|
var_dump($test->get() instanceof TestInterface); |
||||||
|
var_dump($test === $test->get()); |
||||||
|
// fluent chaining of self-returning methods |
||||||
|
var_dump($test->get()->setValue(42)->value); |
||||||
|
} |
||||||
|
} |
||||||
|
?> |
||||||
|
--EXPECT-- |
||||||
|
bool(true) |
||||||
|
bool(true) |
||||||
|
int(42) |
||||||
@ -0,0 +1,28 @@ |
|||||||
|
--TEST-- |
||||||
|
assign coalesce on undefined variable |
||||||
|
--FILE-- |
||||||
|
<?php |
||||||
|
$a ??= 123; |
||||||
|
var_dump($a); |
||||||
|
|
||||||
|
$b ??= 'foo'; |
||||||
|
$b ??= 'bar'; |
||||||
|
var_dump($b); |
||||||
|
|
||||||
|
$c ??= null; |
||||||
|
var_dump(isset($c)); |
||||||
|
$c ??= 'after-null'; |
||||||
|
var_dump($c); |
||||||
|
|
||||||
|
for ($i = 0; $i < 2; $i++) { |
||||||
|
$d ??= printf("default\n"); |
||||||
|
} |
||||||
|
var_dump($d); |
||||||
|
?> |
||||||
|
--EXPECT-- |
||||||
|
int(123) |
||||||
|
string(3) "foo" |
||||||
|
bool(false) |
||||||
|
string(10) "after-null" |
||||||
|
default |
||||||
|
int(8) |
||||||
@ -0,0 +1,62 @@ |
|||||||
|
--TEST-- |
||||||
|
Cross-namespace interface implementation parameter compatibility is declaration-order independent |
||||||
|
--FILE-- |
||||||
|
<?php |
||||||
|
namespace A { |
||||||
|
use B\I0; |
||||||
|
use B\I1; |
||||||
|
use B\I2; |
||||||
|
|
||||||
|
abstract class Test implements I2 |
||||||
|
{ |
||||||
|
public function test(I1 $a): bool |
||||||
|
{ |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
public function testParent(I0 $a): bool |
||||||
|
{ |
||||||
|
return true; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
namespace B { |
||||||
|
interface I0 |
||||||
|
{ |
||||||
|
} |
||||||
|
|
||||||
|
interface I1 extends I0 |
||||||
|
{ |
||||||
|
} |
||||||
|
|
||||||
|
interface I2 |
||||||
|
{ |
||||||
|
public function test(I1 $a): bool; |
||||||
|
|
||||||
|
public function testParent(I1 $a): bool; |
||||||
|
} |
||||||
|
|
||||||
|
class Impl1 implements I1 |
||||||
|
{ |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
namespace { |
||||||
|
class Concrete extends \A\Test |
||||||
|
{ |
||||||
|
} |
||||||
|
|
||||||
|
function main() |
||||||
|
{ |
||||||
|
$obj = new Concrete(); |
||||||
|
var_dump($obj->test(new \B\Impl1())); |
||||||
|
var_dump($obj->testParent(new \B\Impl1())); |
||||||
|
echo "done\n"; |
||||||
|
} |
||||||
|
} |
||||||
|
?> |
||||||
|
--EXPECT-- |
||||||
|
bool(true) |
||||||
|
bool(true) |
||||||
|
done |
||||||
@ -0,0 +1,56 @@ |
|||||||
|
--TEST-- |
||||||
|
interface method `self` return type resolves to the interface's fully-qualified name inside a named namespace |
||||||
|
--FILE-- |
||||||
|
<?php |
||||||
|
|
||||||
|
namespace App { |
||||||
|
interface Chainable |
||||||
|
{ |
||||||
|
public function chain(): self; |
||||||
|
|
||||||
|
public function maybe(bool $present): ?self; |
||||||
|
|
||||||
|
public function combine(self $other): self; |
||||||
|
} |
||||||
|
|
||||||
|
// comment inside a named namespace block (Stmt_Nop) |
||||||
|
class Widget implements Chainable |
||||||
|
{ |
||||||
|
public array $log = []; |
||||||
|
|
||||||
|
public function chain(): self |
||||||
|
{ |
||||||
|
$this->log[] = 'chain'; |
||||||
|
return $this; |
||||||
|
} |
||||||
|
|
||||||
|
public function maybe(bool $present): ?self |
||||||
|
{ |
||||||
|
return $present ? $this : null; |
||||||
|
} |
||||||
|
|
||||||
|
public function combine(Chainable $other): self |
||||||
|
{ |
||||||
|
return $this; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
namespace { |
||||||
|
function main() |
||||||
|
{ |
||||||
|
$w = new \App\Widget(); |
||||||
|
var_dump($w->chain()->chain() instanceof \App\Chainable); |
||||||
|
var_dump(count($w->log)); |
||||||
|
var_dump($w->maybe(true) instanceof \App\Chainable); |
||||||
|
var_dump($w->maybe(false)); |
||||||
|
var_dump($w->combine(new \App\Widget()) === $w); |
||||||
|
} |
||||||
|
} |
||||||
|
?> |
||||||
|
--EXPECT-- |
||||||
|
bool(true) |
||||||
|
int(2) |
||||||
|
bool(true) |
||||||
|
NULL |
||||||
|
bool(true) |
||||||
Loading…
Reference in new issue