Skip to content

Commit b53ba52

Browse files
Handle exception thrown from callable object's __invoke method
1 parent f84df88 commit b53ba52

File tree

3 files changed

+64
-0
lines changed

3 files changed

+64
-0
lines changed

src/Analyser/NodeScopeResolver.php

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1956,8 +1956,23 @@ function (MutatingScope $scope) use ($expr, $nodeCallback, $context): Expression
19561956
$nameType->getCallableParametersAcceptors($scope),
19571957
);
19581958
}
1959+
19591960
$nameResult = $this->processExprNode($expr->name, $scope, $nodeCallback, $context->enterDeep());
19601961
$throwPoints = $nameResult->getThrowPoints();
1962+
if (
1963+
$nameType->isObject()->yes()
1964+
&& $nameType->isCallable()->yes()
1965+
&& (new ObjectType(Closure::class))->isSuperTypeOf($nameType)->no()
1966+
) {
1967+
$invokeResult = $this->processExprNode(
1968+
new MethodCall($expr->name, '__invoke', $expr->getArgs(), $expr->getAttributes()),
1969+
$scope,
1970+
static function (): void {
1971+
},
1972+
$context->enterDeep(),
1973+
);
1974+
$throwPoints = array_merge($throwPoints, $invokeResult->getThrowPoints());
1975+
}
19611976
$scope = $nameResult->getScope();
19621977
} elseif ($this->reflectionProvider->hasFunction($expr->name, $scope)) {
19631978
$functionReflection = $this->reflectionProvider->getFunction($expr->name, $scope);

tests/PHPStan/Rules/Exceptions/TooWideMethodThrowTypeRuleTest.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,4 +43,9 @@ public function testRule(): void
4343
]);
4444
}
4545

46+
public function testBug6233(): void
47+
{
48+
$this->analyse([__DIR__ . '/data/bug-6233.php'], []);
49+
}
50+
4651
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
<?php
2+
3+
namespace Bug6233;
4+
5+
class TestClass {
6+
/**
7+
* @throws \Exception
8+
**/
9+
public function __invoke() {
10+
throw new \Exception();
11+
}
12+
}
13+
14+
class TestClass2 {
15+
/**
16+
* @throws \Exception
17+
**/
18+
public function __invoke() {
19+
throw new \Exception();
20+
}
21+
}
22+
23+
class Container {
24+
/**
25+
* @throws \Exception
26+
**/
27+
public function test(TestClass $class) {
28+
$class();
29+
}
30+
/**
31+
* @throws \Exception
32+
**/
33+
public function testNew() {
34+
(new TestClass)();
35+
}
36+
/**
37+
* @param TestClass|TestClass2 $class
38+
*
39+
* @throws \Exception
40+
**/
41+
public function testUnion(object $class) {
42+
$class();
43+
}
44+
}

0 commit comments

Comments
 (0)