Skip to content

Commit 9b91afb

Browse files
committed
[BE] List type
1 parent 5d17773 commit 9b91afb

32 files changed

+69
-97
lines changed

changelog-2.0.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ When PHPStan 2.0 gets released, this will turn into [releases notes on GitHub](h
55
Major new features 🚀
66
=====================
77

8+
* **Array `list` type** ([#1751](https://github.com/phpstan/phpstan-src/pull/1751)), #3311, #8185, #6243, thanks @rvanvelzen!
9+
* Lists are arrays with sequential integer keys starting at 0
10+
811
Bleeding edge (TODO move to other sections)
912
=====================
1013

@@ -30,8 +33,6 @@ Bleeding edge (TODO move to other sections)
3033
* Report `instanceof` of classes covered by backward compatibility promise but where the assumption might change (https://github.com/phpstan/phpstan-src/commit/996bc69fa977aa64f601bd82b8a0ae39be0cbeef)
3134
* Use explicit mixed for global array variables ([#1411](https://github.com/phpstan/phpstan-src/pull/1411)), thanks @herndlm!
3235
* Add `@readonly` rule that disallows default values ([#1391](https://github.com/phpstan/phpstan-src/pull/1391)), thanks @herndlm!
33-
* **Array `list` type** ([#1751](https://github.com/phpstan/phpstan-src/pull/1751)), #3311, #8185, #6243, thanks @rvanvelzen!
34-
* Lists are arrays with sequential integer keys starting at 0
3536
* Improve error wording of the NonexistentOffset, BooleanAndConstantConditionRule, and BooleanOrConstantConditionRule ([#1882](https://github.com/phpstan/phpstan-src/pull/1882)), thanks @VincentLanglet!
3637
* MissingMagicSerializationMethodsRule ([#1711](https://github.com/phpstan/phpstan-src/pull/1711)), #7482, thanks @staabm!
3738
* Stub files validation - detect duplicate classes and functions (https://github.com/phpstan/phpstan-src/commit/ddf8d5c3859c2c75c20f525a0e2ca8b99032373a, https://github.com/phpstan/phpstan-src/commit/17e4b74335e5235d7cd6708eb687a774a0eeead4)

conf/bleedingEdge.neon

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ parameters:
1919
runtimeReflectionRules: true
2020
notAnalysedTrait: true
2121
curlSetOptTypes: true
22-
listType: true
2322
abstractTraitMethod: true
2423
missingMagicSerializationRule: true
2524
nullContextForVoidReturningFunctions: true

conf/config.neon

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,6 @@ parameters:
5454
runtimeReflectionRules: false
5555
notAnalysedTrait: false
5656
curlSetOptTypes: false
57-
listType: false
5857
abstractTraitMethod: false
5958
missingMagicSerializationRule: false
6059
nullContextForVoidReturningFunctions: false

conf/parametersSchema.neon

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,6 @@ parametersSchema:
4949
runtimeReflectionRules: bool()
5050
notAnalysedTrait: bool()
5151
curlSetOptTypes: bool()
52-
listType: bool()
5352
abstractTraitMethod: bool()
5453
missingMagicSerializationRule: bool()
5554
nullContextForVoidReturningFunctions: bool()

src/Analyser/MutatingScope.php

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -526,10 +526,11 @@ public function getVariableType(string $variableName): Type
526526
return IntegerRangeType::fromInterval(1, null);
527527
}
528528
if ($variableName === 'argv') {
529-
return AccessoryArrayListType::intersectWith(TypeCombinator::intersect(
529+
return TypeCombinator::intersect(
530530
new ArrayType(new IntegerType(), new StringType()),
531531
new NonEmptyArrayType(),
532-
));
532+
new AccessoryArrayListType(),
533+
);
533534
}
534535
if ($this->canAnyVariableExist()) {
535536
return new MixedType();
@@ -3175,7 +3176,7 @@ private function enterFunctionLike(
31753176
if ($this->phpVersion->supportsNamedArguments() && $functionReflection->acceptsNamedArguments()) {
31763177
$parameterType = new ArrayType(new UnionType([new IntegerType(), new StringType()]), $parameterType);
31773178
} else {
3178-
$parameterType = AccessoryArrayListType::intersectWith(new ArrayType(new IntegerType(), $parameterType));
3179+
$parameterType = TypeCombinator::intersect(new ArrayType(new IntegerType(), $parameterType), new AccessoryArrayListType());
31793180
}
31803181
}
31813182
$parameterNode = new Variable($parameter->getName());
@@ -3190,7 +3191,7 @@ private function enterFunctionLike(
31903191
if ($this->phpVersion->supportsNamedArguments() && $functionReflection->acceptsNamedArguments()) {
31913192
$nativeParameterType = new ArrayType(new UnionType([new IntegerType(), new StringType()]), $nativeParameterType);
31923193
} else {
3193-
$nativeParameterType = AccessoryArrayListType::intersectWith(new ArrayType(new IntegerType(), $nativeParameterType));
3194+
$nativeParameterType = TypeCombinator::intersect(new ArrayType(new IntegerType(), $nativeParameterType), new AccessoryArrayListType());
31943195
}
31953196
}
31963197
$nativeExpressionTypes[$paramExprString] = ExpressionTypeHolder::createYes($parameterNode, $nativeParameterType);
@@ -3670,11 +3671,11 @@ public function getFunctionType($type, bool $isNullable, bool $isVariadic): Type
36703671
));
36713672
}
36723673

3673-
return AccessoryArrayListType::intersectWith(new ArrayType(new IntegerType(), $this->getFunctionType(
3674+
return TypeCombinator::intersect(new ArrayType(new IntegerType(), $this->getFunctionType(
36743675
$type,
36753676
false,
36763677
false,
3677-
)));
3678+
)), new AccessoryArrayListType());
36783679
}
36793680

36803681
if ($type instanceof Name) {
@@ -5079,7 +5080,7 @@ private static function generalizeType(Type $a, Type $b, int $depth): Type
50795080
$resultType = TypeCombinator::intersect($resultType, new NonEmptyArrayType());
50805081
}
50815082
if ($constantArraysA->isList()->yes() && $constantArraysB->isList()->yes()) {
5082-
$resultType = AccessoryArrayListType::intersectWith($resultType);
5083+
$resultType = TypeCombinator::intersect($resultType, new AccessoryArrayListType());
50835084
}
50845085
$resultTypes[] = $resultType;
50855086
}
@@ -5122,7 +5123,7 @@ private static function generalizeType(Type $a, Type $b, int $depth): Type
51225123
$resultType = TypeCombinator::intersect($resultType, new NonEmptyArrayType());
51235124
}
51245125
if ($generalArraysA->isList()->yes() && $generalArraysB->isList()->yes()) {
5125-
$resultType = AccessoryArrayListType::intersectWith($resultType);
5126+
$resultType = TypeCombinator::intersect($resultType, new AccessoryArrayListType());
51265127
}
51275128
if ($generalArraysA->isOversizedArray()->yes() && $generalArraysB->isOversizedArray()->yes()) {
51285129
$resultType = TypeCombinator::intersect($resultType, new OversizedArrayType());

src/Analyser/NodeScopeResolver.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2455,7 +2455,7 @@ static function (): void {
24552455
$functionReflection !== null
24562456
&& in_array($functionReflection->getName(), ['fopen', 'file_get_contents'], true)
24572457
) {
2458-
$scope = $scope->assignVariable('http_response_header', AccessoryArrayListType::intersectWith(new ArrayType(new IntegerType(), new StringType())), new ArrayType(new IntegerType(), new StringType()), TrinaryLogic::createYes());
2458+
$scope = $scope->assignVariable('http_response_header', TypeCombinator::intersect(new ArrayType(new IntegerType(), new StringType()), new AccessoryArrayListType()), new ArrayType(new IntegerType(), new StringType()), TrinaryLogic::createYes());
24592459
}
24602460

24612461
if (
@@ -3841,7 +3841,7 @@ static function (?Type $offsetType, Type $valueType, bool $optional) use (&$arra
38413841
? TypeCombinator::intersect($array, new NonEmptyArrayType())
38423842
: $array;
38433843
$constantArray = $isList
3844-
? AccessoryArrayListType::intersectWith($constantArray)
3844+
? TypeCombinator::intersect($constantArray, new AccessoryArrayListType())
38453845
: $constantArray;
38463846
}
38473847

@@ -3884,7 +3884,7 @@ private function getArraySortPreserveListFunctionType(Type $type): Type
38843884
return $type;
38853885
}
38863886

3887-
$newArrayType = AccessoryArrayListType::intersectWith(new ArrayType(new IntegerType(), $type->getIterableValueType()));
3887+
$newArrayType = TypeCombinator::intersect(new ArrayType(new IntegerType(), $type->getIterableValueType()), new AccessoryArrayListType());
38883888
if ($isIterableAtLeastOnce->yes()) {
38893889
$newArrayType = TypeCombinator::intersect($newArrayType, new NonEmptyArrayType());
38903890
}

src/Analyser/TypeSpecifier.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -315,7 +315,7 @@ public function specifyTypesInCondition(
315315
if ($argType->isArray()->yes()) {
316316
$newType = new NonEmptyArrayType();
317317
if ($context->true() && $argType->isList()->yes()) {
318-
$newType = AccessoryArrayListType::intersectWith($newType);
318+
$newType = TypeCombinator::intersect($newType, new AccessoryArrayListType());
319319
}
320320

321321
$result = $result->unionWith(

src/DependencyInjection/ContainerFactory.php

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@
3131
use PHPStan\Reflection\ReflectionProvider;
3232
use PHPStan\Reflection\ReflectionProviderStaticAccessor;
3333
use PHPStan\ShouldNotHappenException;
34-
use PHPStan\Type\Accessory\AccessoryArrayListType;
3534
use PHPStan\Type\Generic\TemplateTypeVariance;
3635
use PHPStan\Type\ObjectType;
3736
use Symfony\Component\Finder\Finder;
@@ -192,7 +191,6 @@ public static function postInitializeContainer(Container $container): void
192191
$container->getService('typeSpecifier');
193192

194193
BleedingEdgeToggle::setBleedingEdge($container->getParameter('featureToggles')['bleedingEdge']);
195-
AccessoryArrayListType::setListTypeEnabled($container->getParameter('featureToggles')['listType']);
196194
TemplateTypeVariance::setInvarianceCompositionEnabled($container->getParameter('featureToggles')['invarianceComposition']);
197195
}
198196

src/PhpDoc/TypeNodeResolver.php

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -409,15 +409,11 @@ private function resolveIdentifierTypeNode(IdentifierTypeNode $typeNode, NameSco
409409
return new NonAcceptingNeverType();
410410

411411
case 'list':
412-
return AccessoryArrayListType::intersectWith(new ArrayType(new IntegerType(), new MixedType()));
412+
return TypeCombinator::intersect(new ArrayType(new IntegerType(), new MixedType()), new AccessoryArrayListType());
413413
case 'non-empty-list':
414-
return AccessoryArrayListType::intersectWith(TypeCombinator::intersect(
415-
new ArrayType(new IntegerType(), new MixedType()),
416-
new NonEmptyArrayType(),
417-
));
418-
case '__always-list':
419414
return TypeCombinator::intersect(
420415
new ArrayType(new IntegerType(), new MixedType()),
416+
new NonEmptyArrayType(),
421417
new AccessoryArrayListType(),
422418
);
423419

@@ -657,7 +653,7 @@ static function (string $variance): TemplateTypeVariance {
657653
return $arrayType;
658654
} elseif (in_array($mainTypeName, ['list', 'non-empty-list'], true)) {
659655
if (count($genericTypes) === 1) { // list<ValueType>
660-
$listType = AccessoryArrayListType::intersectWith(new ArrayType(new IntegerType(), $genericTypes[0]));
656+
$listType = TypeCombinator::intersect(new ArrayType(new IntegerType(), $genericTypes[0]), new AccessoryArrayListType());
661657
if ($mainTypeName === 'non-empty-list') {
662658
return TypeCombinator::intersect($listType, new NonEmptyArrayType());
663659
}
@@ -995,7 +991,7 @@ private function resolveArrayShapeNode(ArrayShapeNode $typeNode, NameScope $name
995991

996992
$arrayType = $builder->getArray();
997993
if ($typeNode->kind === ArrayShapeNode::KIND_LIST) {
998-
$arrayType = AccessoryArrayListType::intersectWith($arrayType);
994+
$arrayType = TypeCombinator::intersect($arrayType, new AccessoryArrayListType());
999995
}
1000996

1001997
return $arrayType;

src/Reflection/InitializerExprTypeResolver.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -568,7 +568,7 @@ public function getArrayType(Expr\Array_ $expr, callable $getTypeCallback): Type
568568

569569
$arrayType = $arrayBuilder->getArray();
570570
if ($isList === true) {
571-
return AccessoryArrayListType::intersectWith($arrayType);
571+
return TypeCombinator::intersect($arrayType, new AccessoryArrayListType());
572572
}
573573

574574
return $arrayType;
@@ -1041,7 +1041,7 @@ public function getPlusType(Expr $left, Expr $right, callable $getTypeCallback):
10411041
$arrayType = TypeCombinator::intersect($arrayType, new NonEmptyArrayType());
10421042
}
10431043
if ($leftType->isList()->yes() && $rightType->isList()->yes()) {
1044-
$arrayType = AccessoryArrayListType::intersectWith($arrayType);
1044+
$arrayType = TypeCombinator::intersect($arrayType, new AccessoryArrayListType());
10451045
}
10461046

10471047
return $arrayType;

0 commit comments

Comments
 (0)