From b4f81dbd777f071d78ccfc453c12e82b6f950f11 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Wed, 8 Sep 2021 13:23:49 +0200 Subject: [PATCH] checkExplicitMixed - replace mixed type recursively --- src/Rules/RuleLevelHelper.php | 14 +++++++++++--- .../PHPStan/Rules/Methods/ReturnTypeRuleTest.php | 16 +++++++++++++++- tests/PHPStan/Rules/Methods/data/bug-5218.php | 16 ++++++++++++++++ 3 files changed, 42 insertions(+), 4 deletions(-) create mode 100644 tests/PHPStan/Rules/Methods/data/bug-5218.php diff --git a/src/Rules/RuleLevelHelper.php b/src/Rules/RuleLevelHelper.php index 7fc9724b81..151da55f84 100644 --- a/src/Rules/RuleLevelHelper.php +++ b/src/Rules/RuleLevelHelper.php @@ -18,6 +18,7 @@ use PHPStan\Type\StrictMixedType; use PHPStan\Type\Type; use PHPStan\Type\TypeCombinator; +use PHPStan\Type\TypeTraverser; use PHPStan\Type\TypeUtils; use PHPStan\Type\UnionType; @@ -60,10 +61,17 @@ public function accepts(Type $acceptingType, Type $acceptedType, bool $strictTyp { if ( $this->checkExplicitMixed - && $acceptedType instanceof MixedType - && $acceptedType->isExplicitMixed() ) { - $acceptedType = new StrictMixedType(); + $acceptedType = TypeTraverser::map($acceptedType, static function (Type $type, callable $traverse): Type { + if ( + $type instanceof MixedType + && $type->isExplicitMixed() + ) { + return new StrictMixedType(); + } + + return $traverse($type); + }); } if ( diff --git a/tests/PHPStan/Rules/Methods/ReturnTypeRuleTest.php b/tests/PHPStan/Rules/Methods/ReturnTypeRuleTest.php index cdc7ad1b48..5da2727615 100644 --- a/tests/PHPStan/Rules/Methods/ReturnTypeRuleTest.php +++ b/tests/PHPStan/Rules/Methods/ReturnTypeRuleTest.php @@ -11,9 +11,12 @@ class ReturnTypeRuleTest extends \PHPStan\Testing\RuleTestCase { + /** @var bool */ + private $checkExplicitMixed = false; + protected function getRule(): \PHPStan\Rules\Rule { - return new ReturnTypeRule(new FunctionReturnTypeCheck(new RuleLevelHelper($this->createReflectionProvider(), true, false, true, false))); + return new ReturnTypeRule(new FunctionReturnTypeCheck(new RuleLevelHelper($this->createReflectionProvider(), true, false, true, $this->checkExplicitMixed))); } public function testReturnTypeRule(): void @@ -527,4 +530,15 @@ public function testTemplateUnion(): void ]); } + public function testBug5218(): void + { + $this->checkExplicitMixed = true; + $this->analyse([__DIR__ . '/data/bug-5218.php'], [ + [ + 'Method Bug5218\IA::getIterator() should return Traversable but returns ArrayIterator.', + 14, + ], + ]); + } + } diff --git a/tests/PHPStan/Rules/Methods/data/bug-5218.php b/tests/PHPStan/Rules/Methods/data/bug-5218.php new file mode 100644 index 0000000000..9388a22e07 --- /dev/null +++ b/tests/PHPStan/Rules/Methods/data/bug-5218.php @@ -0,0 +1,16 @@ + + */ +final class IA implements \IteratorAggregate +{ + /** @var array */ + private $data = []; + + public function getIterator() : \Traversable { + return new \ArrayIterator($this->data); + } +}