-
Notifications
You must be signed in to change notification settings - Fork 7.9k
Pure Intersection types #6799
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
Pure Intersection types #6799
Conversation
Is there any reason to not allow PS: https://3v4l.org/mI6JY not allowed for |
Because it would be inconsistent with union types, also this makes for a bit of sigil soup and is hard to grasp what the meaning of this is, is it Therefore my reasoning is that is too confusing and will need to wait for composite types. |
3c5fc0b
to
46cda17
Compare
Thank you for working on this feature. I understand that you want to keep the first iteration simple and thus leave unions out of the PR. However, if I'm not mistaken, you would create the only type that is not nullable. That feels like an unnecessary edge-case. Would it be very difficult to at least allow the union of an intersect type with null? |
I think UPDATE: I meant union of any number of (possibly purely intersected) types. |
It has nothing to do with ambiguity but I see no point in supporting just Obviously support for full composite type is the end goal, however, I've clearly stated that this is future scope, it could even land in PHP 8.1 as a follow up either by myself or someone else. But I cannot guarantee that I'll get round to that prior to the end of June which is the likely cutoff date for getting an RFC included into PHP 8.1. If internals decide the feature is incomplete so be it, but I prefer getting this restricted addition into the language upon which one can iterate instead of having perfectness being the enemy of the good. |
Zend/tests/type_declarations/intersection_types/invalid_callable_type.phpt
Outdated
Show resolved
Hide resolved
This is brilliant! Regarding composite types and variance... should mixing intersections and unions be allowed in inheritance at this stage? E.g. the following code which I believe is valid from the LSP perspective: interface X {}
interface Y {}
class TestOne implements X, Y {}
class TestTwo implements X, Y {}
class A
{
public function foo(TestOne|TestTwo $param): X&Y {}
}
class B extends A
{
public function foo(X&Y $param): TestOne|TestTwo {}
} |
that's a really good question, personally i think the following should be allowed at this stage. interface X {}
interface Y {}
class TestOne implements X, Y {}
class TestTwo implements X, Y {}
interface A
{
public function foo(TestOne|TestTwo $param): X&Y;
}
interface B extends A
{
public function foo(X&Y $param): TestOne|TestTwo;
}
interface C extends A
{
public function foo(X $param): TestTwo;
}
interface D extends A
{
public function foo(Y $param): TestOne;
}
interface E extends B
{
public function foo(X $param): TestTwo;
}
interface F extends B
{
public function foo(Y $param): TestOne;
} |
46cda17
to
9d65106
Compare
You'll be happy to learn that this worked without any modification :-) (which means I probably got most of the variance code correct) |
29637ec
to
d2e85d9
Compare
d2e85d9
to
eabe3c7
Compare
eabe3c7
to
f30e82f
Compare
fce561a
to
faeadd6
Compare
faeadd6
to
97c2583
Compare
The variance implementation looks wrong to me, but it took me quite a while to figure out why. Consider:
I believe this should pass, because |
I think the example you gave should error, but for a different reason, that is it's impossible to have |
Change the classes to interfaces and the problem is still there, and obviously it will error during Runtime because it can't satisfy two classes, but we do not know this at compile time. |
23497a7
to
203ec25
Compare
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 took a look to check if I understood any edge cases for work on a static analyzer for php
The implementation at a glance doesn't have any issues I can see, but I'm only moderately familiar with it (and I only know a bit about the opcache optimizer and memory management code this uses)
I had some nits on code comments and suggestions/questions for refactoring in a way that is equivalent to the current implementation
@@ -148,15 +148,21 @@ typedef struct { | ||
/* TODO: bit 21 is not used */ |
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.
nit: I wonder if it'd make sense to start using bit 21 for the new constants, not familiar with the code in question. (whether by renumbering _ZEND_TYPE_ARENA_BIT
in php 8.1 (hopefully anything actually using this uses this macro) or using 1u<<21 for the new constants
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 when I started the implementation this bit was still used, but I'll let the decision to renumber to someone else as I don't know if we should do.
Make zend_perform_intersection_covariant_class_type_check() a single function that checks whether a simple type is a subtype of a complex type.
I think this is still not quite correct :/
It wasn't immediatly obvious to me while starring at the code that the case where a parent type is not loadable is handled. Just needed to understand that get_class_from_type() only returns NULL when it is not a class-type
Refactor a bit the handling of iterable as a by product.
de0fe7b
to
ea33768
Compare
The variance code seems correct to me, the only thing which felt weird was the need to load classes when |
@Girgias Loading classes for |
Okay, I'll revert and add a comment to make sure that doesn't get reworked. |
This reverts commit ea33768.
Zend/zend_inheritance.c
Outdated
/* Currently, for object type any class name would be allowed here. | ||
* We still perform a class lookup for forward-compatibility reasons, | ||
* as we may have named types in the future that are not classes | ||
* (such as enums or typedefs). */ |
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 "enums" bit here doesn't make sense anymore :)
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.
Copy pasted this, so I also fixed that comment at the same time.
> Intersection Types > > Support for intersection types has been added. Detect whether a type is an intersection type and throw an error if PHP < 8.1 needs to be supported. Ref: * https://wiki.php.net/rfc/pure-intersection-types * https://www.php.net/manual/en/migration81.new-features.php#migration81.new-features.core.intersection-types * https://www.php.net/manual/en/language.types.type-system.php#language.types.type-system.composite.intersection * php/php-src#6799 * php/php-src@069a9fa
> Intersection Types > > Support for intersection types has been added. Detect whether a type is an intersection type and throw an error if PHP < 8.1 needs to be supported. Ref: * https://wiki.php.net/rfc/pure-intersection-types * https://www.php.net/manual/en/migration81.new-features.php#migration81.new-features.core.intersection-types * https://www.php.net/manual/en/language.types.type-system.php#language.types.type-system.composite.intersection * php/php-src#6799 * php/php-src@069a9fa
> Intersection Types > > Support for intersection types has been added. Detect whether a type is an intersection type and throw an error if PHP < 8.1 needs to be supported. Ref: * https://wiki.php.net/rfc/pure-intersection-types * https://www.php.net/manual/en/migration81.new-features.php#migration81.new-features.core.intersection-types * https://www.php.net/manual/en/language.types.type-system.php#language.types.type-system.composite.intersection * php/php-src#6799 * php/php-src@069a9fa
Add support for pure intersection types
A&B
but no mixing of union and intersection types (i.e.A&B|C
).RFC Draft is located in a separate personal repository, all discussion and amendment to that should either be a PR to the draft or a comment on the mailing list thread.
The main implementation is done and working, however there are still a couple of things missing: