From 70e8bdbb6b2bc218461b2ee1841e94d949024359 Mon Sep 17 00:00:00 2001 From: Vincent Langlet Date: Sun, 1 Sep 2024 13:04:14 +0200 Subject: [PATCH 1/3] Fix list consideration with union of scalar as offset --- .../Constant/ConstantArrayTypeBuilder.php | 4 ++-- .../Analyser/nsrt/array-is-list-offset.php | 19 +++++++++++++++++++ 2 files changed, 21 insertions(+), 2 deletions(-) create mode 100644 tests/PHPStan/Analyser/nsrt/array-is-list-offset.php diff --git a/src/Type/Constant/ConstantArrayTypeBuilder.php b/src/Type/Constant/ConstantArrayTypeBuilder.php index 525b65caed..a306833e8d 100644 --- a/src/Type/Constant/ConstantArrayTypeBuilder.php +++ b/src/Type/Constant/ConstantArrayTypeBuilder.php @@ -199,8 +199,6 @@ public function setOffsetValueType(?Type $offsetType, Type $valueType, bool $opt return; } - $this->isList = TrinaryLogic::createNo(); - $scalarTypes = $offsetType->getConstantScalarTypes(); if (count($scalarTypes) === 0) { $integerRanges = TypeUtils::getIntegerRanges($offsetType); @@ -257,6 +255,8 @@ public function setOffsetValueType(?Type $offsetType, Type $valueType, bool $opt return; } } + + $this->isList = TrinaryLogic::createNo(); } if ($offsetType === null) { diff --git a/tests/PHPStan/Analyser/nsrt/array-is-list-offset.php b/tests/PHPStan/Analyser/nsrt/array-is-list-offset.php new file mode 100644 index 0000000000..911490fac7 --- /dev/null +++ b/tests/PHPStan/Analyser/nsrt/array-is-list-offset.php @@ -0,0 +1,19 @@ + $key + */ + public function test(array $array, int $key) { + assertType('int<0, 1>', $key); + assertType('true', array_is_list($array)); + + $array[$key] = false; + assertType('true', array_is_list($array)); + } +} From 5516a2984f850043c8315cfd101a70641f4899d1 Mon Sep 17 00:00:00 2001 From: Vincent Langlet Date: Sun, 1 Sep 2024 19:20:12 +0200 Subject: [PATCH 2/3] Add test --- .../Constant/ConstantArrayTypeBuilderTest.php | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/tests/PHPStan/Type/Constant/ConstantArrayTypeBuilderTest.php b/tests/PHPStan/Type/Constant/ConstantArrayTypeBuilderTest.php index 0b8bff2efb..604d13c432 100644 --- a/tests/PHPStan/Type/Constant/ConstantArrayTypeBuilderTest.php +++ b/tests/PHPStan/Type/Constant/ConstantArrayTypeBuilderTest.php @@ -5,6 +5,7 @@ use PHPStan\Type\BooleanType; use PHPStan\Type\NullType; use PHPStan\Type\StringType; +use PHPStan\Type\TypeCombinator; use PHPStan\Type\VerbosityLevel; use PHPUnit\Framework\TestCase; @@ -128,4 +129,29 @@ public function testIsList(): void $this->assertFalse($builder->isList()); } + public function testIsListWithUnion(): void + { + $builder = ConstantArrayTypeBuilder::createEmpty(); + + $builder->setOffsetValueType(null, new ConstantIntegerType(0)); + $this->assertTrue($builder->isList()); + + $builder->setOffsetValueType(new ConstantIntegerType(0), new NullType()); + $this->assertTrue($builder->isList()); + + $builder->setOffsetValueType(new ConstantIntegerType(1), new NullType()); + $this->assertTrue($builder->isList()); + + $builder->setOffsetValueType(new ConstantIntegerType(2), new NullType()); + $this->assertTrue($builder->isList()); + + $oneOrZero = TypeCombinator::union( + new ConstantIntegerType(0), + new ConstantIntegerType(1), + ); + + $builder->setOffsetValueType($oneOrZero, new NullType()); + $this->assertTrue($builder->isList()); + } + } From da37e133ec46e45d440dd611ed7be563429eadec Mon Sep 17 00:00:00 2001 From: Vincent Langlet Date: Sun, 1 Sep 2024 21:09:57 +0200 Subject: [PATCH 3/3] Improve test --- .../Type/Constant/ConstantArrayTypeBuilderTest.php | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tests/PHPStan/Type/Constant/ConstantArrayTypeBuilderTest.php b/tests/PHPStan/Type/Constant/ConstantArrayTypeBuilderTest.php index 604d13c432..2d1aaa237c 100644 --- a/tests/PHPStan/Type/Constant/ConstantArrayTypeBuilderTest.php +++ b/tests/PHPStan/Type/Constant/ConstantArrayTypeBuilderTest.php @@ -152,6 +152,14 @@ public function testIsListWithUnion(): void $builder->setOffsetValueType($oneOrZero, new NullType()); $this->assertTrue($builder->isList()); + + $oneOrFour = TypeCombinator::union( + new ConstantIntegerType(1), + new ConstantIntegerType(4), + ); + + $builder->setOffsetValueType($oneOrFour, new NullType()); + $this->assertFalse($builder->isList()); } }