Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ PHP NEWS
?? ??? ????, PHP 8.6.0alpha1

- Core:
. `$x instanceof object` now evaluates like `is_object($x)`, correctly
returning true for any object. (Damien Seguy)
. Added first-class callable cache to share instances for the duration of the
request. (ilutov)
. It is now possible to use reference assign on WeakMap without the key
Expand Down
6 changes: 6 additions & 0 deletions UPGRADING
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ PHP 8.6 UPGRADE NOTES
1. Backward Incompatible Changes
========================================

- Core:
. `$x instanceof object` previously always evaluated to false. It now
evaluates identically to `is_object($x)`, returning true for any object.

- DOM:
. Properties previously documented as @readonly (e.g. DOMNode::$nodeType,
DOMDocument::$xmlEncoding, DOMEntity::$actualEncoding, ::$encoding,
Expand Down Expand Up @@ -181,6 +185,8 @@ PHP 8.6 UPGRADE NOTES
========================================

- Core:
. `$x instanceof object` now evaluates like `is_object($x)`, correctly
returning true for any object.
. It is now possible to use reference assign on WeakMap without the key
needing to be present beforehand.
. It is now possible to define the `__debugInfo()` magic method on enums.
Expand Down
58 changes: 58 additions & 0 deletions Zend/tests/instanceof_object_pseudo_type.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
--TEST--
instanceof with pseudo-type "object" is equivalent to is_object()
--FILE--
<?php

// Objects
$obj = new stdClass;
var_dump($obj instanceof object);

$anon = new class {};
var_dump($anon instanceof object);

// Case-insensitive
var_dump($obj instanceof Object);
var_dump($obj instanceof OBJECT);

// Non-objects (variables, so they go through ZEND_TYPE_CHECK, not the const early-return)
$null = null;
var_dump($null instanceof object);

$int = 42;
var_dump($int instanceof object);

$str = "string";
var_dump($str instanceof object);

$arr = [];
var_dump($arr instanceof object);

// Must be identical to is_object() for any value
$values = [new stdClass, new class {}, null, 42, "str", [], true, 1.5];
foreach ($values as $v) {
if (($v instanceof object) !== is_object($v)) {
echo "MISMATCH for: ";
var_dump($v);
}
}
echo "All match is_object()\n";

// Inside a class scope — class context must not affect the result
class Foo {}
$foo = new Foo;
var_dump($foo instanceof object);
var_dump($foo instanceof Foo); // still works normally

?>
--EXPECT--
bool(true)
bool(true)
bool(true)
bool(true)
bool(false)
bool(false)
bool(false)
bool(false)
All match is_object()
bool(true)
bool(true)
9 changes: 9 additions & 0 deletions Zend/zend_compile.c
Original file line number Diff line number Diff line change
Expand Up @@ -11077,6 +11077,15 @@ static void zend_compile_instanceof(znode *result, zend_ast *ast) /* {{{ */
return;
}

/* "instanceof object" is equivalent to is_object(): emit a type-check instead of a class lookup */
if (class_ast->kind == ZEND_AST_ZVAL
&& Z_TYPE_P(zend_ast_get_zval(class_ast)) == IS_STRING
&& zend_string_equals_ci(zend_ast_get_str(class_ast), ZSTR_KNOWN(ZEND_STR_OBJECT))) {
opline = zend_emit_op_tmp(result, ZEND_TYPE_CHECK, &obj_node, NULL);
opline->extended_value = (1 << IS_OBJECT);
return;
}

zend_compile_class_ref(&class_node, class_ast,
ZEND_FETCH_CLASS_NO_AUTOLOAD | ZEND_FETCH_CLASS_EXCEPTION | ZEND_FETCH_CLASS_SILENT);

Expand Down
Loading