Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conditional argument type not properly narrowing type (for constant string unions?) #10055

@RobertMe

Description

@RobertMe

Bug report

When having a function with a union of (constant) strings as argument and a second parameter for which the type depends on the other argument one could use a conditional parameter type (@param ($param1 is 'foo' ? int : bool) $param2). This only seems to happen when the union type consists of more than 2 types. This as, as far as I tried to debug it and understood the code, the conditional parameter type is split in two ConditionalExpressionHolders, one for the true condition and one for the false condition. These conditions are based on TypeCombinator::intersect and TypeCombinator::remove where supplied arguments are the type of the argument the condition is compared too and the supplied condition type. For the supplied example this thus leads to two ConditionalExpressionHolders, one of ConstantStringType('value3') which results in a boolean and one of UnionType([ConstantStringType('value1'), ConstantStringType('value2')]) which results in a integer.
Later on when the these conditional expressions are tested. But in this case for the match arms / conditions on 'value1' and 'value2' these comparisons fail. This as the ConstantStringType (containing the value1 / value2 as value) are tested for equality against the UnionType which fails.

There are also scenario's which result in other (un)expected results. In case where $param1 consists only of 2 types ('value1'|'value2', without |'value3') it always seems to work fine for example, as in that case the TypeCombinator::intersect and TypeCombinator::remove calls both result in a ConstantStringType which will obviously be fine for the comparison. But when changing the order of the match arms, so 'value3' is the first condition it also works fine.

Code snippet that reproduces the problem

https://phpstan.org/r/5b254792-1ecd-49ed-a140-930184c7a820

Expected output

No errors.

And applying \PHPStan\dumpType($param2) in the match arms should thus result in: value1 => int, value2 => int, value3 => bool.

Did PHPStan help you today? Did it make you happy in any way?

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions