Skip to content

Commit ee64f03

Browse files
committed
Callable with wider parameter type is supertype of callable with narrower parameter type
1 parent 25658f6 commit ee64f03

4 files changed

Lines changed: 92 additions & 3 deletions

File tree

‎src/Type/CallableTypeHelper.php‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ public static function isParametersAcceptorSuperTypeOf(
7474
if ($treatMixedAsAny) {
7575
$isSuperType = $theirParameter->getType()->acceptsWithReason($ourParameterType, true);
7676
} else {
77-
$isSuperType = new AcceptsResult($theirParameter->getType()->isSuperTypeOf($ourParameterType), []);
77+
$isSuperType = new AcceptsResult($ourParameterType->isSuperTypeOf($theirParameter->getType()), []);
7878
}
7979

8080
if ($isSuperType->maybe()) {
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
<?php // lint >= 8.0
2+
3+
declare(strict_types = 1);
4+
5+
namespace Bug11285;
6+
7+
use function PHPStan\Testing\assertType;
8+
9+
/**
10+
* @template T
11+
* @template U
12+
*/
13+
class Templated
14+
{
15+
16+
/**
17+
* @param callable(T|U): void $callback
18+
*/
19+
public function compare(callable $callback): void {
20+
21+
}
22+
}
23+
24+
class ClassA {}
25+
class ClassB {}
26+
27+
28+
class Test
29+
{
30+
/**
31+
* @param Templated<ClassA, ClassB>|Templated<ClassA, ClassA> $t
32+
*/
33+
public function broken(
34+
Templated $t,
35+
): void
36+
{
37+
$t->compare(
38+
static function (ClassA|ClassB $crate): void {
39+
assertType('Bug11285\\ClassA|Bug11285\\ClassB', $crate);
40+
}
41+
);
42+
}
43+
44+
/**
45+
* @param Templated<ClassA, ClassB> $t
46+
*/
47+
public function working(
48+
Templated $t,
49+
): void
50+
{
51+
$t->compare(
52+
static function (ClassA|ClassB $crate): void {
53+
assertType('Bug11285\\ClassA|Bug11285\\ClassB', $crate);
54+
}
55+
);
56+
}
57+
58+
}

‎tests/PHPStan/Type/CallableTypeTest.php‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,12 +43,12 @@ public function dataIsSuperTypeOf(): array
4343
[
4444
new CallableType([new NativeParameterReflection('foo', false, new MixedType(), PassedByReference::createNo(), false, null)], new MixedType(), false),
4545
new CallableType([new NativeParameterReflection('foo', false, new IntegerType(), PassedByReference::createNo(), false, null)], new MixedType(), false),
46-
TrinaryLogic::createMaybe(),
46+
TrinaryLogic::createYes(),
4747
],
4848
[
4949
new CallableType([new NativeParameterReflection('foo', false, new IntegerType(), PassedByReference::createNo(), false, null)], new MixedType(), false),
5050
new CallableType([new NativeParameterReflection('foo', false, new MixedType(), PassedByReference::createNo(), false, null)], new MixedType(), false),
51-
TrinaryLogic::createYes(),
51+
TrinaryLogic::createMaybe(),
5252
],
5353
[
5454
new CallableType([

‎tests/PHPStan/Type/TypeCombinatorTest.php‎

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
use ObjectShapesAcceptance\ClassWithFooIntProperty;
1717
use PHPStan\Fixture\FinalClass;
1818
use PHPStan\Reflection\Callables\SimpleImpurePoint;
19+
use PHPStan\Reflection\Php\DummyParameter;
1920
use PHPStan\Testing\PHPStanTestCase;
2021
use PHPStan\TrinaryLogic;
2122
use PHPStan\Type\Accessory\AccessoryLiteralStringType;
@@ -2568,6 +2569,36 @@ public function dataUnion(): iterable
25682569
ClosureType::class,
25692570
'Closure(): mixed',
25702571
];
2572+
yield [
2573+
[
2574+
new CallableType([
2575+
new DummyParameter('callback', new ObjectType('stdClass'), false, null, false, null),
2576+
], new VoidType(), false),
2577+
new CallableType([
2578+
new DummyParameter('callback', new UnionType([
2579+
new ObjectType('stdClass'),
2580+
new ObjectType('Exception'),
2581+
]), false, null, false, null),
2582+
], new VoidType(), false),
2583+
],
2584+
CallableType::class,
2585+
'callable(Exception|stdClass): void',
2586+
];
2587+
yield [
2588+
[
2589+
new CallableType([
2590+
new DummyParameter('callback', new ObjectType('stdClass'), false, null, false, null),
2591+
], new VoidType(), false),
2592+
new CallableType([
2593+
new DummyParameter('callback', new UnionType([
2594+
new IntegerType(),
2595+
new ObjectType('Exception'),
2596+
]), false, null, false, null),
2597+
], new VoidType(), false),
2598+
],
2599+
UnionType::class,
2600+
'(callable(Exception|int): void)|(callable(stdClass): void)',
2601+
];
25712602
}
25722603

25732604
/**

0 commit comments

Comments
 (0)