Skip to content

Conversation

@VincentLanglet
Copy link
Contributor

No description provided.

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

}

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

Development

Successfully merging this pull request may close these issues.

2 participants