[PHP-DEV] Make Closure covariant to callable

Hello internals,

Ondřej Mirtes (author of PHPStan) remarked to me in August that Closure is not a subtype of callable.
The implementation of this is quite straight forward and can be seen on GitHub. [1]
The question is if there are any concern or not and if this requires an RFC or can just be merged as is.

Best regards,

Gina P. Banyard

[1] Zend: Make Closure covariant to callable by Girgias · Pull Request #15492 · php/php-src · GitHub

On Tue, Nov 12, 2024, at 14:53, Gina P. Banyard wrote:

Hello internals,

Ondřej Mirtes (author of PHPStan) remarked to me in August that Closure is not a subtype of callable.

The implementation of this is quite straight forward and can be seen on GitHub. [1]

The question is if there are any concern or not and if this requires an RFC or can just be merged as is.

Best regards,

Gina P. Banyard

[1] https://github.com/php/php-src/pull/15492

Hey Gina,

I think saying “Closure should be a subtype of callable” would require an RFC. To say that “Closure should satisfy the callable type check” is just an oversight/bug. They are functionally the same IMO, just different perspectives.

— Rob

Le 12 nov. 2024 à 14:53, Gina P. Banyard <internals@gpb.moe> a écrit :

Hello internals,

Ondřej Mirtes (author of PHPStan) remarked to me in August that Closure is not a subtype of callable.
The implementation of this is quite straight forward and can be seen on GitHub. [1]
The question is if there are any concern or not and if this requires an RFC or can just be merged as is.

Best regards,

Gina P. Banyard

[1] Zend: Make Closure covariant to callable by Girgias · Pull Request #15492 · php/php-src · GitHub

Hi Gina,

That seems reasonable.

But personally, I would be more interested in having a type equivalent to `callable&object`, that is all objects that implement the `__invoke()` magic method (this is a strict super-type of \Closure).

—Claude

On 12/11/2024 14:53, Gina P. Banyard wrote:

Hello internals,

Ondřej Mirtes (author of PHPStan) remarked to me in August that Closure is not a subtype of callable.
The implementation of this is quite straight forward and can be seen on GitHub. [1]
The question is if there are any concern or not and if this requires an RFC or can just be merged as is.

Best regards,

Gina P. Banyard

[1] Zend: Make Closure covariant to callable by Girgias · Pull Request #15492 · php/php-src · GitHub

Hi Gina

Makes sense to me.

Kind regards
Niels

On Tue, Nov 12, 2024, at 10:43 AM, Claude Pache wrote:

Le 12 nov. 2024 à 14:53, Gina P. Banyard <internals@gpb.moe> a écrit :

Hello internals,

Ondřej Mirtes (author of PHPStan) remarked to me in August that Closure is not a subtype of callable.
The implementation of this is quite straight forward and can be seen on GitHub. [1]
The question is if there are any concern or not and if this requires an RFC or can just be merged as is.

Best regards,

Gina P. Banyard

[1] Zend: Make Closure covariant to callable by Girgias · Pull Request #15492 · php/php-src · GitHub

Hi Gina,

That seems reasonable.

But personally, I would be more interested in having a type equivalent
to `callable&object`, that is all objects that implement the
`__invoke()` magic method (this is a strict super-type of \Closure).

—Claude

I am in favor of Closure being covarant to callable, and to a new pseudo-type for Closure|Object-with-__invoke. (Maybe Invokable?) I do think they'd require brief RFCs, but both would have my support.

--Larry Garfield

On Tuesday, 12 November 2024 at 16:43, Claude Pache <claude.pache@gmail.com> wrote:

But personally, I would be more interested in having a type equivalent to `callable&object`, that is all objects that implement the `__invoke()` magic method (this is a strict super-type of \Closure).

—Claude

An Invokable interface, similar to Stringable would be the solution to this.
And this is something that Ondřej also brought up in the PR.
I would be in favour for such an interface (considering the cat is already out of the bag of auto-implementing things with Stringable).
But I don't think I have the time/bandwidth to work on this, so if anyone wants something "easy" to work on that would be it.

Best regards,

Gina P. Banyard

There are some weird cases with `callable` which is why they aren't
allowed as a property type. I don't remember all the edges, but if we
are sure that we cannot hit those with simple co-/contra-variance,
then I don't think this needs an RFC and we can just merge the PR.

On Wednesday, 13 November 2024 at 00:46, Levi Morrison <levi.morrison@datadoghq.com> wrote:

There are some weird cases with `callable` which is why they aren't
allowed as a property type. I don't remember all the edges, but if we
are sure that we cannot hit those with simple co-/contra-variance,
then I don't think this needs an RFC and we can just merge the PR.

The reason that callable is not allowed as a property type is due to scope/method visibility issues.
See the discussion section of Nikita's Deprecate partially supported callables RFC: PHP: rfc:deprecate_partially_supported_callables
The callable type is allowed as a parameter and return type, and Closure is "better" defined than just callable.

Best regards,

Gina P. Banyard

> There are some weird cases with `callable` which is why they aren't
> allowed as a property type. I don't remember all the edges, but if we
> are sure that we cannot hit those with simple co-/contra-variance,
> then I don't think this needs an RFC and we can just merge the PR.

The reason that callable is not allowed as a property type is due to scope/method visibility issues.
See the discussion section of Nikita's Deprecate partially supported callables RFC: PHP: rfc:deprecate_partially_supported_callables
The callable type is allowed as a parameter and return type, and Closure is "better" defined than just callable.

Then personally I see no reason to make this an RFC and would
recommend merging it in as a gap in existing features (not really a
new feature).