Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:125354 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 4091B1A00BD for ; Fri, 30 Aug 2024 06:09:51 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=php.net; s=mail; t=1724998305; bh=rJ+Okn0qNqxCNTYD/9MG7g3xDOqSEJFXvvT3Tp6yvGs=; h=References:In-Reply-To:From:Date:Subject:To:Cc:From; b=iz9wuFOXJwCGYdUbn5S0EdZ3cZsQrmBN6F5wEr/h16V3l0LcDHv3QB6tgbQnBt8TQ SWjwxNadVgV73FkpLF2bWXTG/od2CooTUN/mf655wAq4KwAjz/NZKIr/C72j2pyh45 9RNMeRPMLkhPiisHjPOlFSktqQwrJD+99rcF2dnDC/7XqN5xNlGWvjDZoDzzX6Puv4 twPkJP21E7+6e61EdENnY4hm5jcn/jXoXsXQ632gm53W1VUVu1QjVlAQ7E06da9KR9 XHWiXei68biSd+SNhA9sxPsMONImtRwHns10nuTtWtG9fRf7pQPB6Y6710fjpGOYB9 yOp24r2zsuBaA== Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id D6F7C18007B for ; Fri, 30 Aug 2024 06:11:44 +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,FREEMAIL_FROM, 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-yw1-f180.google.com (mail-yw1-f180.google.com [209.85.128.180]) (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 ; Fri, 30 Aug 2024 06:11:41 +0000 (UTC) Received: by mail-yw1-f180.google.com with SMTP id 00721157ae682-690aabe2600so12418487b3.0 for ; Thu, 29 Aug 2024 23:09:46 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1724998186; x=1725602986; darn=lists.php.net; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:from:to:cc:subject:date:message-id:reply-to; bh=paoJ3+jT3eHphPOUcUTY0bssB4OSf6MZh12CDn+p4mM=; b=dN1R2Fd0J7CnaOoYxty6twDS3jY2rBulj6qyRbSl8G7wq/Aj3zCfF02y62sl6xs0U5 m0tyENpsPuMglkH0ibD6Zxga+LxoVUvgQOaNHjS5BQEvkqd7HeZzoyNf9/0RyzyO9a5I dFcGVWZoh+b7wL4G1apAFy2VWD45NEuUWhzp8mXJfLabYGJGuTczXYTPLxDObgte1HVH KnDJf8DwA9Ie4Nmc3YkLjyToGJbZYBWwFODTbxkHvxx9hdyWl2XMcRkPMlAmmppwcqZO zQ+LXMWrdOwQ7whXkQ+YbCk++A8TzwyZCmzM0qnjI1dALfmpKavO/2LYQlKi+HIF0Ayb F+xw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1724998186; x=1725602986; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=paoJ3+jT3eHphPOUcUTY0bssB4OSf6MZh12CDn+p4mM=; b=mAi6bg8KdlxM6hqXEKo/YHG7bGRw+4UEg1G7VghRoI2CTjNhm6vD0wqJiSBM6FLQR3 6ru2QVU7hZz2Ra9haoX0hfrMEHFpSnbCcDmQQA6zytL2hpo49XyqGQ7dWc/8OLoAXg1X LU8H1CQmOrTVRUvgBTFbUB9I62n5hZ2fU8vSJHmpCHFUQatL1WuLhXeV3vLVF6wrFD8X RFzC75qpP3NaoBkuzwfoaGVLjnRFtvXRc21h3/0cLfzN/lUnv8JLp02pXP+h6/e/HpeL bjnlrC9DK+LZTSnfHyeDJU3oSO4aHMpmga/5Z+nMVivZP4lnoZUj3ydxPf0X1LSqdFM2 d/BA== X-Gm-Message-State: AOJu0YzsjswUxKEsy8Z1amQyrjvfZJzrQdFmh63vHdk9/yQaf1zEgz7V nqGtDhVYuR91vkvKckqH59VieSj90/EjJKMl339g9ZcA8OgVUF+/r+CxUZ8+ITPYUq6wkABH0Y6 0TlSK+i50TpZs6rfpYuF0qoLh+UMHaxs+bGU= X-Google-Smtp-Source: AGHT+IF65OTP0pGwPXiB6XizwU22HrOd3b4ko/a5/8x3ea2m/s6Nztv9uiIjGixhxVwpBjZ4kWrASrONgOP/rqOA+Zg= X-Received: by 2002:a05:690c:340c:b0:6be:523:af4d with SMTP id 00721157ae682-6d40f3403eemr8410167b3.11.1724998185648; Thu, 29 Aug 2024 23:09:45 -0700 (PDT) Precedence: bulk list-help: list-post: List-Id: internals.lists.php.net x-ms-reactions: disallow MIME-Version: 1.0 References: In-Reply-To: Date: Fri, 30 Aug 2024 08:09:33 +0200 Message-ID: Subject: Re: [PHP-DEV] [Discussion] Implementing interfaces via traits To: Brent Roose Cc: PHP Internals Content-Type: multipart/alternative; boundary="000000000000180b220620e070f0" From: michal.brzuchalski@gmail.com (=?UTF-8?Q?Micha=C5=82_Marcin_Brzuchalski?=) --000000000000180b220620e070f0 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable Hi Brent, wt., 27 sie 2024 o 09:28 Brent Roose napisa=C5= =82(a): > Good morning internals > > I=E2=80=99d like to test the waters about an RFC idea: allowing traits to > implement interfaces, and consequently a class that uses such a trait wil= l > 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=9Cc= lassic > inheritance=E2=80=9D vs the way Rust and Go approach it [1]. The tl;dr is= that 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 high= ly > 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 in= formation > 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= one way or > another. Let me name a couple of things that happen today: > > > - > > Laravel often provides =E2=80=9Cdefault implementations=E2=80=9D for t= heir 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. > > With the recent RFC proposal for Default Expressions [5], I believe it presents an excellent opportunity to revisit the Interface Default Methods proposal. The Default Expressions RFC addresses similar functionality and, when combined with an opt-in feature flag, could resolve many concerns raised during the previous discussion. *Opt-In Feature Flag:* To address backward compatibility concerns, I propose the introduction of a feature flag, such as declare(default_methods =3D 1);, that could be applied when implementing an interface or when an interface extends another. This approach would allow developers to opt-in explicitly, preventing unintended BC breaks and ensuring that the feature is adopted carefully and intentionally. *Backward Compatibility Concerns:* The main concern from the previous discussion was the risk of BC breaks when new methods are added to an interface, potentially conflicting with existing implementations. Although the original RFC suggested that default implementations could mitigate these risks, contributors were worried that this might encourage developers to introduce BC breaks without proper versioning. The opt-in flag would make it clear when the feature is being used, thereby reducing the risk of unintentional conflicts. *Complexity and Developer Experience:* While the feature could significantly improve the developer experience, it also introduces complexity in how interfaces are used. To alleviate this, the default keyword could be explicitly used to mark default methods, making it easier for developers to understand and manage. For example: interface I1 { default public function foo(): int { return \PHP_INT_MAX; } } This explicit marking not only clarifies the intention behind the method but also aids in distinguishing between regular and default methods, simplifying the mental model required to work with interfaces. I believe these adjustments could make the Interface Default Methods more palatable to the community, ensuring that the feature enhances PHP without introducing unnecessary risks. Just thinking out loud here - looking forward to hearing some thoughts. Cheers, Micha=C5=82 Marcin Brzuchalski *Links:* [4] Interface Default Methods RFC [5] Default Expressions RFC --000000000000180b220620e070f0 Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable
Hi Brent,

wt., 27 sie 2024 o 09:28=C2=A0Br= ent Roose <brent.roose@jetbrains.com> napisa=C5=82(a):

Good morning internals


I=E2=80=99d like to test = the waters about an RFC idea: allowing traits to implement interfaces, and = consequently a class that uses such a trait will automatically implement th= e interface as well.


The original idea comes from Rust, where trai= ts can be used as types. I read a very inspiring post suggested by Larry, o= n the topic of =E2=80=9Cclassic inheritance=E2=80=9D vs the way Rust and Go= approach it [1]. The tl;dr is that both Rust and Go solve several pitfalls= of classical inheritance (the diamond problem and inheritance abuse), than= ks to a much simpler approach. In Rust=E2=80=99s case that is by using trai= ts. If you have the time, I highly recommend reading that post, it=E2=80=99= s super interesting and it gives a lot of good arguments for rethinking inh= eritance.


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


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


<= p dir=3D"ltr" style=3D"line-height:1.38;margin-top:0pt;margin-bottom:0pt"><= span style=3D"font-size:11pt;font-family:Arial,sans-serif;color:rgb(0,0,0);= background-color:transparent;font-variant-numeric:normal;font-variant-east-= asian:normal;font-variant-alternates:normal;vertical-align:baseline">Even t= hough 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= another. Let me name a couple of things that happen today:


<= ul style=3D"margin-top:0px;margin-bottom:0px">
  • Laravel oft= en provides =E2=80=9Cdefault implementations=E2=80=9D for their interfaces = via a trait [2]. As mentioned before, traits already deal with conflict-res= olution, so method collisions aren=E2=80=99t a blocker.

  • Both PHPStan and Psalm have an annotation that forces trait u= sers to implement an interface [3], which is essentially the feature I=E2= =80=99m describing, albeit via docblock annotations instead of proper synta= x.

  • Even though it was not accepted, the in= terface default methods RFC approached the problem from a different angle [= 4]. While a majority disagreed that interfaces should implement their own m= ethods directly, I remember it was a heavily debated topic, and believe tha= t approaching it from the other side might be easier to accept.

    <= /li>
  • =C2=A0

    With the recent= RFC proposal for Default Expressions [5], I believe it presents an excel= lent opportunity to revisit the Interface Default Methods proposal. The Def= ault Expressions RFC addresses similar functionality and, when combined wit= h an opt-in feature flag, could resolve many concerns raised during the pre= vious discussion.

    Opt-In Feature Flag: To address backward compatibility concerns, I propose the introduction of a= feature flag, such as declare(default_methods =3D 1);, that c= ould be applied when implementing an interface or when an interface extends= another. This approach would allow developers to opt-in explicitly, preven= ting unintended BC breaks and ensuring that the feature is adopted carefull= y and intentionally.

    Backward Compatibility Concerns: The main concern from the previous discussion was the risk of BC breaks whe= n new methods are added to an interface, potentially conflicting with exist= ing implementations. Although the original RFC suggested that default imple= mentations could mitigate these risks, contributors were worried that this = might encourage developers to introduce BC breaks without proper versioning= . The opt-in flag would make it clear when the feature is being used, there= by reducing the risk of unintentional conflicts.

    Complexity a= nd Developer Experience: While the feature could significantly improve the developer experience, it = also introduces complexity in how interfaces are used. To alleviate this, t= he default keyword could be explicitly used to mark default me= thods, making it easier for developers to understand and manage. For exampl= e:

    =
    interface I1 {
    default public function foo(): in= t { =20 return \PHP_INT_MAX; =20 } =20 }

    This explicit marking not only clarifies the in= tention behind the method but also aids in distinguishing between regular a= nd default methods, simplifying the mental model required to work with inte= rfaces.

    I believe these adjustments could make the Interface Default = Methods more palatable to the community, ensuring that the feature enhances= PHP without introducing unnecessary risks.

    Just thinking out loud he= re - looking forward to hearing some thoughts.

    Cheers,
    Micha=C5=82= Marcin Brzuchalski

    Links:
    [4] Interface Def= ault Methods RFC
    [5] Default Expressions RFC

    --000000000000180b220620e070f0--