Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:114098 Return-Path: Delivered-To: mailing list internals@lists.php.net Received: (qmail 81124 invoked from network); 22 Apr 2021 10:10:51 -0000 Received: from unknown (HELO php-smtp4.php.net) (45.112.84.5) by pb1.pair.com with SMTP; 22 Apr 2021 10:10:51 -0000 Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id B28681804BD for ; Thu, 22 Apr 2021 03:13:50 -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,RCVD_IN_MSPIKE_H2,SPF_HELO_NONE,SPF_PASS autolearn=no autolearn_force=no version=3.4.2 X-Spam-Virus: No X-Envelope-From: Received: from mail-lj1-f169.google.com (mail-lj1-f169.google.com [209.85.208.169]) (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 ; Thu, 22 Apr 2021 03:13:49 -0700 (PDT) Received: by mail-lj1-f169.google.com with SMTP id u4so51158922ljo.6 for ; Thu, 22 Apr 2021 03:13:49 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=mime-version:references:in-reply-to:from:date:message-id:subject:to :cc; bh=l8CkLdfUvxbooEAHVoxZJsUKevbaARJCuRHXgrp5fTM=; b=C99bl6cGFJuH8haRNVLFTtIqF2yH3g7ei8mWU6hR2MM3pPUx55fPHnCTl87uyOIZle pf764z4tem+eQIfCpyb6EnSbirLLDMyl9MQ0hb3U6Tm8Hi46KoU+9EtAL8orY6gk4ei1 xVrCP9ZctfW51yzJL0BV2BUHeMBWGIZt3awG2cpJwAN+Ex0oaKu6ZlNUpRJSO1IkSlF5 PKMfOELsFI/T3icLhpgGLn3/ARlCv3UadO6sUsfFtQZSLha2WuA7+SE/mOQsFz5E7CCD iCnGBsbW7khjob2haurecr3Z64Ne0JTSpc96slnSzL37u98MCKHpoMB10N9euQvkZgSp +QFQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc; bh=l8CkLdfUvxbooEAHVoxZJsUKevbaARJCuRHXgrp5fTM=; b=tO8KxO6KKw5yZgb8MU89qKt2ds3fTmvlFIy306kfsHsgpAmvmmIiRj6qblGN85LJ+I la7c0OBwUiuz9cYKBAUN7y1WLJz+742ZbRUDIrAwccMBnRyGPEFm+dpSEWXqHUa2CNPo HQEWaRxGFg+QbzNfT+ueHYpj5FedjIeTm11OdxTWq1ppozHjcTXkRDFRBOmkrCG5rTaE GAi98B9bcvlqRLwDgtBUSegxDE2YOWv13iL+mcg/F1gPVE5mpSMeKsWuP0jrkryZ8Wwr 9SxaFDrXpufNGC8Lp0wI6wYBZG1DjQnd7Z1iqkBVVnFtojYAbsZG7Qu8JOjeB1tH6uxu HxFQ== X-Gm-Message-State: AOAM533JuG3CAbTm9jSqmIMYlu2BPcIZYhNy6iXmlfq7smlZCF2ROCMk Q/E+lCIG0AG7rE4boeWtkfmMf7Ixc3IqvN857Yw= X-Google-Smtp-Source: ABdhPJw/G9ODcMG2FXFrpqlvYWuHMOPz3vhPCquu0hE8G8f8xhnZM5YV3d6xte3pYI/MFT6f2Wy7gNpez6Z8A4thOP8= X-Received: by 2002:a2e:7819:: with SMTP id t25mr1984016ljc.93.1619086427066; Thu, 22 Apr 2021 03:13:47 -0700 (PDT) MIME-Version: 1.0 References: In-Reply-To: Date: Thu, 22 Apr 2021 12:13:31 +0200 Message-ID: To: Marco Pivetta Cc: =?UTF-8?B?TcOhdMOpIEtvY3Npcw==?= , PHP Internals List Content-Type: multipart/alternative; boundary="00000000000058953405c08cef25" Subject: Re: [PHP-DEV] [RFC] [Vote] Adding return types to internal methods From: nikita.ppv@gmail.com (Nikita Popov) --00000000000058953405c08cef25 Content-Type: text/plain; charset="UTF-8" On Thu, Apr 22, 2021 at 11:51 AM Marco Pivetta wrote: > On Thu, Apr 22, 2021 at 10:37 AM Nikita Popov > wrote: > >> >> To clarify what you're actually suggesting here: Do you want to always >> have the type returned from getReturnType() >> > > Correct > > >> and only add an additional bool method that tells you whether that is a >> tentative or real type, so that most code can just treat them as being the >> same thing? >> > > No, and also not needed, especially since we're converging towards having > these types explicitly defined in PHP 9. > > The use-cases of reflection **on return types** are generally as follows > (obviously not exclusive list - it's hard to define "use-cases" in large > groups, and be precise): > > 1. use reflection to generate subtypes (mocks, stubs) > 2. use reflection to build a dependency graph of calls (dependency > injection containers) > 3. use reflection to validate data flows (type-checkers) > 4. use reflection for documentation (doc generators, type-checkers) > 5. use reflection for data conversion (serializers, ORMs) > > In the scenario when `ReflectionFunction#getReturnType()` reports the new > types immediately: > > 1. is safe even if `ReflectionFunction#getReturnType()` starts reporting > new type the return type is more restrictive, since variance rules allow > for subclassing to do this. > 2. is safe, because if `mixed` (previous inferred return type) already > fits within a dependency graph, the new more precise type already fits too > 3. is safe because the **returned** type is still more restrictive than > `mixed` > 4. is safe because type-checkers already learned to not trust internal > php-src declared types (and moved to stubs instead) > 5. is safe because the types declared by what is **returned** during > deserialization is stricter than the previous `mixed`, and therefore still > fits > > There will be hiccups, like always, but overall there is little space for > security issues arising from stricter return type declarations: in fact, > the pre-PHP-8.1 scenario (no type declarations) is much more dangerous. > > In the scenario when `ReflectionFunction#getReturnType()` does **not** > report the new types, and instead these types are declared on new > "tentative return type" methods (the RFC at vote): > > 1. 2. 3. 5. until tools consider the new methods, a starker migration to > PHP9 is expected. Tools need to be adjusted to consider the new methods for > 8.1, and to ignore the new methods for 9.0. This will cause a lot of > downstream work > 4. generally does not care about internal reflection API (again, these > tools learned to hop around it with stubs) > > In the scenario when `ReflectionFunction#getReturnType()` does report the > new types, but we add a new method to state that the return type is > "tentative" (approach proposed by NikiC): > > 1. 2. 3. 5. until tools consider the new methods, a starker migration to > PHP9 is expected. Tools need to be adjusted to consider the new methods for > 8.1, and to ignore the new methods for 9.0. This will cause a lot of > downstream work > 4. generally does not care about internal reflection API (again, these > tools learned to hop around it with stubs) > > Overall, I see the change of reported `ReflectionMethod#getReturnType()` > as non-problematic, and tooling around reflection would continue working as > expected, while adding new API requires: > > * more work to get the tooling upgraded to PHP 8.1 > * more work to get the tooling upgraded to PHP 9.0 (when those methods > become obsolete) > * more risk that users of tools that are not yet up-to-date with PHP 8.1 > experience bugs or weird behavior > > In fact, tooling will start reporting incompatibilities in types earlier, > giving people more runway to fix their subtypes for the upcoming 9.0 change. > You make a good case! I think my own perception here is colored by the usage of types in php-src, where the distinction is very important. But php-src is probably the only type analyzer that works on hard guarantees. I do want to add one more use case though: 6. Static analyzers, which might be implementing method compatibility checks (don't know if psalm/phpstan do that), and which would want to handle these cases differently. In particular, just like PHP itself, the wouldn't want to indicate an error for the "tentative return type" + #[ReturnTypeWillChange] combination. Regards, Nikita --00000000000058953405c08cef25--