Skip to content

Commit 745c099

Browse files
committed
use MutatingScope->processAssignVar() instead
1 parent 698fd8b commit 745c099

File tree

3 files changed

+141
-18
lines changed

3 files changed

+141
-18
lines changed

src/Analyser/NodeScopeResolver.php

Lines changed: 96 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2670,9 +2670,22 @@ static function (): void {
26702670
$isArrayPop ? $arrayArgNativeType->popArray() : $arrayArgNativeType->shiftArray(),
26712671
);
26722672

2673-
if ($arrayArg instanceof PropertyFetch || $arrayArg instanceof StaticPropertyFetch) {
2674-
$nodeCallback(new PropertyAssignNode($arrayArg, new TypeExpr($scope->getType($arrayArg)), false), $scope);
2675-
}
2673+
$scope = $this->processAssignVar(
2674+
$scope,
2675+
$stmt,
2676+
$arrayArg,
2677+
$arrayArg,
2678+
static function (Node $node, Scope $scope) use ($nodeCallback): void {
2679+
if (!$node instanceof PropertyAssignNode && !$node instanceof VariableAssignNode) {
2680+
return;
2681+
}
2682+
2683+
$nodeCallback($node, $scope);
2684+
},
2685+
$context,
2686+
static fn (MutatingScope $scope): ExpressionResult => new ExpressionResult($scope, false, false, [], []),
2687+
true,
2688+
)->getScope();
26762689
}
26772690

26782691
if (
@@ -2686,9 +2699,22 @@ static function (): void {
26862699
$arrayArg = $expr->getArgs()[0]->value;
26872700
$scope = $scope->invalidateExpression($arrayArg)->assignExpression($arrayArg, $arrayType, $arrayNativeType);
26882701

2689-
if ($arrayArg instanceof PropertyFetch || $arrayArg instanceof StaticPropertyFetch) {
2690-
$nodeCallback(new PropertyAssignNode($arrayArg, new TypeExpr($scope->getType($arrayArg)), false), $scope);
2691-
}
2702+
$scope = $this->processAssignVar(
2703+
$scope,
2704+
$stmt,
2705+
$arrayArg,
2706+
$arrayArg,
2707+
static function (Node $node, Scope $scope) use ($nodeCallback): void {
2708+
if (!$node instanceof PropertyAssignNode && !$node instanceof VariableAssignNode) {
2709+
return;
2710+
}
2711+
2712+
$nodeCallback($node, $scope);
2713+
},
2714+
$context,
2715+
static fn (MutatingScope $scope): ExpressionResult => new ExpressionResult($scope, false, false, [], []),
2716+
true,
2717+
)->getScope();
26922718
}
26932719

26942720
if (
@@ -2709,9 +2735,22 @@ static function (): void {
27092735
$scope->getNativeType($arrayArg)->shuffleArray(),
27102736
);
27112737

2712-
if ($arrayArg instanceof PropertyFetch || $arrayArg instanceof StaticPropertyFetch) {
2713-
$nodeCallback(new PropertyAssignNode($arrayArg, new TypeExpr($scope->getType($arrayArg)), false), $scope);
2714-
}
2738+
$scope = $this->processAssignVar(
2739+
$scope,
2740+
$stmt,
2741+
$arrayArg,
2742+
$arrayArg,
2743+
static function (Node $node, Scope $scope) use ($nodeCallback): void {
2744+
if (!$node instanceof PropertyAssignNode && !$node instanceof VariableAssignNode) {
2745+
return;
2746+
}
2747+
2748+
$nodeCallback($node, $scope);
2749+
},
2750+
$context,
2751+
static fn (MutatingScope $scope): ExpressionResult => new ExpressionResult($scope, false, false, [], []),
2752+
true,
2753+
)->getScope();
27152754
}
27162755

27172756
if (
@@ -2733,9 +2772,22 @@ static function (): void {
27332772
$arrayArgNativeType->spliceArray($offsetType, $lengthType, $replacementType),
27342773
);
27352774

2736-
if ($arrayArg instanceof PropertyFetch || $arrayArg instanceof StaticPropertyFetch) {
2737-
$nodeCallback(new PropertyAssignNode($arrayArg, new TypeExpr($scope->getType($arrayArg)), false), $scope);
2738-
}
2775+
$scope = $this->processAssignVar(
2776+
$scope,
2777+
$stmt,
2778+
$arrayArg,
2779+
$arrayArg,
2780+
static function (Node $node, Scope $scope) use ($nodeCallback): void {
2781+
if (!$node instanceof PropertyAssignNode && !$node instanceof VariableAssignNode) {
2782+
return;
2783+
}
2784+
2785+
$nodeCallback($node, $scope);
2786+
},
2787+
$context,
2788+
static fn (MutatingScope $scope): ExpressionResult => new ExpressionResult($scope, false, false, [], []),
2789+
true,
2790+
)->getScope();
27392791
}
27402792

27412793
if (
@@ -2750,9 +2802,22 @@ static function (): void {
27502802
$this->getArraySortPreserveListFunctionType($scope->getNativeType($arrayArg)),
27512803
);
27522804

2753-
if ($arrayArg instanceof PropertyFetch || $arrayArg instanceof StaticPropertyFetch) {
2754-
$nodeCallback(new PropertyAssignNode($arrayArg, new TypeExpr($scope->getType($arrayArg)), false), $scope);
2755-
}
2805+
$scope = $this->processAssignVar(
2806+
$scope,
2807+
$stmt,
2808+
$arrayArg,
2809+
$arrayArg,
2810+
static function (Node $node, Scope $scope) use ($nodeCallback): void {
2811+
if (!$node instanceof PropertyAssignNode && !$node instanceof VariableAssignNode) {
2812+
return;
2813+
}
2814+
2815+
$nodeCallback($node, $scope);
2816+
},
2817+
$context,
2818+
static fn (MutatingScope $scope): ExpressionResult => new ExpressionResult($scope, false, false, [], []),
2819+
true,
2820+
)->getScope();
27562821
}
27572822

27582823
if (
@@ -2767,9 +2832,22 @@ static function (): void {
27672832
$this->getArraySortDoNotPreserveListFunctionType($scope->getNativeType($arrayArg)),
27682833
);
27692834

2770-
if ($arrayArg instanceof PropertyFetch || $arrayArg instanceof StaticPropertyFetch) {
2771-
$nodeCallback(new PropertyAssignNode($arrayArg, new TypeExpr($scope->getType($arrayArg)), false), $scope);
2772-
}
2835+
$scope = $this->processAssignVar(
2836+
$scope,
2837+
$stmt,
2838+
$arrayArg,
2839+
$arrayArg,
2840+
static function (Node $node, Scope $scope) use ($nodeCallback): void {
2841+
if (!$node instanceof PropertyAssignNode && !$node instanceof VariableAssignNode) {
2842+
return;
2843+
}
2844+
2845+
$nodeCallback($node, $scope);
2846+
},
2847+
$context,
2848+
static fn (MutatingScope $scope): ExpressionResult => new ExpressionResult($scope, false, false, [], []),
2849+
true,
2850+
)->getScope();
27732851
}
27742852

27752853
if (

tests/PHPStan/Rules/Properties/TypesAssignedToPropertiesRuleTest.php

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -882,6 +882,23 @@ public function testBug13438e(): void
882882
]);
883883
}
884884

885+
public function testBug13438f(): void
886+
{
887+
$this->checkExplicitMixed = true;
888+
$this->analyse([__DIR__ . '/data/bug-13438f.php'], [
889+
[
890+
'Property Bug13438f\Test::$queue (array<int, non-empty-list<int>>) does not accept non-empty-array<int, list<int>>.',
891+
20,
892+
'list<int> might be empty.',
893+
],
894+
[
895+
'Property Bug13438f\Test::$queue (array<int, non-empty-list<int>>) does not accept non-empty-array<int, list<int>>.',
896+
25,
897+
'list<int> might be empty.',
898+
],
899+
]);
900+
}
901+
885902
public function testBug2888(): void
886903
{
887904
$this->checkExplicitMixed = true;
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace Bug13438f;
4+
5+
use function PHPStan\dumpType;
6+
use function PHPStan\Testing\assertType;
7+
8+
class Test
9+
{
10+
/**
11+
* @param array<int, non-empty-list<int>> $queue
12+
*/
13+
public function __construct(
14+
private array $queue,
15+
) {
16+
}
17+
18+
public function test1(): void
19+
{
20+
array_shift($this->queue[5]); // no longer is non-empty-list<int> after this
21+
}
22+
23+
public function test2(): void
24+
{
25+
$this->queue[5] = []; // normally it works thanks to processAssignVar
26+
}
27+
28+
}

0 commit comments

Comments
 (0)