Skip to content

Commit c2c73c0

Browse files
committed
Merge remote-tracking branch 'origin/1.12.x' into 2.0.x
2 parents 26f5957 + 18c75a2 commit c2c73c0

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+374
-118
lines changed

phpstan-baseline.neon

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1263,11 +1263,6 @@ parameters:
12631263
count: 4
12641264
path: src/Type/ObjectWithoutClassType.php
12651265

1266-
-
1267-
message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantBooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isTrue\\(\\) or Type\\:\\:isFalse\\(\\) instead\\.$#"
1268-
count: 1
1269-
path: src/Type/Php/ArrayChunkFunctionReturnTypeExtension.php
1270-
12711266
-
12721267
message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantArrayType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantArrays\\(\\) instead\\.$#"
12731268
count: 2

src/Type/Accessory/AccessoryArrayListType.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,11 @@ public function getValuesArray(): Type
192192
return $this;
193193
}
194194

195+
public function chunkArray(Type $lengthType, TrinaryLogic $preserveKeys): Type
196+
{
197+
return $this;
198+
}
199+
195200
public function fillKeysArray(Type $valueType): Type
196201
{
197202
return new MixedType();

src/Type/Accessory/HasOffsetType.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,11 @@ public function unsetOffset(Type $offsetType): Type
175175
return $this;
176176
}
177177

178+
public function chunkArray(Type $lengthType, TrinaryLogic $preserveKeys): Type
179+
{
180+
return new NonEmptyArrayType();
181+
}
182+
178183
public function fillKeysArray(Type $valueType): Type
179184
{
180185
return new NonEmptyArrayType();

src/Type/Accessory/HasOffsetValueType.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,11 @@ public function getValuesArray(): Type
209209
return new NonEmptyArrayType();
210210
}
211211

212+
public function chunkArray(Type $lengthType, TrinaryLogic $preserveKeys): Type
213+
{
214+
return new NonEmptyArrayType();
215+
}
216+
212217
public function fillKeysArray(Type $valueType): Type
213218
{
214219
return new NonEmptyArrayType();

src/Type/Accessory/NonEmptyArrayType.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,11 @@ public function getValuesArray(): Type
179179
return $this;
180180
}
181181

182+
public function chunkArray(Type $lengthType, TrinaryLogic $preserveKeys): Type
183+
{
184+
return $this;
185+
}
186+
182187
public function fillKeysArray(Type $valueType): Type
183188
{
184189
return $this;

src/Type/Accessory/OversizedArrayType.php

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,11 @@ public function getValuesArray(): Type
175175
return $this;
176176
}
177177

178+
public function chunkArray(Type $lengthType, TrinaryLogic $preserveKeys): Type
179+
{
180+
return $this;
181+
}
182+
178183
public function fillKeysArray(Type $valueType): Type
179184
{
180185
return $this;
@@ -222,12 +227,12 @@ public function isIterable(): TrinaryLogic
222227

223228
public function isIterableAtLeastOnce(): TrinaryLogic
224229
{
225-
return TrinaryLogic::createYes();
230+
return TrinaryLogic::createMaybe();
226231
}
227232

228233
public function getArraySize(): Type
229234
{
230-
return IntegerRangeType::fromInterval(1, null);
235+
return IntegerRangeType::fromInterval(0, null);
231236
}
232237

233238
public function getIterableKeyType(): Type

src/Type/ArrayType.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -513,6 +513,20 @@ public function unsetOffset(Type $offsetType): Type
513513
return $this;
514514
}
515515

516+
public function chunkArray(Type $lengthType, TrinaryLogic $preserveKeys): Type
517+
{
518+
$chunkType = $preserveKeys->yes()
519+
? $this
520+
: TypeCombinator::intersect(new ArrayType(new IntegerType(), $this->getIterableValueType()), new AccessoryArrayListType());
521+
$chunkType = TypeCombinator::intersect($chunkType, new NonEmptyArrayType());
522+
523+
$arrayType = TypeCombinator::intersect(new ArrayType(new IntegerType(), $chunkType), new AccessoryArrayListType());
524+
525+
return $this->isIterableAtLeastOnce()->yes()
526+
? TypeCombinator::intersect($arrayType, new NonEmptyArrayType())
527+
: $arrayType;
528+
}
529+
516530
public function fillKeysArray(Type $valueType): Type
517531
{
518532
$itemType = $this->getItemType();

src/Type/ClosureType.php

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,10 @@
3636
use PHPStan\Type\Generic\TemplateType;
3737
use PHPStan\Type\Generic\TemplateTypeHelper;
3838
use PHPStan\Type\Generic\TemplateTypeMap;
39+
use PHPStan\Type\Generic\TemplateTypeVariance;
3940
use PHPStan\Type\Generic\TemplateTypeVarianceMap;
4041
use PHPStan\Type\Traits\NonArrayTypeTrait;
4142
use PHPStan\Type\Traits\NonGeneralizableTypeTrait;
42-
use PHPStan\Type\Traits\NonGenericTypeTrait;
4343
use PHPStan\Type\Traits\NonIterableTypeTrait;
4444
use PHPStan\Type\Traits\NonOffsetAccessibleTypeTrait;
4545
use PHPStan\Type\Traits\NonRemoveableTypeTrait;
@@ -53,7 +53,6 @@ class ClosureType implements TypeWithClassName, CallableParametersAcceptor
5353
{
5454

5555
use NonArrayTypeTrait;
56-
use NonGenericTypeTrait;
5756
use NonIterableTypeTrait;
5857
use UndecidedComparisonTypeTrait;
5958
use NonOffsetAccessibleTypeTrait;
@@ -540,6 +539,23 @@ private function inferTemplateTypesOnParametersAcceptor(ParametersAcceptor $para
540539
return $typeMap->union($this->getReturnType()->inferTemplateTypes($returnType));
541540
}
542541

542+
public function getReferencedTemplateTypes(TemplateTypeVariance $positionVariance): array
543+
{
544+
$references = $this->getReturnType()->getReferencedTemplateTypes(
545+
$positionVariance->compose(TemplateTypeVariance::createCovariant()),
546+
);
547+
548+
$paramVariance = $positionVariance->compose(TemplateTypeVariance::createContravariant());
549+
550+
foreach ($this->getParameters() as $param) {
551+
foreach ($param->getType()->getReferencedTemplateTypes($paramVariance) as $reference) {
552+
$references[] = $reference;
553+
}
554+
}
555+
556+
return $references;
557+
}
558+
543559
public function traverse(callable $cb): Type
544560
{
545561
if ($this->isCommonCallable) {

src/Type/Constant/ConstantArrayType.php

Lines changed: 53 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ class ConstantArrayType extends ArrayType implements ConstantType
7272
{
7373

7474
private const DESCRIBE_LIMIT = 8;
75+
private const CHUNK_FINITE_TYPES_LIMIT = 5;
7576

7677
private TrinaryLogic $isList;
7778

@@ -649,23 +650,33 @@ public function hasOffsetValueType(Type $offsetType): TrinaryLogic
649650

650651
public function getOffsetValueType(Type $offsetType): Type
651652
{
653+
if (count($this->keyTypes) === 0) {
654+
return new ErrorType();
655+
}
656+
652657
$offsetType = $offsetType->toArrayKey();
653658
$matchingValueTypes = [];
654659
$all = true;
660+
$maybeAll = true;
655661
foreach ($this->keyTypes as $i => $keyType) {
656662
if ($keyType->isSuperTypeOf($offsetType)->no()) {
657663
$all = false;
664+
665+
if (
666+
$keyType instanceof ConstantIntegerType
667+
&& !$offsetType->isString()->no()
668+
&& $offsetType->isConstantScalarValue()->no()
669+
) {
670+
continue;
671+
}
672+
$maybeAll = false;
658673
continue;
659674
}
660675

661676
$matchingValueTypes[] = $this->valueTypes[$i];
662677
}
663678

664679
if ($all) {
665-
if (count($this->keyTypes) === 0) {
666-
return new ErrorType();
667-
}
668-
669680
return $this->getIterableValueType();
670681
}
671682

@@ -678,6 +689,10 @@ public function getOffsetValueType(Type $offsetType): Type
678689
return $type;
679690
}
680691

692+
if ($maybeAll) {
693+
return $this->getIterableValueType();
694+
}
695+
681696
return new ErrorType(); // undefined offset
682697
}
683698

@@ -778,6 +793,36 @@ public function unsetOffset(Type $offsetType): Type
778793
return new self($this->keyTypes, $this->valueTypes, $this->nextAutoIndexes, $optionalKeys, $isList);
779794
}
780795

796+
public function chunkArray(Type $lengthType, TrinaryLogic $preserveKeys): Type
797+
{
798+
$biggerOne = IntegerRangeType::fromInterval(1, null);
799+
$finiteTypes = $lengthType->getFiniteTypes();
800+
if ($biggerOne->isSuperTypeOf($lengthType)->yes() && count($finiteTypes) < self::CHUNK_FINITE_TYPES_LIMIT) {
801+
$results = [];
802+
foreach ($finiteTypes as $finiteType) {
803+
if (!$finiteType instanceof ConstantIntegerType || $finiteType->getValue() < 1) {
804+
return parent::chunkArray($lengthType, $preserveKeys);
805+
}
806+
807+
$length = $finiteType->getValue();
808+
809+
$builder = ConstantArrayTypeBuilder::createEmpty();
810+
811+
$keyTypesCount = count($this->keyTypes);
812+
for ($i = 0; $i < $keyTypesCount; $i += $length) {
813+
$chunk = $this->slice($i, $length, true);
814+
$builder->setOffsetValueType(null, $preserveKeys->yes() ? $chunk : $chunk->getValuesArray());
815+
}
816+
817+
$results[] = $builder->getArray();
818+
}
819+
820+
return TypeCombinator::union(...$results);
821+
}
822+
823+
return parent::chunkArray($lengthType, $preserveKeys);
824+
}
825+
781826
public function fillKeysArray(Type $valueType): Type
782827
{
783828
$builder = ConstantArrayTypeBuilder::createEmpty();
@@ -1183,7 +1228,10 @@ public function reverse(bool $preserveKeys = false): self
11831228
return $this->reverseConstantArray(TrinaryLogic::createFromBoolean($preserveKeys));
11841229
}
11851230

1186-
/** @param positive-int $length */
1231+
/**
1232+
* @deprecated Use chunkArray() instead
1233+
* @param positive-int $length
1234+
*/
11871235
public function chunk(int $length, bool $preserveKeys = false): self
11881236
{
11891237
$builder = ConstantArrayTypeBuilder::createEmpty();

src/Type/IntersectionType.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -724,6 +724,11 @@ public function getValuesArray(): Type
724724
return $this->intersectTypes(static fn (Type $type): Type => $type->getValuesArray());
725725
}
726726

727+
public function chunkArray(Type $lengthType, TrinaryLogic $preserveKeys): Type
728+
{
729+
return $this->intersectTypes(static fn (Type $type): Type => $type->chunkArray($lengthType, $preserveKeys));
730+
}
731+
727732
public function fillKeysArray(Type $valueType): Type
728733
{
729734
return $this->intersectTypes(static fn (Type $type): Type => $type->fillKeysArray($valueType));

0 commit comments

Comments
 (0)