php-standard-library / psalm-plugin

Psalm integration for the PHP Standard Library
MIT License
24 stars 6 forks source link

[Fun] pipe : calculate expected types per stage #6

Closed veewee closed 2 years ago

veewee commented 2 years ago

Supports: psl v2 Not supported: psl v1

This hook calculates the different stages of the Fun\pipe() combinator. It allows for a deep inspection of the different stages.

Examples:

$stages = pipe(
    static fn (string $x): int => 2,
    static fn (string $y): float => 1.2
);
$stages('hello');
ERROR: InvalidArgument - ../tests/static-analysis/Fun/pipe.php:75:9 - Argument 2 of psl\fun\pipe expects Closure(int):float, pure-Closure(string):float(1.2) provided (see https://psalm.dev/004)
        static fn (string $y): float => 1.2
$stages = pipe(
    static fn (string $x): int => 2,
    static fn (int $y): float => 1.2
);
$stages(143);
ERROR: InvalidArgument - ../tests/static-analysis/Fun/pipe.php:89:13 - Argument 1 expects string, 143 provided (see https://psalm.dev/004)
    $stages(143);
$stages = pipe(
    static fn (string $x): int => 2,
);

Psl\invariant(is_int($stages('hello')), 'Expected output of int');
ERROR: RedundantCondition - ../tests/static-analysis/Fun/pipe.php:102:19 - int always contains int (see https://psalm.dev/122)
    Psl\invariant(is_int($stages('hello')), 'Expected output of int');

It currently can only deal with FunctionLike arguments. When the arguments are expressions, this hook will fall back to Closure(mixed): mixed.