Skip to content

Commit a8cae55

Browse files
committed
Setting array offset on a property should pick types from original UnionType still present in the current property type
1 parent d16b1ca commit a8cae55

File tree

3 files changed

+64
-2
lines changed

3 files changed

+64
-2
lines changed

src/Analyser/MutatingScope.php

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -778,13 +778,29 @@ public function getType(Expr $node): Type
778778
return $this->getType($node->getVar())->unsetOffset($this->getType($node->getDim()));
779779
}
780780
if ($node instanceof SetOffsetValueTypeExpr) {
781-
return $this->getType($node->getVar())->setOffsetValueType(
781+
$varNode = $node->getVar();
782+
$varType = $this->getType($varNode);
783+
if ($varNode instanceof OriginalPropertyTypeExpr) {
784+
$currentPropertyType = $this->getType($varNode->getPropertyFetch());
785+
if ($varType instanceof UnionType) {
786+
$varType = $varType->filterTypes(static fn (Type $innerType) => !$innerType->isSuperTypeOf($currentPropertyType)->no());
787+
}
788+
}
789+
return $varType->setOffsetValueType(
782790
$node->getDim() !== null ? $this->getType($node->getDim()) : null,
783791
$this->getType($node->getValue()),
784792
);
785793
}
786794
if ($node instanceof SetExistingOffsetValueTypeExpr) {
787-
return $this->getType($node->getVar())->setExistingOffsetValueType(
795+
$varNode = $node->getVar();
796+
$varType = $this->getType($varNode);
797+
if ($varNode instanceof OriginalPropertyTypeExpr) {
798+
$currentPropertyType = $this->getType($varNode->getPropertyFetch());
799+
if ($varType instanceof UnionType) {
800+
$varType = $varType->filterTypes(static fn (Type $innerType) => !$innerType->isSuperTypeOf($currentPropertyType)->no());
801+
}
802+
}
803+
return $varType->setExistingOffsetValueType(
788804
$this->getType($node->getDim()),
789805
$this->getType($node->getValue()),
790806
);

tests/PHPStan/Rules/Properties/TypesAssignedToPropertiesRuleTest.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -942,4 +942,11 @@ public function testBug13035(): void
942942
$this->analyse([__DIR__ . '/data/bug-13035.php'], []);
943943
}
944944

945+
public function testBug13654(): void
946+
{
947+
$this->checkExplicitMixed = true;
948+
$this->checkImplicitMixed = true;
949+
$this->analyse([__DIR__ . '/data/bug-13654.php'], []);
950+
}
951+
945952
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<?php
2+
3+
namespace Bug13654;
4+
5+
/**
6+
* @phpstan-type TType array{
7+
* text: string,
8+
* missing: string,
9+
* }
10+
*/
11+
class HelloWorld
12+
{
13+
/**
14+
* @var TType|null
15+
*/
16+
private ?array $test = null;
17+
18+
/**
19+
* @param TType $test
20+
*/
21+
public function setTest(array $test): void
22+
{
23+
$this->test = $test;
24+
}
25+
26+
/**
27+
* @return TType
28+
*/
29+
public function modify(): array
30+
{
31+
if ($this->test === null) {
32+
throw new \Exception();
33+
}
34+
35+
$this->test['text'] = 'asdsdsd';
36+
37+
return $this->test;
38+
}
39+
}

0 commit comments

Comments
 (0)