Repository navigation
Conversation
resolveScopeStateType() already resolves late-resolvable types for a tracked expression, but returned a variable's type as stored. A parameter typed as a conditional type intersected with an array shape therefore reached specifyExpressionTypeInPlace() unresolved: narrowing one of its offsets intersected HasOffsetValueType with the unresolved conditional and dropped the shape. Mirrored in the turbo extension. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
puggan
added a commit
to Rolfs-Travel-Group/phpstan
that referenced
this pull request
Nov 12, 2026
PHPStan 2.3.5 plus phpstan/phpstan-src#6915 (fixes phpstan#15644) and phpstan/phpstan-src#6919 (fixes phpstan#15649), the same two fixes as 2.3.4-rolfs-patches. Neither is in a release yet. - phpstan.phar: the 2.3.5 phar with MutatingScope::resolveScopeStateType() and TypeCombinator::processArrayTypes() patched like the PRs; phpstan.phar.asc removed, since the upstream signature no longer matches. - turbo-ext: rebuilt from phpstan-src 2.3.5 + both fixes, PHP 8.5 NTS only, for linux-gnu-x86_64, linux-musl-x86_64, linux-gnu-arm64 and linux-musl-arm64 (version 67acd19, the one the 2.3.5 phar expects). All other upstream binaries are removed, because they lack the fixes; those platforms run without turbo. Temporary, until upstream releases both fixes. Co-Authored-By: Claude Opus 5.5 <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.
Closes phpstan/phpstan#15644
Disclosure: I worked this out with an AI assistant (Claude). The diagnosis, the fix and the test runs below were all done and checked for real.
resolveScopeStateType()resolves late-resolvable types for a tracked expression (TypeUtils::resolveLateResolvableTypes($trackedType)), but returned a variable's type as stored. A parameter typed as a conditional type intersected with an array shape, such astherefore reached
specifyExpressionTypeInPlace()unresolved. Narrowing one of its offsets ($row['a'] ?: null) intersectedHasOffsetValueTypewith the unresolved conditional, and the shape was lost: every later read of$row['b']wasmixed. Before 2.3.0, this path read the variable throughgetType(), which resolves it.The variable branch now resolves late-resolvable types too, the same as the tracked-expression branch above it. The same change is mirrored in
turbo-ext/src/MutatingScope.cpp.Testing
tests/PHPStan/Analyser/nsrt/bug-15644.php, the issue's playground snippet withassertType(): fails without the fix (line 18non-empty-array{recordinfo?: array{id: string}, ...<string, mixed>}, line 19mixed) and passes with it.PHP_INI_SCAN_DIR. The 2 deprecations areReflectionProperty::setAccessible()inObjectTypeTestandForeachHandlerTest, and show up both ways.php:8.5-cliwithmake WARN_FLAGS="$(make -s print-warn-flags)":tests/smoke.phpALL OK,bin/side-by-side.phpOK,tests/signature-parity.phpOK (16,504 members).bin/phpstan analyse --error-format=raw src/Analysergives identical output with the extension loaded (diagnose:enabled (version 67acd19)) and without it.MutatingScope.phpare clean.I didn't run
make lint-turbo(clang-tidy) ormake sanitize-turbolocally.🤖 Generated with Claude Code