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
Solve https://github.com/phpstan/phpstan/issues/5348 #586
Conversation
build/phpstan.neon
Outdated
@@ -21,7 +21,6 @@ parameters: | |||
excludes_analyse: | |||
- ../src/Reflection/SignatureMap/functionMap.php | |||
- ../src/Reflection/SignatureMap/functionMetadata.php | |||
- ../tests/*/data/* |
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.
For local test
@ondrejmirtes This is ready to be reviewed :) |
src/Rules/RuleLevelHelper.php
Outdated
@@ -76,6 +78,17 @@ public function accepts(Type $acceptingType, Type $acceptedType, bool $strictTyp | |||
} | |||
|
|||
if ($acceptingType instanceof UnionType && !$acceptedType instanceof CompoundType) { | |||
if ( |
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.
Hi, I don't see why RuleLevelHelper would have to be changed for this.
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.
Don't know why but there is an early check here:
When I check \DateTimeInterface|int
vs \DateTime|\DateTimeImmutable|int
it's a compound type, so this is not done here and ends up in the UnionType::accepts methods.
But when I check \DateTimeInterface
vs \DateTime|\DateTimeImmutable
there is an early check here which return either true or false, so the UnionType::accepts method is never executed.
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 issue is about DateTime|DateTimeImmutable
accepting DateTimeInterface
. So only UnionType::accepts() should be modified.
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.
acceptingType = DateTime|DateTimeImmutable
acceptedType = DateTimeInterface
if ($acceptingType instanceof UnionType && !$acceptedType instanceof CompoundType) {
We're in this if.
So we're currently doing
foreach ($acceptingType->getTypes() as $innerType) {
if (self::accepts($innerType, $acceptedType, $strictTypes)) {
return true;
}
}
return false;
and since neither DateTime doesn't accept DateTimeInterface, neither DateTimeImmutable accept DateTimeInterface, false is returned.
I can change the check
if ($acceptingType instanceof UnionType && !$acceptedType instanceof CompoundType) {
to something like
if ($acceptingType instanceof UnionType && !$acceptedType instanceof CompoundType && !$acceptedType->equals(new ObjectType(\DateTimeInterface::class))) {
if you prefer, but something has to be done here.
If I remove the code added here, tests are failing.
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.
WDYT @ondrejmirtes ?
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 change in RuleLevelHelper shouldn't be specific to the DateTime situation, but more general. I propose something like this:
diff --git a/src/Rules/RuleLevelHelper.php b/src/Rules/RuleLevelHelper.php
index 240258921..7fc9724b8 100644
--- a/src/Rules/RuleLevelHelper.php
+++ b/src/Rules/RuleLevelHelper.php
@@ -75,7 +75,8 @@ class RuleLevelHelper
$acceptedType = TypeCombinator::removeNull($acceptedType);
}
- if ($acceptingType instanceof UnionType && !$acceptedType instanceof CompoundType) {
+ $accepts = $acceptingType->accepts($acceptedType, $strictTypes);
+ if (!$accepts->yes() && $acceptingType instanceof UnionType && !$acceptedType instanceof CompoundType) {
foreach ($acceptingType->getTypes() as $innerType) {
if (self::accepts($innerType, $acceptedType, $strictTypes)) {
return true;
@@ -103,8 +104,6 @@ class RuleLevelHelper
);
}
- $accepts = $acceptingType->accepts($acceptedType, $strictTypes);
-
return $this->checkUnionTypes ? $accepts->yes() : !$accepts->no();
}
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.
Yeah I didn't like to be specific to the DateTime but It wasn't clear to me what to do.
I used your proposal and seems to work perfectly ; thanks :)
efd31ce
to
0471f87
Compare
Thank you. |
No description provided.