phpstan-src icon indicating copy to clipboard operation
phpstan-src copied to clipboard

Try fixing assigning array offsets on possibly undefined nested array offsets

Open ondrejmirtes opened this issue 11 months ago • 2 comments

ondrejmirtes avatar Mar 09 '25 14:03 ondrejmirtes

<?php

use function PHPStan\Testing\assertType;

function doFoo(int $i): void
{
	$array = [];

	$array[$i]['bar'] = 1;
	$array[$i]['baz'] = 2;

	// on line 10 PHPStan assigns:
	// 1) $array[$i]['baz'] to 2
	// 2) $array[$i] to array{bar: 1, baz: 2}
	// 3) $array = from non-empty-array<int, array{bar: 1}> to non-empty-array<int, array{bar: 1, baz: 2}>
	// but step 3) is basically wrong for most code because assigning "baz" might be on a different offset than array{bar: 1} is on
	// but somehow we need to continue doing this if this PR is supposed to be successful

	assertType('non-empty-array<int, array{bar: 1, baz: 2}>', $array);
}

ondrejmirtes avatar Mar 10 '25 09:03 ondrejmirtes

I realized the above problem could be fixed with a new accessory "ArraySize" type. When doing $array[$i]['baz'] = 2; and by knowing that $array[$i] already exists and by knowing that $array has size 1, we could overwrite the array with a new type. So instead of:

non-empty-array<int, array{bar: 1, baz?: 2}>

We could actually end up with:

non-empty-array<int, array{bar: 1, baz: 2}>

ondrejmirtes avatar Mar 10 '25 17:03 ondrejmirtes