Skip to content

fix(parallel): drop the deprecated SplObjectStorage::contains(), then stop suppressing deprecations in the suite - #40

Merged
lisachenko merged 2 commits into
mainfrom
claude/z-engine-stable-updates-00g5v4
Aug 19, 2026
Merged

fix(parallel): drop the deprecated SplObjectStorage::contains(), then stop suppressing deprecations in the suite#40
lisachenko merged 2 commits into
mainfrom
claude/z-engine-stable-updates-00g5v4

Conversation

@lisachenko

Copy link
Copy Markdown
Owner

Two linked issues, in the order that makes the second one safe.

Closes #39
Closes #38

Why the order matters

Every .phpt in the suite carried error_reporting=E_ALL & ~E_DEPRECATED. That line was added for a dependency: PHPUnit's .phpt runner forces display_errors=1, so a deprecation raised by z-engine — back when it was consumed from a development branch — was prepended to the captured output of every test and failed --EXPECT-- blocks over noise that had nothing to do with this library.

But it filtered this package's own deprecations just as effectively. That is exactly how #39 stayed green: PHP 8.5 deprecated SplObjectStorage::contains(), PreforkTaskDirectory calls it on every task registration and lookup, and 12 tests exercised it in silence.

So removing the suppression first would have turned #38 into a 12-test regression. Fix the deprecation, then take the blindfold off.

Part 1 — fix(parallel): offsetExists() instead of contains()

src/Parallel/PreforkTaskDirectory.php keys its task-to-address map by an \SplObjectStorage and probed it with contains() in both register() and addressOf(). offsetExists() has identical semantics and has existed since PHP 5.3, so there is no floor change and nothing else moves.

I swept the rest of the tree rather than assuming this was the only one:

  • ->contains( in src/ — only these two call sites, both fixed. The one remaining hit anywhere is tests/Support/shared.php, which is $arena->arena()->contains($address, 8) on a shared-data extension object, not SPL.
  • ->attach( / ->detach( — all this package's own methods (SharedArena::attach(), Context::detach()), never the SplObjectStorage ones.
  • Everything else that touches the storage uses array access ($this->addresses[$task]), which is not deprecated.

The strongest check is empirical, and it is in the numbers below: with the fix in place a forced-E_ALL run of the whole suite emits zero diagnostics of any kind on both minors, so there is no second deprecation hiding behind the first.

Part 2 — test(tests): drop the suppression

  • The error_reporting line is gone from all 121 tests/Functional/*.phpt. ffi.enable=1 and opcache.jit=off stay — FFI cannot be enabled at runtime, and the JIT rewrites the executor internals the engine hooks depend on.
  • The guard test is renamed testEveryTestDeclaresTheThreeRequiredIniLines.phpttestEveryTestDeclaresTheTwoRequiredIniLines.phpt and now checks both halves: that each file declares both required lines, and that no file sets error_reporting at all. A filter cannot be quietly reintroduced to silence the next deprecation instead of fixing it.
  • tests/Support/childProcess.php spawned its children with the same three settings and explicitly described itself as mirroring the .phpt files; it drops the line for the same reason.
  • AGENTS.md documented three mandatory lines in two places (the INI-settings section and the test-writing rules). Both now describe two, and the historical note explains what the third was for and why it no longer applies, rather than leaving a dangling reference to a deprecation that no longer occurs.
  • README.md and .github/workflows/ci.yml never named the setting — the CI ini-values are ffi.enable=1, zend.assertions=1, opcache.jit=off — so neither needed a change. Grepping E_DEPRECATED across the tree now returns only the two deliberate historical mentions in AGENTS.md and the guard test's comment.

Measured results

PHPUnit and PHPStan could not be installed in this environment — network egress reaches only lisachenko/* repos, so composer install without --no-dev fails. The suite was run instead with a small runner that reproduces what PHPUnit's PhptTestCase does: it writes the --FILE-- body next to the .phpt so relative includes resolve, applies the file's own --INI-- plus display_errors=1, compares --EXPECT-- exactly and matches --EXPECTREGEX-- unanchored. CI runs the real composer test on both minors.

Dependencies were resolved per minor (rm -rf vendor composer.lock between runs): PHP 8.4.19 → z-engine 8.4.2, PHP 8.5.9 → z-engine 8.5.0.

Step 1 — before any change, forcing error_reporting=E_ALL over each file's own --INI-- block:

PHP z-engine Result
8.5.9 8.5.0 109/121 pass, 12 fail — every failure the SplObjectStorage::contains() deprecation prepended to otherwise-correct output

Step 2 — after Part 1, same forced-E_ALL run:

PHP z-engine Result
8.4.19 8.4.2 121/121 pass, 0 diagnostics
8.5.9 8.5.0 121/121 pass, 0 diagnostics

Step 3 — after Part 2, the ordinary run (each file's own --INI--, no forcing):

PHP z-engine Result
8.4.19 8.4.2 121/121 pass
8.5.9 8.5.0 121/121 pass

No segfault, bus error or hung child in any run. The known flake from #33 (testAnAlreadyCompleteSlotIsAwaitedWithoutParking, ~1 in 4 full-suite runs) did not appear in any of the four full-suite runs, so nothing was retried or re-run.

Files changed

  • src/Parallel/PreforkTaskDirectory.php — two call sites
  • tests/Functional/*.phpt — 121 files, one line removed each; the guard test renamed and rewritten
  • tests/Support/childProcess.php — the mirrored -d flag and its docblock
  • AGENTS.md — two sections

Generated by Claude Code

lisachenko and others added 2 commits August 19, 2026 05:36
PHP 8.5 deprecates SplObjectStorage::contains() in favour of
offsetExists(). PreforkTaskDirectory keyed its task-to-address map by an
SplObjectStorage and probed it with contains() in both register() and
addressOf(), so every prefork test raised the deprecation on 8.5.

offsetExists() has the same semantics and has existed since PHP 5.3, so
this needs no floor change.

The suite never showed it: every .phpt suppresses E_DEPRECATED. Forcing
error_reporting=E_ALL over each file's own --INI-- block on PHP 8.5.9
with z-engine 8.5.0 turned 12 of the 121 tests red, every one of them on
this deprecation; with the call replaced the same forced-E_ALL run is
121/121 on both PHP 8.4.19 (z-engine 8.4.2) and PHP 8.5.9 (z-engine
8.5.0), and no deprecation of any kind is emitted.

Closes #39

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013foRd1XwLwqjUSkSWeWrMe
Every one of the 121 functional tests carried a third --INI-- line,
error_reporting=E_ALL & ~E_DEPRECATED. It was added for a dependency:
PHPUnit's .phpt runner forces display_errors=1, so a deprecation raised
by z-engine — back when it was consumed from a development branch — was
prepended to the captured output of every test and failed --EXPECT--
blocks over noise that had nothing to do with this library.

The stable releases now required (~8.4.2 || ~8.5.0) raise none, and the
line was hiding this package's own deprecations too. That is exactly how
the SplObjectStorage::contains() call PHP 8.5 deprecated stayed green
through 12 tests until it was fixed in the previous commit. Removing the
suppression is only safe in that order, so it goes second.

ffi.enable=1 and opcache.jit=off stay: FFI cannot be enabled at runtime
and the JIT rewrites the executor internals the engine hooks depend on.

The guard test is renamed to match and now checks both halves — that
each file declares both required lines, and that no file sets
error_reporting at all, so a filter cannot be reintroduced to silence a
future deprecation instead of fixing it. tests/Support/childProcess.php
spawns children with the same settings and drops the line for the same
reason. AGENTS.md now documents two lines and why the third went away;
README.md and .github/workflows/ci.yml never named it and are unchanged.

Verified with a runner that reproduces PhptTestCase: 121/121 on PHP
8.4.19 (z-engine 8.4.2) and 121/121 on PHP 8.5.9 (z-engine 8.5.0), with
no diagnostics of any kind in the output.

Closes #38

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013foRd1XwLwqjUSkSWeWrMe
@lisachenko
lisachenko marked this pull request as ready for review August 19, 2026 05:52
@lisachenko
lisachenko merged commit d621b3b into main Aug 19, 2026
6 checks passed
@lisachenko
lisachenko deleted the claude/z-engine-stable-updates-00g5v4 branch August 19, 2026 05:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant