🌐 US-Proxy
class="logged-out env-production page-responsive" style="word-wrap: break-word;" >
Skip to content

Draft: Result cache drops trait errors (false negative) when the trait's file also contains a non-trait symbol #14883

Description

@kayw-geek

Bug report

With a warm result cache, errors inside a trait body can silently disappear — the same code reports them fine right after clear-result-cache. So a cached run and a clean run disagree on identical source.

In practice it shows up through baselines: the dropped errors stop matching their ignoreErrors entries, and with reportUnmatchedIgnoredErrors on (the default) they become non-ignorable ignore.unmatched errors. So CI goes red with a warm cache and green after clearing it.

I narrowed the trigger down to three things happening together:

  • a trait method body gains an error while its signature stays the same,
  • the trait's file also declares a non-trait symbol (a class/enum/etc. next to the trait),
  • the cache was warmed before the change and the classes that use the trait didn't change themselves.

A file containing only the trait does not trigger it.

It seems to come from the trait optimization in ResultCacheManager (the continue 2 around line 436 in 2.2.2): when the changed file contains any non-trait node, the classes that use the trait are never re-queued, so their trait errors are lost. And since ignoreErrors doesn't invalidate the cache, a stale cache from before a refactor keeps being reused.

Code snippet that reproduces the problem

It's a result-cache bug (it needs two runs sharing a cache), so the playground can't show it. Minimal reproduction:

phpstan/phpstan 2.2.2 (also reproduces on 2.1.17+ and current 2.2.x), PHP 8.5, level 9, result cache enabled.

Expected output

A warm cache should report the same errors as a clean run — the trait's property.nonObject errors show up, the baseline matches, and no ignore.unmatched errors appear.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions