Skip to content

Bug: Result of ||/&& is always true/false incorrectly triggered based on docblocks #1254

@rbairwell

Description

@rbairwell

Summary of a problem or a feature request

If you have a docblock providing details of what a method/function is expecting (instead of just 'mixed') but then try and confirm that the method/function was passed the correct types, then PHPStan reports Result of && is always false.

Code snippet that reproduces the problem

<?php declare(strict_types=1);

// passes
foreach ([123, 'tester', new \DateTimeImmutable(), new stdClass()] as $index => $test) {
    print 'Results from index ' . $index . ' = 1: ' . test1($test) . ' 2: '.test2($test).PHP_EOL;
}

/**
 * No type hints for programmers, but validation still in place.
 * @param mixed $time
 * @return string
 */
function test1($time)
{
    if (!\is_string($time) && (!$time instanceof \DateTimeInterface)) {
        return '[invalid argument]';
    }
    return 'Matched';
}

/**
 * No type hints for programmers, but validation still in place.
 * @param mixed $time
 * @return string
 */
function test2($time)
{

    if (!(\is_string($time) || ($time instanceof \DateTimeInterface))) {
        return '[invalid argument]';
    }

    return 'Matched';
}

/**
 * Type hints for programmers, but we still validate just in case.
 * @param string|\DateTimeInterface $time
 * @return string
 */
function test3($time)
{
    if (!\is_string($time) && (!$time instanceof \DateTimeInterface)) {
        return '[invalid argument]';
    }
    return 'Matched';
}
/**
 * Type hints for programmers, but we still validate just in case.
 * @param string|\DateTimeInterface $time
 * @return string
 */
function test4($time)
{

    if (!(\is_string($time) || ($time instanceof \DateTimeInterface))) {
        return '[invalid argument]';
    }

    return 'Matched';
}

Code output:

Results from index 0 = 1: [invalid argument] 2: [invalid argument]
Results from index 1 = 1: Matched 2: Matched
Results from index 2 = 1: Matched 2: Matched
Results from index 3 = 1: [invalid argument] 2: [invalid argument

PHPStan results:

 ------ ------------------------------- 
  Line   analyzed.php                   
 ------ ------------------------------- 
  43     Result of && is always false.  
  56     Result of || is always true.   
 ------ ------------------------------- 

(note - apart from the ignorable/strippable docblocks, the functions test1 & test3 and test2 & test4 are identical)

https://phpstan.org/r/f485b932953a743c8737824d902e8252

Expected output

No errors should be reported - PHPStan should not treat the docblock params as set-in-stone (just as 'human suggestions' as humans can make mistakes) and not report this sort of validation as mistakes.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions