Skip to content

fix(php): index trait methods by receiver while flattening (#1265) - #2706

Open
DeusData wants to merge 3 commits into
mainfrom
fix/php-trait-flatten-index
Open

DeusData wants to merge 3 commits into
mainfrom
fix/php-trait-flatten-index

Conversation

@DeusData

Copy link
Copy Markdown
Owner

What

flatten_trait_into_class (PHP LSP) found each trait's methods by scanning every function in the registry. Every flattened method adds more functions, so the scan grows with its own output. A file with many trait-using classes paid O(classes × functions) (#1265).

The class-field pass now keeps a receiver -> function-id index, updated incrementally as functions are registered. Flattening reads only the trait's own entries that were registered before the current class:

  • Same output: it visits only entries registered before flattening started, the ones the old scan accepted, so the result is identical.
  • Fallback: if the index cannot be built, the previous full scan runs unchanged.
  • Memory: the index and its per-receiver lists live in the LSP call's arena.

Evidence

Suites on 7dc07d9 (ASan test-runner): php_lsp, parallel, pipeline, complexity and incremental, 941 passed.

Lint: internal/cbm/lsp/ is outside CI's LINT_SRCS / LINT_HDRS, so I ran the gates directly on the changed files.

  • clang-format is clean on the lines this PR adds. php_lsp.h already differs from clang-format on main, outside this diff.
  • cppcheck 2.20 first flagged autoVariables: the pass stored the address of a stack-local index in the context. The pointer was restored before return, but the second commit moves the index into the arena, and the warning is gone. One existing style note remains (redundantInitialization of qualified in php_lsp.c), outside this diff.
  • lint-memory-core and the NOLINT check are clean.

Head e9b334e merges main 27c3303. Main has not touched php_lsp.c, php_lsp.h or tests/test_php_lsp.c since 4527fc7, and merge-tree is clean.

Fixes #1265. Refs #765.

flatten_trait_into_class looked up each trait's methods by scanning every
function of the registry, and every flattened method appends more of them.
A file with many trait-using classes paid O(classes x functions), and the
scan grew with its own output.

The class-field pass now keeps a receiver -> function-id index, synced
incrementally as functions are registered, and flattening reads only the
trait's own entries registered before the current class. If the index
cannot be built, the previous full scan runs unchanged. Only entries
registered before flattening started are visited, so the output is
identical.

Tests: the work-counter tests for #1265 (100 -> 200 trait-using classes,
ratio gate 2.5) and #765 (trait collision shapes stay bounded) use the
existing test-only work ceiling.

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
The class-field pass stored the address of a stack-local index in ctx for
the duration of the pass. It was restored before returning, but the
pattern is what cppcheck's autoVariables check rejects. The index now
lives in the call's arena; on an allocation failure it stays NULL and
flattening runs the full scan, as before.

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
…-index

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>

This branch has not been deployed

No deployments
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.

PHP trait extraction consumes 64 GB memory and continues after MCP request timeout

1 participant