-
Notifications
You must be signed in to change notification settings - Fork 551
Report non existent offset on non empty array #4399
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: 2.1.x
Are you sure you want to change the base?
Conversation
d8a12f6 to
2a9b54c
Compare
|
What I currently do not fix: Because when there is more than 10 optional keys |
|
I think the previous behaviour is intentional, as |
I don't think it's intentional. The "play it safe" argument is ok on level < 7, but in my mind that's exactly the purpose of "reportMaybe". Here, even if the array is non empty, we cannot be sure which key si non-optional so we have to report the key might not exists. You have the same issue (as showed by https://phpstan.org/r/a9660963-948d-4d4b-9cb8-166af8806987) with which doesn't report that offset 4 might not exists BECAUSE it's a list, and as soon as you unset the 0 value it's reported In phpstan/phpstan#7143 the same can be reproduce with |
| $optionalKeysCombinations = [ | ||
| [], | ||
| array_slice($this->optionalKeys, 0, 1, true), | ||
| array_slice($this->optionalKeys, -1, 1, true), | ||
| $this->optionalKeys, | ||
| ]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When an array only have optionalKey AND is non-empty, the result of getAllArray intersected with NonEmptyArray will give an array with all the keys and no key will be reported with
$innerType->hasOffsetValueType($innerDimType)->no()
So I have to
- add a smallest array possible to report every optional key (except the first one)
- add another smallest array possible to report the first optional key
If wanted, these two array could be added only if
count($this->keyTypes) === count($this->optionalKeys)
7678343 to
d520c9f
Compare
|
Failure are expected, those bug was never fixed it just stopped to be reported because the array was non-empty. So we have to remove the tests and reopen the issues... |
49c080f to
a98040b
Compare
a98040b to
21e650d
Compare
|
I don't think is something doable... so I dunno how to cover the mutant |
b540fe9 to
7f46afa
Compare
7f46afa to
d297fa8
Compare
src/Type/TypeUtils.php
Outdated
| return $type->getAllArrays(); | ||
| } | ||
|
|
||
| if ($type instanceof IntersectionType && $type->isConstantArray()->yes()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
$type instanceof IntersectionType && $type->isConstantArray()->maybe() doesn't seems to be a relevant case.
Do you agree on reopening those 2 issues @ondrejmirtes @staabm ? |
c28a5f2 to
8431d18
Compare
src/Type/TypeUtils.php
Outdated
| return $type->getAllArrays(); | ||
| } | ||
|
|
||
| if ($type instanceof IntersectionType && $type->isConstantArray()->yes()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wouldn't it be better to just do something with $type->getConstantArrays()? Instead of instanceof IntersectionType? This method returns list<ConstantArrayType> so we know we can call getAllArrays() on it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Refactored with 398b701 and it's way better indeed
8431d18 to
efd51a8
Compare
| if (preg_match('/^([A-Z]{1,3})([0-9]{1,7})(:([A-Z]{1,3})([0-9]{1,7}))?$/', $ref, $matches) !== 1) { | ||
| return $ref; | ||
| } | ||
| if (!isset($matches[3])) { // single cell, not range |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
getting this error back would be frustrating for the phpstan user.
what needs to be done, that we can make the error not show up here?
how does the type look like in $matches and what needs to change so we don't get the error back?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
getting this error back would be frustrating for the phpstan user.
Unlike you I never worked on regex with PHPStan. I don't even understand it well.
If I understand correctly, if the third element exists, both the fourth and fifth should exists ?
According to phpstan/phpstan#11602 (comment) you said it would require a tagged union for this specific case. So $matches should be understood as
list{0: non-falsy-string, 1: non-empty-string, 2: numeric-string}|list{0: non-falsy-string, 1: non-empty-string, 2: numeric-string, 3: string, 4: string, 5: numeric-string}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
said differently: the fix this PR provides for a maybe not-so-important problem feels less important to me than getting back a regression in PHPStan preg_match() handling.
I don't say this PR is not correct, but I feel we should make sure we don't need to regress at least the preg_match() case before merging.
(this might mean I need to dive into PHPStan regex handling)
thats my personal opinion though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the fix this PR provides for a maybe not-so-important problem feels less important to me than getting back a regression in PHPStan preg_match() handling.
That's really opinionated and debated for at least two reason
-
"getting back a regression in PHPStan preg_match() handling" => This is not a real regression in preg_match handling, since the preg_match handling is already not fully working as explained you can look at https://phpstan.org/r/a6d39b21-3365-4b4a-bfa8-6b111b6a9c7a the false-error is already reported with reportPossiblyNonexistentConstantArrayOffset (since the preg_match is not correctly handled).
-
"maybe not-so-important problem feels less important", I feel like the whole preg_match issue could be solved on developper side by checking
if (!isset($matches[5]))instead of$matches[3]. Since you improved the preg_match result as a list, it should imply isset for the key 3 and 4.
Seems like it currently does not https://phpstan.org/r/74ac6bac-5ac9-41b6-987d-281bad7a771d and could be fixed in the next following PR. WDYT ?

Closes phpstan/phpstan#7143
I discovered that a maybe not existent offset
array{'foo'?: 1, 'bar'?: 2}non-empty-array{'foo'?: 1, 'bar'?: 2}It seems like it's because TypeUtils::flattenType does not support Intersection types so
but
Funny thing, fixing it is breaking some non-regression tests like
Misinterpreting Whether Regular Expression Piece Exists phpstan#11602: this was supposed to be fixed by RegexArrayShapeMatcher - enforce list-type when no named captures #3899 but wasn't: the array shape was transformed into an intersection list&array shape, that's why the error wasn't reported anymore. (cc @staabm)
=> A way to see this is the fact it's reported with reportPossiblyNonexistentConstantArrayOffset https://phpstan.org/r/42af1687-c88d-4369-8c0b-7d3d1a14fcaa
Array offset in OR condition can not be resolved. phpstan#6379: this was supposed to be fixed but wasn't too: the array shape was transformed into an intersection non-empty-array&array shape, so the error was not reported anymore.
=> A way to see this is the fact it's reported with reportPossiblyNonexistentConstantArrayOffset https://phpstan.org/r/656d35b8-2ea0-4207-99b7-cd218f2151b9
What should I do in such case ? Removing the non-regression test and you'll open the two issues @ondrejmirtes ?