Skip to content

Commit 5f4a74b

Browse files
committed
Improve partitionT inference
1 parent f3b9034 commit 5f4a74b

File tree

2 files changed

+35
-10
lines changed

2 files changed

+35
-10
lines changed

src/Fp/Psalm/Hook/FunctionReturnTypeProvider/PartitionFunctionReturnTypeProvider.php

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -56,16 +56,28 @@ public static function getFunctionReturnType(FunctionReturnTypeProviderEvent $ev
5656
fn() => proveOf($event->getStatementsSource(), StatementsAnalyzer::class),
5757
fn() => Option::some($type_params),
5858
))
59-
->map(fn(ArrayList $args) => $args
60-
->mapN(ctor(RefinementContext::class))
61-
->map(RefineByPredicate::for(...))
62-
->map(fn(CollectionTypeParams $params) => new Union(
63-
[new TList($params->val_type)],
64-
))
65-
->appended(new Union(
66-
[new TList($type_params->val_type)],
67-
))
68-
->toList())
59+
->map(function(ArrayList $args) use ($type_params) {
60+
$init_types = $args
61+
->mapN(ctor(RefinementContext::class))
62+
->map(RefineByPredicate::for(...))
63+
->map(fn(CollectionTypeParams $params) => $params->val_type);
64+
65+
$last_type = $init_types
66+
->fold($type_params->val_type)(
67+
function(Union $last, Union $current) {
68+
$cloned = clone $last;
69+
$cloned->removeType($current->getId());
70+
71+
return $cloned;
72+
},
73+
);
74+
75+
return $init_types
76+
->appended($last_type)
77+
->map(fn(Union $type) => [new TList($type)])
78+
->map(ctor(Union::class))
79+
->toList();
80+
})
6981
)
7082
->flatMap(fn(array $partitions) => asNonEmptyArray($partitions))
7183
->map(function(array $non_empty_partitions) {

tests/Static/Functions/Collection/PartitionStaticTest.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@
44

55
namespace Tests\Static\Functions\Collection;
66

7+
use Tests\Mock\Bar;
8+
use Tests\Mock\Baz;
9+
use Tests\Mock\Foo;
10+
711
use function Fp\Collection\partitionT;
812

913
final class PartitionStaticTest
@@ -29,4 +33,13 @@ public function testPartitionWithTwoPredicates(array $nums): array
2933
fn(int $v) => $v % 2 === 1,
3034
);
3135
}
36+
37+
/**
38+
* @param list<Foo|Bar|Baz> $list
39+
* @return array{list<Foo>, list<Bar>, list<Baz>}
40+
*/
41+
public function testExhaustiveInference(array $list): array
42+
{
43+
return partitionT($list, fn($i) => $i instanceof Foo, fn($i) => $i instanceof Bar);
44+
}
3245
}

0 commit comments

Comments
 (0)