On Tue, 27 August in 2024 at 10:31, Brent Roose <brent.ro...@jetbrains.com> wrote:
> Good morning internals > > I’d 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 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 “classic > inheritance” 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’s case that is by using traits. If you have the time, I highly > recommend reading that post, it’s 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’s no type information > 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’s type information is available at runtime. On top of that, > traits already have well-defined rules for conflict resolution, so we > wouldn’t 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 “attach a type to a trait” one way or > another. Let me name a couple of things that happen today: > > > - > > Laravel often provides “default implementations” for their interfaces > via a trait [2]. As mentioned before, traits already deal with > conflict-resolution, so method collisions aren’t a blocker. > - > > Both PHPStan and Psalm have an annotation that forces trait users to > implement an interface [3], which is essentially the feature I’m > 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 “new way” of > inheritance, which is described in depth in that post I mentioned earlier > [1]. It’s a different programming style, but I think there are good > arguments to be made for it, even though it will likely not be everyone’s > cup of tea. Modern languages like Rust and Go show that there’s merit in > rethinking classical inheritance, and there are signs that the PHP > community is open to it as well, given the examples with Laravel’s 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/Authenticatable.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/MustVerifyEmail.php > - > > [3a] > > https://phpstan.org/writing-php-code/phpdocs-basics#enforcing-implementing-an-interface-for-traits > - > > [3b] > > https://psalm.dev/docs/annotating_code/supported_annotations/#psalm-require-implements > - > > [4] https://wiki.php.net/rfc/interface-default-methods > > Hi, Brent! Let me link another relevant discussion about adding `@(phpstan|psalm)-require-implements` to the core: https://externals.io/message/116802 . -- Valentin