Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:109549 Return-Path: Delivered-To: mailing list internals@lists.php.net Received: (qmail 62792 invoked from network); 7 Apr 2020 14:17:06 -0000 Received: from unknown (HELO php-smtp4.php.net) (45.112.84.5) by pb1.pair.com with SMTP; 7 Apr 2020 14:17:06 -0000 Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id F00BE1804C2 for ; Tue, 7 Apr 2020 05:44:58 -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=-0.2 required=5.0 tests=BAYES_20,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_FROM,HTML_MESSAGE, RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H2,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-f194.google.com (mail-lj1-f194.google.com [209.85.208.194]) (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, 7 Apr 2020 05:44:58 -0700 (PDT) Received: by mail-lj1-f194.google.com with SMTP id q19so3509015ljp.9 for ; Tue, 07 Apr 2020 05:44:58 -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=11fRsguHKDzUaHar9t19I6mW2gZDXTC5D45jEfs8Vjg=; b=Bc7C5wAMclOg31g59n7cDWUJIZGz+jXf99pxgj2y0L3VPcQqWlNU51fpGSNECm7twH P7wB+dum3Gs0HAr5Jm8jr1wNIQbXDGCd34JuLeyhrZWihHPLwot1gFk6uFfVf+J8vZy8 udm8PGlymfZmibrIZ4NY2lKUaRMDWPVk5idOhQa6QfeS/6uiQVxb9rMI/W41tOKGuOpS NEDQiBt5yJdzqOetzVeWRE3iUUDk9IHR4M8dtkxZ7ZJleULoWXi3ThysymEsEAplAA2l bzK3bHidlfMFBKH8AGBx2JDj2mRJYVXbO5ezNbkUPlRDfvP4/TTA4/Ck4TLp38XOHKns qF4w== 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=11fRsguHKDzUaHar9t19I6mW2gZDXTC5D45jEfs8Vjg=; b=FfIpPLPbGMOZWDJgZfvEPsyD3nm72olBtS421rGAzq/7DxuyjZYZ1sUOuNO5fb0TMd aghOq+rrqhkaYoPt9lPj9ir38MkHkwq6dn4MH3nfJ+3IXnQpjrQDSgVP2hd2n3Qbg9Gv 1FKr0y0RVpBSieOBLFllgxZGwPBpet2iUL8m4HIWMPSJZOGTqyHgjICyg1H61stB9jZt oR9EMX3r7mCOSicZJ4hifEBTZJmqORy3L9gfM1vO8LNGKKdUjLYkOMNs4sAxJfTAA+Ws BeKTHyuzAnAB7XhQZLzhwnaT2ngo3VSYn74inLOyj5N++JJ6OMMJDVyFI+bSg0477k0S ukgA== X-Gm-Message-State: AGi0PuaaWCKsBzy+vZ9pwTSLAdExovopE5oZTC41t8ktuxBBt7BV+rx4 gJI6X54nip7wJ0PT+HSLNGQj6ub+0lgNsfogNJHTSEn4RpM= X-Google-Smtp-Source: APiQypKP0bh6dl4gmP1QIYjvIooeZ0tbcvhZ2uDMJJArW9IQ72NyIwiWulx8B63TUWG9VYojV3+rmZYHqrI2ORaVJoQ= X-Received: by 2002:a2e:7a18:: with SMTP id v24mr1702055ljc.34.1586263494104; Tue, 07 Apr 2020 05:44:54 -0700 (PDT) MIME-Version: 1.0 Date: Tue, 7 Apr 2020 14:44:38 +0200 Message-ID: To: PHP internals Content-Type: multipart/alternative; boundary="000000000000161a5005a2b2c0cc" Subject: Resurrecting named parameters From: nikita.ppv@gmail.com (Nikita Popov) --000000000000161a5005a2b2c0cc Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable Hi internals, It's been a few years since I originally brought up the named parameters RFC: https://wiki.php.net/rfc/named_params This topic has recently come up as part of https://externals.io/message/109220 again, in particular with the observation that the combination of constructor parameter promotion and named parameters will give us, as a side-effect, an ergonomic object initialization syntax that is well-integrated with the remainder of the language. I've reimplemented basic named param support for master in https://github.com/php/php-src/pull/5357, but before going any further here, I want to restart discussion on the various open issues that the named parameter concept in PHP has. I think there's two primary issues: ## LSP checks for parameter names Parameter names currently have no particular significance in PHP, only their position in the signature is important. If named parameters are introduced (in a way that does not require opt-in at the declaration-site), then parameter names become significant. This means that changing a parameter name during inheritance constitutes an LSP violation (for non-constructor methods). There are a number of ways in which this issue may be approached: 1. Silently ignore the problem. No diagnostic is issued when a parameter name is changed during inheritance. An error exception will be thrown when trying to use the (now) unknown parameter name. 2. Throw a notice if a parameter name is changed. While LSP violations are normally fatal errors (in PHP 8), we could use a lower-severity diagnostic for this case, that allows code to still run, but makes developers aware of the problem. (It should be noted that automatic fixup of parameter names using tooling should be fairly easy to implement.) 3. Allow using parameter names from the parent method, even if they have been renamed. This makes things "just work", but seems fairly magic, and has edge cases like a signature foo($a, $b) being changed to foo($b, $a), where it's not possible to implicitly support both at the same time. 4. Make named-parameter opt-in in some fashion, so that parameter names only need to be preserved for methods that have the opt-in marker. I'm not a fan of this, as it greatly diminishes the practical usefulness of named parameters. ## Internal functions There are two problems when it comes to named parameters and internal functions. The first is that the internal parameter names do not always match the parameter names in the documentation. This is nothing we can't solve (in a hopefully mostly automated way), but is work that needs to be done. The larger problem is that internal functions don't have a well-defined concept of parameter default value. Parameter defaults are implicit in C code, and sometimes based on argument count checks. When named parameters are involved, one generally cannot assume that if a later (optional) parameter is passed, all earlier (optional) parameters are passed as well. While it is possible (but rather challenging) to make things work mostly transparently with current ZPP, some functions do need to adjusted to support named parameters, and may cause misbehavior/crashes if they are not. As a rule of thumb, functions that make non-trivial use of ZEND_NUM_ARGS() are affected. This is something we can address for functions in bundled extensions, but may also affect 3rd-party extensions. I think that ideally, we'd deal with internal functions the same way we do for userland functions, by relying on default values that are part of the function declaration. As part of the PHP stub work, we now have information on default values in stub files, but this information is currently not available to the engine. M=C3=A1t=C3=A9 Kocsis has been working on getting this information exposed = in Reflection, see https://github.com/php/php-src/pull/5353. In the current form, accessing these defaults is fairly inefficient, but maybe with some caching, we could base named parameters on this information: If there are no "gaps" in the passed parameters, then named parameters will always work. If an optional parameter is not specified, but a later parameter is, then we will fetch the default value for that parameter, and pass it instead. If the parameter is optional, but has no well-defined default (UNKNOWN in stubs), then the call is not permitted (Error: "Cannot skip parameter $foo with unknown default value", or similar.) Any thoughts on these issues, or named parameters in general would be welcome. Regards, Nikita --000000000000161a5005a2b2c0cc--