Skip to content

Add regression test for invariant template type narrowed by control flow in a method getter#5922

Merged
staabm merged 1 commit into
phpstan:2.2.xfrom
phpstan-bot:create-pull-request/patch-4ocya65
Jun 23, 2026
Merged

Add regression test for invariant template type narrowed by control flow in a method getter#5922
staabm merged 1 commit into
phpstan:2.2.xfrom
phpstan-bot:create-pull-request/patch-4ocya65

Conversation

@phpstan-bot

Copy link
Copy Markdown
Collaborator

Summary

A getter returning a property typed with the same generic, control-flow-narrowed
template type as its own @return was incorrectly reported as a return type
mismatch (e.g. should return class-string<EnumAsFilterInterface<TOperation of int|string>> but returns class-string<EnumAsFilterInterface<TOperation of bool|float|int|string>>).

The underlying cause was fixed in TemplateTypeVariance: an invariant variance
check now returns Yes when both type arguments are the same template parameter
(same scope and name). This PR adds the missing regression test for the
method-getter manifestation of that bug.

Changes

  • Added tests/PHPStan/Rules/Methods/data/bug-11776.php — the verbatim
    reproducer from the issue's playground sample.
  • Registered testBug11776() in
    tests/PHPStan/Rules/Methods/ReturnTypeRuleTest.php, asserting no errors.

Root cause

TemplateTypeVariance::isValidVariance() compared the two template type
arguments via equals() in the invariant branch. When the same template
parameter was narrowed differently along control flow (e.g. the inferred
scalar bound vs. the (int|string)&TOperation intersection from the
constructor), the two TemplateType instances were not equals(), producing a
spurious mismatch. The fix short-circuits to Yes when both sides are the same
template parameter (matching scope and name). This central fix covers every
caller of the invariant variance check.

Test

  • bug-11776.php reproduces the reported method-getter case; it fails with the
    exact issue error when the TemplateTypeVariance fix is reverted and passes
    with it.
  • Probed analogous constructs — passing the property into a method parameter of
    the same narrowed template type, and assigning it to another property of the
    same type — neither reaches the invariant equality check, so they were never
    affected.
  • The function-return sibling of this bug is already covered by bug-13190.

Fixes phpstan/phpstan#11776

…low in a method getter

- Add tests/PHPStan/Rules/Methods/data/bug-11776.php reproducing the
  reported false positive where a getter returning a property typed with
  `class-string<EnumAsFilterInterface<(int|string)&TOperation>>` was
  reported as not matching its own `@return`.
- Register testBug11776() in ReturnTypeRuleTest covering the method-return
  path of the bug fixed in TemplateTypeVariance (invariant variance no
  longer mismatches when both arguments are the same template parameter
  narrowed by control flow).
- Probed analogous constructs (passing the property to a method parameter
  of the same narrowed template type, and assigning it to another property
  of the same type); neither triggers the invariant variance equality
  check, so they were never affected. The function-return sibling is
  already covered by bug-13190.

@staabm staabm left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

verified locally that this is fixed by #5921

@staabm staabm requested a review from VincentLanglet June 23, 2026 14:01
@staabm staabm merged commit ef28940 into phpstan:2.2.x Jun 23, 2026
391 checks passed
@staabm staabm deleted the create-pull-request/patch-4ocya65 branch June 23, 2026 14:04
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.

Union type of not detected in getter

3 participants