New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Forbid template annotation on closures #5499
Conversation
Apparently people use them. /cc: @azjezz |
checked again, hack allows generic closures but implicitly, e.g: function main(): void {
$c = ($v, $val): bool ==> {
foreach($v as $t) {
if ($t === $val) { return true; }
}
return false;
};
$c(vec[1, 2, 3], 3);
} the hack type checker doesn't complain about anything for that example, with psalm, this would be an error because of the missing parameter types. |
so technically, the code that is currently failing in PSL, would pass in Hack if i remove all parameter types, as the type checker would get that it is generic ( even tho not explicitly ), but this would result in an error in psalm. i personally like having support for generic in closures ( even variables/constants, see #3963 ) |
How do you know it's actually generic and not just untyped? |
It's not untyped, hack detects the type automatically depending on the usage of the closure. if we add and it can't be un-typed since hack doesn't allow thing to be un-typed ( at least at the strictest level ) so if psalm is to remove generics, it needs to add the ability to automatically detect type of callables without having to specify them based on usage. |
hm, actually, looking at it, i think one of the failed cases in psl can be fixed without using generics in closure, however, i still need to specify the type: https://psalm.dev/r/65b9344e48 here's a re-implementation with hack that passes: |
I found these snippets: https://psalm.dev/r/65b9344e48<?php
/**
* Performs left-to-right function composition.
*
* Example:
*
* $greet = Fun\pipe(
* static fn(string $value): string => 'Hello' . $value,
* static fn(string $value): string => $value . '!',
* static fn(string $value): string => '¡' . $value
* );
*
* $greet('World')
* => Str('¡Hello World!');
*
* $greet('Jim')
* => Str('¡Hello Jim!');
*
* @template T
*
* @param callable(T): T ...$stages
*
* @return callable(T): T
*
* @pure
*/
function pipe(callable ...$stages): callable
{
return static fn ($input) => reduce(
$stages,
/**
* @param T $input
* @param (callable(T): T) $next
*
* @return T
*/
static fn ($input, callable $next) => $next($input),
$input
);
}
/**
* Reduce iterable using a function.
*
* The reduction function is passed an accumulator value and the current
* iterator value and returns a new accumulator. The accumulator is initialized
* to $initial.
*
* Examples:
*
* Iter\reduce(Iter\range(1, 5), fn($accumulator, $value) => $accumulator + $value, 0)
* => 15
*
* Iter\reduce(Iter\range(1, 5), fn($accumulator, $value) => $accumulator * $value, 1)
* => 120
*
* @template Tk
* @template Tv
* @template Ts
*
* @param iterable<Tk, Tv> $iterable
* @param (callable(Ts, Tv): Ts) $function
* @param Ts $initial
*
* @return Ts
*/
function reduce(iterable $iterable, callable $function, $initial)
{
$accumulator = $initial;
foreach ($iterable as $v) {
$accumulator = $function($accumulator, $v);
}
return $accumulator;
}
|
okay, all PSL issues have been fixed in azjezz/psl#176, i think the "detect callable type based on usage" feature can be tracked in another issue. ( @muglug if you are update the PSL fork, note that psalm configs are now in tools/psalm/psalm.xml, and not the source directory anymore, see azjezz/psl#174 ) |
They don't work properly anyway. Fixes vimeo#5472
0a036b6
to
8a8e042
Compare
Thanks! |
They don't work properly anyway.
Fixes #5472