Skip to content

Commit 98f6aae

Browse files
committed
Merge remote-tracking branch 'origin/1.12.x' into 2.0.x
2 parents b0df849 + a960f74 commit 98f6aae

File tree

6 files changed

+944
-2
lines changed

6 files changed

+944
-2
lines changed

phpstan-baseline.neon

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1326,7 +1326,7 @@ parameters:
13261326
-
13271327
message: '#^Doing instanceof PHPStan\\Type\\ArrayType is error\-prone and deprecated\. Use Type\:\:isArray\(\) or Type\:\:getArrays\(\) instead\.$#'
13281328
identifier: phpstanApi.instanceofType
1329-
count: 3
1329+
count: 4
13301330
path: src/Type/IntersectionType.php
13311331

13321332
-
@@ -1347,6 +1347,12 @@ parameters:
13471347
count: 3
13481348
path: src/Type/IntersectionType.php
13491349

1350+
-
1351+
message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#'
1352+
identifier: phpstanApi.instanceofType
1353+
count: 1
1354+
path: src/Type/IntersectionType.php
1355+
13501356
-
13511357
message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#'
13521358
identifier: phpstanApi.instanceofType

src/Analyser/NodeScopeResolver.php

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5072,7 +5072,30 @@ private function processAssignVar(
50725072
$offsetNativeValueType = $varNativeType;
50735073

50745074
$valueToWrite = $this->produceArrayDimFetchAssignValueToWrite($offsetTypes, $offsetValueType, $valueToWrite);
5075-
$nativeValueToWrite = $this->produceArrayDimFetchAssignValueToWrite($offsetNativeTypes, $offsetNativeValueType, $nativeValueToWrite);
5075+
5076+
$nativeValueToWrite = $valueToWrite;
5077+
if (!$offsetValueType->equals($offsetNativeValueType) || !$valueToWrite->equals($nativeValueToWrite)) {
5078+
$nativeValueToWrite = $this->produceArrayDimFetchAssignValueToWrite($offsetNativeTypes, $offsetNativeValueType, $nativeValueToWrite);
5079+
} else {
5080+
foreach ($offsetTypes as $i => $offsetType) {
5081+
$offsetNativeType = $offsetNativeTypes[$i];
5082+
if ($offsetType === null) {
5083+
if ($offsetNativeType !== null) {
5084+
throw new ShouldNotHappenException();
5085+
}
5086+
5087+
continue;
5088+
} elseif ($offsetNativeType === null) {
5089+
throw new ShouldNotHappenException();
5090+
}
5091+
if ($offsetType->equals($offsetNativeType)) {
5092+
continue;
5093+
}
5094+
5095+
$nativeValueToWrite = $this->produceArrayDimFetchAssignValueToWrite($offsetNativeTypes, $offsetNativeValueType, $nativeValueToWrite);
5096+
break;
5097+
}
5098+
}
50765099

50775100
if ($varType->isArray()->yes() || !(new ObjectType(ArrayAccess::class))->isSuperTypeOf($varType)->yes()) {
50785101
if ($var instanceof Variable && is_string($var->name)) {

src/Type/Constant/ConstantArrayTypeBuilder.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@ public function setOffsetValueType(?Type $offsetType, Type $valueType, bool $opt
127127

128128
if (count($this->keyTypes) > self::ARRAY_COUNT_LIMIT) {
129129
$this->degradeToGeneralArray = true;
130+
$this->oversized = true;
130131
}
131132

132133
return;
@@ -193,6 +194,7 @@ public function setOffsetValueType(?Type $offsetType, Type $valueType, bool $opt
193194

194195
if (count($this->keyTypes) > self::ARRAY_COUNT_LIMIT) {
195196
$this->degradeToGeneralArray = true;
197+
$this->oversized = true;
196198
}
197199

198200
return;

src/Type/IntersectionType.php

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
use PHPStan\Type\Accessory\NonEmptyArrayType;
3131
use PHPStan\Type\Constant\ConstantArrayType;
3232
use PHPStan\Type\Constant\ConstantIntegerType;
33+
use PHPStan\Type\Constant\ConstantStringType;
3334
use PHPStan\Type\Generic\TemplateType;
3435
use PHPStan\Type\Generic\TemplateTypeMap;
3536
use PHPStan\Type\Generic\TemplateTypeVariance;
@@ -743,6 +744,30 @@ public function getOffsetValueType(Type $offsetType): Type
743744

744745
public function setOffsetValueType(?Type $offsetType, Type $valueType, bool $unionValues = true): Type
745746
{
747+
if ($this->isOversizedArray()->yes()) {
748+
return $this->intersectTypes(static function (Type $type) use ($offsetType, $valueType, $unionValues): Type {
749+
// avoid new HasOffsetValueType being intersected with oversized array
750+
if (!$type instanceof ArrayType) {
751+
return $type->setOffsetValueType($offsetType, $valueType, $unionValues);
752+
}
753+
754+
if (!$offsetType instanceof ConstantStringType && !$offsetType instanceof ConstantIntegerType) {
755+
return $type->setOffsetValueType($offsetType, $valueType, $unionValues);
756+
}
757+
758+
if (!$offsetType->isSuperTypeOf($type->getKeyType())->yes()) {
759+
return $type->setOffsetValueType($offsetType, $valueType, $unionValues);
760+
}
761+
762+
return TypeCombinator::intersect(
763+
new ArrayType(
764+
TypeCombinator::union($type->getKeyType(), $offsetType),
765+
TypeCombinator::union($type->getItemType(), $valueType),
766+
),
767+
new NonEmptyArrayType(),
768+
);
769+
});
770+
}
746771
return $this->intersectTypes(static fn (Type $type): Type => $type->setOffsetValueType($offsetType, $valueType, $unionValues));
747772
}
748773

tests/PHPStan/Analyser/AnalyserIntegrationTest.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1338,6 +1338,12 @@ public function testBug10538(): void
13381338
$this->assertNoErrors($errors);
13391339
}
13401340

1341+
public function testBug10847(): void
1342+
{
1343+
$errors = $this->runAnalyse(__DIR__ . '/data/bug-10847.php');
1344+
$this->assertNoErrors($errors);
1345+
}
1346+
13411347
public function testBug10772(): void
13421348
{
13431349
if (PHP_VERSION_ID < 80100) {

0 commit comments

Comments
 (0)