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 created with array_combine is reported as missing keys on PHP 7.x #7469

Closed
finwe opened this issue Jun 13, 2022 · 12 comments · Fixed by phpstan/phpstan-src#1596
Closed
Labels
Milestone

Comments

@finwe
Copy link
Contributor

finwe commented Jun 13, 2022

Bug report

Array created with array_combine is reported as missing keys on PHP 7.x as soon as I try to change some of the keys. Only the changed keys are then recognized as part of the array as seen on the code snippet below.

It doesn't matter where the values array comes from, file_get_contents in the code snippet is a pseudocode, when it comes eg from fgetcsv, same errors are being reported.

Code snippet that reproduces the problem

https://phpstan.org/r/ef9f9a4f-1cbe-425b-b2f6-c691b829bbc2

Expected output

No errors reported even on PHP 7.1-7.4

@ondrejmirtes
Copy link
Member

I think @canvural last touched it in phpstan/phpstan-src#1139 so please look into it, thank you :)

@ondrejmirtes ondrejmirtes added this to the Easy fixes milestone Jun 13, 2022
@canvural
Copy link
Contributor

I think the issue here is that array_combine can return false on PHP7, if both arrays don't have same number of elements. So that needs to be checked. After $data === false check, PHPStan doesn't produce any error.

@ondrejmirtes
Copy link
Member

Oh right: https://phpstan.org/r/bfe4a72c-847d-487b-b32d-a5582b06b59c

But I think the problem is Dumped type: *ERROR* on PHP 7.x here: https://phpstan.org/r/c1f9ba72-c70c-4ccc-9f06-236ed41d3b39

But I guess that @canvural no longer has to feel obligated to fix that problem :)

@canvural
Copy link
Contributor

What would be the correct dumped type there? Dumped type: *ERROR* seems reasonable if you pass false to explode. Or do you mean this shouldn't happen at least in level 4?

@ondrejmirtes
Copy link
Member

Type inference isn't influenced by rule levels, \PHPStan\dumpType() will print the same thing on all levels.

The bug in this case is really weird and it's not related to array_combine() nor explode() but most likely is going to be somewhere in NodeScopeResolver. Compare the dumped type on line 28 in this example: https://phpstan.org/r/fb6cc630-b7ac-438d-ac92-c1b134b166a5

@phpstan-bot
Copy link
Contributor

@ondrejmirtes After the latest push in 1.8.x, PHPStan now reports different result with your code snippet:

@@ @@
 PHP 8.0 – 8.1 (1 error)
 ==========
 
-26: Dumped type: non-empty-array<'address'|'bankAccount'|'birthDate'|'email'|'firstName'|'ic'|'invoicing'|'invoicingAddress'|'languages'|'lastName'|'note'|'phone'|'radio'|'videoOnline'|'videoTvc'|'voiceExample', mixed>
+26: Dumped type: non-empty-array<'address'|'bankAccount'|'birthDate'|'email'|'firstName'|'ic'|'invoicing'|'invoicingAddress'|'languages'|'lastName'|'note'|'phone'|'radio'|'videoOnline'|'videoTvc'|'voiceExample', mixed>&hasOffsetValue('languages', non-empty-array<int, string>)
 
 PHP 7.1 – 7.4 (4 errors)
 ==========
Full report

PHP 8.0 – 8.1 (1 error)

Line Error
26 `Dumped type: non-empty-array<'address'

PHP 7.1 – 7.4 (4 errors)

Line Error
26 Dumped type: *ERROR*
32 Offset 'videoTvc' does not exist on array{videoOnline: mixed}.
33 Offset 'radio' does not exist on array{videoOnline: mixed, videoTvc: mixed}.
35 Offset 'invoicing' does not exist on array{videoOnline: mixed, videoTvc: mixed, radio: mixed}.

@phpstan-bot
Copy link
Contributor

@ondrejmirtes After the latest push in 1.8.x, PHPStan now reports different result with your code snippet:

@@ @@
 24: Parameter #2 $values of function array_combine expects array, string|false given.
 25: Dumped type: mixed
 26: Dumped type: non-empty-array<int, string>
-28: Dumped type: non-empty-array<'address'|'bankAccount'|'birthDate'|'email'|'firstName'|'ic'|'invoicing'|'invoicingAddress'|'languages'|'lastName'|'note'|'phone'|'radio'|'videoOnline'|'videoTvc'|'voiceExample', mixed>
-29: Dumped type: mixed
+28: Dumped type: non-empty-array<'address'|'bankAccount'|'birthDate'|'email'|'firstName'|'ic'|'invoicing'|'invoicingAddress'|'languages'|'lastName'|'note'|'phone'|'radio'|'videoOnline'|'videoTvc'|'voiceExample', mixed>&hasOffsetValue('languages', non-empty-array<int, string>)
+29: Dumped type: non-empty-array<int, string>
 
 PHP 7.1 – 7.4 (9 errors)
 ==========
Full report

PHP 8.0 – 8.1 (5 errors)

Line Error
24 `Parameter #2 $values of function array_combine expects array, string
25 Dumped type: mixed
26 Dumped type: non-empty-array<int, string>
28 `Dumped type: non-empty-array<'address'
29 Dumped type: non-empty-array<int, string>

PHP 7.1 – 7.4 (9 errors)

Line Error
24 `Parameter #2 $values of function array_combine expects array, string
25 `Cannot access offset 'languages' on array<'address'
25 Dumped type: mixed
26 `Cannot access offset 'languages' on array<'address'
26 Dumped type: non-empty-array<int, string>
27 `Cannot access offset 'languages' on array<'address'
27 `Cannot access offset 'languages' on array<'address'
28 Dumped type: *ERROR*
29 Dumped type: mixed

@phpstan-bot
Copy link
Contributor

@finwe After the latest push in 1.8.x, PHPStan now reports different result with your code snippet:

@@ @@
-PHP 8.0 – 8.1
-==========
-
-No errors
-
-PHP 7.1 – 7.4 (3 errors)
-==========
-
-31: Offset 'videoTvc' does not exist on array{videoOnline: mixed}.
-32: Offset 'radio' does not exist on array{videoOnline: mixed, videoTvc: mixed}.
-34: Offset 'invoicing' does not exist on array{videoOnline: mixed, videoTvc: mixed, radio: mixed}.
+No errors

@phpstan-bot
Copy link
Contributor

@ondrejmirtes After the latest push in 1.8.x, PHPStan now reports different result with your code snippet:

@@ @@
-PHP 8.0 – 8.1 (1 error)
-==========
-
-26: Dumped type: non-empty-array<'address'|'bankAccount'|'birthDate'|'email'|'firstName'|'ic'|'invoicing'|'invoicingAddress'|'languages'|'lastName'|'note'|'phone'|'radio'|'videoOnline'|'videoTvc'|'voiceExample', mixed>
-
-PHP 7.1 – 7.4 (4 errors)
-==========
-
-26: Dumped type: *ERROR*
-32: Offset 'videoTvc' does not exist on array{videoOnline: mixed}.
-33: Offset 'radio' does not exist on array{videoOnline: mixed, videoTvc: mixed}.
-35: Offset 'invoicing' does not exist on array{videoOnline: mixed, videoTvc: mixed, radio: mixed}.
+26: Dumped type: non-empty-array<'address'|'bankAccount'|'birthDate'|'email'|'firstName'|'ic'|'invoicing'|'invoicingAddress'|'languages'|'lastName'|'note'|'phone'|'radio'|'videoOnline'|'videoTvc'|'voiceExample', mixed>&hasOffsetValue('languages', non-empty-array<int, string>)
Full report
Line Error
26 `Dumped type: non-empty-array<'address'

@phpstan-bot
Copy link
Contributor

@ondrejmirtes After the latest push in 1.8.x, PHPStan now reports different result with your code snippet:

@@ @@
 24: Parameter #2 $values of function array_combine expects array, string|false given.
 25: Dumped type: mixed
 26: Dumped type: non-empty-array<int, string>
-28: Dumped type: non-empty-array<'address'|'bankAccount'|'birthDate'|'email'|'firstName'|'ic'|'invoicing'|'invoicingAddress'|'languages'|'lastName'|'note'|'phone'|'radio'|'videoOnline'|'videoTvc'|'voiceExample', mixed>
-29: Dumped type: mixed
+28: Dumped type: non-empty-array<'address'|'bankAccount'|'birthDate'|'email'|'firstName'|'ic'|'invoicing'|'invoicingAddress'|'languages'|'lastName'|'note'|'phone'|'radio'|'videoOnline'|'videoTvc'|'voiceExample', mixed>&hasOffsetValue('languages', non-empty-array<int, string>)
+29: Dumped type: non-empty-array<int, string>
 
 PHP 7.1 – 7.4 (9 errors)
 ==========
@@ @@
 26: Dumped type: non-empty-array<int, string>
 27: Cannot access offset 'languages' on array<'address'|'bankAccount'|'birthDate'|'email'|'firstName'|'ic'|'invoicing'|'invoicingAddress'|'languages'|'lastName'|'note'|'phone'|'radio'|'videoOnline'|'videoTvc'|'voiceExample', mixed>|false.
 27: Cannot access offset 'languages' on array<'address'|'bankAccount'|'birthDate'|'email'|'firstName'|'ic'|'invoicing'|'invoicingAddress'|'languages'|'lastName'|'note'|'phone'|'radio'|'videoOnline'|'videoTvc'|'voiceExample', mixed>|false.
-28: Dumped type: *ERROR*
-29: Dumped type: mixed
+28: Dumped type: non-empty-array<'address'|'bankAccount'|'birthDate'|'email'|'firstName'|'ic'|'invoicing'|'invoicingAddress'|'languages'|'lastName'|'note'|'phone'|'radio'|'videoOnline'|'videoTvc'|'voiceExample', mixed>&hasOffsetValue('languages', non-empty-array<int, string>)
+29: Dumped type: non-empty-array<int, string>
Full report

PHP 8.0 – 8.1 (5 errors)

Line Error
24 `Parameter #2 $values of function array_combine expects array, string
25 Dumped type: mixed
26 Dumped type: non-empty-array<int, string>
28 `Dumped type: non-empty-array<'address'
29 Dumped type: non-empty-array<int, string>

PHP 7.1 – 7.4 (9 errors)

Line Error
24 `Parameter #2 $values of function array_combine expects array, string
25 `Cannot access offset 'languages' on array<'address'
25 Dumped type: mixed
26 `Cannot access offset 'languages' on array<'address'
26 Dumped type: non-empty-array<int, string>
27 `Cannot access offset 'languages' on array<'address'
27 `Cannot access offset 'languages' on array<'address'
28 `Dumped type: non-empty-array<'address'
29 Dumped type: non-empty-array<int, string>

@ondrejmirtes
Copy link
Member

Looks like this one solved it :) phpstan/phpstan-src@1537424

@github-actions
Copy link

github-actions bot commented Sep 7, 2022

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Sep 7, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants