Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:91998 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 38640 invoked from network); 29 Mar 2016 22:21:50 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 29 Mar 2016 22:21:50 -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.172 as permitted sender) X-PHP-List-Original-Sender: nikita.ppv@gmail.com X-Host-Fingerprint: 209.85.161.172 mail-yw0-f172.google.com Received: from [209.85.161.172] ([209.85.161.172:34245] helo=mail-yw0-f172.google.com) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id F1/88-24137-DFFFAF65 for ; Tue, 29 Mar 2016 17:21:49 -0500 Received: by mail-yw0-f172.google.com with SMTP id h129so37072284ywb.1 for ; Tue, 29 Mar 2016 15:21:49 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:date:message-id:subject:from:to; bh=wVRP+KQ2x09WAj8NRYXT7XXuqupb2KyBz2/UtwyM90Y=; b=KVR/Rqz5LJ7JRxpIQXB8oJh1mrH1pginDXO1SRdSSfnaDM8FdRUvE80zLkOGVgQxe2 LuKQ447JYaA9qRPAGKJjsyu+8SidMqMfq6P+PD1MEKUoP+crX7Tjc6A25vMkqrGlqOT5 YscIJ8H6OVjwtiSlrQ1EoUrbGQ3Gwl2aBNvmWn60z3lAhepHgbM4qf35Bb8XdB5qopKB 4Bhe9NlhSQUWVe13Ssjc2nWLn8mfudWkUCfOgC92i/jwS8N4gGzaF0+06Cz4wP4dKjYQ QWaWA87kv+nKj5yt8/HIIhuBnDLulKlQDJSXk+7C5kl3qYaAq8+McGRqiLdoTkdlZlyi L0AA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:date:message-id:subject:from:to; bh=wVRP+KQ2x09WAj8NRYXT7XXuqupb2KyBz2/UtwyM90Y=; b=nKhcX1q7K/y4R2cl0a0rlfRa/MHHFnrCXRHYyMOR++tpdniQR8WhfPGy/fYBLLoo6H k8VvtN1sZxiMSPSTH7MBckRB2pb0WO1aAr0V5fp0cwYG53BBVLKsHXcjkGFL16HCG22W 232OdCUjHhPXIq6Ayl/PNqpLZmQub4iKBW5g5gEqGNT2u1mX0GwDLvbeOYJ2gFjEILI6 Y51AKu8TpbTqOehQS8E8rEJnfFRaCusAwdjrq5w0g0ncZZyUlWtLnijQskaGcw1xXBob zfdMFqwXV3sJBfNlSqhY/pMIjob9pJ5q+T/1e0z5Ps//K7Xptc76KWIxE1/GmSR+GkiE sG9A== X-Gm-Message-State: AD7BkJLCejdXbjCQ4pltrO+qgVuemFzeniOaysLsNw0s3Uh6ctwzrnuSlLi/PFdEwlTyfBPP9KgT3KhXryXitQ== MIME-Version: 1.0 X-Received: by 10.129.148.2 with SMTP id l2mr2326363ywg.298.1459290106429; Tue, 29 Mar 2016 15:21:46 -0700 (PDT) Received: by 10.129.148.70 with HTTP; Tue, 29 Mar 2016 15:21:46 -0700 (PDT) Date: Wed, 30 Mar 2016 00:21:46 +0200 Message-ID: To: PHP internals Content-Type: multipart/alternative; boundary=94eb2c07b5166b0abb052f37746b Subject: Forbid binding methods to incompatible $this From: nikita.ppv@gmail.com (Nikita Popov) --94eb2c07b5166b0abb052f37746b Content-Type: text/plain; charset=UTF-8 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 --94eb2c07b5166b0abb052f37746b--