From af88720a518b6e39b7c1509d7fbc19440d72a585 Mon Sep 17 00:00:00 2001 From: Richard van Velzen Date: Fri, 1 Apr 2022 14:29:04 +0200 Subject: [PATCH 1/9] Make ParametersAcceptorSelector::selectSingle() return union-ed conditional types See phpstan/phpstan/issues/3853#issuecomment-1082351763 --- src/Reflection/ParametersAcceptorSelector.php | 2 +- src/Reflection/SingleParametersAcceptor.php | 52 +++++++++++++++++++ src/Type/ConditionalType.php | 2 +- src/Type/Traits/ConditionalTypeTrait.php | 2 +- ...icReturnTypeExtensionTypeInferenceTest.php | 1 + .../data/TestDynamicReturnTypeExtensions.php | 20 +++++++ ...ic-method-return-getsingle-conditional.php | 20 +++++++ .../PHPStan/Analyser/dynamic-return-type.neon | 4 ++ 8 files changed, 100 insertions(+), 3 deletions(-) create mode 100644 src/Reflection/SingleParametersAcceptor.php create mode 100644 tests/PHPStan/Analyser/data/dynamic-method-return-getsingle-conditional.php diff --git a/src/Reflection/ParametersAcceptorSelector.php b/src/Reflection/ParametersAcceptorSelector.php index 15d13d5f63..d69697629d 100644 --- a/src/Reflection/ParametersAcceptorSelector.php +++ b/src/Reflection/ParametersAcceptorSelector.php @@ -48,7 +48,7 @@ public static function selectSingle( throw new ShouldNotHappenException('Multiple variants - use selectFromArgs() instead.'); } - return $parametersAcceptors[0]; + return new SingleParametersAcceptor($parametersAcceptors[0]); } /** diff --git a/src/Reflection/SingleParametersAcceptor.php b/src/Reflection/SingleParametersAcceptor.php new file mode 100644 index 0000000000..7faea3eaed --- /dev/null +++ b/src/Reflection/SingleParametersAcceptor.php @@ -0,0 +1,52 @@ +acceptor->getTemplateTypeMap(); + } + + public function getResolvedTemplateTypeMap(): TemplateTypeMap + { + return $this->acceptor->getResolvedTemplateTypeMap(); + } + + /** + * @return array + */ + public function getParameters(): array + { + return $this->acceptor->getParameters(); + } + + public function isVariadic(): bool + { + return $this->acceptor->isVariadic(); + } + + public function getReturnType(): Type + { + return TypeTraverser::map($this->acceptor->getReturnType(), static function (Type $type, callable $traverse) { + while ($type instanceof ConditionalType || $type instanceof ConditionalTypeForParameter) { + $type = $type->getResult(); + } + + return $traverse($type); + }); + } + +} diff --git a/src/Type/ConditionalType.php b/src/Type/ConditionalType.php index 02bb7c31d8..45d91cb8c8 100644 --- a/src/Type/ConditionalType.php +++ b/src/Type/ConditionalType.php @@ -91,7 +91,7 @@ private function resolve(): Type } if ($this->isResolved()) { - return TypeCombinator::union($this->if, $this->else); + return $this->getResult(); } return $this; diff --git a/src/Type/Traits/ConditionalTypeTrait.php b/src/Type/Traits/ConditionalTypeTrait.php index 0231649aa5..62cb645557 100644 --- a/src/Type/Traits/ConditionalTypeTrait.php +++ b/src/Type/Traits/ConditionalTypeTrait.php @@ -288,7 +288,7 @@ public function isGreaterThanOrEqual(Type $otherType): TrinaryLogic return $otherType->isSmallerThanOrEqual($result); } - private function getResult(): Type + public function getResult(): Type { if ($this->result === null) { return $this->result = TypeCombinator::union($this->if, $this->else); diff --git a/tests/PHPStan/Analyser/DynamicReturnTypeExtensionTypeInferenceTest.php b/tests/PHPStan/Analyser/DynamicReturnTypeExtensionTypeInferenceTest.php index 85eebb189f..f6272e75dc 100644 --- a/tests/PHPStan/Analyser/DynamicReturnTypeExtensionTypeInferenceTest.php +++ b/tests/PHPStan/Analyser/DynamicReturnTypeExtensionTypeInferenceTest.php @@ -11,6 +11,7 @@ public function dataAsserts(): iterable { yield from $this->gatherAssertTypes(__DIR__ . '/data/dynamic-method-return-types.php'); yield from $this->gatherAssertTypes(__DIR__ . '/data/dynamic-method-return-compound-types.php'); + yield from $this->gatherAssertTypes(__DIR__ . '/data/dynamic-method-return-getsingle-conditional.php'); } /** diff --git a/tests/PHPStan/Analyser/data/TestDynamicReturnTypeExtensions.php b/tests/PHPStan/Analyser/data/TestDynamicReturnTypeExtensions.php index 3fd9f8b0b4..a86f0eaaf7 100644 --- a/tests/PHPStan/Analyser/data/TestDynamicReturnTypeExtensions.php +++ b/tests/PHPStan/Analyser/data/TestDynamicReturnTypeExtensions.php @@ -189,3 +189,23 @@ public function getTypeFromMethodCall(MethodReflection $methodReflection, Method } } + + +class ConditionalGetSingle implements DynamicMethodReturnTypeExtension { + + public function getClass(): string + { + return \DynamicMethodReturnGetSingleConditional\Foo::class; + } + + public function isMethodSupported(MethodReflection $methodReflection): bool + { + return $methodReflection->getName() === 'get'; + } + + public function getTypeFromMethodCall(MethodReflection $methodReflection, MethodCall $methodCall, Scope $scope): Type + { + return ParametersAcceptorSelector::selectSingle($methodReflection->getVariants())->getReturnType(); + } + +} diff --git a/tests/PHPStan/Analyser/data/dynamic-method-return-getsingle-conditional.php b/tests/PHPStan/Analyser/data/dynamic-method-return-getsingle-conditional.php new file mode 100644 index 0000000000..270658e7ef --- /dev/null +++ b/tests/PHPStan/Analyser/data/dynamic-method-return-getsingle-conditional.php @@ -0,0 +1,20 @@ +get(0)); + assertType('bool', $this->get(1)); + assertType('bool', $this->get(2)); + } +} diff --git a/tests/PHPStan/Analyser/dynamic-return-type.neon b/tests/PHPStan/Analyser/dynamic-return-type.neon index b8bd815fb4..6d781ca77f 100644 --- a/tests/PHPStan/Analyser/dynamic-return-type.neon +++ b/tests/PHPStan/Analyser/dynamic-return-type.neon @@ -27,3 +27,7 @@ services: class: PHPStan\Tests\FooGetSelf tags: - phpstan.broker.dynamicMethodReturnTypeExtension + - + class: PHPStan\Tests\ConditionalGetSingle + tags: + - phpstan.broker.dynamicMethodReturnTypeExtension From a71c9779a7149d8a2ecd7326d42ee66e4e2ab750 Mon Sep 17 00:00:00 2001 From: Richard van Velzen Date: Fri, 1 Apr 2022 16:44:29 +0200 Subject: [PATCH 2/9] Make it work? --- src/Reflection/ParametersAcceptorSelector.php | 10 ++++++++-- src/Reflection/SingleParametersAcceptor.php | 18 ++++++++++++------ src/Type/TypeUtils.php | 18 ++++++++++++++++++ .../Analyser/AnalyserIntegrationTest.php | 2 +- 4 files changed, 39 insertions(+), 9 deletions(-) diff --git a/src/Reflection/ParametersAcceptorSelector.php b/src/Reflection/ParametersAcceptorSelector.php index d69697629d..5e87e64c74 100644 --- a/src/Reflection/ParametersAcceptorSelector.php +++ b/src/Reflection/ParametersAcceptorSelector.php @@ -17,6 +17,7 @@ use PHPStan\Type\NullType; use PHPStan\Type\Type; use PHPStan\Type\TypeCombinator; +use PHPStan\Type\TypeUtils; use PHPStan\Type\UnionType; use function array_key_last; use function array_slice; @@ -32,7 +33,7 @@ class ParametersAcceptorSelector /** * @template T of ParametersAcceptor * @param T[] $parametersAcceptors - * @return T + * @return T|SingleParametersAcceptor */ public static function selectSingle( array $parametersAcceptors, @@ -48,7 +49,12 @@ public static function selectSingle( throw new ShouldNotHappenException('Multiple variants - use selectFromArgs() instead.'); } - return new SingleParametersAcceptor($parametersAcceptors[0]); + $parametersAcceptor = $parametersAcceptors[0]; + if (TypeUtils::containsConditional($parametersAcceptor->getReturnType())) { + return new SingleParametersAcceptor($parametersAcceptor); + } + + return $parametersAcceptor; } /** diff --git a/src/Reflection/SingleParametersAcceptor.php b/src/Reflection/SingleParametersAcceptor.php index 7faea3eaed..79f201a989 100644 --- a/src/Reflection/SingleParametersAcceptor.php +++ b/src/Reflection/SingleParametersAcceptor.php @@ -11,6 +11,8 @@ class SingleParametersAcceptor implements ParametersAcceptor { + private ?Type $returnType = null; + public function __construct(private ParametersAcceptor $acceptor) { } @@ -40,13 +42,17 @@ public function isVariadic(): bool public function getReturnType(): Type { - return TypeTraverser::map($this->acceptor->getReturnType(), static function (Type $type, callable $traverse) { - while ($type instanceof ConditionalType || $type instanceof ConditionalTypeForParameter) { - $type = $type->getResult(); - } + if ($this->returnType === null) { + return $this->returnType = TypeTraverser::map($this->acceptor->getReturnType(), static function (Type $type, callable $traverse) { + while ($type instanceof ConditionalType || $type instanceof ConditionalTypeForParameter) { + $type = $type->getResult(); + } + + return $traverse($type); + }); + } - return $traverse($type); - }); + return $this->returnType; } } diff --git a/src/Type/TypeUtils.php b/src/Type/TypeUtils.php index 91dcc50bb0..b70a126dc8 100644 --- a/src/Type/TypeUtils.php +++ b/src/Type/TypeUtils.php @@ -328,4 +328,22 @@ public static function containsCallable(Type $type): bool return false; } + public static function containsConditional(Type $type): bool + { + if ($type instanceof ConditionalType || $type instanceof ConditionalTypeForParameter) { + return true; + } + + $contains = false; + TypeTraverser::map($type, static function (Type $type, callable $traverse) use (&$contains): Type { + if ($type instanceof ConditionalType || $type instanceof ConditionalTypeForParameter) { + $contains = true; + } + + return !$contains ? $traverse($type) : $type; + }); + + return $contains; + } + } diff --git a/tests/PHPStan/Analyser/AnalyserIntegrationTest.php b/tests/PHPStan/Analyser/AnalyserIntegrationTest.php index 40396e50fb..3d7d92affc 100644 --- a/tests/PHPStan/Analyser/AnalyserIntegrationTest.php +++ b/tests/PHPStan/Analyser/AnalyserIntegrationTest.php @@ -622,7 +622,7 @@ public function testBug6896(): void } $errors = $this->runAnalyse(__DIR__ . '/data/bug-6896.php'); - $this->assertCount(4, $errors); + $this->assertCount(2, $errors); } public function testBug6940(): void From 28342ca80605d7b797e35a374911f8a9c3a36192 Mon Sep 17 00:00:00 2001 From: Richard van Velzen Date: Sat, 2 Apr 2022 08:20:46 +0200 Subject: [PATCH 3/9] Leave creating flattened return type variants to the acceptors --- src/Reflection/FunctionVariant.php | 14 ++++- src/Reflection/FunctionVariantWithPhpDocs.php | 14 +++++ src/Reflection/ParametersAcceptorSelector.php | 8 +-- src/Reflection/ResolvedFunctionVariant.php | 18 ++++++- src/Reflection/SingleParametersAcceptor.php | 52 +------------------ src/Type/TypeUtils.php | 17 ++---- 6 files changed, 56 insertions(+), 67 deletions(-) diff --git a/src/Reflection/FunctionVariant.php b/src/Reflection/FunctionVariant.php index 9936ae9244..6b623b80e9 100644 --- a/src/Reflection/FunctionVariant.php +++ b/src/Reflection/FunctionVariant.php @@ -4,9 +4,10 @@ use PHPStan\Type\Generic\TemplateTypeMap; use PHPStan\Type\Type; +use PHPStan\Type\TypeUtils; /** @api */ -class FunctionVariant implements ParametersAcceptor +class FunctionVariant implements ParametersAcceptor, SingleParametersAcceptor { /** @@ -51,4 +52,15 @@ public function getReturnType(): Type return $this->returnType; } + public function flattenConditionalsInReturnType(): static + { + return new self( + $this->templateTypeMap, + $this->resolvedTemplateTypeMap, + $this->parameters, + $this->isVariadic, + TypeUtils::flattenConditionals($this->returnType) + ); + } + } diff --git a/src/Reflection/FunctionVariantWithPhpDocs.php b/src/Reflection/FunctionVariantWithPhpDocs.php index aae15cb864..1873f33c0c 100644 --- a/src/Reflection/FunctionVariantWithPhpDocs.php +++ b/src/Reflection/FunctionVariantWithPhpDocs.php @@ -4,6 +4,7 @@ use PHPStan\Type\Generic\TemplateTypeMap; use PHPStan\Type\Type; +use PHPStan\Type\TypeUtils; /** @api */ class FunctionVariantWithPhpDocs extends FunctionVariant implements ParametersAcceptorWithPhpDocs @@ -53,4 +54,17 @@ public function getNativeReturnType(): Type return $this->nativeReturnType; } + public function flattenConditionalsInReturnType(): static + { + return new self( + $this->getTemplateTypeMap(), + $this->getResolvedTemplateTypeMap(), + $this->getParameters(), + $this->isVariadic(), + TypeUtils::flattenConditionals($this->getReturnType()), + TypeUtils::flattenConditionals($this->phpDocReturnType), + $this->nativeReturnType + ); + } + } diff --git a/src/Reflection/ParametersAcceptorSelector.php b/src/Reflection/ParametersAcceptorSelector.php index 5e87e64c74..ddb50abadf 100644 --- a/src/Reflection/ParametersAcceptorSelector.php +++ b/src/Reflection/ParametersAcceptorSelector.php @@ -17,6 +17,7 @@ use PHPStan\Type\NullType; use PHPStan\Type\Type; use PHPStan\Type\TypeCombinator; +use PHPStan\Type\TypeTraverser; use PHPStan\Type\TypeUtils; use PHPStan\Type\UnionType; use function array_key_last; @@ -33,7 +34,7 @@ class ParametersAcceptorSelector /** * @template T of ParametersAcceptor * @param T[] $parametersAcceptors - * @return T|SingleParametersAcceptor + * @return T */ public static function selectSingle( array $parametersAcceptors, @@ -50,8 +51,9 @@ public static function selectSingle( } $parametersAcceptor = $parametersAcceptors[0]; - if (TypeUtils::containsConditional($parametersAcceptor->getReturnType())) { - return new SingleParametersAcceptor($parametersAcceptor); + + if ($parametersAcceptor instanceof SingleParametersAcceptor) { + $parametersAcceptor = $parametersAcceptor->flattenConditionalsInReturnType(); } return $parametersAcceptor; diff --git a/src/Reflection/ResolvedFunctionVariant.php b/src/Reflection/ResolvedFunctionVariant.php index c0e6d27c4a..45bac6d783 100644 --- a/src/Reflection/ResolvedFunctionVariant.php +++ b/src/Reflection/ResolvedFunctionVariant.php @@ -8,10 +8,11 @@ use PHPStan\Type\Generic\TemplateTypeMap; use PHPStan\Type\Type; use PHPStan\Type\TypeTraverser; +use PHPStan\Type\TypeUtils; use function array_key_exists; use function array_map; -class ResolvedFunctionVariant implements ParametersAcceptor +class ResolvedFunctionVariant implements ParametersAcceptor, SingleParametersAcceptor { /** @var ParameterReflection[]|null */ @@ -88,6 +89,21 @@ public function getReturnType(): Type return $type; } + public function flattenConditionalsInReturnType(): static + { + $returnType = $this->getReturnType(); + + $result = new self( + $this->parametersAcceptor, + $this->resolvedTemplateTypeMap, + $this->passedArgs + ); + + $result->returnType = TypeUtils::flattenConditionals($returnType); + + return $result; + } + private function resolveConditionalTypes(Type $type): Type { return TypeTraverser::map($type, function (Type $type, callable $traverse): Type { diff --git a/src/Reflection/SingleParametersAcceptor.php b/src/Reflection/SingleParametersAcceptor.php index 79f201a989..57c77be557 100644 --- a/src/Reflection/SingleParametersAcceptor.php +++ b/src/Reflection/SingleParametersAcceptor.php @@ -2,57 +2,9 @@ namespace PHPStan\Reflection; -use PHPStan\Type\ConditionalType; -use PHPStan\Type\ConditionalTypeForParameter; -use PHPStan\Type\Generic\TemplateTypeMap; -use PHPStan\Type\Type; -use PHPStan\Type\TypeTraverser; - -class SingleParametersAcceptor implements ParametersAcceptor +interface SingleParametersAcceptor { - private ?Type $returnType = null; - - public function __construct(private ParametersAcceptor $acceptor) - { - } - - public function getTemplateTypeMap(): TemplateTypeMap - { - return $this->acceptor->getTemplateTypeMap(); - } - - public function getResolvedTemplateTypeMap(): TemplateTypeMap - { - return $this->acceptor->getResolvedTemplateTypeMap(); - } - - /** - * @return array - */ - public function getParameters(): array - { - return $this->acceptor->getParameters(); - } - - public function isVariadic(): bool - { - return $this->acceptor->isVariadic(); - } - - public function getReturnType(): Type - { - if ($this->returnType === null) { - return $this->returnType = TypeTraverser::map($this->acceptor->getReturnType(), static function (Type $type, callable $traverse) { - while ($type instanceof ConditionalType || $type instanceof ConditionalTypeForParameter) { - $type = $type->getResult(); - } - - return $traverse($type); - }); - } - - return $this->returnType; - } + public function flattenConditionalsInReturnType(): static; } diff --git a/src/Type/TypeUtils.php b/src/Type/TypeUtils.php index b70a126dc8..baa70858b6 100644 --- a/src/Type/TypeUtils.php +++ b/src/Type/TypeUtils.php @@ -328,22 +328,15 @@ public static function containsCallable(Type $type): bool return false; } - public static function containsConditional(Type $type): bool + public static function flattenConditionals(Type $type): Type { - if ($type instanceof ConditionalType || $type instanceof ConditionalTypeForParameter) { - return true; - } - - $contains = false; - TypeTraverser::map($type, static function (Type $type, callable $traverse) use (&$contains): Type { - if ($type instanceof ConditionalType || $type instanceof ConditionalTypeForParameter) { - $contains = true; + return TypeTraverser::map($type, static function (Type $type, callable $traverse) { + while ($type instanceof ConditionalType || $type instanceof ConditionalTypeForParameter) { + $type = $type->getResult(); } - return !$contains ? $traverse($type) : $type; + return $traverse($type); }); - - return $contains; } } From 83b829af884531e4f6b9f1ac23558e83cf303734 Mon Sep 17 00:00:00 2001 From: Richard van Velzen Date: Sat, 2 Apr 2022 08:27:24 +0200 Subject: [PATCH 4/9] Fix cs --- src/Reflection/FunctionVariant.php | 2 +- src/Reflection/FunctionVariantWithPhpDocs.php | 2 +- src/Reflection/ParametersAcceptorSelector.php | 2 -- src/Reflection/ResolvedFunctionVariant.php | 2 +- 4 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/Reflection/FunctionVariant.php b/src/Reflection/FunctionVariant.php index 6b623b80e9..0c0250e4f4 100644 --- a/src/Reflection/FunctionVariant.php +++ b/src/Reflection/FunctionVariant.php @@ -59,7 +59,7 @@ public function flattenConditionalsInReturnType(): static $this->resolvedTemplateTypeMap, $this->parameters, $this->isVariadic, - TypeUtils::flattenConditionals($this->returnType) + TypeUtils::flattenConditionals($this->returnType), ); } diff --git a/src/Reflection/FunctionVariantWithPhpDocs.php b/src/Reflection/FunctionVariantWithPhpDocs.php index 1873f33c0c..2458f2699e 100644 --- a/src/Reflection/FunctionVariantWithPhpDocs.php +++ b/src/Reflection/FunctionVariantWithPhpDocs.php @@ -63,7 +63,7 @@ public function flattenConditionalsInReturnType(): static $this->isVariadic(), TypeUtils::flattenConditionals($this->getReturnType()), TypeUtils::flattenConditionals($this->phpDocReturnType), - $this->nativeReturnType + $this->nativeReturnType, ); } diff --git a/src/Reflection/ParametersAcceptorSelector.php b/src/Reflection/ParametersAcceptorSelector.php index ddb50abadf..cdfa607ec9 100644 --- a/src/Reflection/ParametersAcceptorSelector.php +++ b/src/Reflection/ParametersAcceptorSelector.php @@ -17,8 +17,6 @@ use PHPStan\Type\NullType; use PHPStan\Type\Type; use PHPStan\Type\TypeCombinator; -use PHPStan\Type\TypeTraverser; -use PHPStan\Type\TypeUtils; use PHPStan\Type\UnionType; use function array_key_last; use function array_slice; diff --git a/src/Reflection/ResolvedFunctionVariant.php b/src/Reflection/ResolvedFunctionVariant.php index 45bac6d783..a49a3408d8 100644 --- a/src/Reflection/ResolvedFunctionVariant.php +++ b/src/Reflection/ResolvedFunctionVariant.php @@ -96,7 +96,7 @@ public function flattenConditionalsInReturnType(): static $result = new self( $this->parametersAcceptor, $this->resolvedTemplateTypeMap, - $this->passedArgs + $this->passedArgs, ); $result->returnType = TypeUtils::flattenConditionals($returnType); From fe8cae84f0ac91037fa856109d360f5b774bacc2 Mon Sep 17 00:00:00 2001 From: Richard van Velzen Date: Sat, 2 Apr 2022 08:32:47 +0200 Subject: [PATCH 5/9] Ensure static return type --- src/Reflection/FunctionVariant.php | 11 ++++------- src/Reflection/FunctionVariantWithPhpDocs.php | 13 ++++--------- src/Reflection/ResolvedFunctionVariant.php | 7 +------ 3 files changed, 9 insertions(+), 22 deletions(-) diff --git a/src/Reflection/FunctionVariant.php b/src/Reflection/FunctionVariant.php index 0c0250e4f4..4aa15010fb 100644 --- a/src/Reflection/FunctionVariant.php +++ b/src/Reflection/FunctionVariant.php @@ -54,13 +54,10 @@ public function getReturnType(): Type public function flattenConditionalsInReturnType(): static { - return new self( - $this->templateTypeMap, - $this->resolvedTemplateTypeMap, - $this->parameters, - $this->isVariadic, - TypeUtils::flattenConditionals($this->returnType), - ); + $result = clone $this; + $result->returnType = TypeUtils::flattenConditionals($result->returnType); + + return $result; } } diff --git a/src/Reflection/FunctionVariantWithPhpDocs.php b/src/Reflection/FunctionVariantWithPhpDocs.php index 2458f2699e..8e858ba52f 100644 --- a/src/Reflection/FunctionVariantWithPhpDocs.php +++ b/src/Reflection/FunctionVariantWithPhpDocs.php @@ -56,15 +56,10 @@ public function getNativeReturnType(): Type public function flattenConditionalsInReturnType(): static { - return new self( - $this->getTemplateTypeMap(), - $this->getResolvedTemplateTypeMap(), - $this->getParameters(), - $this->isVariadic(), - TypeUtils::flattenConditionals($this->getReturnType()), - TypeUtils::flattenConditionals($this->phpDocReturnType), - $this->nativeReturnType, - ); + $result = parent::flattenConditionalsInReturnType(); + $result->phpDocReturnType = TypeUtils::flattenConditionals($result->phpDocReturnType); + + return $result; } } diff --git a/src/Reflection/ResolvedFunctionVariant.php b/src/Reflection/ResolvedFunctionVariant.php index a49a3408d8..726bbe74e5 100644 --- a/src/Reflection/ResolvedFunctionVariant.php +++ b/src/Reflection/ResolvedFunctionVariant.php @@ -93,12 +93,7 @@ public function flattenConditionalsInReturnType(): static { $returnType = $this->getReturnType(); - $result = new self( - $this->parametersAcceptor, - $this->resolvedTemplateTypeMap, - $this->passedArgs, - ); - + $result = clone $this; $result->returnType = TypeUtils::flattenConditionals($returnType); return $result; From 133743430741be4827027dc6963938db0e59f37f Mon Sep 17 00:00:00 2001 From: Richard van Velzen Date: Sat, 2 Apr 2022 08:42:02 +0200 Subject: [PATCH 6/9] Downgrade static type --- build/rector-downgrade.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/build/rector-downgrade.php b/build/rector-downgrade.php index 2e732a8dd9..bdbfbdfa16 100644 --- a/build/rector-downgrade.php +++ b/build/rector-downgrade.php @@ -9,6 +9,7 @@ use Rector\DowngradePhp74\Rector\Property\DowngradeTypedPropertyRector; use Rector\DowngradePhp80\Rector\Catch_\DowngradeNonCapturingCatchesRector; use Rector\DowngradePhp80\Rector\Class_\DowngradePropertyPromotionRector; +use Rector\DowngradePhp80\Rector\ClassMethod\DowngradeStaticTypeDeclarationRector; use Rector\DowngradePhp80\Rector\ClassMethod\DowngradeTrailingCommasInParamUseRector; use Rector\DowngradePhp80\Rector\FunctionLike\DowngradeUnionTypeDeclarationRector; use Rector\DowngradePhp80\Rector\Property\DowngradeUnionTypeTypedPropertyRector; @@ -39,6 +40,7 @@ $services->set(DowngradeUnionTypeTypedPropertyRector::class); $services->set(DowngradePropertyPromotionRector::class); $services->set(DowngradeUnionTypeDeclarationRector::class); + $services->set(DowngradeStaticTypeDeclarationRector::class); } if ($targetPhpVersionId < 70400) { From 0c7fd112b7172759b9aafa7bb27d340b23f64ea3 Mon Sep 17 00:00:00 2001 From: Richard van Velzen Date: Sat, 2 Apr 2022 08:52:06 +0200 Subject: [PATCH 7/9] Move static return type to phpdoc --- build/rector-downgrade.php | 2 -- src/Reflection/FunctionVariant.php | 5 ++++- src/Reflection/FunctionVariantWithPhpDocs.php | 5 ++++- src/Reflection/ResolvedFunctionVariant.php | 5 ++++- src/Reflection/SingleParametersAcceptor.php | 5 ++++- 5 files changed, 16 insertions(+), 6 deletions(-) diff --git a/build/rector-downgrade.php b/build/rector-downgrade.php index bdbfbdfa16..2e732a8dd9 100644 --- a/build/rector-downgrade.php +++ b/build/rector-downgrade.php @@ -9,7 +9,6 @@ use Rector\DowngradePhp74\Rector\Property\DowngradeTypedPropertyRector; use Rector\DowngradePhp80\Rector\Catch_\DowngradeNonCapturingCatchesRector; use Rector\DowngradePhp80\Rector\Class_\DowngradePropertyPromotionRector; -use Rector\DowngradePhp80\Rector\ClassMethod\DowngradeStaticTypeDeclarationRector; use Rector\DowngradePhp80\Rector\ClassMethod\DowngradeTrailingCommasInParamUseRector; use Rector\DowngradePhp80\Rector\FunctionLike\DowngradeUnionTypeDeclarationRector; use Rector\DowngradePhp80\Rector\Property\DowngradeUnionTypeTypedPropertyRector; @@ -40,7 +39,6 @@ $services->set(DowngradeUnionTypeTypedPropertyRector::class); $services->set(DowngradePropertyPromotionRector::class); $services->set(DowngradeUnionTypeDeclarationRector::class); - $services->set(DowngradeStaticTypeDeclarationRector::class); } if ($targetPhpVersionId < 70400) { diff --git a/src/Reflection/FunctionVariant.php b/src/Reflection/FunctionVariant.php index 4aa15010fb..2077930681 100644 --- a/src/Reflection/FunctionVariant.php +++ b/src/Reflection/FunctionVariant.php @@ -52,7 +52,10 @@ public function getReturnType(): Type return $this->returnType; } - public function flattenConditionalsInReturnType(): static + /** + * @return static + */ + public function flattenConditionalsInReturnType(): self { $result = clone $this; $result->returnType = TypeUtils::flattenConditionals($result->returnType); diff --git a/src/Reflection/FunctionVariantWithPhpDocs.php b/src/Reflection/FunctionVariantWithPhpDocs.php index 8e858ba52f..2e17f3ebdb 100644 --- a/src/Reflection/FunctionVariantWithPhpDocs.php +++ b/src/Reflection/FunctionVariantWithPhpDocs.php @@ -54,7 +54,10 @@ public function getNativeReturnType(): Type return $this->nativeReturnType; } - public function flattenConditionalsInReturnType(): static + /** + * @return static + */ + public function flattenConditionalsInReturnType(): self { $result = parent::flattenConditionalsInReturnType(); $result->phpDocReturnType = TypeUtils::flattenConditionals($result->phpDocReturnType); diff --git a/src/Reflection/ResolvedFunctionVariant.php b/src/Reflection/ResolvedFunctionVariant.php index 726bbe74e5..bf48999f9e 100644 --- a/src/Reflection/ResolvedFunctionVariant.php +++ b/src/Reflection/ResolvedFunctionVariant.php @@ -89,7 +89,10 @@ public function getReturnType(): Type return $type; } - public function flattenConditionalsInReturnType(): static + /** + * @return static + */ + public function flattenConditionalsInReturnType(): self { $returnType = $this->getReturnType(); diff --git a/src/Reflection/SingleParametersAcceptor.php b/src/Reflection/SingleParametersAcceptor.php index 57c77be557..ccc938b34b 100644 --- a/src/Reflection/SingleParametersAcceptor.php +++ b/src/Reflection/SingleParametersAcceptor.php @@ -5,6 +5,9 @@ interface SingleParametersAcceptor { - public function flattenConditionalsInReturnType(): static; + /** + * @return static + */ + public function flattenConditionalsInReturnType(): self; } From 5afa64de9c311f1d0a8be1fb81e8f23048bec35f Mon Sep 17 00:00:00 2001 From: Richard van Velzen Date: Sat, 2 Apr 2022 08:54:06 +0200 Subject: [PATCH 8/9] Fix for old php --- src/Reflection/FunctionVariant.php | 2 +- src/Reflection/FunctionVariantWithPhpDocs.php | 2 +- src/Reflection/ResolvedFunctionVariant.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Reflection/FunctionVariant.php b/src/Reflection/FunctionVariant.php index 2077930681..771f4ac7fe 100644 --- a/src/Reflection/FunctionVariant.php +++ b/src/Reflection/FunctionVariant.php @@ -55,7 +55,7 @@ public function getReturnType(): Type /** * @return static */ - public function flattenConditionalsInReturnType(): self + public function flattenConditionalsInReturnType(): SingleParametersAcceptor { $result = clone $this; $result->returnType = TypeUtils::flattenConditionals($result->returnType); diff --git a/src/Reflection/FunctionVariantWithPhpDocs.php b/src/Reflection/FunctionVariantWithPhpDocs.php index 2e17f3ebdb..51596d2b98 100644 --- a/src/Reflection/FunctionVariantWithPhpDocs.php +++ b/src/Reflection/FunctionVariantWithPhpDocs.php @@ -57,7 +57,7 @@ public function getNativeReturnType(): Type /** * @return static */ - public function flattenConditionalsInReturnType(): self + public function flattenConditionalsInReturnType(): SingleParametersAcceptor { $result = parent::flattenConditionalsInReturnType(); $result->phpDocReturnType = TypeUtils::flattenConditionals($result->phpDocReturnType); diff --git a/src/Reflection/ResolvedFunctionVariant.php b/src/Reflection/ResolvedFunctionVariant.php index bf48999f9e..b7a4e17017 100644 --- a/src/Reflection/ResolvedFunctionVariant.php +++ b/src/Reflection/ResolvedFunctionVariant.php @@ -92,7 +92,7 @@ public function getReturnType(): Type /** * @return static */ - public function flattenConditionalsInReturnType(): self + public function flattenConditionalsInReturnType(): SingleParametersAcceptor { $returnType = $this->getReturnType(); From 7204844864b4a33dbd7fe60f4ac298b9beab52b0 Mon Sep 17 00:00:00 2001 From: Richard van Velzen Date: Sat, 2 Apr 2022 10:56:11 +0200 Subject: [PATCH 9/9] Use new self() instead of clone --- src/Reflection/FunctionVariant.php | 10 ++++++++-- src/Reflection/FunctionVariantWithPhpDocs.php | 12 ++++++++++-- src/Reflection/ResolvedFunctionVariant.php | 11 +++++++---- 3 files changed, 25 insertions(+), 8 deletions(-) diff --git a/src/Reflection/FunctionVariant.php b/src/Reflection/FunctionVariant.php index 771f4ac7fe..4970bb6ce3 100644 --- a/src/Reflection/FunctionVariant.php +++ b/src/Reflection/FunctionVariant.php @@ -57,8 +57,14 @@ public function getReturnType(): Type */ public function flattenConditionalsInReturnType(): SingleParametersAcceptor { - $result = clone $this; - $result->returnType = TypeUtils::flattenConditionals($result->returnType); + /** @var static $result */ + $result = new self( + $this->templateTypeMap, + $this->resolvedTemplateTypeMap, + $this->parameters, + $this->isVariadic, + TypeUtils::flattenConditionals($this->returnType), + ); return $result; } diff --git a/src/Reflection/FunctionVariantWithPhpDocs.php b/src/Reflection/FunctionVariantWithPhpDocs.php index 51596d2b98..2de7029ade 100644 --- a/src/Reflection/FunctionVariantWithPhpDocs.php +++ b/src/Reflection/FunctionVariantWithPhpDocs.php @@ -59,8 +59,16 @@ public function getNativeReturnType(): Type */ public function flattenConditionalsInReturnType(): SingleParametersAcceptor { - $result = parent::flattenConditionalsInReturnType(); - $result->phpDocReturnType = TypeUtils::flattenConditionals($result->phpDocReturnType); + /** @var static $result */ + $result = new self( + $this->getTemplateTypeMap(), + $this->getResolvedTemplateTypeMap(), + $this->getParameters(), + $this->isVariadic(), + TypeUtils::flattenConditionals($this->getReturnType()), + TypeUtils::flattenConditionals($this->phpDocReturnType), + $this->nativeReturnType, + ); return $result; } diff --git a/src/Reflection/ResolvedFunctionVariant.php b/src/Reflection/ResolvedFunctionVariant.php index b7a4e17017..c15f218c6e 100644 --- a/src/Reflection/ResolvedFunctionVariant.php +++ b/src/Reflection/ResolvedFunctionVariant.php @@ -94,10 +94,13 @@ public function getReturnType(): Type */ public function flattenConditionalsInReturnType(): SingleParametersAcceptor { - $returnType = $this->getReturnType(); - - $result = clone $this; - $result->returnType = TypeUtils::flattenConditionals($returnType); + /** @var static $result */ + $result = new self( + $this->parametersAcceptor, + $this->resolvedTemplateTypeMap, + $this->passedArgs, + ); + $result->returnType = TypeUtils::flattenConditionals($this->getReturnType()); return $result; }