test: cover by-reference return override semantics

master
韩天峰 12 hours ago
parent cd92f89a4b
commit 24924673ec
  1. 16
      phpunit/code/override_byref_return_abstract_dropped.php
  2. 16
      phpunit/code/override_byref_return_interface_dropped.php
  3. 18
      phpunit/src/MethodOverrideByRefReturnTest.php
  4. 47
      tests/compiler/ref/abstract-interface-add-byref-return.phpt
  5. 71
      tests/compiler/ref/override-add-byref-return.phpt

@ -0,0 +1,16 @@
<?php
abstract class AbstractByRefReturn
{
abstract public function &value(): array;
}
class ConcreteByRefReturn extends AbstractByRefReturn
{
public function value(): array
{
return [];
}
}
function main() {}

@ -0,0 +1,16 @@
<?php
interface ByRefReturnContract
{
public function &value(): array;
}
class ByRefReturnImplementation implements ByRefReturnContract
{
public function value(): array
{
return [];
}
}
function main() {}

@ -21,4 +21,22 @@ class MethodOverrideByRefReturnTest extends BaseTest
'override_byref_return_dropped.php', 'override_byref_return_dropped.php',
); );
} }
public function testAbstractMethodImplementationCannotDropByRefReturn(): void
{
$this->exec(
'Declaration of `ConcreteByRefReturn::value()` must be compatible with '
. '`AbstractByRefReturn::value()`',
'override_byref_return_abstract_dropped.php',
);
}
public function testInterfaceImplementationCannotDropByRefReturn(): void
{
$this->exec(
'Declaration of `ByRefReturnImplementation::value()` must be compatible with '
. '`ByRefReturnContract::value()`',
'override_byref_return_interface_dropped.php',
);
}
} }

@ -0,0 +1,47 @@
--TEST--
Abstract and interface implementations may add a by-reference return
--FILE--
<?php
abstract class AbstractValueSource
{
abstract public function abstractValue(): int;
}
interface ValueSourceContract
{
public function interfaceValue(): int;
}
final class ReferenceValueSource extends AbstractValueSource implements ValueSourceContract
{
private int $abstractStored = 5;
private int $interfaceStored = 7;
public function &abstractValue(): int
{
return $this->abstractStored;
}
public function &interfaceValue(): int
{
return $this->interfaceStored;
}
}
function main(): void
{
$source = new ReferenceValueSource();
$abstractAlias =& $source->abstractValue();
$abstractAlias = 50;
var_dump($source->abstractValue());
$interfaceAlias =& $source->interfaceValue();
$interfaceAlias = 70;
var_dump($source->interfaceValue());
}
?>
--EXPECT--
int(50)
int(70)

@ -0,0 +1,71 @@
--TEST--
An override may add a by-reference return and preserve alias semantics
--FILE--
<?php
class ByRefReturnParent
{
public function value(): int
{
return -1;
}
}
final class ByRefReturnChild extends ByRefReturnParent
{
private int $stored = 10;
public function &value(): int
{
return $this->stored;
}
}
class StaticByRefReturnParent
{
public static function value(): int
{
return -1;
}
}
final class StaticByRefReturnChild extends StaticByRefReturnParent
{
private static int $stored = 20;
public static function &value(): int
{
return self::$stored;
}
}
function readByRefReturnParent(ByRefReturnParent $value): int
{
return $value->value();
}
function main(): void
{
$child = new ByRefReturnChild();
var_dump(readByRefReturnParent($child));
$instanceAlias =& $child->value();
$instanceAlias = 42;
var_dump($child->value());
var_dump(readByRefReturnParent($child));
$instanceCopy = $child->value();
$instanceCopy = 99;
var_dump($child->value());
$staticAlias =& StaticByRefReturnChild::value();
$staticAlias = 84;
var_dump(StaticByRefReturnChild::value());
}
?>
--EXPECT--
int(10)
int(42)
int(42)
int(42)
int(84)
Loading…
Cancel
Save