diff --git a/src/Type/CallableType.php b/src/Type/CallableType.php index 9d9cfb65e4..4709fe5c61 100644 --- a/src/Type/CallableType.php +++ b/src/Type/CallableType.php @@ -138,7 +138,7 @@ public function accepts(Type $type, bool $strictTypes): AcceptsResult return $type->isAcceptedBy($this, $strictTypes); } - return $this->isSuperTypeOfInternal($type, true)->toAcceptsResult(); + return $this->isSuperTypeOfInternal($type, true, $strictTypes)->toAcceptsResult(); } public function isSuperTypeOf(Type $type): IsSuperTypeOfResult @@ -147,10 +147,10 @@ public function isSuperTypeOf(Type $type): IsSuperTypeOfResult return $type->isSubTypeOf($this); } - return $this->isSuperTypeOfInternal($type, false); + return $this->isSuperTypeOfInternal($type, false, true); } - private function isSuperTypeOfInternal(Type $type, bool $treatMixedAsAny): IsSuperTypeOfResult + private function isSuperTypeOfInternal(Type $type, bool $treatMixedAsAny, bool $strictTypes): IsSuperTypeOfResult { $isCallable = new IsSuperTypeOfResult($type->isCallable(), []); if ($isCallable->no()) { @@ -183,7 +183,7 @@ private function isSuperTypeOfInternal(Type $type, bool $treatMixedAsAny): IsSup if (!$variant instanceof CallableParametersAcceptor) { return IsSuperTypeOfResult::createNo([]); } - $isSuperType = CallableTypeHelper::isParametersAcceptorSuperTypeOf($this, $variant, $treatMixedAsAny); + $isSuperType = CallableTypeHelper::isParametersAcceptorSuperTypeOf($this, $variant, $treatMixedAsAny, $strictTypes); if ($variantsResult === null) { $variantsResult = $isSuperType; } else { diff --git a/src/Type/CallableTypeHelper.php b/src/Type/CallableTypeHelper.php index 4e99e94cc9..2f5b9f89b2 100644 --- a/src/Type/CallableTypeHelper.php +++ b/src/Type/CallableTypeHelper.php @@ -16,6 +16,7 @@ public static function isParametersAcceptorSuperTypeOf( CallableParametersAcceptor $ours, CallableParametersAcceptor $theirs, bool $treatMixedAsAny, + bool $strictTypes = true, ): IsSuperTypeOfResult { $theirParameters = $theirs->getParameters(); @@ -72,7 +73,7 @@ public static function isParametersAcceptorSuperTypeOf( } if ($treatMixedAsAny) { - $isSuperType = $theirParameter->getType()->accepts($ourParameterType, true); + $isSuperType = $theirParameter->getType()->accepts($ourParameterType, $strictTypes); $isSuperType = new IsSuperTypeOfResult($isSuperType->result, $isSuperType->reasons); } else { $isSuperType = $theirParameter->getType()->isSuperTypeOf($ourParameterType); diff --git a/tests/PHPStan/Rules/Functions/CallToFunctionParametersRuleTest.php b/tests/PHPStan/Rules/Functions/CallToFunctionParametersRuleTest.php index 6bb50169fe..6cb5815c53 100644 --- a/tests/PHPStan/Rules/Functions/CallToFunctionParametersRuleTest.php +++ b/tests/PHPStan/Rules/Functions/CallToFunctionParametersRuleTest.php @@ -2746,4 +2746,10 @@ public function testBug13247(): void $this->analyse([__DIR__ . '/data/bug-13247.php'], []); } + #[RequiresPhp('>= 8.1')] + public function testBug11619(): void + { + $this->analyse([__DIR__ . '/data/bug-11619.php'], []); + } + } diff --git a/tests/PHPStan/Rules/Functions/data/bug-11619.php b/tests/PHPStan/Rules/Functions/data/bug-11619.php new file mode 100644 index 0000000000..ca66d37b56 --- /dev/null +++ b/tests/PHPStan/Rules/Functions/data/bug-11619.php @@ -0,0 +1,30 @@ += 8.1 + +namespace Bug11619; + +final class Foo implements \Stringable { + + private function __construct(public readonly string $value) { + } + + public static function fromString(string $string): self { + return new self($string); + } + + public function __toString(): string { + return $this->value; + } + +} + +function test(): void +{ + $options = [ + Foo::fromString('c'), + Foo::fromString('b'), + Foo::fromString('a'), + ]; + + uasort($options, 'strnatcasecmp'); + usort($options, 'strnatcasecmp'); +}