Warn about mismatch of callables passed to usort, array_filter, array_map, etc
Related to #726
Also, warn about using uksort with a callable that doesn't accept int or strings, depending on the real array type.
Here a example source code I wanted using on a new issue for uasort:
<?php
class ValueObject {
private $value;
public function __construct( $value ) {
$this->value = $value;
}
public function getSomething() {
return $this->value;
}
}
class ValueObject2 {
private $value2;
public function __construct( $value2 ) {
$this->value2 = $value2;
}
public function getSomething2() {
return $this->value2;
}
}
class TestUasort {
/** @var ValueObject[] */
protected $valueObjects;
/**
* @param ValueObject[] $valueObjects
*/
public function __construct( $valueObjects ) {
$this->valueObjects = $valueObjects;
}
public function doSomething() {
// Could phan infer the types inside the closures to check the function names?
usort( $this->valueObjects, static function ( $a, $b ) {
'@phan-debug-var $a, $b';
return $b->getSomething2() <=> $a->getSomething();
} );
// Or to check the type hints against the array?
usort( $this->valueObjects, static function ( ValueObject2 $a, ValueObject2 $b ) {
'@phan-debug-var $a, $b';
return $b->getSomething2() <=> $a->getSomething2();
} );
// Mixing types in the sort closures are mistakes
usort( $this->valueObjects, static function ( ValueObject2 $a, ValueObject $b ) {
'@phan-debug-var $a, $b';
return $b->getSomething() <=> $a->getSomething2();
} );
// Fully typehinted is working:
usort( $this->valueObjects, static function ( ValueObject $a, ValueObject $b ) {
'@phan-debug-var $a, $b';
return $b->getSomething() <=> $a->getSomething();
} );
$valueObjects = $this->valueObjects;
'@phan-debug-var $valueObjects';
}
}
(new TestUasort( [
new ValueObject(1),
new ValueObject(2),
]))->doSomething();
It's probably doable by changing src/Phan/Plugin/Internal/MiscParamPlugin.php to analyze the function when called with two args of the types of elements (if !UnionType->isEmpty()) - an example that could be used as a reference would be src/Phan/Plugin/Internal/ClosureReturnTypeOverridePlugin.php for how arguments are built to be passed to ArgumentType::analyzeForCallback (etc.)
Similar approach is already taken for array_map in src/Phan/Plugin/Internal/ArrayReturnTypeOverridePlugin.php for #726