Bug #77336 [Opn->Nab]: objects with __toString() get destroyed when typehinted and passed by reference
Edit report at https://bugs.php.net/bug.php?id=77336&edit=1
ID: 77336
Updated by: nikic@php.net
Reported by: alex dot howansky at gmail dot com
Summary: objects with __toString() get destroyed when
typehinted and passed by reference
-Status: Open
+Status: Not a bug
Type: Bug
Package: Scripting Engine problem
Operating System: Ubuntu 16.04
PHP Version: 7.x
Block user comment: N
Private report: N
New Comment:
Per my above comment, this is working as intended and there's really no other way it can work
within weak typing semantics.
Previous Comments:
------------------------------------------------------------------------
[2018-12-22 10:36:45] cmb@php.net
If two() is not supposed to ever modify the passed argument, why
declare the parameter as by-reference, in the first place? If
two() may modify the passed argument, one cannot assume that $foo
will retain its value, anyway. Suggested reading:
<http://schlueters.de/blog/archives/125-Do-not-use-PHP-references.html>
------------------------------------------------------------------------
[2018-12-21 23:03:14] nikic@php.net
Type declarations ensure that the type of the parameter is correct on entry to the function,
possibly through use of a type coercion. In the case of references, the variable inside the function
and outside the function are the same, so the coercion also affects the value outside the function.
I think the only possible alternative behavior here would be to forbid type coercions entirely if
the parameter is a reference -- there is no way to only change the type inside the function, while
preserving the reference.
In any case, you can opt out of the type coercions by specifying declare(strict_types=1), as is good
practice to avoid these kinds of surprises. (And of course, best combined with not using
references...)
------------------------------------------------------------------------
[2018-12-21 22:47:13] alex dot howansky at gmail dot com
Description:
------------
If an object has a __toString() method and is passed to a function as a parameter that is typehinted
to string and passed by reference, then the object gets destroyed and replaced with the string.
Without the typehint, the object passed by reference remains intact. Defining a typehint on a
function's parameter should not impact the calling code beyond raising a TypeError exception.
Test script:
---------------
function one(&$str) { }
function two(string &$str) { }
class Foo {
public function __toString() { return ''; }
}
$foo = new Foo();
echo gettype($foo); // object
one($foo);
echo gettype($foo); // object
two($foo);
echo gettype($foo); // string
Expected result:
----------------
The passed object should not be destroyed. The typehint should be used only to verify that the
parameter meets a requirement, not to actively change its type.
In addition, if overwriting the object is determined to be the correct behavior, then I feel it
should at least raise an E_NOTICE when changing a variable's type.
------------------------------------------------------------------------
--
Edit this bug report at https://bugs.php.net/bug.php?id=77336&edit=1
Thread (4 messages)