Repository navigation
Report inheritance cycles with a rule instead of a reflection error - #6712
Open
SanderMuller wants to merge 2 commits into
Open
SanderMuller wants to merge 2 commits into
SanderMuller wants to merge 2 commits into
Conversation
A class that extends itself, interfaces that extend each other and traits that use each other cannot be declared in PHP. A class on a parent class cycle now has no parent instead of throwing CircularReference, and a trait inside a trait on a cycle processes only the traits reflection says it uses. CircularInheritanceRule reports the cycle on each of its members, at level 0. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
BetterReflection 6.73.0.6 (ondrejmirtes/BetterReflection#47) no longer throws
CircularReferencefor an inheritance cycle. A class-like on a cycle has no supertypes of its kind instead. Since 613b1b1, 2.3.x therefore reports nothing for such a cycle. This is the phpstan-src part of the change, with a rule that reports the cycle.The changes:
CircularInheritanceRule, at level 0, reports the cycle on each of its members. The identifiers areclass.circularExtends,interface.circularExtendsandtraitUse.circular, and the error cannot be ignored. Examples:Class Foo extends itself.andClass Foo extends Bar, which extends Foo.ClassReflection::getParentClass()returnsnullfor a class that extends itself, instead of throwingCircularReference. A class that extends a class on a cycle keeps that parent.TraitUseHandlerprocesses only the traits that reflection says the trait uses. A trait on a trait cycle uses none.ClassReflection.cppandTraitUseHandler.cppget the same changes.The
TraitUseHandlerchange also fixes a crash on 2.3.x. Take a class that uses a trait on a cycle, where the members of one trait use the members of the other one. Analysing it stops with an internal error,MissingPropertyFromReflectionException. The newAnalyserIntegrationTest::testTraitCycleMembers()covers this case. A trait on a cycle uses no traits, so the class gets the members of the first trait only. The test therefore also expectsAccess to an undefined property.The last part of the
result-cache-parse-errore2e step fails on 2.3.x since 613b1b1. It expected a reflection error for a class that extends itself, and that error is gone. The step now checks that the rule reports the class, and that the result cache is saved.Verification:
CircularInheritanceRuleTestcovers:testTraitCycleMembers()fails on 2.3.x with the internal error.result-cache-circular-inheritancebreaks a class cycle and closes a trait cycle between two runs, and checks that the cached errors follow.make testspasses with and without the Turbo extension (22,512 tests, 74 skipped).make phpstan, phpcs andmake lintreport no errors.smoke.phpreports ALL OK, andside-by-side.php,signature-parity.phpandwalk-trace.phppass. On the rule's fixtures and the cycle fixtures ofAnalyserIntegrationTest, the raw output is identical with the extension loaded and not loaded.Performance on wordpress-develop at level 9, cold runs from source without Turbo, on an M4 Pro. Base is
cb3b7e994. Each value is the median of 3 alternating rounds, with the range in brackets. The output is identical, because wordpress-develop has no inheritance cycles.🤖 Generated with Claude Code