Skip to content
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

Merged
merged 4 commits into from Jul 30, 2021

Conversation

VincentLanglet
Copy link
Contributor

No description provided.

@@ -21,7 +21,6 @@ parameters:
excludes_analyse:
- ../src/Reflection/SignatureMap/functionMap.php
- ../src/Reflection/SignatureMap/functionMetadata.php
- ../tests/*/data/*
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For local test

@VincentLanglet VincentLanglet changed the title Trying to solve https://github.com/phpstan/phpstan/issues/5348 Solve https://github.com/phpstan/phpstan/issues/5348 Jul 22, 2021
@VincentLanglet VincentLanglet marked this pull request as ready for review July 22, 2021 11:57
@VincentLanglet
Copy link
Contributor Author

@ondrejmirtes This is ready to be reviewed :)

@@ -76,6 +78,17 @@ public function accepts(Type $acceptingType, Type $acceptedType, bool $strictTyp
}

if ($acceptingType instanceof UnionType && !$acceptedType instanceof CompoundType) {
if (
Copy link
Member

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.

Copy link
Contributor Author

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.

Copy link
Member

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.

Copy link
Contributor Author

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.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WDYT @ondrejmirtes ?

Copy link
Member

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();
 	}
 

Copy link
Contributor Author

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 :)

@ondrejmirtes ondrejmirtes merged commit f3d449f into phpstan:master Jul 30, 2021
@ondrejmirtes
Copy link
Member

Thank you.

@VincentLanglet VincentLanglet deleted the datetime branch July 30, 2021 09:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
2 participants