Skip to content

Fix #9634: Cannot use "T is never" in conditional return#5082

Open
phpstan-bot wants to merge 1 commit intophpstan:2.1.xfrom
phpstan-bot:create-pull-request/patch-to7kx0v
Open

Fix #9634: Cannot use "T is never" in conditional return#5082
phpstan-bot wants to merge 1 commit intophpstan:2.1.xfrom
phpstan-bot:create-pull-request/patch-to7kx0v

Conversation

@phpstan-bot
Copy link
Collaborator

Summary

When using (T is never ? false : bool) as a conditional return type on a generic interface method, PHPStan incorrectly reported "Condition 'T is never' in conditional return type is always false." The fix allows never to correctly recognize that a template type T might be instantiated to never.

Changes

  • Added TemplateType handling in src/Type/NonAcceptingNeverType.phpisSuperTypeOf() now returns Maybe for template types instead of No
  • Added the same TemplateType handling in src/Type/NeverType.php for consistency
  • New rule test in tests/PHPStan/Rules/PhpDoc/data/bug-9634.php and test method in tests/PHPStan/Rules/PhpDoc/MethodConditionalReturnTypeRuleTest.php
  • New type inference test in tests/PHPStan/Analyser/nsrt/bug-9634.php verifying that Option<never>::isSome() resolves to false and Option<int>::isSome() resolves to bool

Root cause

NonAcceptingNeverType::isSuperTypeOf() (the type used for explicitly written never in PHPDoc) returned No for all types except NeverType and NonAcceptingNeverType. When ConditionalReturnTypeRuleHelper checked whether the condition T is never could ever be true by calling $targetType->isSuperTypeOf($subjectType), the never target returned No for the template type T, causing the rule to report the condition as "always false". However, a template type T can be instantiated to never (since never is a subtype of any bound), so the correct answer is Maybe.

Test

  • Rule test verifies that (T is never ? false : bool) no longer produces a false positive error
  • NSRT test verifies that when T is bound to never, the conditional resolves to false, and when T is bound to int, it resolves to bool

Fixes phpstan/phpstan#9634

- Added TemplateType handling in NonAcceptingNeverType::isSuperTypeOf()
  and NeverType::isSuperTypeOf() to return Maybe instead of No, since a
  template type can be instantiated to never
- New regression tests in tests/PHPStan/Rules/PhpDoc/data/bug-9634.php
  and tests/PHPStan/Analyser/nsrt/bug-9634.php

Closes phpstan/phpstan#9634
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant