Skip to content

Regression for arrayFilter.strict #283

Description

@stefanfisk

There's been a recent regression for arrayFilter.strict where certain array types cause the error to longer be generated. Here's is a playground link which shows a mix of working and broken types https://phpstan.org/r/fbf8aca7-4b24-4591-b982-662087459dcb.

I'm afraid that I don't have time right now to investigate which exact version introduced this issue. But I noticed it after upgrading phpstan/phpstan from 2.1.22 to 2.1.25.

Activity

  1. ondrejmirtes commented on Sep 16, 2025

    @ondrejmirtes
    Member

    Which line is wrong?

  2. stefanfisk commented on Sep 16, 2025

    @stefanfisk
    Author

    Unless I am mistaken all of the calls to array_filter() should have arrayFilter.strict since the parameter is never passed.

  3. VincentLanglet commented on Oct 5, 2025

    @VincentLanglet
    Contributor

    I don't fully understand the purpose of the condition in case of an UnionType

    if ($itemType instanceof UnionType) {
    $hasTruthy = false;
    $hasFalsey = false;
    foreach ($itemType->getTypes() as $innerType) {
    $booleanType = $innerType->toBoolean();
    if ($booleanType->isTrue()->yes()) {
    $hasTruthy = true;
    continue;
    }
    if ($booleanType->isFalse()->yes()) {
    $hasFalsey = true;
    continue;
    }
    $hasTruthy = false;
    $hasFalsey = false;
    break;
    }
    if ($hasTruthy && $hasFalsey) {
    return [];
    }

    When there is both sure truthy types and sure falsey types in the Union, the error is not reported.

    This was added in 8afd4af

    So this seems to be a wanted behavior...

  4. stefanfisk commented on Oct 6, 2025

    @stefanfisk
    Author

    I can see the utility in only reporting the error when the type has ambiguous truthiness.

    But does it make sense that array_filter([1, 2, '0', new \stdClass()]) doesn't result in an error? '0' will be cast to false and then removed which AFAIU is exactly the sort of case that the rule targets.

  5. ondrejmirtes commented on Oct 6, 2025

    @ondrejmirtes
    Member

    I guess the code with UnionType could be replaced with Type::getFiniteTypes() call.

  6. VincentLanglet commented on Oct 7, 2025

    @VincentLanglet
    Contributor

    I guess the code with UnionType could be replaced with Type::getFiniteTypes() call.

    What would be the idea ?
    [1, 2, '0'] will still be ignored if using getFiniteTypes (since 1 is truthy and '0' is falsy) ;
    but maybe it's a wanted behavior and this issue should be closed

    What is unclear to me at first are the case where you want to ignore the array_filter rules ondrej

    • If it's only boolean, it's clear it will keeps true and remove false
    • If it's only array, it's clear it will keeps non empty array
    • If it's only int, you report an error when it could be considered clear that it will keeps non 0 value
    • If it's only string, it make sens to report error because it's unclear if we're removing '' and/or '0'
    • If it's null|object, you seems to not want to report an error

    Maybe the rule should be ignored if

    count(TypeCombinator::intersect($type, $falseyType)->getFiniteTypes()) <= 1
    
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions