Skip to content

Commit 0fbac5b

Browse files
committed
Merge branch 2.2.x into 2.3.x
2 parents eb0d2fd + 175e3fb commit 0fbac5b

19 files changed

Lines changed: 596 additions & 15 deletions

‎composer.json‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838
"ondrejmirtes/better-reflection": "6.70.0.6",
3939
"ondrejmirtes/composer-attribute-collector": "^1.2.0",
4040
"ondrejmirtes/php-merge": "^4.1",
41-
"phpstan/php-8-stubs": "0.4.35",
41+
"phpstan/php-8-stubs": "0.4.37",
4242
"phpstan/phpdoc-parser": "2.3.5",
4343
"react/child-process": "^0.7",
4444
"react/event-loop": "^1.2",

‎composer.lock‎

Lines changed: 7 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎phpstan-baseline.neon‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -684,6 +684,12 @@ parameters:
684684
count: 2
685685
path: src/Rules/RuleErrorBuilder.php
686686

687+
-
688+
rawMessage: Doing instanceof PHPStan\Type\Generic\GenericObjectType is error-prone and deprecated.
689+
identifier: phpstanApi.instanceofType
690+
count: 1
691+
path: src/Rules/RuleLevelHelper.php
692+
687693
-
688694
rawMessage: Doing instanceof PHPStan\Type\IntersectionType is error-prone and deprecated.
689695
identifier: phpstanApi.instanceofType

‎src/Rules/RuleLevelHelper.php‎

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,13 @@
66
use PHPStan\Analyser\Scope;
77
use PHPStan\DependencyInjection\AutowiredParameter;
88
use PHPStan\DependencyInjection\AutowiredService;
9+
use PHPStan\Reflection\ParametersAcceptor;
910
use PHPStan\Reflection\ReflectionProvider;
1011
use PHPStan\Type\BenevolentUnionType;
1112
use PHPStan\Type\CallableType;
1213
use PHPStan\Type\ClosureType;
1314
use PHPStan\Type\ErrorType;
15+
use PHPStan\Type\Generic\GenericObjectType;
1416
use PHPStan\Type\Generic\TemplateMixedType;
1517
use PHPStan\Type\IntersectionType;
1618
use PHPStan\Type\MixedType;
@@ -49,6 +51,29 @@ public function __construct(
4951
{
5052
}
5153

54+
/**
55+
* @param callable(Type): Type $traverse
56+
*/
57+
private function traverseWithoutMapping(Type $type, ?Type $acceptingType, callable $traverse): Type
58+
{
59+
if ($type instanceof GenericObjectType && $acceptingType !== null) {
60+
return $type->traverseSimultaneously($acceptingType, function (Type $type, Type $acceptingType) use ($traverse): Type {
61+
if (
62+
!$this->checkNullables
63+
&& !$type instanceof BenevolentUnionType
64+
&& TypeCombinator::containsNull($type)
65+
&& !TypeCombinator::containsNull($acceptingType)
66+
) {
67+
return $traverse(TypeCombinator::removeNull($type));
68+
}
69+
70+
return $type;
71+
});
72+
}
73+
74+
return $traverse($type);
75+
}
76+
5277
/** @api */
5378
public function isThis(Expr $expression): bool
5479
{
@@ -93,9 +118,10 @@ private function transformAcceptedType(Type $acceptingType, Type $acceptedType):
93118
return $acceptedType;
94119
}
95120

121+
$acceptingReturnType = $acceptingType instanceof ParametersAcceptor ? $acceptingType->getReturnType() : null;
96122
return new CallableType(
97123
$acceptedType->getParameters(),
98-
$traverse($acceptedType->getReturnType()),
124+
$this->traverseWithoutMapping($acceptedType->getReturnType(), $acceptingReturnType, $traverse),
99125
$acceptedType->isVariadic(),
100126
$acceptedType->getTemplateTypeMap(),
101127
$acceptedType->getResolvedTemplateTypeMap(),
@@ -109,9 +135,10 @@ private function transformAcceptedType(Type $acceptingType, Type $acceptedType):
109135
return $acceptedType;
110136
}
111137

138+
$acceptingReturnType = $acceptingType instanceof ParametersAcceptor ? $acceptingType->getReturnType() : null;
112139
return new ClosureType(
113140
$acceptedType->getParameters(),
114-
$traverse($acceptedType->getReturnType()),
141+
$this->traverseWithoutMapping($acceptedType->getReturnType(), $acceptingReturnType, $traverse),
115142
$acceptedType->isVariadic(),
116143
$acceptedType->getTemplateTypeMap(),
117144
$acceptedType->getResolvedTemplateTypeMap(),
@@ -127,6 +154,10 @@ private function transformAcceptedType(Type $acceptingType, Type $acceptedType):
127154
);
128155
}
129156

157+
if ($acceptedType instanceof GenericObjectType) {
158+
return $this->traverseWithoutMapping($acceptedType, $acceptingType, $traverse);
159+
}
160+
130161
if (
131162
!$this->checkNullables
132163
&& !$acceptingType instanceof NullType

‎src/Turbo/TurboProcessRestarter.php‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,13 @@ public static function restartIfSuitable(array $argv): void
107107
// second try either
108108
return;
109109
}
110+
if (
111+
isset($_SERVER['BLACKFIRE_AGENT_SOCKET'])
112+
) {
113+
// pcntl_exec() is not supported by blackfire
114+
// see https://support.blackfire.platform.sh/hc/en-us/articles/4843014509202-Conflicts-with-pcntl-exec-calls
115+
return;
116+
}
110117
if (
111118
!function_exists('pcntl_exec')
112119
|| !function_exists('pcntl_fork')

‎tests/PHPStan/Rules/Functions/CallToFunctionParametersRuleTest.php‎

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
class CallToFunctionParametersRuleTest extends RuleTestCase
2121
{
2222

23+
private bool $checkNullables = true;
24+
2325
private bool $checkExplicitMixed = false;
2426

2527
private bool $checkImplicitMixed = false;
@@ -32,7 +34,7 @@ protected function getRule(): Rule
3234
new FunctionCallParametersCheck(
3335
new RuleLevelHelper(
3436
$broker,
35-
checkNullables: true,
37+
checkNullables: $this->checkNullables,
3638
checkThisOnly: false,
3739
checkUnionTypes: true,
3840
checkExplicitMixed: $this->checkExplicitMixed,
@@ -3164,4 +3166,16 @@ public function testBug6732(): void
31643166
]);
31653167
}
31663168

3169+
public function testBug9377(): void
3170+
{
3171+
$this->checkNullables = false;
3172+
$this->analyse([__DIR__ . '/data/bug-9377.php'], []);
3173+
}
3174+
3175+
public function testBug11041(): void
3176+
{
3177+
$this->checkNullables = false;
3178+
$this->analyse([__DIR__ . '/data/bug-11041.php'], []);
3179+
}
3180+
31673181
}

‎tests/PHPStan/Rules/Functions/ClosureReturnTypeRuleTest.php‎

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,14 @@
1313
class ClosureReturnTypeRuleTest extends RuleTestCase
1414
{
1515

16+
private bool $checkNullables = true;
17+
1618
protected function getRule(): Rule
1719
{
1820
return new ClosureReturnTypeRule(new FunctionReturnTypeCheck(
1921
new RuleLevelHelper(
2022
self::createReflectionProvider(),
21-
checkNullables: true,
23+
checkNullables: $this->checkNullables,
2224
checkThisOnly: false,
2325
checkUnionTypes: true,
2426
checkExplicitMixed: false,
@@ -154,4 +156,10 @@ public function testBug14914(): void
154156
$this->analyse([__DIR__ . '/data/bug-14914.php'], []);
155157
}
156158

159+
public function testBug12008(): void
160+
{
161+
$this->checkNullables = false;
162+
$this->analyse([__DIR__ . '/data/bug-12008.php'], []);
163+
}
164+
157165
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
<?php // lint >= 7.4
2+
3+
declare(strict_types = 1);
4+
5+
namespace Bug11041;
6+
7+
/**
8+
* @template TKey
9+
* @template TValue
10+
*/
11+
class Collection
12+
{
13+
14+
/** @var array<TKey, TValue> */
15+
private array $items;
16+
17+
/** @param array<TKey, TValue> $items */
18+
public function __construct(array $items)
19+
{
20+
$this->items = $items;
21+
}
22+
23+
/**
24+
* @param TKey $key
25+
* @return TValue
26+
*/
27+
public function get($key)
28+
{
29+
return $this->items[$key];
30+
}
31+
32+
}
33+
34+
/** @param Collection<int, string|null> $collection */
35+
function testFunc(Collection $collection): void
36+
{
37+
}
38+
39+
$collection = new Collection([0 => 'foo', 1 => 'bar', 2 => null, 3 => 'baz']);
40+
41+
testFunc($collection);
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
<?php // lint >= 8.2
2+
3+
declare(strict_types = 1);
4+
5+
namespace Bug12008;
6+
7+
use Closure;
8+
9+
interface ProductOverview
10+
{
11+
12+
public function getId(): ?int;
13+
14+
}
15+
16+
/**
17+
* @template T
18+
*/
19+
readonly class Pagination
20+
{
21+
22+
/**
23+
* @param iterable<T> $records
24+
*/
25+
public function __construct(
26+
public iterable $records,
27+
)
28+
{
29+
}
30+
31+
}
32+
33+
class HelloWorld
34+
{
35+
36+
private function respondToApiRequest(Closure|null $data): never
37+
{
38+
exit;
39+
}
40+
41+
/** @param list<ProductOverview> $products */
42+
public function run(array $products): never
43+
{
44+
$this->respondToApiRequest(function () use ($products) {
45+
return new Pagination(array_map(
46+
fn (ProductOverview $product) => [
47+
'id' => $product->getId(),
48+
],
49+
$products,
50+
));
51+
});
52+
}
53+
54+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace Bug9377;
4+
5+
/**
6+
* @template T
7+
*/
8+
class HelloWorld
9+
{
10+
11+
}
12+
13+
/** @param HelloWorld<array{id: int|null}> $foo */
14+
function foo($foo): void
15+
{
16+
}
17+
18+
/** @return HelloWorld<array{id: int|null}> */
19+
function bar(): HelloWorld
20+
{
21+
return new HelloWorld();
22+
}
23+
24+
$a = bar();
25+
26+
foo($a);

0 commit comments

Comments
 (0)