Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:98435 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 40983 invoked from network); 8 Mar 2017 17:09:13 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 8 Mar 2017 17:09:13 -0000 Authentication-Results: pb1.pair.com header.from=php@fleshgrinder.com; sender-id=unknown Authentication-Results: pb1.pair.com smtp.mail=php@fleshgrinder.com; spf=permerror; sender-id=unknown Received-SPF: error (pb1.pair.com: domain fleshgrinder.com from 77.244.243.83 cause and error) X-PHP-List-Original-Sender: php@fleshgrinder.com X-Host-Fingerprint: 77.244.243.83 mx102.easyname.com Received: from [77.244.243.83] ([77.244.243.83:36446] helo=mx102.easyname.com) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id 03/19-06022-8BA30C85 for ; Wed, 08 Mar 2017 12:09:13 -0500 Received: from cable-81-173-135-7.netcologne.de ([81.173.135.7] helo=[192.168.178.20]) by mx.easyname.com with esmtpsa (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.84_2) (envelope-from ) id 1clf5I-0000kB-Gs; Wed, 08 Mar 2017 17:09:10 +0000 Reply-To: internals@lists.php.net References: <996dc359-cbc1-1c76-dacc-f748d0941aa6@fleshgrinder.com> To: Ryan Pallas , "internals@lists.php.net" Cc: Andrey Andreev Message-ID: <769ccce3-5d17-e674-cc7c-e8dae05fc36b@fleshgrinder.com> Date: Wed, 8 Mar 2017 18:09:03 +0100 User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:45.0) Gecko/20100101 Thunderbird/45.8.0 MIME-Version: 1.0 In-Reply-To: Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 7bit X-DNSBL-PBLSPAMHAUS: YES Subject: Re: [PHP-DEV] [Discussion] is_string(), string type and objects implementing __toString() From: php@fleshgrinder.com (Fleshgrinder) On 3/8/2017 5:50 PM, Ryan Pallas wrote: > On Wed, Mar 8, 2017 at 9:50 AM, Ryan Pallas wrote: > >> >> >> On Wed, Mar 8, 2017 at 8:51 AM, Fleshgrinder 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