Skip to content

Conversation

VincentLanglet
Copy link
Contributor

@VincentLanglet VincentLanglet commented Aug 6, 2025

Static analysis is failing because TypeTraverserInstanceofVisitor doesn't support SimultaneousTypeTraverser (not sure it should).

The only current test failing is

16: Function ReturnListNullables\doFoo() should return array<string>|null but returns list<string|null>.

but I feel like we could reproduce more errors because...

UnionType/Intersection types doesn't work well with the SimultaneousTypeTraverser because

  • when it's called with A&B&C and A we're not traversing because second type is not an Intersection
  • when it's called with A&B&C and A&C we're not traversing because types count are different

The main issue would be, when traversing A&B&C and A&C, to match types in order to

  • traverse (A, A)
  • traverse (B, Never)
  • traverse (C, C)

@ondrejmirtes
Copy link
Member

The output from issue-bot is yummy here! https://github.com/phpstan/phpstan-src/actions/runs/16773630245

Please add regression tests for those.

I feel like we could improve IntersectionType::traverseSimultaneously() for all the common pseudotypes like non-empty-string, list etc. represented with IntersectionType.

I feel that even when there's non-empty-string on left side and string on the right side and vice versa, the callback should still be invoked for them.

This needs extensive tests of course.

@ondrejmirtes
Copy link
Member

Linking phpstan/phpstan#9096

@VincentLanglet
Copy link
Contributor Author

The output from issue-bot is yummy here! phpstan/phpstan-src/actions/runs/16773630245

Please add regression tests for those.

Sure, but shouldn't we fix the actual tests first ?

I feel like we could improve IntersectionType::traverseSimultaneously() for all the common pseudotypes like non-empty-string, list etc. represented with IntersectionType.

I feel that even when there's non-empty-string on left side and string on the right side and vice versa, the callback should still be invoked for them.

Yeah, but I dunno how to improve the implementation of the existing traverseSimultaneously, it's not easy :/

@VincentLanglet
Copy link
Contributor Author

I feel like 6597ef6#r167671380 is helping us.

And maybe same should be done for IntersectionType

@ondrejmirtes
Copy link
Member

Yeah, I'm thinking about how to implement it.

@ondrejmirtes
Copy link
Member

Right now I have this failing test:

diff --git a/tests/PHPStan/Type/SimultaneousTypeTraverserTest.php b/tests/PHPStan/Type/SimultaneousTypeTraverserTest.php
index 76dc038873..750a7a56bd 100644
--- a/tests/PHPStan/Type/SimultaneousTypeTraverserTest.php
+++ b/tests/PHPStan/Type/SimultaneousTypeTraverserTest.php
@@ -125,6 +125,13 @@ class SimultaneousTypeTraverserTest extends PHPStanTestCase
 			$chooseScalarSubtype,
 			"'aaa'|Foo",
 		];
+
+		yield [
+			'list<string|null>',
+			'array<string>',
+			$chooseScalarSubtype,
+			'list<string>',
+		];
 	}
 
 	/**

@ondrejmirtes
Copy link
Member

Alright here's something 0693e5a

But I don't think it works well for constant arrays for example or other situations, but some use cases could be solved now.

@VincentLanglet
Copy link
Contributor Author

Alright here's something 0693e5a

But I don't think it works well for constant arrays for example or other situations, but some use cases could be solved now.

Isn't it weird to only have the case if ($this->isArray()->yes() && $right->isArray()->yes()) { handled in the IntersectionType::traverseSimultaneously ? I feel like you lost all the other possible intersection like

  • string + Accessory
  • object like A&B
  • ...

@ondrejmirtes
Copy link
Member

Well it might not even be needed, depends on how the callback is written. You can send me some failing tests with expectations.

@VincentLanglet
Copy link
Contributor Author

Current status, 2 errors:

1) PHPStan\Rules\Functions\ReturnTypeRuleTest::testListWithNullablesUnchecked
Failed asserting that two strings are identical.
--- Expected
+++ Actual
@@ @@
-'
+'16: Function ReturnListNullables\doFoo() should return array<string>|null but returns list<string|null>.
 '

/home/runner/work/phpstan-src/phpstan-src/src/Testing/RuleTestCase.php:179
/home/runner/work/phpstan-src/phpstan-src/tests/PHPStan/Rules/Functions/ReturnTypeRuleTest.php:186

2) PHPStan\Rules\Functions\ReturnTypeRuleTest::testBug8846
Failed asserting that two strings are identical.
--- Expected
+++ Actual
@@ @@
-'
+'23: Function Bug8846\test() should return Bug8846\Foo::THREE|Bug8846\Foo::TWO but returns Bug8846\Foo.
 '

First one is maybe an Intersection type with $this->isArray()->yes() (list) but $right->isArray()->maybe() (array|null)...

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