Similar to #1044, but with a complex type asserted
https://getpsalm.org/r/7396e44181
<?php
/**
* @template T
* @template-typeof T $type
*
* @psalm-assert-if-true iterable<mixed,T> $i
*
* @param iterable<mixed,mixed> $i
* @param class-string $type
*/
function allInstanceOf(iterable $i, string $type): bool {
/** @psalm-suppress MixedAssignment */
foreach ($i as $elt) {
if (!$elt instanceof $type) {
return false;
}
}
return true;
}
interface IBlogPost { public function getId(): int; }
function getData(): iterable {
return [];
}
$data = getData();
assert(allInstanceOf($data, IBlogPost::class));
foreach ($data as $post) {
echo $post->getId(); // should be fine
}
Expected: No issues
Actual:
Psalm output (using commit 51c6621):
ERROR: UndefinedClass - 35:10 - Class or interface T does not exist
@psalm-assert currently isn't designed to assert any complicated type (union, generic or intersection), but I should definitely figure this out.
This is a big diff, but it gets the feature over the line. The challenge was adapting the Reconciler class, which is designed to reconcile things that can be asserted in conditionals with lists of variable types so it could also reconcile these hand-made generic assertions which can't actually be expressed in a conditional (atm at least, Hack has some cool ways around this)
Most helpful comment
This is a big diff, but it gets the feature over the line. The challenge was adapting the
Reconcilerclass, which is designed to reconcilethings that can be asserted in conditionalswithlists of variable typesso it could also reconcile these hand-made generic assertions which can't actually be expressed in a conditional (atm at least, Hack has some cool ways around this)