Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

array_merge lost non-empty-string keys type #1135

Merged
merged 7 commits into from Mar 30, 2022
Merged

Conversation

staabm
Copy link
Contributor

@staabm staabm commented Mar 28, 2022

suggestion for a fix of bug #6927.

I am wondering why the generalize call was in the ArrayMergeFunctionDynamicReturnTypeExtension

.. the only thing I could think of are "cosmetic" reasons for error messages, since the types we get when dropping the generalize call seem to be more precise and still valid? lets see what CI thinks about it.

the generalize call was added a long time ago with 002aa73

closes phpstan/phpstan#6927

@staabm staabm changed the title stab at bug 6927 array_merge lost non-empty-string keys type Mar 28, 2022
@staabm
Copy link
Contributor Author

staabm commented Mar 28, 2022

unrelated: there is a interessting test-case, I tried to add.

	/**
	 * @param array<numeric-string&non-empty-string, string> $params1
	 * @param array<numeric-string, string> $params2
	 */
	function foo5(array $params1, array $params2): void
	{
		$params2 = array_merge($params1, $params2);

		assertType('array<numeric-string, string>', $params2);
	}

it errors with

There was 1 failure:

1) PHPStan\Analyser\NodeScopeResolverTest::testFileAsserts with data set "C:\dvl\Workspace\phpstan-src-staabm\tests\PHPStan\Analyser/data/bug-6927.php:61" ('type', 'C:\dvl\Workspace\phpstan-src-...27.php', PHPStan\Type\Constant\ConstantStringType Object (...), PHPStan\Type\ArrayType Object (...), 61)
Expected type array<numeric-string, string>, got type array<int, string> in C:\dvl\Workspace\phpstan-src-staabm\tests\PHPStan\Analyser/data/bug-6927.php on line 61.
Failed asserting that two strings are identical.
--- Expected
+++ Actual
@@ @@
-'array<numeric-string, string>'
+'array<int, string>'

C:\dvl\Workspace\phpstan-src-staabm\src\Testing\TypeInferenceTestCase.php:97
C:\dvl\Workspace\phpstan-src-staabm\tests\PHPStan\Analyser\NodeScopeResolverTest.php:846

which is a different bug IMO.. but interessting nevertheless

edit: opened a new issue for that

@ondrejmirtes
Copy link
Member

I agree, it shouldn't be generalized.

@staabm
Copy link
Contributor Author

staabm commented Mar 30, 2022

the remaining error

Error: Property Composer\Util\Http\CurlDownloader::$jobs (
array<array{url: string, origin: string, attributes: array{retryAuthFailure: bool, redirects: int, retries: int, storeAuth: bool}, options: array, progress: array, curlHandle: resource, filename: string|false, headerHandle: resource, ...}>) 
does not accept 
non-empty-array<array{url: string, origin: string, attributes: array{retryAuthFailure: bool, redirects: int, retries: int, storeAuth: bool}, options: array, progress: array, curlHandle: CurlHandle|resource, filename: string|false|null, headerHandle: resource, ...}>.

seems legit and unrelated, because resource and CurlHandle|resource, and also string|false and string|false|null do not match.
see https://github.com/composer/composer/blob/3ae111140facdba8ae82adcd1085e4adfc7d715c/src/Composer/Util/Http/CurlDownloader.php#L261-L273

the code seems not to be dependent on array_merge which is the one we change with this PR.

@staabm staabm marked this pull request as ready for review March 30, 2022 12:39
@@ -4707,31 +4707,31 @@ public function dataArrayFunctions(): array
'array_values($generalStringKeys)',
],
[
'non-empty-array<int|(literal-string&non-empty-string), stdClass>',
'array{foo: stdClass, 1: stdClass}',
Copy link
Contributor Author

@staabm staabm Mar 30, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

changed existing tests, to more specific types - as the PR gets better results in these cases.

Comment on lines +54 to +55
* @param array{return: int, stdout: string, stderr: string} $params1
* @param array{return: int, stdout?: string, stderr?: string} $params2
Copy link
Contributor Author

@staabm staabm Mar 30, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this test is inspired by a scenario which failed with a previous version of this PR within the composer code-base

$newArrayBuilder = ConstantArrayTypeBuilder::createEmpty();
foreach ($argTypes as $argType) {
if (!$argType instanceof ConstantArrayType) {
throw new ShouldNotHappenException();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could push only ConstantArrayType into $argTypes and this condition would not be necessary :)

Copy link
Contributor Author

@staabm staabm Mar 30, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

but then I couldn't re-use the $artTypes for the 2nd-foreach loop..?

or I have all non-constant-array-args to be resolved twice via scope->getType
or alternatively I need 2 arrays to hold the different args per type

@ondrejmirtes
Copy link
Member

Thank you, let's try this!

@ondrejmirtes
Copy link
Member

The same thing that happened last time someone tried to do this happened again :( #641 (comment)

This version is about 30 % slower on Slevomat's codebase than previous commit. I'm gonna revert this. Can you please send a new PR that just removes the generalization to see if it fixes the related issues? https://github.com/phpstan/phpstan-src/pull/1135/files#diff-235402991c12d4f1091a88a9c19ed82c38749ed4e4dce1322474ed6c6d7fdcc8L47-R92

@ondrejmirtes
Copy link
Member

Oh, previous commit is also slow, I overlooked it. Well, we have a rabbit hole to go through.

@ondrejmirtes
Copy link
Member

Alright, it's the same speed as the last stable version, we can release this as it is. (It might have something to do I'm on battery right now, I'm used to seeing faster numbers though.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
3 participants