Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:92018 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 5071 invoked from network); 30 Mar 2016 09:36:25 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 30 Mar 2016 09:36:25 -0000 Authentication-Results: pb1.pair.com header.from=nikita.ppv@gmail.com; sender-id=pass Authentication-Results: pb1.pair.com smtp.mail=nikita.ppv@gmail.com; spf=pass; sender-id=pass Received-SPF: pass (pb1.pair.com: domain gmail.com designates 209.85.161.181 as permitted sender) X-PHP-List-Original-Sender: nikita.ppv@gmail.com X-Host-Fingerprint: 209.85.161.181 mail-yw0-f181.google.com Received: from [209.85.161.181] ([209.85.161.181:33425] helo=mail-yw0-f181.google.com) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id BF/53-24137-81E9BF65 for ; Wed, 30 Mar 2016 04:36:25 -0500 Received: by mail-yw0-f181.google.com with SMTP id h65so51091062ywe.0 for ; Wed, 30 Mar 2016 02:36:24 -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=rJKQXioCTiTYUTnBOwRRwLS0SOwdYEgUt3HDHFjxTzw=; b=C0G3sb2bPHZ/AnVArwNRa4T5P3F6DgABkvAk3gdsP4H5gvs645aoRaqEVhqGpEO4FW GbEaGVjhveIWr56uuDXPm8BLD4nHVFLJxvubdTo3toDrHTa3Fr9xYJiQ4hoa0k2nUyXV gii8syH0qD97aqOUCjQXTV6+c1Q7GWYJVE/FQk6muyqW5TQE8ZIUe2I3WpWq5xwwlXyH JwtJ/cl+dATo1swqY/Fd3D/qqbBEOU4StmfNQ6ZYPsWyRwTOycltLt1HLDQx9pnk6yHU 7olTbwGzu2Bh7oMgbPHHm+2NTV/0se4YV2XG2Z0g8idtgSzHPKrOhXLI3WKRxG0MN8ks BqBQ== 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=rJKQXioCTiTYUTnBOwRRwLS0SOwdYEgUt3HDHFjxTzw=; b=GK8cgermom/AwKe3gJRY2fvcYVRfwHzLzFDV7QQZP19Egtvyl9+vATZUZdOsabERwQ ySWSbynGKvx149+lA2TNO005o1ziFODUMSxZov90MCDiGgrix4VvQgcKwNMKN6ML9OEH vou0Px4TECqjqPlDUN02O8uH7xKZ5J7FtPgSOPerYUCHc7UurUH15RY8H5yhp7mygFUH ZNhHNQ/7p47QGqITbmnYyDgfU4asIomRSaYgiMlnu5bkkQpT+7N3FtEcQT5tDYszuiie wvT5YDbwSYumAfaoMmLG7GpXBoCMuAKh3o8dQcWfmRFvxUMsx7zAfZwg9tenOVAQHb28 H3JA== X-Gm-Message-State: AD7BkJK7Eya6nl+W32VuHrVW4FR9UzDHO5FmvyB95K2AXrPxK/765OH74oCHI1W5iQV3ksTJPqoFRHJryOeNLQ== MIME-Version: 1.0 X-Received: by 10.129.48.65 with SMTP id w62mr3770774yww.147.1459330582037; Wed, 30 Mar 2016 02:36:22 -0700 (PDT) Received: by 10.129.148.70 with HTTP; Wed, 30 Mar 2016 02:36:21 -0700 (PDT) In-Reply-To: References: Date: Wed, 30 Mar 2016 11:36:21 +0200 Message-ID: To: Chris Riley Cc: PHP internals Content-Type: multipart/alternative; boundary=001a11408754f3ce31052f40e0b2 Subject: Re: [PHP-DEV] Forbid binding methods to incompatible $this From: nikita.ppv@gmail.com (Nikita Popov) --001a11408754f3ce31052f40e0b2 Content-Type: text/plain; charset=UTF-8 On Wed, Mar 30, 2016 at 11:29 AM, Chris Riley wrote: > On 29 March 2016 at 23:21, Nikita Popov wrote: > >> Hi internals! >> >> Currently, inside instance methods the following invariant holds: >> >> assert(is_null($this) || is_object($this)) >> >> This is a problem. I'd like to guarantee the following invariant instead: >> >> assert(is_null($this) || $this instanceof self) >> >> That is, ensure that if $this is not null, then it must be an object >> "compatible" with the class, i.e. be in its inheritance hierarchy. >> >> The absence of this guarantee, apart from being a major WTF in itself, >> also >> prevents us from optimizing operations involving $this. In particular, the >> following optimizations are not possible: >> >> a) If typed properties land, we will not be able to use the type of >> $this->typedProperty for optimization, because $this->typedProperty might >> actually be referencing a property of a totally unrelated class. >> b) We are not able to early-bind arguments to private or final method >> calls, i.e. determine at compile-time whether an argument will use >> by-value >> or by-reference argument passing and optimize accordingly. >> c) We are not able to inline calls to private or final methods. (The >> possibility of null is an issue in this instance as well, though a lesser >> one.) >> >> The good news is that, as of PHP 7.0, we are *very* close to guaranteeing >> that "$this instanceof self" already. There exists only one little known >> loophole: Obtaining a closure object wrapping the method using >> ReflectionMethod::getClosure() and binding to an unrelated $this using >> Closure::bindTo(). >> >> In PHP 7.0 we already heavily cut down [1] on what bindTo() is to allowed >> to do on fake method closures. Namely, it was completely forbidden to >> rebind the scope of methods, as this was already interacting badly with >> optimizations in 7.0. We did not forbid binding to an incompatible $this >> because it was not yet causing immediate issues at the time. >> >> I'd like to remedy this oversight now and restrict $this binding of fake >> method closures to compatible contexts only, i.e. for a method A::foo() >> allow only instances of A or one of its descendant classes to be bound. >> This limitation already exists for fake method closures targeting internal >> methods. >> >> Are there any objections to this change? If not, I'll merge the patch [2]. >> If yes, I'll write an RFC, as this change, while of no direct consequence >> for PHP programmers, is important for the PHP implementation. >> >> Regards, >> Nikita >> >> [1]: http://markmail.org/message/sjihplebuwsmdwex >> [2]: >> https://github.com/php/php-src/compare/master...nikic:forbigIncompatThis >> > > > Hi, > > Will this patch break any use cases similar to: > > class Bar { > private $a = 'hidden'; > } > > $x = new Bar(); > $y = function() { return $this->a); > $z = $x->bindTo($x, $x); > echo $z(); //hidden > > ? > > If not, I have no objections. > Nope. Rebinding on "real" closures continues to work as usual, including using it to access private properties of objects. This change only affects closures created by ReflectionMethod::getClosure(), i.e. closures that are really methods in disguise. Nikita --001a11408754f3ce31052f40e0b2--