-
Notifications
You must be signed in to change notification settings - Fork 545
Preserve constant array when setting a union of constant scalar keys #4520
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
|
/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 #4372 but not sure. |
|
Also /cc @staabm because you might have touched this more recently 😊 |
| if ($offsetType !== null) { | ||
| $constantScalars = $offsetType->getConstantScalarTypes(); | ||
| $constantScalarsCount = count($constantScalars); | ||
| if ($constantScalarsCount > 1 && $constantScalarsCount < ConstantArrayTypeBuilder::ARRAY_COUNT_LIMIT) { | ||
| $arrays = []; | ||
| foreach ($constantScalars as $constantScalar) { | ||
| $builder = ConstantArrayTypeBuilder::createFromConstantArray($this); | ||
| $builder->setOffsetValueType($constantScalar, $valueType); | ||
| $arrays[] = $builder->getArray(); | ||
| } | ||
|
|
||
| return TypeCombinator::union($this, ...$arrays); | ||
| } | ||
| } |
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.
I wonder, whether this code should be moved into the impl of ConstantArrayTypeBuilder->setOffsetValueType()?
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.
It should be handled there but this code should not be copied, but adapted (it's not so easy to do it there). I just wanted to try a quick PoC first.
| return new ErrorType(); // undefined offset | ||
| } | ||
|
|
||
| public function setOffsetValueType(?Type $offsetType, Type $valueType, bool $unionValues = true): Type |
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.
looking at this unionValues parameter, makes me feel we nearly everytime ignore it.
I wonder whether this bool represents the same 2 use-cases as setOffsetValueType() vs. setExistingOffsetValueType().
like unionValues=true is the same as setOffsetValueType()
and unionValues=false is the same as setExistingOffsetValueType()
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 unionValues parameter is some hack I came up with, there's no deeper thought in it and it's likely the proper solution is different.
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 unionValues parameter is some hack I came up with,
What is the purpose of this hack ?
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.
I did some research yesterday. it was introduced with 5d64483
| $arrays[] = $builder->getArray(); | ||
| } | ||
|
|
||
| return TypeCombinator::union($this, ...$arrays); |
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.
I might be tired but why
return TypeCombinator::union($this, ...$arrays);
and not
| return TypeCombinator::union($this, ...$arrays); | |
| return TypeCombinator::union(...$arrays); |
?
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.
I was also tired, it makes sense without the $this 😊 Updated that.
| if ($offsetType !== null) { | ||
| $constantScalars = $offsetType->getConstantScalarTypes(); | ||
| $constantScalarsCount = count($constantScalars); | ||
| if ($constantScalarsCount > 1 && $constantScalarsCount < ConstantArrayTypeBuilder::ARRAY_COUNT_LIMIT) { |
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.
Do we need similar handling for integer ranges with less than array-limit elements?
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.
Yes, that would make sense!
7ab4b71 to
50eec8c
Compare
|
Looking at failure => Related to for loop, which generalize the result computed after the second loop. phpstan-src/src/Analyser/NodeScopeResolver.php Lines 1239 to 1241 in 770b08c
And looking at all the other issues, I think it's also the fact that for loop generalize result creating less precise ones, except: Seems expected to me |
No description provided.