Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:108950 Return-Path: Delivered-To: mailing list internals@lists.php.net Received: (qmail 3536 invoked from network); 10 Mar 2020 16:13:01 -0000 Received: from unknown (HELO php-smtp4.php.net) (45.112.84.5) by pb1.pair.com with SMTP; 10 Mar 2020 16:13:01 -0000 Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id 008001804E6 for ; Tue, 10 Mar 2020 07:33:56 -0700 (PDT) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on php-smtp4.php.net X-Spam-Level: X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_FROM,HTML_MESSAGE, RCVD_IN_DNSWL_NONE,SPF_HELO_NONE,SPF_PASS autolearn=no autolearn_force=no version=3.4.2 X-Spam-ASN: AS15169 209.85.128.0/17 X-Spam-Virus: No X-Envelope-From: Received: from mail-lj1-f171.google.com (mail-lj1-f171.google.com [209.85.208.171]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange ECDHE (P-256) server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by php-smtp4.php.net (Postfix) with ESMTPS for ; Tue, 10 Mar 2020 07:33:55 -0700 (PDT) Received: by mail-lj1-f171.google.com with SMTP id a10so14351802ljp.11 for ; Tue, 10 Mar 2020 07:33:55 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=mime-version:from:date:message-id:subject:to; bh=1J6i3r+TTZKObDNrwAoBncqYX0Xe5tT6psyRCibA340=; b=N62MZfsVC9L+svpIz99sZ1gUoSUlm+fZKKiQxMWShBcjfvSj8ocHQoY1KmmRQ5m79n qXr/CtrgwP+fWvoJ7QS1nhYQDEIGTckzqw8PfvkBpkw89FoWWZb0op5euIKvvofp+gXX QW+SlCSPO7acb4D21/EwTdMnjqEcAkXGtM8HR7mPbcKEw4Q4bgkpG1OWk9FixDMmGXVV aO0iY0zxAxwUv6LpYR4lS4s5Zai8HY3guzPs2prYXd4hZAHYfEwZefxIfj+w+xJFlG9P MBlkLlAosGPtpuQrXDCSSOEVs1kXUJeXETb4kWjFBhm419rVNecZFFFX9cdj8ix4Nd+b qI0g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:from:date:message-id:subject:to; bh=1J6i3r+TTZKObDNrwAoBncqYX0Xe5tT6psyRCibA340=; b=KRnGLrtYQLqCYj4njekB6J6rh8EloVwc4BxRt3f1wyGZBhUoKpkBxkDT36bRJlIadx 7x25ps55Zw+lee5OovKXKIlaVzpAMoDsayt2MhNCen6m4hZSxzVGBiKSAkqmPtvYDDvc EizZzZ1q34+xvbebLPRbnpEyQKN270EHo+YMiecQVUbACSHeFGJmKca+vNnG7lbVf4FG L/VhjsvfV7O/UAwEVyJriSiTqAKMjFCG/KOT5UsTFRzEJR9v7mCT3y7mLqo4fbgsQ5qr mHP7o9lnKqi2V07z5o5NuvJv54rMjFiB1KnDVCgUkXbNU4PfTswQb/crS2Y7MZA2xNd6 AWKQ== X-Gm-Message-State: ANhLgQ3DsWKirJiScsXzLnZDiiBsdQmUCKUh/ox67wCqfZ/4fwh0iKuY 0DJlaybT64V+O5AxuC7suVmHQpV5gHI87cWzc+kjuJNO77U= X-Google-Smtp-Source: ADFU+vsjXIaPylWlXYUsEQI4Q5sAE2E3HEgu+LV50OxW+J4PmE4ezdlDBYsY0L9vE0mQo0iv+qvWtHmCdsbviHAhgB0= X-Received: by 2002:a2e:7806:: with SMTP id t6mr13171618ljc.145.1583850832914; Tue, 10 Mar 2020 07:33:52 -0700 (PDT) MIME-Version: 1.0 Date: Tue, 10 Mar 2020 15:33:37 +0100 Message-ID: To: PHP internals Content-Type: multipart/alternative; boundary="00000000000045f25e05a081023b" Subject: Fixing fetch mode for object property access (SimpleXML auto-vivification breakage) From: nikita.ppv@gmail.com (Nikita Popov) --00000000000045f25e05a081023b Content-Type: text/plain; charset="UTF-8" Hi internals, While reviewing the RFC for read-only properties, I encountered the following long-standing issue once again: $foo->bar->baz = 42; should be the same as $bar = $foo->bar; $bar->baz = 42; but isn't, because the "$foo->bar" is compiled as write-fetch rather than read-fetch. This is incorrect, because here $foo->bar is not modified itself -- the object it contains is modified. This does not matter a lot right now, but is problematic when it comes to readonly properties (and also property accessors). The readonly property implementation would incorrectly treat the first snippet as an error, because the PHP engine treats it as a write to $foo->bar. The historical context for this peculiar behavior is the "auto-vivification" feature that has been removed in PHP 8: $x = new stdClass; $x->a->b = 'c'; var_dump($x); On PHP 7.4 this results in: Warning: Creating default object from empty value in /in/MVgRo on line 4 object(stdClass)#1 (1) { ["a"]=> object(stdClass)#2 (1) { ["b"]=> string(1) "c" } } That is, it allows a "deep" initialization of the object, even though the intermediate level has not been initialized. In PHP 8 this results in an Error exception: Fatal error: Uncaught Error: Attempt to assign property 'b' of non-object in /in/MVgRo:4 This change has already happened, and as such no longer poses an issue for compiling property accesses with correct fetch-mode. However, a similar behavior still exists in SimpleXML: $x = simplexml_load_string(""); $x->a->b->c = 'Test'; echo $x->asXML(); Results in: Test Here again, an intermediate layer is implicitly initialized. After fixing the fetch-mode, an Error exception is thrown instead: Fatal error: Uncaught Error: Attempt to assign property 'c' of non-object in /home/nikic/php-src/t150.php:3 As such, the behavior will be in line with normal objects in PHP 8. It should also be noted that the current behavior is undocumented -- the documentation uses addChild() for this purpose. After writing out this mail, I'm not sure there is anything to discuss here really, as this just aligns SimpleXML behavior with an already accepted BC break in PHP 8, but I guess I should at least let people know about this :) For reference, a prototype implementation for this change is available at https://github.com/php/php-src/pull/5250. Regards, Nikita --00000000000045f25e05a081023b--