diff --git a/conf/config.neon b/conf/config.neon index 70d25334e3..6f9e7b2ebf 100644 --- a/conf/config.neon +++ b/conf/config.neon @@ -27,6 +27,7 @@ parameters: - RecursiveCallbackFilterIterator - AppendIterator - NoRewindIterator + - LimitIterator explicitMixedInUnknownGenericNew: false explicitMixedForGlobalVariables: false explicitMixedViaIsArray: false diff --git a/stubs/iterable.stub b/stubs/iterable.stub index dd9b7fab1d..c0be506f6e 100644 --- a/stubs/iterable.stub +++ b/stubs/iterable.stub @@ -321,3 +321,27 @@ class NoRewindIterator extends IteratorIterator { public function key() {} } +/** + * @template-covariant TKey + * @template-covariant TValue + * @template TIterator as Iterator + * + * @template-implements OuterIterator + * @template-extends IteratorIterator + */ +class LimitIterator extends IteratorIterator implements OuterIterator { + /** + * @param TIterator $iterator + */ + public function __construct(Iterator $iterator, int $offset = 0, int $count = -1) {} + + /** + * @return TValue + */ + public function current() {} + + /** + * @return TKey + */ + public function key() {} +} diff --git a/tests/PHPStan/Analyser/AnalyserIntegrationTest.php b/tests/PHPStan/Analyser/AnalyserIntegrationTest.php index 6a83f4103f..2bc3323d59 100644 --- a/tests/PHPStan/Analyser/AnalyserIntegrationTest.php +++ b/tests/PHPStan/Analyser/AnalyserIntegrationTest.php @@ -602,13 +602,15 @@ public function testBug6896(): void } $errors = $this->runAnalyse(__DIR__ . '/data/bug-6896.php'); - $this->assertCount(3, $errors); + $this->assertCount(4, $errors); $this->assertSame('Generic type IteratorIterator<(int|string), mixed> in PHPDoc tag @return does not specify all template types of class IteratorIterator: TKey, TValue, TIterator', $errors[0]->getMessage()); $this->assertSame(38, $errors[0]->getLine()); - $this->assertSame('Method Bug6896\RandHelper::getPseudoRandomWithUrl() return type with generic class Bug6896\XIterator does not specify its types: TKey, TValue', $errors[1]->getMessage()); + $this->assertSame('Generic type LimitIterator<(int|string), mixed> in PHPDoc tag @return does not specify all template types of class LimitIterator: TKey, TValue, TIterator', $errors[1]->getMessage()); $this->assertSame(38, $errors[1]->getLine()); - $this->assertSame('Method Bug6896\RandHelper::getPseudoRandomWithUrl() should return array|Bug6896\XIterator|(iterable&LimitIterator)|IteratorIterator but returns TRandList of array|Traversable.', $errors[2]->getMessage()); - $this->assertSame(42, $errors[2]->getLine()); + $this->assertSame('Method Bug6896\RandHelper::getPseudoRandomWithUrl() return type with generic class Bug6896\XIterator does not specify its types: TKey, TValue', $errors[2]->getMessage()); + $this->assertSame(38, $errors[2]->getLine()); + $this->assertSame('Method Bug6896\RandHelper::getPseudoRandomWithUrl() should return array|Bug6896\XIterator|IteratorIterator|LimitIterator but returns TRandList of array|Traversable.', $errors[3]->getMessage()); + $this->assertSame(42, $errors[3]->getLine()); } public function testBug6940(): void