Skip to content

Fix @phpstan-assert not working correctly with union types#4920

Merged
staabm merged 8 commits intophpstan:2.1.xfrom
staabm:fix-union
Feb 15, 2026
Merged

Fix @phpstan-assert not working correctly with union types#4920
staabm merged 8 commits intophpstan:2.1.xfrom
staabm:fix-union

Conversation

@staabm
Copy link
Contributor

@staabm staabm commented Feb 13, 2026

@staabm staabm marked this pull request as ready for review February 13, 2026 10:59
@staabm staabm requested a review from ondrejmirtes February 13, 2026 10:59
@phpstan-bot
Copy link
Collaborator

This pull request has been marked as ready for review.

@staabm staabm changed the title Fix @phpstan-assert not working correctly with union types Fix @phpstan-assert not working correctly with union types Feb 13, 2026
staabm and others added 8 commits February 13, 2026 16:56
- UnionTypeMethodReflection::getAsserts() was using intersectWith() which
  concatenates assert tags, causing specifyTypesFromAsserts to intersect
  the asserted types (string & int = never) instead of unioning them
- Added Assertions::unionWith() that groups assertions by parameter identity
  and unions their types via TypeCombinator::union()
- Changed UnionTypeMethodReflection to use unionWith() instead of intersectWith()
- Assertions without a matching counterpart in the other union member are dropped
- New regression test in tests/PHPStan/Analyser/nsrt/bug-14108.php
@staabm staabm merged commit 0b4157d into phpstan:2.1.x Feb 15, 2026
638 of 643 checks passed
@staabm staabm deleted the fix-union branch February 15, 2026 06:42
ondrejmirtes pushed a commit that referenced this pull request Feb 15, 2026
Previously, getSelfOutType(), getAttributes(), and getResolvedPhpDoc()
on Union/IntersectionType{Method,Property}Reflection only used the first
member ($this->methods[0] / $this->properties[0]), losing information
from other members. This applies the same merging pattern from PR #4920
(which fixed assertion merging) to these other metadata methods:

- getSelfOutType(): Union self-out types for union types, intersect for
  intersection types. Returns null if any member lacks a self-out type.
- getAttributes(): For union types, only keep attributes present in ALL
  members (intersection semantics). For intersection types, collect
  attributes from ANY member (union semantics), deduplicating by name.
- getResolvedPhpDoc(): Return null instead of arbitrarily returning the
  first member's PHPDoc block, which could be misleading.

https://claude.ai/code/session_01KdvoAVF2YDBnuJ3gmgU9hQ
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.

3 participants