Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:127165 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 1A7A91AE4DC for ; Tue, 22 Apr 2025 13:41:13 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=php.net; s=mail; t=1745329133; bh=EJMusV1EMNhEDIWnyAY2g+IeBGcZCqqK/nueo36BBUU=; h=Date:To:From:Subject:From; b=MuEY2fz8UC+AYLT2VuEXK3JphnwPpOtJxalTzo2DnCTgqWwM4Q90wLsUIJ4ofwQpK ZiTYBuDIAaptaJSuBkaJJ+KzMo/ayUN0pIF4Wxdhq3e22gGKBChVcdk8N4QqubEcUQ xXfK9dnPvQ/hvL9ZGK5Y0dwGZHXNKoswJRjMntH1twbFkYfAMtWbZ6p8H46R8n5e8V CQ2GPtqX0XsWEtYD17L9ui+apub8KyPILXZG50yc5qUO1TIQAsqb1pQRkiAf3ZHMVn onqsugpS0xjteC+SslKGeZ+nwHrb9pbIJC7G/sJxzVCKfaO3w6Xqe0slK1UyVFedr9 InL9qHwg/ilIQ== Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id 6D72C180080 for ; Tue, 22 Apr 2025 13:38:48 +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.7 required=5.0 tests=BAYES_05,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,DMARC_PASS,RCVD_IN_DNSWL_NONE, SPF_HELO_NONE,SPF_PASS autolearn=no autolearn_force=no version=4.0.0 X-Spam-Virus: Error (Cannot connect to unix socket '/var/run/clamav/clamd.ctl': connect: Connection refused) X-Envelope-From: Received: from mail-0201.mail-europe.com (mail-0201.mail-europe.com [51.77.79.158]) (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 ; Tue, 22 Apr 2025 13:37:18 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gpb.moe; s=protonmail3; t=1745329073; x=1745588273; bh=glmg4NmGP1gS/bh7VEjSIcflqrd8i8sD7Tq5pNKWqbY=; h=Date:To:From:Subject:Message-ID:Feedback-ID:From:To:Cc:Date: Subject:Reply-To:Feedback-ID:Message-ID:BIMI-Selector: List-Unsubscribe:List-Unsubscribe-Post; b=8Zp9ZXUIhMjpmCgYE3nVWnpj8OJaDyAcMSvagmfv26TeoIE55mnXoTHiiOQM1PtQt DemAVudKfY0GdYmYnXFtHVWi99GxhFr6MfFmfMoJGblch0NCsqtWQ+qvBkjNDGZ62v VAZm9poF/swd7kGdy4aFWvj6YXn8O1mxyZB/v/IxXrGtkyvNS2X1dcrDRxUoPfZfDX aFJKfs4SbrjEMWvCPVYLVoHqzKMMoOrQz/ADPdlDmZfZXcMB+XgVPutIfdrP3wmknQ Qn4/AhuWK5+zaMsEk6WVoLNOGJIuRt7jlZ7Aj8Icf4vLuoN2tc7TuiWdVyLSM8nf0t +ynHgovFMdgwQ== Date: Tue, 22 Apr 2025 13:37:48 +0000 To: PHP internals Subject: [PHP-DEV][Pre-RFC] Associated Types Message-ID: Feedback-ID: 96993444:user:proton X-Pm-Message-ID: 2f609787a956349a882ff41807236f5e2993e5b4 Precedence: bulk list-help: list-post: List-Id: internals.lists.php.net x-ms-reactions: disallow MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable From: internals@gpb.moe ("Gina P. Banyard") Hello internals, The discussion about allowing never types as parameter types made me think = about what problem it is truly trying to solve, which is using the same type as parameters and return values between multip= le methods of a common interface. This is normally solved with generics, but as shown generics are hard TM [1= ] and a lot of the complexity resides in allowing the generic type to be se= t at *use* site of the class with generic parameters. However, this does not apply to template/generic types on interfaces, as th= e bound type is determined by the implementing class at compile time. As such, a few weeks ago, I created a PoC [2] where one can declare a templ= ate/associated type T on interfaces that require an implementing class uses= the same type when specifying T. The syntax in the PoC is currently: ``` interface I { type T : int|string; public function foo(T $param): T; } class CS implements I { public function foo(string $param): string { return $param . '!'; } } ``` I.e. the associated type is indicated by a "type" keyword, optionally follo= wed by a colon `:` and a type constraint. The type corresponding to the associated type is currently "guessed" by the= first usage in a concrete class. Having talked with Arnaud off-list, it seems that using the "usual" generic= syntax of (assuming our parser can cope with it): ``` interface I { public function foo(T $param): T; } class CS implements I { public function foo(string $param): string { return $param . '!'; } } ``` is possible and would not conflict with any future proposal for generics. Importantly, this feature would NOT support doing the followings: - `$o instanceof I` - Using `I` in type declarations Meaning you do not get static type information, similarly to the `never` as= parameter type, but one is guaranteed that there is no funky type variance and incompatibil= ities between different methods (or parameter and return types of the same = method) in a concrete implementation of an interface. Effectively, static analysis tools must either assume T is `mixed`, or hook= it into their generic types feature. Which is what the current status is for various interfaces (e.g. ArrayAcces= s). I am intending on getting this feature ready for 8.5, and the reason I brin= g it up to the list now, without a proper RFC, is to explain my reasoning f= or why I am voting against the never parameter type RFC. [3] For any questions, feel free to reply, but please do remember that this is = still a bit in flux. Best regards, Gina P. Banyard [1] https://thephp.foundation/blog/2024/08/19/state-of-generics-and-collect= ions/ [2] https://github.com/php/php-src/pull/18260 [3] https://wiki.php.net/rfc/never-parameters-v2