Skip to content
Merged
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
1 change: 1 addition & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ PHP NEWS
. Enacted the follow-up phase of the "Path to Saner Increment/Decrement
operators" RFC, meaning that incrementing non-numeric strings is now
deprecated. (Girgias).
. Various closure binding issues are now deprecated. (alexandre-daubois)

- Filter:
. Added support for configuring the URI parser for FILTER_VALIDATE_URL
Expand Down
10 changes: 10 additions & 0 deletions UPGRADING
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,16 @@ PHP 8.5 UPGRADE NOTES
operators" RFC, meaning that incrementing non-numeric strings is now
deprecated. Instead the str_increment() function should be used.
RFC: https://wiki.php.net/rfc/deprecations_php_8_5#enact_follow-up_phase_of_the_path_to_saner_incrementdecrement_operators_rfc
. The following closure binding issues, which already emit an E_WARNING, are
now deprecated:
- Binding an instance to a static closure
- Binding methods to objects that are not instances of the class
(or subclass) that the method is defined
- Unbinding $this from a method
- Unbinding $this from a closure that uses `$this`
- Binding a closure to the scope of an internal class
- Rebinding the scope of a closure created from a function or method
RFC: https://wiki.php.net/rfc/deprecations_php_8_5#deprecate_closure_binding_issues

- Curl:
. The curl_close() function has been deprecated, as CurlHandle objects are
Expand Down
2 changes: 1 addition & 1 deletion Zend/tests/bug70681.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,5 @@ var_dump($c("foo"));

?>
--EXPECTF--
Warning: Cannot unbind $this of method in %s on line %d
Warning: Cannot unbind $this of method, this will be an error in PHP 9 in %s on line %d
int(3)
2 changes: 1 addition & 1 deletion Zend/tests/closures/bug70630.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,4 @@ $x = (new ReflectionFunction("substr"))->getClosure();
$x->call(new a);
?>
--EXPECTF--
Warning: Cannot rebind scope of closure created from function in %s on line %d
Warning: Cannot rebind scope of closure created from function, this will be an error in PHP 9 in %s on line %d
4 changes: 2 additions & 2 deletions Zend/tests/closures/bug70685.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ var_dump($c);

?>
--EXPECTF--
Warning: Cannot bind method SplDoublyLinkedList::count() to object of class cls in %s on line %d
Warning: Cannot bind method SplDoublyLinkedList::count() to object of class cls, this will be an error in PHP 9 in %s on line %d
NULL

Warning: Cannot rebind scope of closure created from method in %s on line %d
Warning: Cannot rebind scope of closure created from method, this will be an error in PHP 9 in %s on line %d
NULL
2 changes: 1 addition & 1 deletion Zend/tests/closures/closure_040.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,4 @@ $cas->bindTo($a, 'A');
--EXPECTF--
Closure::bindTo(): Argument #2 ($newScope) must be of type object|string|null, array given

Warning: Cannot bind an instance to a static closure in %s on line %d
Warning: Cannot bind an instance to a static closure, this will be an error in PHP 9 in %s on line %d
6 changes: 3 additions & 3 deletions Zend/tests/closures/closure_041.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -80,16 +80,16 @@ bound: no
scoped to A: bool(true)
bound: no

Warning: Cannot unbind $this of closure using $this in %s on line %d
Warning: Cannot unbind $this of closure using $this, this will be an error in PHP 9 in %s on line %d
NULL

After binding, with same-class instance for the bound ones

Warning: Cannot bind an instance to a static closure in %s on line %d
Warning: Cannot bind an instance to a static closure, this will be an error in PHP 9 in %s on line %d
scoped to A: bool(false)
bound: A (should be scoped to dummy class)

Warning: Cannot bind an instance to a static closure in %s on line %d
Warning: Cannot bind an instance to a static closure, this will be an error in PHP 9 in %s on line %d
scoped to A: bool(true)
bound: A
After binding, with different instance for the bound ones
Expand Down
8 changes: 4 additions & 4 deletions Zend/tests/closures/closure_043.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,9 @@ bool(false)

After binding, null scope, with instance

Warning: Cannot bind an instance to a static closure in %s on line %d
Warning: Cannot bind an instance to a static closure, this will be an error in PHP 9 in %s on line %d

Warning: Cannot bind an instance to a static closure in %s on line %d
Warning: Cannot bind an instance to a static closure, this will be an error in PHP 9 in %s on line %d
After binding, with scope, no instance
bool(true)
bool(false)
Expand All @@ -68,7 +68,7 @@ bool(false)

After binding, with scope, with instance

Warning: Cannot bind an instance to a static closure in %s on line %d
Warning: Cannot bind an instance to a static closure, this will be an error in PHP 9 in %s on line %d

Warning: Cannot bind an instance to a static closure in %s on line %d
Warning: Cannot bind an instance to a static closure, this will be an error in PHP 9 in %s on line %d
Done.
4 changes: 2 additions & 2 deletions Zend/tests/closures/closure_044.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ bool(false)
bool(false)


Warning: Cannot unbind $this of closure using $this in %s on line %d
Warning: Cannot unbind $this of closure using $this, this will be an error in PHP 9 in %s on line %d
NULL

After binding, null scope, with instance
Expand All @@ -67,7 +67,7 @@ bool(true)
bool(false)


Warning: Cannot unbind $this of closure using $this in %s on line %d
Warning: Cannot unbind $this of closure using $this, this will be an error in PHP 9 in %s on line %d
NULL

After binding, with scope, with instance
Expand Down
2 changes: 1 addition & 1 deletion Zend/tests/closures/closure_046.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ bool(false)
bool(false)


Warning: Cannot unbind $this of closure using $this in %s on line %d
Warning: Cannot unbind $this of closure using $this, this will be an error in PHP 9 in %s on line %d
NULL

After binding, with same-class instance for the bound one
Expand Down
44 changes: 22 additions & 22 deletions Zend/tests/closures/closure_061.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -118,13 +118,13 @@ bindTo(new Cls, null):
Success!

bindTo(new Cls, Cls::class):
Cannot rebind scope of closure created from function
Cannot rebind scope of closure created from function, this will be an error in PHP 9

bindTo(null, Cls::class):
Cannot rebind scope of closure created from function
Cannot rebind scope of closure created from function, this will be an error in PHP 9

bindTo(null, stdClass::class):
Cannot bind closure to scope of internal class stdClass
Cannot bind closure to scope of internal class stdClass, this will be an error in PHP 9

bindTo(new stdClass, null):
Success!
Expand All @@ -139,13 +139,13 @@ bindTo(new Cls, null):
Success!

bindTo(new Cls, Cls::class):
Cannot rebind scope of closure created from function
Cannot rebind scope of closure created from function, this will be an error in PHP 9

bindTo(null, Cls::class):
Cannot rebind scope of closure created from function
Cannot rebind scope of closure created from function, this will be an error in PHP 9

bindTo(null, stdClass::class):
Cannot bind closure to scope of internal class stdClass
Cannot bind closure to scope of internal class stdClass, this will be an error in PHP 9

bindTo(new stdClass, null):
Success!
Expand All @@ -157,25 +157,25 @@ bindTo(null, Cls::class):
Success!

bindTo(new Cls, null):
Cannot bind an instance to a static closure
Cannot bind an instance to a static closure, this will be an error in PHP 9

bindTo(new Cls, Cls::class):
Cannot bind an instance to a static closure
Cannot bind an instance to a static closure, this will be an error in PHP 9

bindTo(null, null):
Cannot rebind scope of closure created from method
Cannot rebind scope of closure created from method, this will be an error in PHP 9

bindTo(null, ClsChild::class):
Cannot rebind scope of closure created from method
Cannot rebind scope of closure created from method, this will be an error in PHP 9

bindTo(null, ClsUnrelated::class):
Cannot rebind scope of closure created from method
Cannot rebind scope of closure created from method, this will be an error in PHP 9

(new Cls)->method()
-------------------

bindTo(null, Cls::class):
Cannot unbind $this of method
Cannot unbind $this of method, this will be an error in PHP 9

bindTo(new Cls, Cls::class):
Success!
Expand All @@ -184,16 +184,16 @@ bindTo(new ClsChild, Cls::class):
Success!

bindTo(new ClsUnrelated, Cls::class):
Cannot bind method Cls::method() to object of class ClsUnrelated
Cannot bind method Cls::method() to object of class ClsUnrelated, this will be an error in PHP 9

bindTo(new Cls, null):
Cannot rebind scope of closure created from method
Cannot rebind scope of closure created from method, this will be an error in PHP 9

bindTo(new Cls, ClsUnrelated::class):
Cannot rebind scope of closure created from method
Cannot rebind scope of closure created from method, this will be an error in PHP 9

bindTo(new Cls, ClsChild::class):
Cannot rebind scope of closure created from method
Cannot rebind scope of closure created from method, this will be an error in PHP 9

(new SplDoublyLinkedList)->count()
----------------------------------
Expand All @@ -205,19 +205,19 @@ bindTo(new SplStack, SplDoublyLinkedList::class):
Success!

bindTo(new ClsUnrelated, SplDoublyLinkedList::class):
Cannot bind method SplDoublyLinkedList::count() to object of class ClsUnrelated
Cannot bind method SplDoublyLinkedList::count() to object of class ClsUnrelated, this will be an error in PHP 9

bindTo(null, null):
Cannot unbind $this of method
Cannot unbind $this of method, this will be an error in PHP 9

bindTo(null, SplDoublyLinkedList::class):
Cannot unbind $this of method
Cannot unbind $this of method, this will be an error in PHP 9

bindTo(new SplDoublyLinkedList, null):
Cannot rebind scope of closure created from method
Cannot rebind scope of closure created from method, this will be an error in PHP 9

bindTo(new SplDoublyLinkedList, ClsUnrelated::class):
Cannot rebind scope of closure created from method
Cannot rebind scope of closure created from method, this will be an error in PHP 9

(function() {})()
-----------------
Expand All @@ -235,7 +235,7 @@ bindTo(null, Cls::class):
Success!

bindTo(null, stdClass::class):
Cannot bind closure to scope of internal class stdClass
Cannot bind closure to scope of internal class stdClass, this will be an error in PHP 9

bindTo(new stdClass, null):
Success!
2 changes: 1 addition & 1 deletion Zend/tests/closures/closure_062.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ Test::staticMethod();
--EXPECTF--
instance scoped, non-static, $this used

Warning: Cannot unbind $this of closure using $this in %s on line %d
Warning: Cannot unbind $this of closure using $this, this will be an error in PHP 9 in %s on line %d
instance scoped, static, $this used
instance scoped, non-static, $this not used
static scoped, non-static, $this used
Expand Down
2 changes: 1 addition & 1 deletion Zend/tests/closures/closure_call.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ int(0)
int(0)
int(3)

Warning: Cannot bind closure to scope of internal class stdClass in %s line %d
Warning: Cannot bind closure to scope of internal class stdClass, this will be an error in PHP 9 in %s line %d
NULL
int(21)
int(3)
2 changes: 1 addition & 1 deletion Zend/tests/closures/closure_from_callable_rebinding.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,4 @@ $fn->call(new B);

?>
--EXPECTF--
Warning: Cannot bind method A::method() to object of class B in %s on line %d
Warning: Cannot bind method A::method() to object of class B, this will be an error in PHP 9 in %s on line %d
14 changes: 7 additions & 7 deletions Zend/zend_closures.c
Original file line number Diff line number Diff line change
Expand Up @@ -81,41 +81,41 @@ static bool zend_valid_closure_binding(
bool is_fake_closure = (func->common.fn_flags & ZEND_ACC_FAKE_CLOSURE) != 0;
if (newthis) {
if (func->common.fn_flags & ZEND_ACC_STATIC) {
zend_error(E_WARNING, "Cannot bind an instance to a static closure");
zend_error(E_WARNING, "Cannot bind an instance to a static closure, this will be an error in PHP 9");
return 0;
}

if (is_fake_closure && func->common.scope &&
!instanceof_function(Z_OBJCE_P(newthis), func->common.scope)) {
/* Binding incompatible $this to an internal method is not supported. */
zend_error(E_WARNING, "Cannot bind method %s::%s() to object of class %s",
zend_error(E_WARNING, "Cannot bind method %s::%s() to object of class %s, this will be an error in PHP 9",
ZSTR_VAL(func->common.scope->name),
ZSTR_VAL(func->common.function_name),
ZSTR_VAL(Z_OBJCE_P(newthis)->name));
return 0;
}
} else if (is_fake_closure && func->common.scope
&& !(func->common.fn_flags & ZEND_ACC_STATIC)) {
zend_error(E_WARNING, "Cannot unbind $this of method");
zend_error(E_WARNING, "Cannot unbind $this of method, this will be an error in PHP 9");
return 0;
} else if (!is_fake_closure && !Z_ISUNDEF(closure->this_ptr)
&& (func->common.fn_flags & ZEND_ACC_USES_THIS)) {
zend_error(E_WARNING, "Cannot unbind $this of closure using $this");
zend_error(E_WARNING, "Cannot unbind $this of closure using $this, this will be an error in PHP 9");
return 0;
}

if (scope && scope != func->common.scope && scope->type == ZEND_INTERNAL_CLASS) {
/* rebinding to internal class is not allowed */
zend_error(E_WARNING, "Cannot bind closure to scope of internal class %s",
zend_error(E_WARNING, "Cannot bind closure to scope of internal class %s, this will be an error in PHP 9",
ZSTR_VAL(scope->name));
return 0;
}

if (is_fake_closure && scope != func->common.scope) {
if (func->common.scope == NULL) {
zend_error(E_WARNING, "Cannot rebind scope of closure created from function");
zend_error(E_WARNING, "Cannot rebind scope of closure created from function, this will be an error in PHP 9");
} else {
zend_error(E_WARNING, "Cannot rebind scope of closure created from method");
zend_error(E_WARNING, "Cannot rebind scope of closure created from method, this will be an error in PHP 9");
}
return 0;
}
Expand Down
12 changes: 7 additions & 5 deletions docs/source/miscellaneous/stubs.rst
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,8 @@ The generated ``class_Atmosphere_methods`` must be used when registering the ``A

Additional meta information can be attached to functions, with the following PHPDoc tags:

- ``@deprecated``: Triggers the usual deprecation notice when the function/method is called.
- ``@deprecated``: Triggers the usual deprecation notice when the function/method is called. As of
PHP 8.4 the `#[Deprecated]` attribute should be used instead.

- ``@alias``: If a function/method is an alias of another function/method, then the aliased
function/method name has to be provided as value. E.g. the function ``sizeof()`` has the ``@alias
Expand All @@ -244,7 +245,7 @@ Additional meta information can be attached to functions, with the following PHP

- ``@genstubs-expose-comment-block``: By adding this annotation at the beginning of a PHPDoc block,
the content of the PHPDoc block will be exposed for
`ReflectionFunctionAbstract::getDocComment()`. This feature was added in PHP 8.4.0.
`ReflectionFunctionAbstract::getDocComment()`. This feature was added in PHP 8.4.

.. _tentative return type: https://wiki.php.net/rfc/internal_method_return_types

Expand Down Expand Up @@ -337,7 +338,7 @@ Like functions and methods, classes also support meta information passed via PHP

- ``@genstubs-expose-comment-block``: By adding this tag at the beginning of a PHPDoc block, the
content of the PHPDoc block will be exposed for `ReflectionClass::getDocComment()`. This feature
is only available as of PHP 8.4.0.
is only available as of PHP 8.4.

This is an example with all the flags:

Expand Down Expand Up @@ -452,11 +453,12 @@ with ``@cvalue M_PI`` to the C-level constant ``M_PI`` (define by PHP's internal

Constants can take the following extra meta information passed via PHPDoc tags:

- ``@deprecated``: Triggers a deprecation notice when the constant is used.
- ``@deprecated``: Triggers a deprecation notice when the constant is used. As of PHP 8.5 the
`#[Deprecated]` attribute should be used instead.

- ``@genstubs-expose-comment-block``: By adding this tag at the beginning of a PHPDoc block, the
content of the PHPDoc block will be exposed for `ReflectionClass::getDocComment()`. This feature
is only available as of PHP 8.4.0.
is only available as of PHP 8.4.

************************************
Maintaining Backward Compatibility
Expand Down