Skip to content

Prevent unnecessary work in IntersectionType#5054

Merged
staabm merged 4 commits intophpstan:2.1.xfrom
staabm:unne
Feb 28, 2026
Merged

Prevent unnecessary work in IntersectionType#5054
staabm merged 4 commits intophpstan:2.1.xfrom
staabm:unne

Conversation

@staabm
Copy link
Contributor

@staabm staabm commented Feb 27, 2026

return early when possible.

before this PR we built the whole result, merging part results and interpreting the combined overall result in the end.
we can save unnecessary work exiting early in case one of the part results are YES (similar how its done in TrinaryLogic::maxMin).


Wordpress repro

2.1.x

➜  wordpress-develop git:(trunk) hyperfine 'php ../../bin/phpstan analyse --debug src/wp-includes/html-api/class-wp-html-processor.php -v'
Benchmark 1: php ../../bin/phpstan analyse --debug src/wp-includes/html-api/class-wp-html-processor.php -v
  Time (mean ± σ):      8.962 s ±  0.061 s    [User: 8.224 s, System: 0.366 s]
  Range (min … max):    8.880 s …  9.060 s    10 runs

this PR

➜  wordpress-develop git:(trunk) hyperfine 'php ../../bin/phpstan analyse --debug src/wp-includes/html-api/class-wp-html-processor.php -v'
Benchmark 1: php ../../bin/phpstan analyse --debug src/wp-includes/html-api/class-wp-html-processor.php -v
  Time (mean ± σ):      8.647 s ±  0.112 s    [User: 7.864 s, System: 0.368 s]
  Range (min … max):    8.548 s …  8.932 s    10 runs

I think similar things can be done for union

@staabm staabm marked this pull request as ready for review February 27, 2026 08:44
@phpstan-bot
Copy link
Collaborator

This pull request has been marked as ready for review.

Copy link
Contributor

@VincentLanglet VincentLanglet left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TrinaryLogic has lazyMaxMin, isn't the right moment to introduce IsSuperTypeOfResult::lazy method ? (And maybe the same for AcceptsResult ?)

@staabm
Copy link
Contributor Author

staabm commented Feb 28, 2026

TrinaryLogic has lazyMaxMin, isn't the right moment to introduce IsSuperTypeOfResult::lazy method ? (And maybe the same for AcceptsResult ?)

good idea, adjusted accordingly.
(I did not do it in the first place, because there is only a single use-case for maxMin() and this one is now the only use case for lazyMaxMin)

Comment on lines +165 to +173
$results = [];
foreach ($objects as $object) {
$isAcceptedBy = $callback($object);
if ($isAcceptedBy->result->yes()) {
return $isAcceptedBy;
}
$results[] = $isAcceptedBy;
}
return self::maxMin(...$results);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This add another foreach.
Looking at TrinaryLogic::lazyMaxMin it does not call self::maxMin.

Should we implement it this way

public static function lazyMaxMin(
    array $objects,
    callable $callback,
): self
{
    if ($objects === []) {
        throw new ShouldNotHappenException();
    }

    $results = [];
    $reasons = [];
    foreach ($objects as $object) {
        $isAcceptedBy = $callback($object);
        if ($isAcceptedBy->result->yes()) {
            return $isAcceptedBy;
        }
        $results[] = $isAcceptedBy->result;
        foreach ($isAcceptedBy->reasons as $reason) {
            $reasons[] = $reason;
        }
    }

    return new self(TrinaryLogic::maxMin(...$results), array_values(array_unique($reasons)));
}

instead ?

(I also wonder if we should -- now or later -- avoid calling TrinaryLogic::maxMin to remove an extra foreach and doing it in the existing one)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok - unrolled all nested loops now

@staabm staabm merged commit 1bbe9dc into phpstan:2.1.x Feb 28, 2026
635 of 647 checks passed
@staabm staabm deleted the unne branch February 28, 2026 10:55
@staabm
Copy link
Contributor Author

staabm commented Feb 28, 2026

Thank you!

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