From f27f0a3c1284acdce7c4cf10d676fcd226e4a572 Mon Sep 17 00:00:00 2001 From: Can Vural Date: Thu, 13 Jan 2022 13:59:26 +0100 Subject: [PATCH] Fix inferring template types in ClosureType --- src/Type/ClosureType.php | 2 +- .../PHPStan/Analyser/data/generic-unions.php | 32 +++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/src/Type/ClosureType.php b/src/Type/ClosureType.php index 5c9ebacb01f..d6747060e4e 100644 --- a/src/Type/ClosureType.php +++ b/src/Type/ClosureType.php @@ -334,7 +334,7 @@ public function inferTemplateTypes(Type $receivedType): TemplateTypeMap return $receivedType->inferTemplateTypesOn($this); } - if ($receivedType->isCallable()->no()) { + if ($receivedType->isCallable()->no() || ! $receivedType instanceof self) { return TemplateTypeMap::createEmpty(); } diff --git a/tests/PHPStan/Analyser/data/generic-unions.php b/tests/PHPStan/Analyser/data/generic-unions.php index 7ebc5bb89b8..0616294cb0c 100644 --- a/tests/PHPStan/Analyser/data/generic-unions.php +++ b/tests/PHPStan/Analyser/data/generic-unions.php @@ -61,3 +61,35 @@ public function foo( } } + +/** + * + * @template TGetDefault + * @template TKey + * + * @param TKey $key + * @param TGetDefault|(\Closure(): TGetDefault) $default + * @return TKey|TGetDefault + */ +function getWithDefault($key, $default = null) +{ + if(rand(0,10) > 5) { + return $key; + } + + if (is_callable($default)) { + return $default(); + } + + return $default; +} + +assertType('int|null', getWithDefault(3)); +assertType('int|string', getWithDefault(3, 'foo')); +assertType('int|string', getWithDefault(3, function () { + return 'foo'; +})); +assertType('GenericUnions\Foo|int', getWithDefault(3, function () { + return new Foo; +})); +assertType('GenericUnions\Foo|int', getWithDefault(3, new Foo));