You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
if.alwaysTrue when found in traits isn't reported correctly through context of a user class #14932
As seen in the example, deadCode.unreachable is found twice, in the context of the using classes.
But if.alwaysTrue is only found in the trait itself.
When generating a baseline, it seems to just "randomly" pick a class to write the ignored error for, leading to inconsistent results in our development vs CI pipeline.
Analysis result:
3/3 [▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓] 100% < 1 sec
------ ------------------------------
Line FooTrait.php
------ ------------------------------
15 If condition is always true.
🪪 if.alwaysTrue
------ ------------------------------
------ -------------------------------------------------------
Line FooTrait.php (in context of class Bar)
------ -------------------------------------------------------
19 Unreachable statement - code above always terminates.
🪪 deadCode.unreachable
------ -------------------------------------------------------
------ -------------------------------------------------------
Line FooTrait.php (in context of class Foo)
------ -------------------------------------------------------
19 Unreachable statement - code above always terminates.
🪪 deadCode.unreachable
------ -------------------------------------------------------
I was able to reliably replicate it by running phpstan on a single core, with a single class that uses a trait and reports an error. Error is baselined. Then there is a simple repeatable loop:
run phpstan -> no errors
add second class that uses the trait and run phpstan -> error
run phpstan 1 to N times (without any changes) -> no error
Removing the second class and running the same loop replicates the behavior.
phpstan-trait-flicker.zip
This is a minimal reproduction. Just extract the archive, cd to directory and run ./replicate.sh
Likely root cause - the winner therefore depends on the iteration order of collected data, and that order is unstable:
Cold run: ParallelAnalyser appends $collectedData[$file] in worker-message arrival order — a race between worker processes.
Warm run: collected data is replayed from the result cache, which ResultCacheManager::save()ksorts — deterministic alphabetical order, different from the arrival order of the run that populated it.
Partial run with a new file: mergeCollectedData() preserves key positions for existing files and appends new files at the end — so a newly added using class wins exactly once, until the next run replays the ksorted save.
Because CollectedDataNode rules run in AnalyserResultFinalizerafter the result cache is saved (AnalyseApplication), these errors are never stored in the cache's error map and are re-derived — with a potentially different winner — on every run.
I believe I ran into the same problem after updating from 2.2.1 to 2.2.8. I got errors that alwaysTrue or alwaysFalse was not matched, regenerated the baseline and then in my pipeline I got this:
Line app/Models/Db/Training.php
------ ----------------------------------------------------------------------
Ignored error pattern #^Negated boolean expression is always
false\.$# (booleanNot.alwaysFalse) in path
/builds/hexfit/hexfit/api/backend-laravel/app/Models/Db/Training.php
was not matched in reported errors.
🪪 ignore.unmatched (non-ignorable)
----- -----------------------------------------------------------------------
Line app/Models/Traits/SharingObject.php
------ -----------------------------------------------------------------------
37 Negated boolean expression is always false.
🪪 booleanNot.alwaysFalse
The Training class uses the Trait HexfitModel. My AI just patched the baseline file to fix my pipeline:
Activity
mabar commentedon Jul 21, 2026
This error occurs since phpstan/phpstan-src#5309 - reproducible from
2.2.0up to latest2.2.x-dev@ce1a7f1(upcoming 2.2.6, post related fix phpstan/phpstan-src#6033)I was able to reliably replicate it by running phpstan on a single core, with a single class that uses a trait and reports an error. Error is baselined. Then there is a simple repeatable loop:
Removing the second class and running the same loop replicates the behavior.
phpstan-trait-flicker.zip
This is a minimal reproduction. Just extract the archive,
cdto directory and run./replicate.shLikely root cause - the winner therefore depends on the iteration order of collected data, and that order is unstable:
ParallelAnalyserappends$collectedData[$file]in worker-message arrival order — a race between worker processes.ResultCacheManager::save()ksorts — deterministic alphabetical order, different from the arrival order of the run that populated it.mergeCollectedData()preserves key positions for existing files and appends new files at the end — so a newly added using class wins exactly once, until the next run replays the ksorted save.Because
CollectedDataNoderules run inAnalyserResultFinalizerafter the result cache is saved (AnalyseApplication), these errors are never stored in the cache's error map and are re-derived — with a potentially different winner — on every run.pelletiermaxime commentedon Aug 12, 2026
I believe I ran into the same problem after updating from 2.2.1 to 2.2.8. I got errors that alwaysTrue or alwaysFalse was not matched, regenerated the baseline and then in my pipeline I got this:
The Training class uses the Trait HexfitModel. My AI just patched the baseline file to fix my pipeline:
github-actions commentedon Sep 27, 2026
This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.