Skip to content

[perf] Check return literals before override guard in two return-type rules - #8710

Merged
TomasVotruba merged 1 commit into
mainfrom
hoist-literal-filter-return-type
Oct 19, 2026
Merged

TomasVotruba merged 1 commit into
mainfrom
hoist-literal-filter-return-type

Conversation

@TomasVotruba

Copy link
Copy Markdown
Member

NumericReturnTypeFromStrictScalarReturnsRector and BoolReturnTypeFromBooleanConstReturnsRector subscribe to ClassMethod. Both ran ClassMethodReturnTypeOverrideGuard::shouldSkipClassMethod() - parent/override reflection - before checking whether the returns are actually int/float (or true/false) literals. A method whose single return is not such a literal (the common case) paid for the override lookup only to then fail the literal check and return null.

The node-only literal check now runs first, so a method returning a non-literal expression bails before the reflection. The check reads only AST (Int_/Float_/UnaryMinus, ConstFetch + true/false), so the outcome is unchanged - the fail path returned null either way.

Behavior unchanged - all 8 fixtures across both rules pass.

Bench included (bench/return_type_literal_filter_bench.php), driving refactor() over 151 methods that return a non-literal expression. CPU per call, two runs each:

rule before us/call after us/call
NumericReturnTypeFromStrictScalarReturns ~31 ~12.6
BoolReturnTypeFromBooleanConstReturns ~28 ~11.7

~2.5x faster on that hot path. The remaining cost is findReturnsScoped(), which runs regardless. Run php bench/return_type_literal_filter_bench.php on each branch to reproduce.

Siblings checked and left as-is: StringReturnTypeFromStrictScalarReturnsRector already runs its literal check before the guard; NumericReturnTypeFromStrictReturnsRector has no node-only filter for the common case (its work is type inference).

@TomasVotruba
TomasVotruba merged commit 160f4b1 into main Oct 19, 2026
48 of 49 checks passed
@TomasVotruba
TomasVotruba deleted the hoist-literal-filter-return-type branch October 19, 2026 09:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant