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

Improve ConstantArrayType::unsetOffset #1537

Merged
merged 1 commit into from Jul 26, 2022

Conversation

herndlm
Copy link
Contributor

@herndlm herndlm commented Jul 21, 2022

Basically adds support for union offsets.

Previously it generalized too early to a generic array IMO.

@herndlm herndlm force-pushed the constant-array-unset-offset branch from 2b02425 to 7af6056 Compare July 21, 2022 22:20
@herndlm
Copy link
Contributor Author

herndlm commented Jul 21, 2022

oh no, no clue about the 5 windows failures with error types. what could that be?

namespace failures from my side


and I still don't understand the slevomat failure. it seems to be also related to the unions of constant arrays where some properties end up being optional in the resulting array.. but if the type is correct, maybe the array_key_exists extension really should not specify constants? not sure..

has been fixed by Ondrej in the tagged unions preparations


and the prestashop error is something I'm still looking at. UPDATE: the union normalization is adding the non-empty-array type as in #1537 (comment) :/

also been fixed by Ondrej

@herndlm
Copy link
Contributor Author

herndlm commented Jul 22, 2022

found out a bit more about the prestashop errors at least. looks like because of the if condition with empty at https://github.com/PrestaShop/PrestaShop/blob/6c3797271697278b31e2bd0905d54cea6131d335/classes/pdf/HTMLTemplateInvoice.php#L438 there are multiple scopes and the final scope, that has the correct unset union type, is being merged with the current one that has the original type of $breakdowns. Basically this leads to smth like array{foo: array, bar: array}|array{foo: array}|array{bar: array} where the first shape is the original type and the other 2 are the unset unions. The outcome then is array{foo?: array, bar?: array}&non-empty-array which makes sense I guess, but leads to the Variable $breakdowns in empty() always exists and is not falsy. below. hmm
I think this is a case where the non-empty-array intersection should not be there, but since it comes from scope merging I'm unsure what the problem is exactly.

irrelevant, since it has been fixed by Ondrej as mentioned in the previous comment. But I extracted a test case based on that and put it here just to be sure.

@herndlm herndlm force-pushed the constant-array-unset-offset branch 2 times, most recently from 1a7cf21 to eda95ea Compare July 26, 2022 07:30
}
}

assertType('array{}|array{a?: bool, b?: numeric-string, c?: int<-1, 1>, d?: int<0, 1>}', $breakdowns);
Copy link
Contributor Author

@herndlm herndlm Jul 26, 2022

Choose a reason for hiding this comment

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

This was array<'a'|'b'|'c'|'d', bool|int<-1, 1>|numeric-string> before. See https://phpstan.org/r/6c90923e-abf5-492d-8bf6-c5f95a6627e6

I added it because something very similar to this was failing in prestashop while developing. It has been unblocked/fixed by Ondrej's recent changes (IIRC there was a non-empty-array intersection before), but I want to avoid it failing again. And it is a nice example I think.

The union with an empty array could be optimised away. If this isn't already done in the tagged unions branch anyway.. :)

@@ -802,8 +802,6 @@ public function testBug7094(): void

$this->assertSame('Parameter #1 $attr of method Bug7094\Foo::setAttributes() expects array{foo?: string, bar?: 5|6|7, baz?: bool}, non-empty-array<string, 5|6|7|bool|string> given.', $errors[5]->getMessage());
$this->assertSame(29, $errors[5]->getLine());
$this->assertSame('Parameter #1 $attr of method Bug7094\Foo::setAttributes() expects array{foo?: string, bar?: 5|6|7, baz?: bool}, array<\'bar\'|\'baz\'|\'foo\', 5|6|7|bool|string> given.', $errors[6]->getMessage());
$this->assertSame(49, $errors[6]->getLine());
Copy link
Contributor Author

@herndlm herndlm Jul 26, 2022

Choose a reason for hiding this comment

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

the extracted case is basically https://phpstan.org/r/4ca3ec8a-9f81-4b87-a321-c62a7e58b768
this should be fine IMO, phpstan got a tiny bit smarter here.

@herndlm herndlm force-pushed the constant-array-unset-offset branch from 9ef1528 to a31a0f1 Compare July 26, 2022 08:02
@herndlm herndlm force-pushed the constant-array-unset-offset branch from a31a0f1 to 41637f4 Compare July 26, 2022 08:03
@herndlm
Copy link
Contributor Author

herndlm commented Jul 26, 2022

this is now ready. has been unblocked by recent changes basically.
maybe it even helps with the tagged unions or with in_array specification. if not it improves things a tiny bit I guess :)

@herndlm herndlm marked this pull request as ready for review July 26, 2022 08:16
@ondrejmirtes ondrejmirtes merged commit 541b2c8 into phpstan:1.8.x Jul 26, 2022
@ondrejmirtes
Copy link
Member

Really nice, thank you :)

@herndlm herndlm deleted the constant-array-unset-offset branch July 26, 2022 08:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
2 participants