Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:91819 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 17775 invoked from network); 21 Mar 2016 17:05:56 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 21 Mar 2016 17:05:56 -0000 Authentication-Results: pb1.pair.com smtp.mail=nikita.ppv@gmail.com; spf=pass; sender-id=pass Authentication-Results: pb1.pair.com header.from=nikita.ppv@gmail.com; sender-id=pass Received-SPF: pass (pb1.pair.com: domain gmail.com designates 209.85.161.170 as permitted sender) X-PHP-List-Original-Sender: nikita.ppv@gmail.com X-Host-Fingerprint: 209.85.161.170 mail-yw0-f170.google.com Received: from [209.85.161.170] ([209.85.161.170:32983] helo=mail-yw0-f170.google.com) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id FF/10-16266-3F920F65 for ; Mon, 21 Mar 2016 12:05:56 -0500 Received: by mail-yw0-f170.google.com with SMTP id h65so79580730ywe.0 for ; Mon, 21 Mar 2016 10:05:55 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:in-reply-to:references:date:message-id:subject:from:to :cc; bh=/3XRqINVheYDmgWfupBdJUS+OLckXxEwLco20Ptf8Gs=; b=jMAooHxSVtvv1SqbpIqNRUKdvodIMQ68iBJHeOTNXLg1Vf35sZTeaU0qoi+Iw/IqSY SbL8EDvk9wJ0vYrzEEKD9kaBkOErQH/e8GCS9K+oIMtkhS5qrJslNR6YbEpWCQ7LKaC4 XQNFlT1PqdXrCdxOqq9e6/hmVxljqKeFWdCgk9bSKa+fP4XVanMaLIWp8qql2KF4+K7R GD+ENKpOBXyxcH9jqCAUrfPkETmxydYzyLK4LZ7q5wZV2q8cxmp5Z4S449FNggE4jPH9 Cef1M9QPm8PE8UqI+nVJr6zPQrcRlXUu6mgzCT66//1JvYQlhfP/Jyd9tng2m7TKPAzj BjBw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:in-reply-to:references:date :message-id:subject:from:to:cc; bh=/3XRqINVheYDmgWfupBdJUS+OLckXxEwLco20Ptf8Gs=; b=j6geEHKUgOhnyBdt99HQ0KirYCUHPPkYcUUvHfGw2EPLn5NDuvcaoPP0wAF0oGajSq cutwKyX1qXYLVLc3maGXSg0NT7P8yoxU8KyYI2NWi4k1UOIZuH2XYeRGibnBO8d9/SHn +HYn+1fnGMWwxWJGjTgJHIjiqq3xZqWh01fwq7OgvQxLlx3XD/+sh1jF0GPQ1GJrMtfF gfOTzfUAf1UxisZkLLVajW8fp78QW7XY7dgUNlDV0deaW6YT675ozyacbswPA9Ci9VZO eppDJ7l/SA7MtmMkx8M/GRgSCwec2tlaDnqXPV2KwUsmcN3NPWd/mD+rk5T9L5vrJxkZ x8pA== X-Gm-Message-State: AD7BkJKcXCcZlsJPtNLxw5oh4BkiCUu8a9h883Q4X6l3ahzzbwENlamHwFfJGCWHNz2cmzMVhXvvJEceaNV5Lw== MIME-Version: 1.0 X-Received: by 10.37.19.66 with SMTP id 63mr15022635ybt.75.1458579952426; Mon, 21 Mar 2016 10:05:52 -0700 (PDT) Received: by 10.129.148.70 with HTTP; Mon, 21 Mar 2016 10:05:52 -0700 (PDT) In-Reply-To: <56F01545.8080008@gmail.com> References: <1458149992.3969.2.camel@kuechenschabe> <1458151531.3969.8.camel@kuechenschabe> <1458153695.3969.16.camel@kuechenschabe> <3F.70.02405.6803BE65@pb1.pair.com> <56F01545.8080008@gmail.com> Date: Mon, 21 Mar 2016 18:05:52 +0100 Message-ID: To: Rowan Collins Cc: PHP internals Content-Type: multipart/alternative; boundary=001a113e436ef0e3ca052e921b72 Subject: Re: [PHP-DEV] [RFC Discussion] Typed Properties From: nikita.ppv@gmail.com (Nikita Popov) --001a113e436ef0e3ca052e921b72 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: quoted-printable On Mon, Mar 21, 2016 at 4:37 PM, Rowan Collins wrote: > Andrea Faulds wrote on 17/03/2016 22:32: > >> Hi Johannes, >> >> Johannes Schl=C3=BCter wrote: >> >>> On Wed, 2016-03-16 at 19:15 +0100, Bob Weinand wrote: >>> >>>> >>>> Eih, only to typed properties. Everything else would be insane ;-) >>>> Sorry for being imprecise. >>>> >>> >>> Ok, quite a lot better, but still weird difference to the language. >>> >>> >>> There's a notable amount of places where references are being used and >>> often users aren't aware. (Binding parameters in database queries, in >>> order to support OUT parameters, comes to mind, many array functions >>> take an array, some functions use it to report error codes, ...) >>> >>> I guess this will be a famous support issue. >>> >>> And yeah, I'd love to "fix" all those places and get rid of the >>> references, but BC ... it's quite massive :-) >>> >>> >> Disallowing references here might make users more aware of which >> functions take parameters by reference, and avoid accidentally modifying >> values. So this part of the RFC might be a good thing. >> > > > I'm not a fan of this kind of side-effect coupling - "because this featur= e > is new, it also triggers other new features". If you want no-ref > properties, that should be something a user chooses directly, e.g. "class > Foo { public noref $bar; }". > > Adding an "array" typehint to something absolutely should not prevent it > being passed to sort(), IMHO. > > Perhaps we could have an IS_TYPED_REF zval? You don't actually need to > store the desired type, only assert that the old and new reference target= s > are of the *same* type when performing assignment. > While it is no secret that we don't particularly like references, this is not the reason why they are forbidden. There is no conspiracy to punish users of references by denying them use of new typing features. No, the reasons here are technical. Let me illustrate some of the issues involved in more detail. Lets start with some more "conceptual" issue. Consider this code: class Foo { public int $bar =3D 42; } $foo =3D new Foo; $bar =3D& $foo->bar; unset($foo); $bar =3D "xyz"; How does this code behave? The assignment $bar =3D "xyz" violates the "int" typehint. However, the object those typed property we're referencing has already been destroyed. Is the reference still typed or not? If you answered "yes" to this question, consider an additional fact: It is an implementation invariant that a reference with refcount 1 can be converted to a value (a reference-set containing a single variable has value semantics). The places where this happens or does not happens are not evident to userland developers. The above code would throw, but if you inserted a switch on $bar before hand it wouldn't. Wat? If you answered "no" to this question, also consider another issue: In the above example, the point where $foo is destroyed is clear. But what if the destruction is actually triggered by a garbage collection run? As its not possible to predict when garbage collection runs, you may have two directly consecutive and identical statements, one of which throws, while the other doesn't. (Not even to mention how impractical it is to track the destruction of the object those property you're referencing.) That's one issue. Another problem is related to "spooky action at a distance". If you deal with parameter types or typed properties, you know what you're in for. If you know the type of the object, you know what type is expected. With references, this is generally not the case. You do not know where the reference is coming from originally and what type constraint it might have. Unless we actually keep track of which typed property a reference is associated with (and maybe also where in the code it was taken), you couldn't even know *why* you're getting a type error. Now, for the most part, references in PHP are fairly explicit. You need to include a & sigil during assignment and argument passing. You could argue that, if you see that you're accepting an argument by reference, you just have to take the possibility of it being typed into account. However, this is simply not true. While references are mostly explicit, they aren't always. If you create an array $array =3D [&$foo->bar] and then pass around that array *by value*, $array[0] will still be a reference. This means that an $array[0] =3D "xyz" assignment, in a piece of code that does not itself use references in any way, can still end up with a type error. Typed references are a ticking time bomb. They contagiously pervade through the code and may go off at any point. Any point at all, even if it doesn't visibly involve references. Now, these are some of the "conceptual" issues. Even discounting them, we'd still be up against a large purely implementational problem if we wanted to support typed references. Your suggestion of using IS_TYPED_REF that just checks if the type of the new value matches with that of the existing value will fail in the presence of object types, as they are instanceof based. We would have to store the desired type of the value. For debugging purposes at least, we'd likely also store the class and property enforcing the constraint. This constraint would need to be enforced in all places that might possibly assign to a reference. For the places in the virtual machine, we could manage. There's a limited (albeit large) number of places where reference assignments can occur and we could add checks to them (even though ensuring that existing code does not performance regress might be non-trivial). But reference assignments happen not only in the engine. We have a large body of extension code that assumes you can change a reference just by writing into a zval. PHP 7 contained a large change to the way references are handled, and we are *still* finding new places (even in bundled extension code) that haven't been updated. Changing these kinds of fundamental assumptions always has fallout. As things stand now, you essentially have a choice between typed properties without reference for PHP 7.1, or typed properties with references for PHP 9.0. I'd also like to note that it is always possible to add support for references at a later point in time, should we find a good way of dealing with them. Thanks, Nikita --001a113e436ef0e3ca052e921b72--