Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:118769 Return-Path: Delivered-To: mailing list internals@lists.php.net Received: (qmail 44974 invoked from network); 6 Oct 2022 16:41:26 -0000 Received: from unknown (HELO php-smtp4.php.net) (45.112.84.5) by pb1.pair.com with SMTP; 6 Oct 2022 16:41:26 -0000 Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id 85338180505 for ; Thu, 6 Oct 2022 09:41:25 -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=-1.9 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_ENVFROM_END_DIGIT, FREEMAIL_FROM,RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H2,SPF_HELO_NONE, SPF_PASS,T_SCC_BODY_TEXT_LINE 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-lf1-f52.google.com (mail-lf1-f52.google.com [209.85.167.52]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange ECDHE (P-256) server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by php-smtp4.php.net (Postfix) with ESMTPS for ; Thu, 6 Oct 2022 09:41:25 -0700 (PDT) Received: by mail-lf1-f52.google.com with SMTP id bp15so3524053lfb.13 for ; Thu, 06 Oct 2022 09:41:25 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=to:references:message-id:content-transfer-encoding:cc:date :in-reply-to:from:subject:mime-version:from:to:cc:subject:date :message-id:reply-to; bh=2SVNxwmFwxprx+fLpSGY9Ie46bBt9c0aLNcVWvWB1OU=; b=jYlJTKTsKMYOI64zrljoAlBxkB3xfZs9tQDpPRz9bHMdQKs9xX1XFzTttmoIEHv/rS jOeFbMwj47/rSytP/Jm/1HJIoI74ogw8youCU5dLLkjBCKztfSgUKC6YfkGD/sWDDhAr bPRkz+M3AC9mtm6sibWblYFdrz+pZT+6SVzs8BB8WBrQd/KjPgYUXaVX1Cny3qyAcP/V M/XBCDNZxYoPWRlyDsZ6E9NzxGXdaOZ6SOCJeHqqfv5jGArG7Nry0llocdtjffEOH1W0 wL9SO8nP2TxvaU+RTUNjHHoUrdCr8bLQmm2FxZmIQc/zkXg69DBQQxCN/BKgPryoNCko 6VrA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=to:references:message-id:content-transfer-encoding:cc:date :in-reply-to:from:subject:mime-version:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=2SVNxwmFwxprx+fLpSGY9Ie46bBt9c0aLNcVWvWB1OU=; b=mJN6YF9yXUpduy9htthCeES3UtdnDxfnoG6u80NmEOfi30MVGgZ0h6BIK6tfRoZzvT ec1/oegKx65sLtzHg/pHQDAyC8TOB+ulLrCKYpktiOMxw+eOnTrnPD6uJLPj2r+pief2 oXVYD7WxYpStQIrRF0XtHL1vPLefxXcQ/Zl9EFbFQ9xUM529yjhftJrdM6kgNfsszcSl 9TiWXcTKQmhh3Y1gaRW6HnkyTsWPvIv1O7UoicExCDG/56/Ov2C1kYaGKo3aRl2ny+9j DMiqLrAKCVh6bJhfLHi9/50aqcN8Zg/as1Lma83WzaGjEUJWLoD9ysRwKet/z1XTjdBk PHHQ== X-Gm-Message-State: ACrzQf1mUytmtzE/65C9zLOsCzMkSN+4f5RQsZCo/SbCNqU8+fCdEQPc G6KSRjoqeyjMVX9SWAHzS+g0EUnT+MkDFw== X-Google-Smtp-Source: AMsMyM5iAAVOP80tvBDfufQXqICepun83VGTx7LH6tjEcOjQ30Xgf2+3ame/rXL6Wch8DLjaGzTlLQ== X-Received: by 2002:a05:6512:419:b0:4a2:2e45:bf0 with SMTP id u25-20020a056512041900b004a22e450bf0mr358713lfk.356.1665074483789; Thu, 06 Oct 2022 09:41:23 -0700 (PDT) Received: from smtpclient.apple ([213.109.238.56]) by smtp.gmail.com with ESMTPSA id c8-20020a056512104800b004a01105eea2sm2746111lfb.150.2022.10.06.09.41.22 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Thu, 06 Oct 2022 09:41:23 -0700 (PDT) Content-Type: text/plain; charset=us-ascii Mime-Version: 1.0 (Mac OS X Mail 16.0 \(3696.120.41.1.1\)) In-Reply-To: <1aa20877-3365-0ace-25d2-1cb1be8f3bcc@gmail.com> Date: Thu, 6 Oct 2022 19:41:21 +0300 Cc: PHP Internals Content-Transfer-Encoding: quoted-printable Message-ID: <55686BD4-4C67-4A4F-8BE4-BDF0149296FB@gmail.com> References: <1aa20877-3365-0ace-25d2-1cb1be8f3bcc@gmail.com> To: Rowan Tommins X-Mailer: Apple Mail (2.3696.120.41.1.1) Subject: Re: [PHP-DEV] Experimental features From: autaut03@gmail.com (Alex Wells) > On 6 Oct 2022, at 16:06, Rowan Tommins = wrote: >=20 > On 06/10/2022 12:16, Alex Wells wrote: >> A marker merely just tells the compiler "hey, allow me to use this = feature right here", i.e. it denotes a piece of code as allowed to use = the feature, not enable it. Effectively, all experimental features are = just regular features that are "always on" and hence can be optimized = the same way regular features are. The marker serves two purposes: allow = simple discovery of usages (by the compiler or other tools) and force = the developer to acknowledge they're using an experimental feature with = an unstable API/syntax/spec. >=20 >=20 > I don't really understand the distinction between "enabling" and = "being able to use", nor what it would mean for a feature to = "experimental" but also integrated fully into the language. >=20 > In general, I'm finding it quite hard to follow the idea in the = abstract - the definition of "feature" seems very fuzzy. Could someone = give some examples from another language, or concrete examples where it = would be used in PHP, and then work through the details of what would be = expected to happen in what version of PHP? >=20 >=20 >> Regarding the monitoring - that is a problem that needs to be solved = and there are multiple solutions: GitHub issues, corporate/public = messengers (Slack?) or the internals mailing list. >=20 >=20 > There are certainly ways to approach it; I'm just agreeing with a = previous commenter that this would need to be an explicit part of any = proposal, not just hand-waved away. >=20 > Regards, >=20 > --=20 > Rowan Tommins > [IMSoP] >=20 > --=20 > PHP Internals - PHP Runtime Development Mailing List > To unsubscribe, visit: https://www.php.net/unsub.php >=20 I'll try my best to elaborate, although I the author of the proposal = will likely do a better job. A feature is generally considered any addition to the language or it's = standard library - that could be a new set of functions, new syntax etc. = Experimental features refer to features whose stability is = "experimental". Kotlin divides their features into four stability levels: experimental, = alpha, beta and stable. Each of those might have their own = preconditions, BC promises and release cycle rules. A feature with = "experimental" stability level requires an opt-in: a piece of code that = uses the new feature must be marked with an annotation. For example, = Kotlin has recently introduced a new feature - unsigned integer types. = This inlcudes new types and a new syntax. This is how you'd use them: ```kotlin @OptIn(ExperimentalUnsignedTypes::class) fun unsignedInt(): UInt { return 123u } @OptIn(ExperimentalUnsignedTypes::class) fun main(args: Array) { println( unsignedInt() ) } ``` `123u` here denotes an integer that is unsigned. The `u` part is the new = syntax. `UInt` is the new type. Notice two `OptIn` annotations - one for = the function which returns the new type, and the other for it's = dependent. The second annotation is needed because of the return type - = Kotlin assumes the return type is used, effectively assuming you're = using the new type in your function, which requires opt-in. This changes if `unsignedInt` returns `Int` (a regular type, not part of = the experimental feature) instead: ```kotlin @OptIn(ExperimentalUnsignedTypes::class) fun unsignedInt(): Int { return 123u as Int // cast UInt to Int } fun main(args: Array) { println( unsignedInt() ) } ``` Notice how an opt-in is no longer needed for `main`. If you omit the opt-in altogether, this is what the compiler (and the = IDE) will throw at you: `Main.kt: (7, 20): This declaration is = experimental and its usage should be marked with = '@kotlin.ExperimentalUnsignedTypes' or = '@OptIn(kotlin.ExperimentalUnsignedTypes::class)'` Of course, in Kotlin there also mechanism to opt-in more than just a = single function. This can be done on file, module or even project level: ``` @file:OptIn(ExperimentalUnsignedTypes::class) // or module-wide sourceSets { someModule { languageSettings.optIn("org.mylibrary.OptInAnnotation") } } // or project-wide compiler flag -opt-in=3Dorg.mylibrary.OptInAnnotation ``` //// Onto the PHP application. It's similar, although obviously due to the = dynamic nature of the language the compiler wouldn't be able to force = opt-ins nearly on the same level as Kotlin compiler does. This isn't to = say experimental features can't be implemented properly in PHP. Let's say PHP wants to experiment with a new function - = `json_validate()`. The idea is simple: follow the regular RFC process = and release the function the same way you would without experimental = functions. The only thing that is needed is to mark the function as one = that requires an opt-in: ```php #[Experimental(ExperimentalLevel.WARNING)] class ExperimentalJsonValidate {} #[RequiresOptIn(ExperimentalJsonValidate::class)] function json_validate($something): something {} ``` Then, any consumer of that function would be required to opt-in: ```php #[OptIn(ExperimentalJsonValidate::class)] function main() { json_validate(); // all good } ``` If an opt-in is missing, PHP will trigger an warning (during runtime): ```php function main() { json_validate(); // trigger_error('Must be opted-in', E_WARNING) } ``` Few months after the release (let's say 8.2), PHP collects feedback and = analyses codebases (which is easy thanks to the attribute) and decides = it wants to change the name to `json_revalidate`. This is of course over = exaggerated, but it's to prove the point. Just as any other change in = PHP, this would require an RFC. If it's accepted, the change is done. Under regular circumstances (no experimental features), such a change = would have to at least have a deprecation notice for one minor/major = release prior to it (so the minimum version this could be done in is = 8.4). Moreover, such changes would usually be avoided at all costs, = because this is a big breaking change.=20 Experimental features on the other hand are explicit opt-in - users know = it can be changed at any time, without a warning, a deprecation or = anything for that matter, in any release. That allows the change to be = done without really worrying of BC and also much earlier (8.3 or even = 8.2.1 if you decide so). Also, the `#OptIn` attribute allows consumers = to easily find all places where an experimental feature was used in case = a breaking change was done. The same concept can also be applied to new syntax - let's say generics, = except with a more strict error (E_FATAL, for example). This has been = briefly discussed here: = https://github.com/PHPGenerics/php-generics-rfc/issues/49