diff --git a/src/Type/ObjectType.php b/src/Type/ObjectType.php index edaead6006..05705fe683 100644 --- a/src/Type/ObjectType.php +++ b/src/Type/ObjectType.php @@ -946,7 +946,7 @@ public function getArraySize(): Type return new ErrorType(); } - return IntegerRangeType::fromInterval(0, null); + return RecursionGuard::run($this, fn (): Type => $this->getMethod('count', new OutOfClassScope())->getOnlyVariant()->getReturnType()); } public function getIterableKeyType(): Type diff --git a/tests/PHPStan/Analyser/nsrt/bug-7607.php b/tests/PHPStan/Analyser/nsrt/bug-7607.php index e8d6aa5911..5a654694cd 100644 --- a/tests/PHPStan/Analyser/nsrt/bug-7607.php +++ b/tests/PHPStan/Analyser/nsrt/bug-7607.php @@ -30,7 +30,7 @@ public function blank($value) return false; } - if ($value instanceof Countable) { + if ($value instanceof \Countable) { return count($value) === 0; } diff --git a/tests/PHPStan/Analyser/nsrt/countable.php b/tests/PHPStan/Analyser/nsrt/countable.php index 740430a4c5..d2cafc3d4e 100644 --- a/tests/PHPStan/Analyser/nsrt/countable.php +++ b/tests/PHPStan/Analyser/nsrt/countable.php @@ -15,9 +15,31 @@ static public function doFoo() { } } +class Bar implements \Countable { + + /** + * @return -1 + */ + public function count() : int { + return -1; + } + + static public function doBar() { + $bar = new Bar(); + assertType('-1', $bar->count()); + } +} + class NonCountable {} +function doNonCountable() { + assertType('*ERROR*', count(new NonCountable())); +} + function doFoo() { assertType('int<0, max>', count(new Foo())); - assertType('*ERROR*', count(new NonCountable())); +} + +function doBar() { + assertType('-1', count(new Bar())); }