-
Notifications
You must be signed in to change notification settings - Fork 504
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
Fix issue with template of union #3535
Conversation
src/Analyser/MutatingScope.php
Outdated
@@ -5602,8 +5603,10 @@ private function filterTypeWithMethod(Type $typeWithMethod, string $methodName): | |||
{ | |||
if ($typeWithMethod instanceof UnionType) { | |||
$newTypes = []; | |||
$oneTypeHasBeenRemoved = false; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think whether this is a problem which should be solved with a Type
method.
maybe we can use a Type
method in which you pass in a callable and it returns a preserved union type (maybe such method even exists...?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The whole method filterTypeWithMethod
could be introduce as something like Type::filter
if wanted but this would "only" be a refacto. (Which may be in another PR)
There is UnionType::traverse
public function traverse(callable $cb): Type
{
$types = [];
$changed = false;
foreach ($this->types as $type) {
$newType = $cb($type);
if ($type !== $newType) {
$changed = true;
}
$types[] = $newType;
}
if ($changed) {
return TypeCombinator::union(...$types);
}
return $this;
}
but it doesn't do the exact same thing ; we can still notice a changed
check is done the same way.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
don't want to disturb you guys too much, but another idea to throw in - does TypeTraverser::map()
help in any way here maybe? e.g. the types you don't want you could replace with a NeverType
potentially? that should leave the outer TemplateUnionType
untouched at least. that could be a replacement for the foreach, AFAIK TypeCombinator::union()
should keep the TemplateUnionType then and remove the never I suppose.
but not sure if that makes it even more complicated potentially 😅
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I get it, but the variable name should be different. Something like $unionTypeHasChanged
.
Also it's a lot of repeated code. I'd welcome some refactoring first, and then the change should be done in a single place.
1ac6714
to
95cf6ed
Compare
Hi, what do you think about this PR @ondrejmirtes ? Thanks |
I have no idea how |
The idea was kinda similar to
the goal is to keep the same object when nothing change (here when no type is removed). Because the existing code
always change the instance of
But when |
src/Analyser/MutatingScope.php
Outdated
@@ -5602,8 +5603,10 @@ private function filterTypeWithMethod(Type $typeWithMethod, string $methodName): | |||
{ | |||
if ($typeWithMethod instanceof UnionType) { | |||
$newTypes = []; | |||
$oneTypeHasBeenRemoved = false; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I get it, but the variable name should be different. Something like $unionTypeHasChanged
.
Also it's a lot of repeated code. I'd welcome some refactoring first, and then the change should be done in a single place.
95cf6ed
to
c5a4041
Compare
PR is simplified now |
We could improve this further, right? Even if something changes in UnionType subtype, in this method we could make sure the correct class is created. The subtypes from the top of my head are:
|
I understand the use case for BenevolentUnion (__benevolent(A|B|C) become __benevolent(A|B)), but it's complicated for me to see the use case for TemplateUnionType and TemplateBenevolentUnionType. Do you have an example to add to the tests ? |
Examples:
|
2b65b6b
to
9121f72
Compare
src/Type/UnionType.php
Outdated
if ($this instanceof BenevolentUnionType) { | ||
$result = TypeUtils::toBenevolentUnion($result); | ||
} | ||
if ($this instanceof TemplateType) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd rather have this logic in the subtypes in overridden methods.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
e72bd7d
to
1c25206
Compare
Thank you. |
Closes phpstan/phpstan#11663
Cf phpstan/phpstan#11663 (comment) I dunno if there is a already-known better way to handle such situation.