Skip to content

Keep a union benevolent when its members absorbed benevolent members - #6960

Merged
ondrejmirtes merged 1 commit into
2.3.xfrom
keep-benevolent-union-when-member-absorbed
Nov 5, 2026
Merged

ondrejmirtes merged 1 commit into
2.3.xfrom
keep-benevolent-union-when-member-absorbed

Conversation

@ondrejmirtes

Copy link
Copy Markdown
Member

TypeCombinator::union() kept the result benevolent only when every result member described exactly like a benevolent input member. Merging (int<min, -1>|int<1, max>|string) with 0 produces int, which matches none of them, so the union became a plain int|string.

Since the loose-comparison narrowing (9d55d96), the PHP 7 false branch of $key == 'shipping' removes 0 from an array key, and merging the switch branches back hit this. The same happened on any PHP version after e.g. if ($key !== 0) {}.

A result member that is a supertype of a benevolent member now keeps the union benevolent; a member that absorbed nothing benevolent (e.g. float) still makes it plain. The native TypeCombinator mirror in turbo-ext gets the same change.

array_rand() on an array with explicit int keys and a $mixed key now returns (int|string) as well, for the same reason.

Closes phpstan/phpstan#15667

TypeCombinator::union() kept the result benevolent only when every member
described exactly like a benevolent input member. Merging
(int<min, -1>|int<1, max>|string) with 0 produces int, which matches none
of them, so the union lost its benevolence - e.g. an array key after a
switch narrowed it with loose comparisons on PHP 7.

Amp-Thread-ID: https://ampcode.com/threads/T-01a1ad8d-7160-7699-b079-02097b61a80b
@ondrejmirtes
ondrejmirtes merged commit 70bd516 into 2.3.x Nov 5, 2026
568 of 569 checks passed
@ondrejmirtes
ondrejmirtes deleted the keep-benevolent-union-when-member-absorbed branch November 5, 2026 21:30
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.

switch on an array key loses the benevolent (int|string) when analysing for PHP < 8.0

1 participant