Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:126015 X-Original-To: internals@lists.php.net Delivered-To: internals@lists.php.net Received: from php-smtp4.php.net (php-smtp4.php.net [45.112.84.5]) by qa.php.net (Postfix) with ESMTPS id 7DCF61A00BD for ; Thu, 21 Nov 2024 08:15:30 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=php.net; s=mail; t=1732177090; bh=xwS+XAhHSHpFzBCLhMCJc2BqekzQENTPuLXphbdfngQ=; h=From:Subject:Date:References:To:In-Reply-To:From; b=EtuXOoO3AOfd8WicZOky16zJb4Fhe2H97NzFvTRhqKY4l8AfJCOXpYgxjiVQDO2gv oXBmO37yXMEOHu0dqkFmWxSCPyOjuvtGY0S/XPTdtUevOi5nJwB4Ghjmfcrp+66fRe QxJXFcvyl0kWlWKU30GtWdZKfbV4wD0tkgaPDQymPa6ZKxJA//JpGwR26H3QwFvi78 vNYLXHh/nNkSiVmS7ck+7akJA+y1LM7W2p4sN4UxUKBrtNhchNfnzJmf8y+SmVHpoo eDVnTG3xcqNAwvacCtDce0T6BQHnjK1z99rQysUWALQm9rMHiqNJ4HePpGEo+wCqI8 /8iiafTOO6OyA== Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id 5F54B1801D7 for ; Thu, 21 Nov 2024 08:18:09 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 4.0.0 (2022-12-13) on php-smtp4.php.net X-Spam-Level: X-Spam-Status: No, score=0.6 required=5.0 tests=BAYES_50,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,DMARC_PASS,FREEMAIL_FROM, RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H2,SPF_HELO_NONE,SPF_PASS autolearn=no autolearn_force=no version=4.0.0 X-Spam-Virus: No X-Envelope-From: Received: from mail-ed1-f50.google.com (mail-ed1-f50.google.com [209.85.208.50]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by php-smtp4.php.net (Postfix) with ESMTPS for ; Thu, 21 Nov 2024 08:18:06 +0000 (UTC) Received: by mail-ed1-f50.google.com with SMTP id 4fb4d7f45d1cf-5cfc19065ffso706317a12.3 for ; Thu, 21 Nov 2024 00:15:26 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1732176924; x=1732781724; darn=lists.php.net; h=message-id:in-reply-to:to:references:date:subject:mime-version :content-transfer-encoding:from:from:to:cc:subject:date:message-id :reply-to; bh=FxVluBVF4TTUf/tXRGE7j2V1gFvaXS4EgfDuxD+G8GY=; b=nqZtAWkH70nDCnyQ+wnhTDPgisLYZ8BVJ5KF1LzPcnkxE6ysOs1ELLuX1rMlxXiNrx HxMBrcKsSWwlV81DtGlRXlWTchx4xX8C6Jq0a1m+QrqTiTTlD5TmpHxOWb/SPzpuRbYl 9a7wJeN6fLj3cqtPp/9fEldDSpl5ICt1Gb/Ndu2FGwlec1W0Yodfd8wBG/2uPdDZa7CL WXl8mgookzsf668JPJ9vaFsECe9vZAsVMaW3gVgCnbgXDzLWiRQYNMArE44NISw0LEJR iMsAcnl1bViFkM9iTvTy7BJazX8TijWeQd0ZC/npI9vd9sppIg89VG7AK8+HfH0a/gkC FZFA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1732176924; x=1732781724; h=message-id:in-reply-to:to:references:date:subject:mime-version :content-transfer-encoding:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=FxVluBVF4TTUf/tXRGE7j2V1gFvaXS4EgfDuxD+G8GY=; b=iBIux57HOkjzSyq9ErROli4bzaXR2m8PgbqS39x+Kxm8N84SlUiGOqBeXbmr6rQuI7 nGoa324FXSYJfp59vvQvr9jmCFfOmVilKdMKK11+P33dTGT0tE3aTdB+b0MAfYB9z/EF x3miSnkR9562zKAUiRm2Zq2e02rg3qlc4dMBc7NIiaZqGDl71It/bfYsyFSA2KBUVMVm bAe4qYX5JDeJoh6z+rGTCVhPVXV7M/f5aQPrmgWGE1MJ3RlISZ0/jqkVEDreFYSrxvIO 021k1WnqU7sX46xzJvF8RoKcU4RMRZMnTZTSq1uhwz1uQ6En6wQBmJ3n+AZw2S2WoOuV jgow== X-Gm-Message-State: AOJu0YzY5QlDPzyC0rz2JrEcl0uIaDYKJSDSRVw+IOvGg4y2s0Rn172v gp5g6ai1ZA++z/Y47YlgVV7c4DeMIcRkkYD64ENtMSbS3QSu5ZpglhD3ChOy X-Gm-Gg: ASbGncsGjQVcSn4xMoJfcNhGir0nOpHWVa5UkDxalU7qhGNnryxCqsKMu85kmYb+7hQ 9DquVVnF+Bl9607gHibQm+uPdjqmCPlJbaCM7ih9yoQIx3GgBzmvHfWwkfYkytWPn4mrN+Nq5NX OSSLcbcRjhXiUKDD5kevjqxVch1MIeED5ONI7w83mLtH5RjhLp55bdsW7pfOjp4rcPoBNJOIAdZ 98fKsdxerLDR9BFDCFGnSFnRlrRh+6WrkI/aqQMHusqA67fmEkjYV7FBbm5Qph8wJo6jFxM8Un9 ZRZHcdc0CO+7juqmdVWoZp6p6o8tFtEMdEX5seM1l8Mw X-Google-Smtp-Source: AGHT+IG2y1r/3ff5VkN/CGq0IRjQgTcDCV+IjOJKp1KujT+uWJQKvFOzCGLQVemsoxVZ7yRkCfkzmA== X-Received: by 2002:a17:906:fd89:b0:a9a:17f5:79a8 with SMTP id a640c23a62f3a-aa4dd54835dmr471548666b.13.1732176924332; Thu, 21 Nov 2024 00:15:24 -0800 (PST) Received: from smtpclient.apple (host-95-229-168-3.business.telecomitalia.it. [95.229.168.3]) by smtp.gmail.com with ESMTPSA id 4fb4d7f45d1cf-5cff44ef8d3sm1597323a12.31.2024.11.21.00.15.23 for (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Thu, 21 Nov 2024 00:15:24 -0800 (PST) Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: quoted-printable Precedence: bulk list-help: list-post: List-Id: internals.lists.php.net x-ms-reactions: disallow Mime-Version: 1.0 (Mac OS X Mail 16.0 \(3826.200.121\)) Subject: Re: [PHP-DEV] opcache_compile_file() declares top-level functions Date: Thu, 21 Nov 2024 09:15:12 +0100 References: To: internals@lists.php.net In-Reply-To: Message-ID: X-Mailer: Apple Mail (2.3826.200.121) From: daniil.gentili@gmail.com (Daniil Gentili) Hi Ilija, I believe the removal of function caching is a bit of an overreaction: = it was always known, to those who used it, that preloading will cache = functions, and requires an include guard to avoid function redeclaration = errors, and in fact it is a very useful feature. There is nothing wrong with this behaviour, and it does what you expect = it to do. Regards, Daniil Gentili > On 20 Nov 2024, at 22:22, Ilija Tovilo wrote: >=20 > Hi everyone >=20 > We recently received a bug report regarding the behavior of > opcache_compile_file() [1]. The documentation specifies: >=20 > https://www.php.net/manual/en/function.opcache-compile-file.php >=20 >> This function compiles a PHP script and adds it to the opcode cache = without executing it. This can be used to prime the cache after a Web = server restart by pre-caching files that will be included in later = requests. >=20 > Arguably, "without executing it" implies that, aside from putting the > script into opcache, there are no other observable side-effects. This > assumption is currently incorrect. To be more specific, > opcache_compile_file() differs from require in two ways: >=20 > * The "main" function of the script (containing all the code at the > top-level) is not executed. > * Classes will not be added to the class table. >=20 > Confusingly, top-level functions _will_ be added to the function > table. This has some weird consequences: >=20 > * opcache_compile_file() can be called multiple times on files > containing classes. However, the same is not true for files containing > functions. The second call will lead to a function redeclaration > error. >=20 > ```php > // index.php > opcache_compile_file(__DIR__ . '/test.php'); > opcache_compile_file(__DIR__ . '/test.php'); >=20 > // test.php > class Foo {} // No problem > function foo() {} // Fatal error: Cannot redeclare function foo() > ``` >=20 > * Similarly, after calling opcache_compile_file() on files containing > classes, the same file may later be required without issues. This does > not work for files containing functions for the same reason. >=20 > ```php > // index.php > opcache_compile_file(__DIR__ . '/test.php'); > require __DIR__ . '/test.php'; >=20 > // test.php > class Foo {} // No problem > function foo() {} // Fatal error: Cannot redeclare function foo() > ``` >=20 > * Mixing functions with classes is incompatible. An attempt to use one > of the classes from one of the functions will either error because of > an undeclared class, or trigger the autoloader and include the file > again, leading to a function redeclaration error. >=20 > ```php > // index.php > spl_autoload_register(function ($name) { > if ($name =3D=3D=3D 'Foo') { > require __DIR__ . '/b.php'; > } > }); > opcache_compile_file(__DIR__ . '/test.php'); > foo(); >=20 > // test.php > class Foo {} > function foo() { > // Triggers the autoloader, the autoloader fails due to: > // Fatal error: Cannot redeclare function foo() > var_dump(new Foo()); > } > ``` >=20 > * Functions that are conditionally declared will not be added to the > function table, since they are not top-level functions, even if the > condition always evaluates to true. >=20 > ```php > // index.php > opcache_compile_file(__DIR__ . '/test.php'); > foo(); // Uncaught Error: Call to undefined function foo() >=20 > // test.php > if (true) { > function foo() {} > } > ``` >=20 > This behavior is inconsistent and confusing. Arguably, the correct > behavior is to never register functions in opcache_compile_file() to > begin with, since opcache_compile_file() exists to prime the cache, > rather than execute code. I created a PR with this change [2]. This is > breaking, since code using opcache_compile_file() might currently > depend on functions being declared and then calling them directly. > Such code would have to be adjusted to use require instead. >=20 > Are there any concerns with making this change for 8.5? Are there any > use-cases this would break? >=20 > Of note is that it may be beneficial to provide a related function > that allows compiling files and declaring symbols without executing > the "main" function. This could be useful static analysis tools that > want to reflect on files without executing them. That said, there are > existing solutions in userland that solve this problem in a better > way, like BetterReflection [3]. >=20 > Ilija >=20 > [1] https://github.com/php/php-src/issues/16668 > [2] https://github.com/php/php-src/pull/16862 > [3] https://github.com/Roave/BetterReflection