phpstan-src icon indicating copy to clipboard operation
phpstan-src copied to clipboard

Preserve constant array when setting a union of constant scalar keys

Open ondrejmirtes opened this issue 1 month ago • 6 comments

ondrejmirtes avatar Nov 03 '25 18:11 ondrejmirtes

/cc @VincentLanglet This change solves a few issues, including your own: https://github.com/phpstan/phpstan-src/actions/runs/19044800760

Unfortunately it introduces also some problems which I can't dig into right now. Could you please debug why some existing tests are failing and some errors reappear?

I think some of it might be related to https://github.com/phpstan/phpstan-src/pull/4372 but not sure.

ondrejmirtes avatar Nov 03 '25 18:11 ondrejmirtes

Also /cc @staabm because you might have touched this more recently 😊

ondrejmirtes avatar Nov 03 '25 18:11 ondrejmirtes

Looking at failure

1) PHPStan\Rules\Classes\InstantiationRuleTest::testBug7594
Failed asserting that two strings are identical.
--- Expected
+++ Actual
@@ @@
-'
+'55: Parameter #1 $boolAbilities of class Bug7594\HelloWorld constructor expects array<0|1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16|17, bool>, array<int<0, max>, bool> given.
 '

=> Related to for loop, which generalize the result computed after the second loop. https://github.com/phpstan/phpstan-src/blob/770b08c052d846ac6b78e947d24f890d5b415915/src/Analyser/NodeScopeResolver.php#L1239-L1241

And looking at all the other issues, I think it's also the fact that for loop generalize result creating less precise ones, except:

4) PHPStan\Analyser\NodeScopeResolverTest::testFile with data set "tests\PHPStan\Analyser\nsrt\constant-array-type-set.php" ('D:\a\phpstan-src\phpstan-src\...et.php')
Failed assertions in D:\a\phpstan-src\phpstan-src\tests\PHPStan\Analyser\nsrt\constant-array-type-set.php:

Line 24:
Expected: array{bool, bool, bool}
Actual:   array{false, false, true}|array{false, true, false}|array{true, false, false}

Line 36:
Expected: array{0: bool, 1: bool, 2: bool, 3?: true}
Actual:   array{false, false, false, true}|array{false, false, true}|array{false, true, false}|array{true, false, false}

Line 42:
Expected: array{bool, bool, false}
Actual:   array{false, true, false}|array{true, false, false}

Line 104:
Expected: array{bool, bool, false}
Actual:   array{false, true, false}|array{true, false, false}

Seems expected to me

VincentLanglet avatar Nov 05 '25 20:11 VincentLanglet

pick this commit and you get a green build: https://github.com/staabm/phpstan-src/commit/333d1c4115c528eb41f563314385e606355cba5b

problem is/was: the PR without this fix created unions with lots of elements in the ConstantArray types. this got either turned into OversizedArrayType or generalized while analyzing loops.

staabm avatar Nov 06 '25 07:11 staabm

And pick https://github.com/staabm/phpstan-src/commit/4cbca5ecf291d9de74a715757e560fa05cdf23a8 on top to get IntegerRangeType support

staabm avatar Nov 06 '25 08:11 staabm

I decided to send a new PR, so I can see impact on issue-bot

staabm avatar Nov 06 '25 08:11 staabm