Re: The case for transpiled generics
| From: | Brent Roose | Date: | Fri, 18 Sep 2020 04:28:37 +0000 |
| Subject: | Re: The case for transpiled generics | ||
| References: | 1 2 | Groups: | php.internals |
| Request: | Send a blank email to internals+get-111897@lists.php.net to get a copy of this message | ||
Hi all
To make myself clear, since I realise I used a confusing term in the subject of my mail. What
I'm proposing is runtime-erased generics, the way Matthew describes them: PHP completely
ignores them during runtime, and wouldn't do anything with them during compile time. It's
up to third party tooling to do type checks. And I just want to point out to people who haven't
used any static analysers in PHP before: they are very_ insightful in knowning what your code does,
without running it. I don't think there's reason to fear to not checking these types at
runtime, since static analysis truly takes care of them.
Thanks Matthew for pitching in, I believe the opinion of the ones building and maintaining the
current static analysis toolset in PHP is essential in this discussion.
Kind regards
Brent
> On 17 Sep 2020, at 23:00, Matthew Brown <matthewmatthew@gmail.com> wrote:
>
> I think the addition of runtime-erased generics would be a good thing for the language.
>
> I don’t think PHP should perform any sort of checking of generic parameters at compile time.
> No other equivalent interpreter performs those compile-time checks, and it’s also *very* complex
> — since adding support for generics in Psalm I’ve spent the ensuing two years fixing many bugs
> and filling various holes that have cropped up. Hack, introduced in 2014 and written by bunch of
> people far smarter than me, had at least one hole in its type-checker’s generics handling that was
> only patched last year.
>
> PHP could develop a separate official type-checker to be used alongside its interpreter,
> similar to Hack’s (hh_check) or TypeScript’s (typescript-checker), but that’s an entirely
> separate conversation.
>
> ———
>
> If this proposal happens, the documentation should make it *super* clear that all generic types
> are erased at runtime.
>
> Erased generics would not support code like this:
>
> ```
> function filter<T of object>(array<int, object> $arr) : array<int, T> {
> $new = [];
> foreach ($arr as $a) {
> if ($a instanceof T) {
> $new[] = $a;
> }
> }
> }
> ```
>
> Instead PHP would need to support a type classname<T> (or similar) to allow passing
> generic params explicitly.
>
> ```
> function filter<T of object>(array<int, object> $arr, classname<T> $t_class)
> : array<int, T> {
> $new = [];
> foreach ($arr as $a) {
> if ($a instanceof $t_class) {
> $new[] = $a;
> }
> }
> }
> ```
>
> The implementation would also need a way of denoting covariant (pretty common) and
> contravariant (very rare) generic parameters, like Hack does.
>
>
>> On Sep 17, 2020, at 7:34 AM, Brent Roose <brendt@stitcher.io> wrote:
>>
>> Hello internals
>>
>> Today I'd like to hear your thoughts on what might be a controversial topic, though I
>> think it's worth having this discussion. I want to make the case for adding generic syntax,
>> without actually enforing any additional type checks at runtime. Please hear me out.
>>
>> We've been discussing generics for years now [1][2], all without any result.
>> Nikita's latest attempt [3] stalled because, from what I gathered and amongst other things,
>> doing generic type checks at runtime has a significant impact on performance.
>>
>> On the other hand, static analysers have been making their rise for a few years now.
>> Granted: not the whole community might like this kind of type strictness, and PHP doesn't force
>> them to; but still projects like PhpStorm acknowledge their significance — they will add built-in
>> support for both psalm and PHPStan later this year [4]. Rasmus Lerdorf also showed interest in the
>> idea of improving PHP's static analysis capabilities two years ago [5].
>>
>> That all to say that there's a significant part of the PHP community who's
>> interested in embracing the benefits of static analysis.
>>
>> If we look outside of our PHP bubble, we can see the same thing happening in JavaScript:
>> the core benefit that TypeScript adds is its robust static analysis. Sure those developers need an
>> extra compilation step to transpile their code to plain old JavaScript, but it seems that they
>> are… fine with that?
>>
>> I'd like to discuss a similar idea for PHP. If runtime generics aren't possible
>> because of performance issues, why not explore the other option: adding generic syntax that is
>> ignored by the interpreter, but can be used by static analysis tools — third party of built-into
>> PHP, that's another discussion. I realise this thought goes against the "PHP mindset"
>> we've been programming with for more than 20 years, but we I think we shouldn't ignore
>> what's happening in the PHP- and wider progamming community: static analysis is relevant,
>> whether you want to use it or not, and a stricter type system is prefered by many.
>>
>> Now I know there are alternatives we can use today. Static analysers already support
>> generics, using doc blocks. I'm not trying to argue that it's impossible to achieve the
>> same results with the toolset we have, but rather that there's room for improvement from the
>> developer's point of view. History has shown that such convenience additions to PHP have been a
>> difficult pill to swallow for some, but on the other hand those kind of changes _have_ been
>> happening more and more often anyway: property promotion, short closures, named arguments,
>> attributes, yes even types themselves: you can write the same working PHP program without any of
>> those features, and yet they have been proven so useful and wanted over the last years.
>>
>> As a sidenote: the idea of transpiling is already present in PHP. Looking at constructor
>> property promotion: a purely syntactical feature, which is transformed to simpler PHP code at
>> runtime. Nikita called this principle "desugaring" in the constructor property promotion
>> RFC [6].
>>
>> So here's my case for transpiled generics summarized:
>>
>> - There's no significant runtime performance impact
>> - The PHP community is already embracing static analysis
>> - Transpiling has been proved to be a viable workflow, thanks to TypeScript
>> - As with all things-PHP: it's opt-in. You don't have to use the syntax if you
>> don't want to and you won't experience any downsides
>>
>> So with all that being said, I'm looking forward to hearing your thoughts.
>>
>> Kind regards
>> Brent
>>
>> [1] https://wiki.php.net/rfc/generics
>> <https://wiki.php.net/rfc/generics>
>> [2] https://wiki.php.net/rfc/generic-arrays
>> <https://wiki.php.net/rfc/generic-arrays>
>> [3]
>> https://github.com/PHPGenerics/php-generics-rfc/issues/45
>> <https://github.com/PHPGenerics/php-generics-rfc/issues/45>
>> [4]
>> https://blog.jetbrains.com/phpstorm/2020/07/phpstan-and-psalm-support-coming-to-phpstorm/
>> <https://blog.jetbrains.com/phpstorm/2020/07/phpstan-and-psalm-support-coming-to-phpstorm/>
>>
>> [5] https://externals.io/message/101477#101592
>> <https://externals.io/message/101477#101592>
>> [6]
>> https://wiki.php.net/rfc/constructor_promotion#desugaring
>> <https://wiki.php.net/rfc/constructor_promotion#desugaring>