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
Try to fix issue 8087 #1808
Try to fix issue 8087 #1808
Conversation
36830af
to
b3eee55
Compare
b3eee55
to
9acd633
Compare
The change provided by this PR is fixing the issue phpstan/phpstan#8087 (comment) Some tests are failing because.
is now understood as
Currently the following tests:
and
but they shouldn't IMHO. But I'm not sure what is possible to do with PHPStan, and what is wanted. |
I just saw that #1823 has added a new |
phpstan/phpstan#6173 seems related |
0ff15d5
to
cbf413f
Compare
Instead of doing 9acd633 (which was failing some tests) When setting a value for a specific constant key, it shouldn't override the whole array value type. But now, all the tests (old and new ones) are green. Is this ok this way ? |
Wdyt about this solution @ondrejmirtes ? |
src/Type/ArrayType.php
Outdated
@@ -286,9 +286,11 @@ public function setOffsetValueType(?Type $offsetType, Type $valueType, bool $uni | |||
|
|||
$array = new self( | |||
TypeCombinator::union($this->keyType, $offsetType), | |||
$unionValues ? TypeCombinator::union($this->itemType, $valueType) : $valueType, | |||
$unionValues || $offsetType instanceof ConstantStringType || $offsetType instanceof ConstantIntegerType |
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 don't love this fix, what sense does it make? Why do you choose to union the values even for !$unionValues
?
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 you have the following kind of array
non-empty-array<string, mixed>&hasOffsetValue('uses', array)
And when you're doing
$array['uses'][] = '';
Phpstan is trying to do
$valueToWrite = $offsetValueType->setOffsetValueType($offsetType, $valueToWrite, $i === 0);
where $i
is 1, so unionValues is false.
setOffsetValueType
is called on an intersection Type so it's applied on every types
hasOffsetValue('uses', array)
become hasOffsetValue('uses', non-empty-array)
and non-empty-array<string, mixed>
become non-empty-array<string, non-empty-array>
(which is wrong)
I wanted that non-empty-array<string, mixed>
stay like it was. So I thought that when you're calling setOffsetValue with a specific constant key, the generic array type should still keep the union strategy. (in this case mixed will stay mixed).
But maybe something should be done to the IntersectionType::offsetValue
method.
Something like, if there is hasOffsetValueType
, the ArrayType
must not call 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.
In fact the issue is that
$array['uses'][] = '';
and
$array['uses'] = [...$array['uses'], ''];
doesn't behave the same way.
bd951f5
to
ede9c22
Compare
ede9c22
to
22a2c7c
Compare
So I rewrite the setOffsetValueType code by merging together all the specific code to the ConstantStringType/ConstantIntegerType, (without changing anything) it's if ($offsetType instanceof ConstantStringType || $offsetType instanceof ConstantIntegerType) {
if ($offsetType->isSuperTypeOf($this->keyType)->yes()) {
$builder = ConstantArrayTypeBuilder::createEmpty();
$builder->setOffsetValueType($offsetType, $valueType);
return $builder->getArray();
}
return TypeCombinator::intersect(
new self(
TypeCombinator::union($this->keyType, $offsetType),
$unionValues ? TypeCombinator::union($this->itemType, $valueType) : $valueType,
),
new HasOffsetValueType($offsetType, $valueType),
new NonEmptyArrayType()
);
}
return TypeCombinator::intersect(
new self(
TypeCombinator::union($this->keyType, $offsetType),
$unionValues ? TypeCombinator::union($this->itemType, $valueType) : $valueType,
),
new NonEmptyArrayType()
); And now, it makes more sens to me to remove the
Since we're intersecting with |
Alright, let's try this. Thank you! |
🎉 nice that you figured out a simplified fix |
Yeah, it's satisfying. I feel like this was the most complex PR I had to make so far. :) Now I just need to find what to do with #1795 in order to allow me to bump phpstan dependencies on my work project. 🤞 |
PHPStan bug is rarely blocking, you can almost always ignore the error and update anyway. |
no point holding yourself back from finding other potential issues elsewhere and i do love it when you |
I agree on solo project or on a project with other phpstan-lovers. But when it's a project with some phpstan-beginners or complaining people
PHPStan is a great tool, and more and more people appreciate working with it, but sometimes it require time before ^^' |
you can say that again 😅 , i have experienced this myself introducing phpstan to my org aswell, people love the path of least resistance, but that should definitely be questioned in code review |
Closes phpstan/phpstan#8087