Skip to content

Report a possibly missing offset on a type that only maybe has offsets - #6725

Open
SanderMuller wants to merge 1 commit into
phpstan:2.3.xfrom
SanderMuller:offset-missing-key-on-maybe-accessible
Open

SanderMuller wants to merge 1 commit into
phpstan:2.3.xfrom
SanderMuller:offset-missing-key-on-maybe-accessible

Conversation

@SanderMuller

Copy link
Copy Markdown
Contributor

On array{host?: string}|false, NonexistentOffsetInArrayDimFetchRule reported only the false part and returned, so the possibly missing 'host' key on the array part was never reported:

function foo(string $url): void {
	$parsed = parse_url($url);
	echo $parsed['host'];
	// before: Cannot access offset 'host' on array{scheme?: string, host?: string, ...}|false.
	// after, in addition: Offset 'host' might not exist on array{scheme?: string, host?: string, ...}|false.
}

With array{host?: string}|null the missing key was already reported, so the result depended on whether the second member is null or false.

  • The rule now continues into NonexistentOffsetInArrayDimFetchCheck after the "Cannot access offset" error, for reads only. A write creates the offset, so it stops there as before.
  • The check skips the members that are not certainly offset-accessible, because the rule already reports them. Without that, array{host: string}|false would get a "might not exist" for the false part, although the key always exists on the array part.
  • ArrayDestructuringRule had the same early return for a type that is only maybe an array. [$a, $b] = $arrayOrFalse reported only "Cannot use array destructuring on ...|false". It now checks the keys on the array part as well.

On WordPress trunk from 2026-10-07 at level 8, this adds 46 errors and removes none. 42 of them are a possibly missing key on a parse_url() or wp_get_attachment_metadata() result. The other 4 come from a null or string member next to the array, which array|null already reported before this change. WordPress once fixed this exact case in WordPress/wordpress-develop@68b2338: $parsed['host'] on a relative parse_url() result in media.php. Before that fix, PHPStan reported only the false part on that line.

🤖 Generated with Claude Code

On array{host?: string}|false, NonexistentOffsetInArrayDimFetchRule
reported only "Cannot access offset 'host' on ...|false" and returned, so
the possibly missing 'host' key on the array part was never reported.
Continue to the offset check after that error, for reads only: a write
creates the offset. The check now skips the members that are not
certainly offset-accessible, which the rule already reports, so
array{host: string}|false does not get a "might not exist".

ArrayDestructuringRule had the same early return for a type that is only
maybe an array, such as array|false. It now checks the keys on the array
part as well.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@SanderMuller
SanderMuller force-pushed the offset-missing-key-on-maybe-accessible branch from 12258aa to 981ca41 Compare October 9, 2026 23:24
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.

1 participant