Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:125305 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 969AD1A00BD for ; Tue, 27 Aug 2024 07:25:45 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=php.net; s=mail; t=1724743658; bh=ZjFxBX6+J0iRRG359RfuPw5lBw3Vvwms/xGlaWLO9Dw=; h=From:Date:Subject:To:From; b=oEC5s1D5A9ZGyDn+9uvm/BdXFQ71svydq7sacjEQ3OQGgm5Xa7FWd/pdWaw67QvPR +vGcxAGiwNJleyDVnYV/2ZIrjploirTWZ40UWruzhbuyKjDM4xDqv6F/ot3uDlUITv d7IgEgQd1LKuNMnDYyOBvpXvQR5tp8G/KV5lq+EHg4EKDZbPK5GaadSKED1/FcyPEA dPL8Y02vPRAvJC8gHptiDrOjdyQhIt9a6+tNGpIw1d0ZaFw8ErkHfQYFV/5h3JYLdg Wn8PJEUJcAbCDMnZhYDDkMIwjAvE5JGcTH4jgW0x+VPerAkhDiCZeE5hQtDCmR0HFg BO6pjLcNjivjA== Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id 9BCFD180051 for ; Tue, 27 Aug 2024 07:27:37 +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,HTML_MESSAGE, RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H2,SPF_HELO_NONE,SPF_PASS, T_KAM_HTML_FONT_INVALID autolearn=no autolearn_force=no version=4.0.0 X-Spam-Virus: No X-Envelope-From: Received: from mail-pl1-f172.google.com (mail-pl1-f172.google.com [209.85.214.172]) (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, 27 Aug 2024 07:27:37 +0000 (UTC) Received: by mail-pl1-f172.google.com with SMTP id d9443c01a7336-20202df1c2fso40021855ad.1 for ; Tue, 27 Aug 2024 00:25:43 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=jetbrains.com; s=googleapps; t=1724743543; x=1725348343; darn=lists.php.net; h=to:subject:message-id:date:from:mime-version:from:to:cc:subject :date:message-id:reply-to; bh=tV9fwCkR2sMtNPhuiJq/Tb3+fJbPjZlzI38kTjR/Z+8=; b=FW4etgnUkjolkHB9BsS0ejXs25CC2MS6K49AWSNqFq3lUVwlaE9mOzkYuV4jLvi3+F iyxTSTX4W1wZ+cmSIrWJAC+R9dVLdLwqKL3qMv1SMLUcoH1aIYqbb9S1g3kWy6zsz5Rw 0lvznGs1TS+U7R7FrR7sq6Bs+IAL6hrvztnbo= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1724743543; x=1725348343; h=to:subject:message-id:date:from:mime-version:x-gm-message-state :from:to:cc:subject:date:message-id:reply-to; bh=tV9fwCkR2sMtNPhuiJq/Tb3+fJbPjZlzI38kTjR/Z+8=; b=mczEAZEU47j0ECfDg66DjzlkfW+VEybfDb6V3ZJoH2Ep3mEFimq04Px4HzkN0yYP28 Otm+cNsrZMWxZy7fkU6lim3anH74lUrU0Xe+EJeaTSveyBnmjD2SMKwWPnNsE6Rjg0F5 SUmFzzB84cyzSJhdjYJuQByU/ftsFLpSisGJFxamk9aj9CNBEC7A9MtzuUXwVutOGjF+ At25v5c1nkeTjobsf+cI9f0DMlofGOKphEiO8a9R9ZMh1EQ5cVfcMN97eu3Lku33dS22 Y42EoXlirU3jZe4qGiA6w29Dh+mPdiIEL6/hDS4HYJjECT/5RK35Rvy+uQTFMSy32Z6L 5S5g== X-Gm-Message-State: AOJu0Yy3oQGTH+l00yt/5GkOnoPI++cCN/d+zWaG4MiaHo4NYo6/4HW3 bBntjL6KVRZ6ytQqTYBvxAEk0Q3dsTShDba5dtothlZNNmS7vmR8DpXeM9FrLPdUnOkKQ52lzrL bryWNBiBMS07XkH5oR0OeWl9WbQYyGO5pSRRJpYKLTBUT8ulfCQ== X-Google-Smtp-Source: AGHT+IFHXS95xle9ouxxXmUSZcX2KxDE65xZ5aq063/NTD/NX4SVn9m0/y/nePdhGo8miDjZ4HLb5HZXeuh7TiPCy9Y= X-Received: by 2002:a17:902:dac9:b0:201:f2a4:cf74 with SMTP id d9443c01a7336-204dddc4482mr35793335ad.22.1724743542318; Tue, 27 Aug 2024 00:25:42 -0700 (PDT) Precedence: bulk list-help: list-post: List-Id: internals.lists.php.net x-ms-reactions: disallow MIME-Version: 1.0 Date: Tue, 27 Aug 2024 09:25:31 +0200 Message-ID: Subject: [PHP-DEV] [Discussion] Implementing interfaces via traits To: PHP Internals Content-Type: multipart/alternative; boundary="0000000000002bf2b60620a52628" From: brent.roose@jetbrains.com (Brent Roose) --0000000000002bf2b60620a52628 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable Good morning internals I=E2=80=99d like to test the waters about an RFC idea: allowing traits to i= mplement interfaces, and consequently a class that uses such a trait will automatically implement the interface as well. The original idea comes from Rust, where traits can be used as types. I read a very inspiring post suggested by Larry, on the topic of =E2=80=9Ccla= ssic inheritance=E2=80=9D vs the way Rust and Go approach it [1]. The tl;dr is t= hat both Rust and Go solve several pitfalls of classical inheritance (the diamond problem and inheritance abuse), thanks to a much simpler approach. In Rust=E2=80=99s case that is by using traits. If you have the time, I highly recommend reading that post, it=E2=80=99s super interesting and it gives a = lot of good arguments for rethinking inheritance. Back to PHP, using traits as types seems impossible, since traits are a compile-time copy/paste mechanism, which means there=E2=80=99s no type info= rmation available about them at runtime. However, allowing traits to implement interfaces would solve this problem: these interfaces would be copied over to classes during compile-time, and the interface=E2=80=99s type information is available at runtime. On top of= that, traits already have well-defined rules for conflict resolution, so we wouldn=E2=80=99t need any additional syntax to handle edge cases. Even though PHP traits differ from Rust, PHP developers already seem to like the idea of being able to =E2=80=9Cattach a type to a trait=E2=80=9D o= ne way or another. Let me name a couple of things that happen today: - Laravel often provides =E2=80=9Cdefault implementations=E2=80=9D for the= ir interfaces via a trait [2]. As mentioned before, traits already deal with conflict-resolution, so method collisions aren=E2=80=99t a blocker. - Both PHPStan and Psalm have an annotation that forces trait users to implement an interface [3], which is essentially the feature I=E2=80=99m describing, albeit via docblock annotations instead of proper syntax. - Even though it was not accepted, the interface default methods RFC approached the problem from a different angle [4]. While a majority disagreed that interfaces should implement their own methods directly, I remember it was a heavily debated topic, and believe that approaching it from the other side might be easier to accept. In the end, the goal of this RFC would be to promote a =E2=80=9Cnew way=E2= =80=9D of inheritance, which is described in depth in that post I mentioned earlier [1]. It=E2=80=99s a different programming style, but I think there are good arguments to be made for it, even though it will likely not be everyone=E2= =80=99s cup of tea. Modern languages like Rust and Go show that there=E2=80=99s mer= it in rethinking classical inheritance, and there are signs that the PHP community is open to it as well, given the examples with Laravel=E2=80=99s = default implementation traits, static analyser support, as well as the interface default methods RFC last year. If internals are open to the idea, I would like to draft a proper RFC for it. Please let me know your thoughts! Brent Links: - [1] https://lwn.net/Articles/548560/ - [2a] https://github.com/laravel/framework/blob/11.x/src/Illuminate/Auth/Authe= nticatable.php - [2b] https://github.com/laravel/framework/blob/11.x/src/Illuminate/Contracts/= Auth/Authenticatable.php - [2c] https://github.com/laravel/framework/blob/11.x/src/Illuminate/Contracts/= Auth/MustVerifyEmail.php - [2d] https://github.com/laravel/framework/blob/11.x/src/Illuminate/Auth/MustV= erifyEmail.php - [3a] https://phpstan.org/writing-php-code/phpdocs-basics#enforcing-implementi= ng-an-interface-for-traits - [3b] https://psalm.dev/docs/annotating_code/supported_annotations/#psalm-requ= ire-implements - [4] https://wiki.php.net/rfc/interface-default-methods --0000000000002bf2b60620a52628 Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable

Good morning internals


I=E2=80=99d like to test the wa= ters about an RFC idea: allowing traits to implement interfaces, and conseq= uently a class that uses such a trait will automatically implement the inte= rface as well.


The original idea comes from Rust, where traits can= be used as types. I read a very inspiring post suggested by Larry, on the = topic of =E2=80=9Cclassic inheritance=E2=80=9D vs the way Rust and Go appro= ach it [1]. The tl;dr is that both Rust and Go solve several pitfalls of cl= assical inheritance (the diamond problem and inheritance abuse), thanks to = a much simpler approach. In Rust=E2=80=99s case that is by using traits. If= you have the time, I highly recommend reading that post, it=E2=80=99s supe= r interesting and it gives a lot of good arguments for rethinking inheritan= ce.


Back to PHP, using traits as types seems impossible, since tra= its are a compile-time copy/paste mechanism, which means there=E2=80=99s no= type information available about them at runtime.


However, allowi= ng traits to implement interfaces would solve this problem: these interface= s would be copied over to classes during compile-time, and the interface=E2= =80=99s type information is available at runtime. On top of that, traits al= ready have well-defined rules for conflict resolution, so we wouldn=E2=80= =99t need any additional syntax to handle edge cases.


Even though= PHP traits differ from Rust, PHP developers already seem to like the idea = of being able to =E2=80=9Cattach a type to a trait=E2=80=9D one way or anot= her. Let me name a couple of things that happen today:


  • Laravel often provide= s =E2=80=9Cdefault implementations=E2=80=9D for their interfaces via a trai= t [2]. As mentioned before, traits already deal with conflict-resolution, s= o method collisions aren=E2=80=99t a blocker.

  • B= oth PHPStan and Psalm have an annotation that forces trait users to impleme= nt an interface [3], which is essentially the feature I=E2=80=99m describin= g, albeit via docblock annotations instead of proper syntax.

  • Even though it was not accepted, the interface default method= s RFC approached the problem from a different angle [4]. While a majority d= isagreed that interfaces should implement their own methods directly, I rem= ember it was a heavily debated topic, and believe that approaching it from = the other side might be easier to accept.


In the end, th= e goal of this RFC would be to promote a =E2=80=9Cnew way=E2=80=9D of inher= itance, which is described in depth in that post I mentioned earlier [1]. I= t=E2=80=99s a different programming style, but I think there are good argum= ents to be made for it, even though it will likely not be everyone=E2=80=99= s cup of tea. Modern languages like Rust and Go show that there=E2=80=99s m= erit in rethinking classical inheritance, and there are signs that the PHP = community is open to it as well, given the examples with Laravel=E2=80=99s = default implementation traits, static analyser support, as well as the inte= rface default methods RFC last year.


If internals are open to the = idea, I would like to draft a proper RFC for it. Please let me know your th= oughts!


Brent


Links:


--0000000000002bf2b60620a52628--