mirror of
https://github.com/php/php-src.git
synced 2025-08-15 21:48:51 +02:00
Implement object type annotation
RFC: https://wiki.php.net/rfc/object-typehint
This commit is contained in:
parent
dd15b34018
commit
8e10c9d373
24 changed files with 363 additions and 116 deletions
1
NEWS
1
NEWS
|
@ -8,6 +8,7 @@ PHP NEWS
|
|||
. Fixed bug #74761 (Unary operator expected error on some systems). (petk)
|
||||
. Allow loading PHP/Zend extensions by name in ini files (extension=<name>).
|
||||
(francois at tekwire dot net)
|
||||
. Added object type annotation. (brzuchal)
|
||||
|
||||
- OpenSSL:
|
||||
. Fixed bug #74798 (pkcs7_en/decrypt does not work if \x0a is used in content).
|
||||
|
|
|
@ -41,6 +41,7 @@ PHP 7.2 UPGRADE NOTES
|
|||
. Minimum supported Windows versions are Windows 7/Server 2008 R2.
|
||||
. Initial trait property value compatibility check will no longer perform
|
||||
any casts. (Bug #74269)
|
||||
. "object" (in any case) can no longer be used as a class name.
|
||||
|
||||
- BCMath:
|
||||
. The bcmod() function no longer truncates fractional numbers to integers. As
|
||||
|
@ -101,6 +102,8 @@ PHP 7.2 UPGRADE NOTES
|
|||
(https://wiki.php.net/rfc/allow-abstract-function-override)
|
||||
. A trailing comma in group use statements is now allowed.
|
||||
(https://wiki.php.net/rfc/list-syntax-trailing-commas)
|
||||
. The "object" type annotation is now supported.
|
||||
(https://wiki.php.net/rfc/object-typehint)
|
||||
|
||||
- DBA:
|
||||
. Implemented support for the LMDB backend.
|
||||
|
|
|
@ -5,7 +5,7 @@ Bug #26698 (Thrown exceptions while evaluting argument to pass as parameter cras
|
|||
|
||||
ini_set("report_memleaks", 0); // the exception thrown in this test results in a memory leak, which is fine
|
||||
|
||||
class Object
|
||||
class ObjectOne
|
||||
{
|
||||
function getNone()
|
||||
{
|
||||
|
@ -23,7 +23,7 @@ class Proxy
|
|||
{
|
||||
try
|
||||
{
|
||||
$res = new Object();
|
||||
$res = new ObjectOne();
|
||||
$this->three($res->getNone());
|
||||
}
|
||||
catch(Exception $e)
|
||||
|
@ -36,7 +36,7 @@ class Proxy
|
|||
{
|
||||
try
|
||||
{
|
||||
$res = new Object();
|
||||
$res = new ObjectOne();
|
||||
$this->three(1, $res->getNone());
|
||||
}
|
||||
catch(Exception $e)
|
||||
|
@ -49,7 +49,7 @@ class Proxy
|
|||
{
|
||||
try
|
||||
{
|
||||
$res = new Object();
|
||||
$res = new ObjectOne();
|
||||
$this->three(1, 2, $res->getNone());
|
||||
}
|
||||
catch(Exception $e)
|
||||
|
|
|
@ -9,7 +9,7 @@ function my_error_handler($errno, $errstr, $errfile, $errline) {
|
|||
|
||||
set_error_handler('my_error_handler');
|
||||
|
||||
class Object
|
||||
class ObjectOne
|
||||
{
|
||||
public $x;
|
||||
|
||||
|
@ -26,7 +26,7 @@ class Overloaded
|
|||
|
||||
function __construct($x)
|
||||
{
|
||||
$this->x = new Object($x);
|
||||
$this->x = new ObjectOne($x);
|
||||
}
|
||||
|
||||
function __get($prop)
|
||||
|
@ -47,7 +47,7 @@ var_dump($y->x->x);
|
|||
var_dump($y->x->x = 3);
|
||||
var_dump($y->y = 3);
|
||||
var_dump($y->y);
|
||||
var_dump($y->z = new Object(4));
|
||||
var_dump($y->z = new ObjectOne(4));
|
||||
var_dump($y->z->x);
|
||||
$t = $y->z;
|
||||
var_dump($t->x = 5);
|
||||
|
@ -56,7 +56,7 @@ var_dump($y->z->x = 6);
|
|||
?>
|
||||
===DONE===
|
||||
--EXPECTF--
|
||||
object(Object)#%d (1) {
|
||||
object(ObjectOne)#%d (1) {
|
||||
["x"]=>
|
||||
int(2)
|
||||
}
|
||||
|
@ -66,9 +66,9 @@ Overloaded::__set(y,3)
|
|||
int(3)
|
||||
Overloaded::__get(y)
|
||||
int(3)
|
||||
string(55) "Object of class Object could not be converted to string"
|
||||
string(58) "Object of class ObjectOne could not be converted to string"
|
||||
Overloaded::__set(z,)
|
||||
object(Object)#%d (1) {
|
||||
object(ObjectOne)#%d (1) {
|
||||
["x"]=>
|
||||
int(4)
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ define('OBJECT_COUNT', 10000);
|
|||
|
||||
$containers = array();
|
||||
|
||||
class Object {
|
||||
class ObjectOne {
|
||||
protected $_guid = 0;
|
||||
public function __construct() {
|
||||
global $containers;
|
||||
|
@ -20,7 +20,7 @@ class Object {
|
|||
}
|
||||
|
||||
for ($i = 0; $i < OBJECT_COUNT; ++$i) {
|
||||
new Object();
|
||||
new ObjectOne();
|
||||
}
|
||||
|
||||
// You probably won't see this because of the "zend_mm_heap corrupted"
|
||||
|
|
10
Zend/tests/object_types/invalid_default_value.phpt
Normal file
10
Zend/tests/object_types/invalid_default_value.phpt
Normal file
|
@ -0,0 +1,10 @@
|
|||
--TEST--
|
||||
Object type can only default to null
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
function test(object $obj = 42) { }
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
Fatal error: Default value for parameters with a object type can only be NULL in %s on line %d
|
|
@ -0,0 +1,15 @@
|
|||
--TEST--
|
||||
Missing class method a object return type during inheritance
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
class One {
|
||||
public function a() : object {}
|
||||
}
|
||||
|
||||
class Two extends One {
|
||||
public function a() {}
|
||||
}
|
||||
|
||||
--EXPECTF--
|
||||
Fatal error: Declaration of Two::a() must be compatible with One::a(): object in %s on line 9
|
|
@ -0,0 +1,15 @@
|
|||
--TEST--
|
||||
Missing interface method a object return type during inheritance
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
interface One {
|
||||
public function a() : object;
|
||||
}
|
||||
|
||||
interface Two extends One {
|
||||
public function a();
|
||||
}
|
||||
|
||||
--EXPECTF--
|
||||
Fatal error: Declaration of Two::a() must be compatible with One::a(): object in %s on line %d
|
26
Zend/tests/object_types/return_type_in_class.phpt
Normal file
26
Zend/tests/object_types/return_type_in_class.phpt
Normal file
|
@ -0,0 +1,26 @@
|
|||
--TEST--
|
||||
Adding a class method object return type
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
interface One {
|
||||
public function a() : object;
|
||||
}
|
||||
|
||||
class Two implements One {
|
||||
public function a() : object {}
|
||||
}
|
||||
|
||||
$three = new class extends Two {
|
||||
public function a() : object {
|
||||
return 12345;
|
||||
}
|
||||
};
|
||||
$three->a();
|
||||
--EXPECTF--
|
||||
|
||||
Fatal error: Uncaught TypeError: Return value of class@anonymous::a() must be an object, integer returned in %s:13
|
||||
Stack trace:
|
||||
#0 %s(16): class@anonymous->a()
|
||||
#1 {main}
|
||||
thrown in %s on line 13
|
16
Zend/tests/object_types/return_type_in_function.phpt
Normal file
16
Zend/tests/object_types/return_type_in_function.phpt
Normal file
|
@ -0,0 +1,16 @@
|
|||
--TEST--
|
||||
Adding a function object return type
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
function a() : object {
|
||||
return 12345;
|
||||
}
|
||||
a();
|
||||
--EXPECTF--
|
||||
|
||||
Fatal error: Uncaught TypeError: Return value of a() must be an object, integer returned in %s:4
|
||||
Stack trace:
|
||||
#0 %s(6): a()
|
||||
#1 {main}
|
||||
thrown in %s on line 4
|
|
@ -0,0 +1,26 @@
|
|||
--TEST--
|
||||
Adding class method a object return type during inheritance is allowed
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
class One {
|
||||
public function a() {}
|
||||
}
|
||||
|
||||
class Two extends One {
|
||||
public function a() : object {}
|
||||
}
|
||||
|
||||
$three = new class extends Two {
|
||||
public function a() : object {
|
||||
return 12345;
|
||||
}
|
||||
};
|
||||
$three->a();
|
||||
|
||||
--EXPECTF--
|
||||
Fatal error: Uncaught TypeError: Return value of class@anonymous::a() must be an object, integer returned in %s:13
|
||||
Stack trace:
|
||||
#0 %s(16): class@anonymous->a()
|
||||
#1 {main}
|
||||
thrown in /%s on line 13
|
|
@ -0,0 +1,26 @@
|
|||
--TEST--
|
||||
Adding interface method a object return type during inheritance is allowed
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
interface One {
|
||||
public function a();
|
||||
}
|
||||
|
||||
interface Two extends One {
|
||||
public function a() : object;
|
||||
}
|
||||
|
||||
$three = new class implements Two {
|
||||
public function a() : object {
|
||||
return 12345;
|
||||
}
|
||||
};
|
||||
$three->a();
|
||||
|
||||
--EXPECTF--
|
||||
Fatal error: Uncaught TypeError: Return value of class@anonymous::a() must be an object, integer returned in %s:13
|
||||
Stack trace:
|
||||
#0 %s(16): class@anonymous->a()
|
||||
#1 {main}
|
||||
thrown in /%s on line 13
|
31
Zend/tests/object_types/return_type_reflection.phpt
Normal file
31
Zend/tests/object_types/return_type_reflection.phpt
Normal file
|
@ -0,0 +1,31 @@
|
|||
--TEST--
|
||||
Reflecting object return type
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
interface One {
|
||||
public function a() : object;
|
||||
}
|
||||
|
||||
class Two implements One {
|
||||
public function a() : object {}
|
||||
}
|
||||
|
||||
function a() : object {}
|
||||
|
||||
$returnTypeOne = (new ReflectionClass(One::class))->getMethod('a')->getReturnType();
|
||||
var_dump($returnTypeOne->isBuiltin(), (string)$returnTypeOne);
|
||||
|
||||
$returnTypeTwo = (new ReflectionClass(Two::class))->getMethod('a')->getReturnType();
|
||||
var_dump($returnTypeTwo->isBuiltin(), (string)$returnTypeTwo);
|
||||
|
||||
$returnTypea = (new ReflectionFunction('a'))->getReturnType();
|
||||
var_dump($returnTypea->isBuiltin(), (string)$returnTypea);
|
||||
|
||||
--EXPECTF--
|
||||
bool(true)
|
||||
string(6) "object"
|
||||
bool(true)
|
||||
string(6) "object"
|
||||
bool(true)
|
||||
string(6) "object"
|
19
Zend/tests/object_types/type_hint_in_class_method.phpt
Normal file
19
Zend/tests/object_types/type_hint_in_class_method.phpt
Normal file
|
@ -0,0 +1,19 @@
|
|||
--TEST--
|
||||
Adding a class method object type hint
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
class One {
|
||||
public function a(object $obj) {}
|
||||
}
|
||||
|
||||
$one = new One();
|
||||
$one->a(new One());
|
||||
$one->a(123);
|
||||
--EXPECTF--
|
||||
|
||||
Fatal error: Uncaught TypeError: Argument 1 passed to One::a() must be an object, integer given, called in %s:4
|
||||
Stack trace:
|
||||
#0 %s(9): One->a(123)
|
||||
#1 {main}
|
||||
thrown in %s on line 4
|
17
Zend/tests/object_types/type_hint_in_function.phpt
Normal file
17
Zend/tests/object_types/type_hint_in_function.phpt
Normal file
|
@ -0,0 +1,17 @@
|
|||
--TEST--
|
||||
Adding a function object type hint
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
class A {}
|
||||
function a(object $obj) {}
|
||||
|
||||
a(new A());
|
||||
a(123);
|
||||
--EXPECTF--
|
||||
|
||||
Fatal error: Uncaught TypeError: Argument 1 passed to a() must be an object, integer given, called in %s.php on line 7 and defined in %s:4
|
||||
Stack trace:
|
||||
#0 %s(7): a(123)
|
||||
#1 {main}
|
||||
thrown in %s on line 4
|
31
Zend/tests/object_types/type_hint_reflection.phpt
Normal file
31
Zend/tests/object_types/type_hint_reflection.phpt
Normal file
|
@ -0,0 +1,31 @@
|
|||
--TEST--
|
||||
Reflecting object type hint
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
interface One {
|
||||
public function a(object $obj);
|
||||
}
|
||||
|
||||
class Two implements One {
|
||||
public function a(object $obj) {}
|
||||
}
|
||||
|
||||
function a(object $obj) {}
|
||||
|
||||
$typeHintOne = (new ReflectionClass(One::class))->getMethod('a')->getParameters()[0]->getType();
|
||||
var_dump($typeHintOne->isBuiltin(), (string)$typeHintOne);
|
||||
|
||||
$typeHintTwo = (new ReflectionClass(Two::class))->getMethod('a')->getParameters()[0]->getType();
|
||||
var_dump($typeHintTwo->isBuiltin(), (string)$typeHintTwo);
|
||||
|
||||
$typeHinta = (new ReflectionFunction('a'))->getParameters()[0]->getType();
|
||||
var_dump($typeHinta->isBuiltin(), (string)$typeHinta);
|
||||
|
||||
--EXPECTF--
|
||||
bool(true)
|
||||
string(6) "object"
|
||||
bool(true)
|
||||
string(6) "object"
|
||||
bool(true)
|
||||
string(6) "object"
|
|
@ -162,6 +162,7 @@ static const struct reserved_class_name reserved_class_names[] = {
|
|||
{ZEND_STRL("true")},
|
||||
{ZEND_STRL("void")},
|
||||
{ZEND_STRL("iterable")},
|
||||
{ZEND_STRL("object")},
|
||||
{NULL, 0}
|
||||
};
|
||||
|
||||
|
@ -207,6 +208,7 @@ static const builtin_type_info builtin_types[] = {
|
|||
{ZEND_STRL("bool"), _IS_BOOL},
|
||||
{ZEND_STRL("void"), IS_VOID},
|
||||
{ZEND_STRL("iterable"), IS_ITERABLE},
|
||||
{ZEND_STRL("object"), IS_OBJECT},
|
||||
{NULL, 0, IS_UNDEF}
|
||||
};
|
||||
|
||||
|
@ -5565,6 +5567,12 @@ void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast) /* {{{ */
|
|||
"with iterable type can only be an array or NULL");
|
||||
}
|
||||
break;
|
||||
|
||||
case IS_OBJECT:
|
||||
zend_error_noreturn(E_COMPILE_ERROR, "Default value for parameters "
|
||||
"with a %s type can only be NULL",
|
||||
zend_get_type_by_const(ZEND_TYPE_CODE(arg_info->type)), zend_get_type_by_const(ZEND_TYPE_CODE(arg_info->type)));
|
||||
break;
|
||||
|
||||
default:
|
||||
if (!ZEND_SAME_FAKE_TYPE(ZEND_TYPE_CODE(arg_info->type), Z_TYPE(default_node.u.constant))) {
|
||||
|
|
|
@ -648,7 +648,6 @@ static ZEND_COLD void zend_verify_type_error_common(
|
|||
{
|
||||
zend_bool is_interface = 0;
|
||||
*fname = ZSTR_VAL(zf->common.function_name);
|
||||
|
||||
if (zf->common.scope) {
|
||||
*fsep = "::";
|
||||
*fclass = ZSTR_VAL(zf->common.scope->name);
|
||||
|
@ -674,6 +673,10 @@ static ZEND_COLD void zend_verify_type_error_common(
|
|||
}
|
||||
} else {
|
||||
switch (ZEND_TYPE_CODE(arg_info->type)) {
|
||||
case IS_OBJECT:
|
||||
*need_msg = "be an ";
|
||||
*need_kind = "object";
|
||||
break;
|
||||
case IS_CALLABLE:
|
||||
*need_msg = "be callable";
|
||||
*need_kind = "";
|
||||
|
|
|
@ -2,9 +2,9 @@
|
|||
Reflection Bug #38194 (ReflectionClass::isSubclassOf() returns TRUE for the class itself)
|
||||
--FILE--
|
||||
<?php
|
||||
class Object { }
|
||||
class ObjectOne { }
|
||||
|
||||
$objectClass= new ReflectionClass('Object');
|
||||
$objectClass = new ReflectionClass('ObjectOne');
|
||||
var_dump($objectClass->isSubclassOf($objectClass));
|
||||
?>
|
||||
--EXPECT--
|
||||
|
|
|
@ -3,21 +3,21 @@ Bug #38217 (ReflectionClass::newInstanceArgs() tries to allocate too much memory
|
|||
--FILE--
|
||||
<?php
|
||||
|
||||
class Object {
|
||||
class ObjectOne {
|
||||
public function __construct() {
|
||||
}
|
||||
}
|
||||
|
||||
$class= new ReflectionClass('Object');
|
||||
$class= new ReflectionClass('ObjectOne');
|
||||
var_dump($class->newInstanceArgs());
|
||||
|
||||
class Object1 {
|
||||
class ObjectTwo {
|
||||
public function __construct($var) {
|
||||
var_dump($var);
|
||||
}
|
||||
}
|
||||
|
||||
$class= new ReflectionClass('Object1');
|
||||
$class= new ReflectionClass('ObjectTwo');
|
||||
try {
|
||||
var_dump($class->newInstanceArgs());
|
||||
} catch (Throwable $e) {
|
||||
|
@ -29,10 +29,10 @@ var_dump($class->newInstanceArgs(array('test')));
|
|||
echo "Done\n";
|
||||
?>
|
||||
--EXPECTF--
|
||||
object(Object)#%d (0) {
|
||||
object(ObjectOne)#%d (0) {
|
||||
}
|
||||
Exception: Too few arguments to function Object1::__construct(), 0 passed and exactly 1 expected
|
||||
Exception: Too few arguments to function ObjectTwo::__construct(), 0 passed and exactly 1 expected
|
||||
string(4) "test"
|
||||
object(Object1)#%d (0) {
|
||||
object(ObjectTwo)#%d (0) {
|
||||
}
|
||||
Done
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
ZE2 ArrayAccess
|
||||
--FILE--
|
||||
<?php
|
||||
class object implements ArrayAccess {
|
||||
class ObjectOne implements ArrayAccess {
|
||||
|
||||
public $a = array('1st', 1, 2=>'3rd', '4th'=>4);
|
||||
|
||||
|
@ -24,7 +24,7 @@ class object implements ArrayAccess {
|
|||
}
|
||||
}
|
||||
|
||||
$obj = new Object;
|
||||
$obj = new ObjectOne;
|
||||
|
||||
var_dump($obj->a);
|
||||
|
||||
|
@ -95,75 +95,75 @@ array(4) {
|
|||
int(4)
|
||||
}
|
||||
===EMPTY===
|
||||
object::offsetExists(0)
|
||||
object::offsetGet(0)
|
||||
ObjectOne::offsetExists(0)
|
||||
ObjectOne::offsetGet(0)
|
||||
bool(false)
|
||||
object::offsetExists(1)
|
||||
object::offsetGet(1)
|
||||
ObjectOne::offsetExists(1)
|
||||
ObjectOne::offsetGet(1)
|
||||
bool(false)
|
||||
object::offsetExists(2)
|
||||
object::offsetGet(2)
|
||||
ObjectOne::offsetExists(2)
|
||||
ObjectOne::offsetGet(2)
|
||||
bool(false)
|
||||
object::offsetExists(4th)
|
||||
object::offsetGet(4th)
|
||||
ObjectOne::offsetExists(4th)
|
||||
ObjectOne::offsetGet(4th)
|
||||
bool(false)
|
||||
object::offsetExists(5th)
|
||||
ObjectOne::offsetExists(5th)
|
||||
bool(true)
|
||||
object::offsetExists(6)
|
||||
ObjectOne::offsetExists(6)
|
||||
bool(true)
|
||||
===isset===
|
||||
object::offsetExists(0)
|
||||
ObjectOne::offsetExists(0)
|
||||
bool(true)
|
||||
object::offsetExists(1)
|
||||
ObjectOne::offsetExists(1)
|
||||
bool(true)
|
||||
object::offsetExists(2)
|
||||
ObjectOne::offsetExists(2)
|
||||
bool(true)
|
||||
object::offsetExists(4th)
|
||||
ObjectOne::offsetExists(4th)
|
||||
bool(true)
|
||||
object::offsetExists(5th)
|
||||
ObjectOne::offsetExists(5th)
|
||||
bool(false)
|
||||
object::offsetExists(6)
|
||||
ObjectOne::offsetExists(6)
|
||||
bool(false)
|
||||
===offsetGet===
|
||||
object::offsetGet(0)
|
||||
ObjectOne::offsetGet(0)
|
||||
string(3) "1st"
|
||||
object::offsetGet(1)
|
||||
ObjectOne::offsetGet(1)
|
||||
int(1)
|
||||
object::offsetGet(2)
|
||||
ObjectOne::offsetGet(2)
|
||||
string(3) "3rd"
|
||||
object::offsetGet(4th)
|
||||
ObjectOne::offsetGet(4th)
|
||||
int(4)
|
||||
object::offsetGet(5th)
|
||||
ObjectOne::offsetGet(5th)
|
||||
|
||||
Notice: Undefined index: 5th in %sarray_access_001.php on line %d
|
||||
NULL
|
||||
object::offsetGet(6)
|
||||
ObjectOne::offsetGet(6)
|
||||
|
||||
Notice: Undefined offset: 6 in %sarray_access_001.php on line %d
|
||||
NULL
|
||||
===offsetSet===
|
||||
WRITE 1
|
||||
object::offsetSet(1,Changed 1)
|
||||
object::offsetGet(1)
|
||||
ObjectOne::offsetSet(1,Changed 1)
|
||||
ObjectOne::offsetGet(1)
|
||||
string(9) "Changed 1"
|
||||
WRITE 2
|
||||
object::offsetSet(4th,Changed 4th)
|
||||
object::offsetGet(4th)
|
||||
ObjectOne::offsetSet(4th,Changed 4th)
|
||||
ObjectOne::offsetGet(4th)
|
||||
string(11) "Changed 4th"
|
||||
WRITE 3
|
||||
object::offsetSet(5th,Added 5th)
|
||||
object::offsetGet(5th)
|
||||
ObjectOne::offsetSet(5th,Added 5th)
|
||||
ObjectOne::offsetGet(5th)
|
||||
string(9) "Added 5th"
|
||||
WRITE 4
|
||||
object::offsetSet(6,Added 6)
|
||||
object::offsetGet(6)
|
||||
ObjectOne::offsetSet(6,Added 6)
|
||||
ObjectOne::offsetGet(6)
|
||||
string(7) "Added 6"
|
||||
object::offsetGet(0)
|
||||
ObjectOne::offsetGet(0)
|
||||
string(3) "1st"
|
||||
object::offsetGet(2)
|
||||
ObjectOne::offsetGet(2)
|
||||
string(3) "3rd"
|
||||
object::offsetSet(6,changed 6)
|
||||
object::offsetGet(6)
|
||||
ObjectOne::offsetSet(6,changed 6)
|
||||
ObjectOne::offsetGet(6)
|
||||
string(9) "changed 6"
|
||||
string(9) "changed 6"
|
||||
===unset===
|
||||
|
@ -181,10 +181,10 @@ array(6) {
|
|||
[6]=>
|
||||
string(9) "changed 6"
|
||||
}
|
||||
object::offsetUnset(2)
|
||||
object::offsetUnset(4th)
|
||||
object::offsetUnset(7)
|
||||
object::offsetUnset(8th)
|
||||
ObjectOne::offsetUnset(2)
|
||||
ObjectOne::offsetUnset(4th)
|
||||
ObjectOne::offsetUnset(7)
|
||||
ObjectOne::offsetUnset(8th)
|
||||
array(4) {
|
||||
[0]=>
|
||||
string(3) "1st"
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
ZE2 ArrayAccess::offsetSet without return
|
||||
--FILE--
|
||||
<?php
|
||||
class object implements ArrayAccess {
|
||||
class ObjectOne implements ArrayAccess {
|
||||
|
||||
public $a = array('1st', 1, 2=>'3rd', '4th'=>4);
|
||||
|
||||
|
@ -24,7 +24,7 @@ class object implements ArrayAccess {
|
|||
}
|
||||
}
|
||||
|
||||
$obj = new Object;
|
||||
$obj = new ObjectOne;
|
||||
|
||||
var_dump($obj->a);
|
||||
|
||||
|
@ -95,75 +95,75 @@ array(4) {
|
|||
int(4)
|
||||
}
|
||||
===EMPTY===
|
||||
object::offsetExists(0)
|
||||
object::offsetGet(0)
|
||||
ObjectOne::offsetExists(0)
|
||||
ObjectOne::offsetGet(0)
|
||||
bool(false)
|
||||
object::offsetExists(1)
|
||||
object::offsetGet(1)
|
||||
ObjectOne::offsetExists(1)
|
||||
ObjectOne::offsetGet(1)
|
||||
bool(false)
|
||||
object::offsetExists(2)
|
||||
object::offsetGet(2)
|
||||
ObjectOne::offsetExists(2)
|
||||
ObjectOne::offsetGet(2)
|
||||
bool(false)
|
||||
object::offsetExists(4th)
|
||||
object::offsetGet(4th)
|
||||
ObjectOne::offsetExists(4th)
|
||||
ObjectOne::offsetGet(4th)
|
||||
bool(false)
|
||||
object::offsetExists(5th)
|
||||
ObjectOne::offsetExists(5th)
|
||||
bool(true)
|
||||
object::offsetExists(6)
|
||||
ObjectOne::offsetExists(6)
|
||||
bool(true)
|
||||
===isset===
|
||||
object::offsetExists(0)
|
||||
ObjectOne::offsetExists(0)
|
||||
bool(true)
|
||||
object::offsetExists(1)
|
||||
ObjectOne::offsetExists(1)
|
||||
bool(true)
|
||||
object::offsetExists(2)
|
||||
ObjectOne::offsetExists(2)
|
||||
bool(true)
|
||||
object::offsetExists(4th)
|
||||
ObjectOne::offsetExists(4th)
|
||||
bool(true)
|
||||
object::offsetExists(5th)
|
||||
ObjectOne::offsetExists(5th)
|
||||
bool(false)
|
||||
object::offsetExists(6)
|
||||
ObjectOne::offsetExists(6)
|
||||
bool(false)
|
||||
===offsetGet===
|
||||
object::offsetGet(0)
|
||||
ObjectOne::offsetGet(0)
|
||||
string(3) "1st"
|
||||
object::offsetGet(1)
|
||||
ObjectOne::offsetGet(1)
|
||||
int(1)
|
||||
object::offsetGet(2)
|
||||
ObjectOne::offsetGet(2)
|
||||
string(3) "3rd"
|
||||
object::offsetGet(4th)
|
||||
ObjectOne::offsetGet(4th)
|
||||
int(4)
|
||||
object::offsetGet(5th)
|
||||
ObjectOne::offsetGet(5th)
|
||||
|
||||
Notice: Undefined index: 5th in %sarray_access_002.php on line %d
|
||||
NULL
|
||||
object::offsetGet(6)
|
||||
ObjectOne::offsetGet(6)
|
||||
|
||||
Notice: Undefined offset: 6 in %sarray_access_002.php on line %d
|
||||
NULL
|
||||
===offsetSet===
|
||||
WRITE 1
|
||||
object::offsetSet(1,Changed 1)
|
||||
object::offsetGet(1)
|
||||
ObjectOne::offsetSet(1,Changed 1)
|
||||
ObjectOne::offsetGet(1)
|
||||
string(9) "Changed 1"
|
||||
WRITE 2
|
||||
object::offsetSet(4th,Changed 4th)
|
||||
object::offsetGet(4th)
|
||||
ObjectOne::offsetSet(4th,Changed 4th)
|
||||
ObjectOne::offsetGet(4th)
|
||||
string(11) "Changed 4th"
|
||||
WRITE 3
|
||||
object::offsetSet(5th,Added 5th)
|
||||
object::offsetGet(5th)
|
||||
ObjectOne::offsetSet(5th,Added 5th)
|
||||
ObjectOne::offsetGet(5th)
|
||||
string(9) "Added 5th"
|
||||
WRITE 4
|
||||
object::offsetSet(6,Added 6)
|
||||
object::offsetGet(6)
|
||||
ObjectOne::offsetSet(6,Added 6)
|
||||
ObjectOne::offsetGet(6)
|
||||
string(7) "Added 6"
|
||||
object::offsetGet(0)
|
||||
ObjectOne::offsetGet(0)
|
||||
string(3) "1st"
|
||||
object::offsetGet(2)
|
||||
ObjectOne::offsetGet(2)
|
||||
string(3) "3rd"
|
||||
object::offsetSet(6,changed 6)
|
||||
object::offsetGet(6)
|
||||
ObjectOne::offsetSet(6,changed 6)
|
||||
ObjectOne::offsetGet(6)
|
||||
string(9) "changed 6"
|
||||
string(9) "changed 6"
|
||||
===unset===
|
||||
|
@ -181,10 +181,10 @@ array(6) {
|
|||
[6]=>
|
||||
string(9) "changed 6"
|
||||
}
|
||||
object::offsetUnset(2)
|
||||
object::offsetUnset(4th)
|
||||
object::offsetUnset(7)
|
||||
object::offsetUnset(8th)
|
||||
ObjectOne::offsetUnset(2)
|
||||
ObjectOne::offsetUnset(4th)
|
||||
ObjectOne::offsetUnset(7)
|
||||
ObjectOne::offsetUnset(8th)
|
||||
array(4) {
|
||||
[0]=>
|
||||
string(3) "1st"
|
||||
|
|
|
@ -4,7 +4,7 @@ ZE2 ArrayAccess::offsetGet ambiguties
|
|||
error_reporting=4095
|
||||
--FILE--
|
||||
<?php
|
||||
class object implements ArrayAccess {
|
||||
class ObjectOne implements ArrayAccess {
|
||||
|
||||
public $a = array('1st', 1, 2=>'3rd', '4th'=>4);
|
||||
|
||||
|
@ -37,7 +37,7 @@ class object implements ArrayAccess {
|
|||
}
|
||||
}
|
||||
|
||||
$obj = new Object;
|
||||
$obj = new ObjectOne;
|
||||
|
||||
var_dump($obj[1]);
|
||||
var_dump($obj[2]);
|
||||
|
@ -47,13 +47,13 @@ var_dump($obj[2]);
|
|||
?>
|
||||
===DONE===
|
||||
--EXPECTF--
|
||||
object::offsetGet(1)
|
||||
ObjectOne::offsetGet(1)
|
||||
string(6) "fooBar"
|
||||
object::offsetGet(2)
|
||||
ObjectOne::offsetGet(2)
|
||||
int(1)
|
||||
object::offsetGet(2)
|
||||
ObjectOne::offsetGet(2)
|
||||
|
||||
Notice: Indirect modification of overloaded element of object has no effect in %sarray_access_003.php on line 39
|
||||
object::offsetGet(2)
|
||||
Notice: Indirect modification of overloaded element of ObjectOne has no effect in %sarray_access_003.php on line 39
|
||||
ObjectOne::offsetGet(2)
|
||||
int(1)
|
||||
===DONE===
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
ZE2 ArrayAccess::offsetGet ambiguties
|
||||
--FILE--
|
||||
<?php
|
||||
class object implements ArrayAccess {
|
||||
class ObjectOne implements ArrayAccess {
|
||||
|
||||
public $a = array('1st', 1, 2=>'3rd', '4th'=>4);
|
||||
|
||||
|
@ -35,7 +35,7 @@ class object implements ArrayAccess {
|
|||
}
|
||||
}
|
||||
|
||||
$obj = new Object;
|
||||
$obj = new ObjectOne;
|
||||
|
||||
var_dump($obj[1]);
|
||||
var_dump($obj[2]);
|
||||
|
@ -45,13 +45,13 @@ var_dump($obj[2]);
|
|||
?>
|
||||
===DONE===
|
||||
--EXPECTF--
|
||||
object::offsetGet(1)
|
||||
ObjectOne::offsetGet(1)
|
||||
string(6) "fooBar"
|
||||
object::offsetGet(2)
|
||||
ObjectOne::offsetGet(2)
|
||||
int(1)
|
||||
object::offsetGet(2)
|
||||
ObjectOne::offsetGet(2)
|
||||
|
||||
Notice: Indirect modification of overloaded element of object has no effect in %sarray_access_004.php on line 39
|
||||
object::offsetGet(2)
|
||||
Notice: Indirect modification of overloaded element of ObjectOne has no effect in %sarray_access_004.php on line 39
|
||||
ObjectOne::offsetGet(2)
|
||||
int(1)
|
||||
===DONE===
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue