Commit a4d238f
committed
Allow passing methods with arguments to
Since 01863f2
introduced `callable(static): mixed` type hint for the `extensionMethod` parameter,
it is no longer possible to pass functions with more than one argument to it.
This is because argument of type `callable(static): mixed` only has a limited
number of subtypes: functions that can be called with the `static` argument,
i.e. those functions expecting any superclass of `static`.
The functions can also narrow down as they want since the return type
since `mixed` is supertype of every type.
The functions cannot have any extra arguments since the container
would not know what to pass to them. But having fewer arguments is fine
since PHP will ignore any extra arguments passed to a function.
Formally, the subtyping relation of callables must respect
the variance rules:
https://www.php.net/manual/en/language.oop5.variance.php
If we want to allow wider range of subtypes, we must choose a suitably
wide supertype in the type lattice. One option would be just using `mixed`
or `callable` but those do not really guide user very well.
We want to include at least the `static` argument since that
is always passed by `__call`.
One option would be using a _bottom_ type (`never`) as the parameter type
since it is a subtype of any type – the function with `never` argument
can never be called so substituting it with a function that accepts
a supertype cannot break any callers, satisfying the contravariance
rule. For the return type, we can use a _top_ type (`mixed`) since
callers expecting mixed must be able to deal with narrower types
so functions returning a subtype cannot break anything either,
thus covariance of return type.
The main limitation is that we can only have as many arguments
as we specify in the type signature as mentioned above.
I chose 9 extra arguments since that should be enough for most uses.
https://phpstan.org/writing-php-code/phpdoc-types#bottom-type
Though, since the function with `never` argument cannot be called
because there are no values that can inhabit `never` type, and thus
there is nothing to be passed to arguments, we need to cast down the
arguments in `__call` to `never` types. This is a valid operation
since `never` is a subtype of any type but it is a bit weird.
https://phpstan.org/writing-php-code/phpdocs-basics#inline-%40varextensionMethod
1 parent 90aac9e commit a4d238f
2 files changed
Lines changed: 6 additions & 4 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
36 | 36 | | |
37 | 37 | | |
38 | 38 | | |
39 | | - | |
| 39 | + | |
40 | 40 | | |
41 | 41 | | |
42 | 42 | | |
| |||
626 | 626 | | |
627 | 627 | | |
628 | 628 | | |
| 629 | + | |
629 | 630 | | |
630 | 631 | | |
631 | 632 | | |
632 | 633 | | |
633 | 634 | | |
634 | 635 | | |
635 | 636 | | |
636 | | - | |
| 637 | + | |
637 | 638 | | |
638 | 639 | | |
639 | 640 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
50 | 50 | | |
51 | 51 | | |
52 | 52 | | |
53 | | - | |
| 53 | + | |
54 | 54 | | |
55 | 55 | | |
56 | 56 | | |
| |||
566 | 566 | | |
567 | 567 | | |
568 | 568 | | |
| 569 | + | |
569 | 570 | | |
570 | 571 | | |
571 | 572 | | |
| |||
576 | 577 | | |
577 | 578 | | |
578 | 579 | | |
579 | | - | |
| 580 | + | |
580 | 581 | | |
581 | 582 | | |
582 | 583 | | |
| |||
0 commit comments