Re: [Discussion] is_string(), string type and objects implementing __toString()

From: Date: Wed, 08 Mar 2017 17:09:03 +0000
Subject: Re: [Discussion] is_string(), string type and objects implementing __toString()
References: 1 2 3 4 5 6 7  Groups: php.internals 
Request: Send a blank email to internals+get-98435@lists.php.net to get a copy of this message
On 3/8/2017 5:50 PM, Ryan Pallas wrote: > On Wed, Mar 8, 2017 at 9:50 AM, Ryan Pallas <derokorian@gmail.com> wrote: > >> >> >> On Wed, Mar 8, 2017 at 8:51 AM, Fleshgrinder <php@fleshgrinder.com> wrote: >> >>> Hey! :) >>> >>> The reference is actually not a problem for a Stringable because you >>> would get the "Only variables can be passed by reference" error with an >>> object if strict_types is enabled. >>> >>> Simply because the object **MUST** be converted into a string. The >>> object itself does not satisfy the constraint, but the object clearly >>> states that it can be converted into a string at any point. >>> >> >> This is the part I disagree with. The object clearly states that it can be >> turned into a string when you are done using it as a object. If it gets >> turned into a string, you can no longer use it as a object. >> >> There is a difference between changing an int to string and an object to >> string, in that afterwards the int->string can continue to be treated as an >> int afterwards, thanks to loose typing (otherwise it wouldn't have become a >> string in the first place). However with an object->string afterwards it >> can ONLY be treated as a string, it can no longer be treated as an object. >> Meaning >> >> $int = 3; >> foo(3); >> > Sorry this should have been: > foo($int); > >> var_dump(++$int); // 4, success, no errors >> >> $obj = new Foo('a'); >> foo($obj); >> var_dump($obj->method()); // Fatal error: call to member function method >> on string. >> >> To me, this doesn't make sense. >> >>> >>> Not doing so would violate what strict_types actually >>> promise us. ;) >>> >>> -- >>> Richard "Fleshgrinder" Fussenegger >>> >> >> > function foo(string &$s) { $s = 'foo'; } final class Stringable { public function __toString() { return 'stringable'; } } $stringable = new Stringable; foo($stringable); // Fatal error: Only variables can be passed by reference in ... $string = (string) $stringable; foo($string); // Heureka! Why is that? At the point where we reach the call foo($stringable) we need to perform various checks, which will lead to the conclusion that we require a string and that the value of $stringable is an object that can be converted to a string. That is exactly what we do. Hence, the call is not foo($stringable) but rather foo('stringable'), the value that we received from the conversion. The conversion is in place, just like a cast would be, hence ... foo((string) $stringable); ... is equivalent to ... foo($stringable); ... with a type constraint of string for that particular argument. Obviously we should yield another error message in such cases, to ensure that people are not confused. However, this is only about the logic. This means by implication that a ... function foo(stringable &$s) { } ... is impossible. Something we encounter a lot lately with many features that we would like to have. This is also one of the reasons why many higher languages do not support pointers in their type systems. -- Richard "Fleshgrinder" Fussenegger

« previous php.internals (#98435) next »