-
Notifications
You must be signed in to change notification settings - Fork 7.9k
Implement basic variance support #4185
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
Conversation
I've included #4184 in here as well now, because it requires some additional handling (some things work by accident without it). |
Fixes bug #76451, and more importantly lays necessary groundwork for covariant/contravariant types. Bug #76451 is just an edge case, but once covariance is introduced this will become a common problem instead.
The autoload case is supposed to work, but doesn't actually :(
Rebased over #4184. |
// Illegal: A::parent is ill-defined | ||
class A { | ||
public function method(parent $x) {} | ||
} |
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.
Why is this allowed at all?
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 had originally added a compile-time check for this in 7.4, but reverted it again in deb44d4 because it broke Mockery, which is used by Laravel. Maybe we can do this for PHP 8.
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.
might be a good idea to add this into deprecations for PHP-7.4
Which should make it more obvious if an inheritance check fails due to a cycle.
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.
In general the PR is OK, but it is a subject for future optimizations and reduction of implementation limitations (For example, the second example from RFC and Zend/tests/type_declarations/variance/class_order_autoload.phpt might be supported).
@@ -6392,6 +6394,7 @@ zend_op *zend_compile_class_decl(zend_ast *ast, zend_bool toplevel) /* {{{ */ | |||
&& !(CG(compiler_options) & ZEND_COMPILE_PRELOAD) /* delay inheritance till preloading */ | |||
&& ((parent_ce->type != ZEND_INTERNAL_CLASS) || !(CG(compiler_options) & ZEND_COMPILE_IGNORE_INTERNAL_CLASSES)) | |||
&& ((parent_ce->type != ZEND_USER_CLASS) || !(CG(compiler_options) & ZEND_COMPILE_IGNORE_OTHER_FILES) || (parent_ce->info.user.filename == ce->info.user.filename)) | |||
&& zend_can_early_bind(ce, parent_ce) |
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.
We should try to reduce overhead of zend_can_early_bind(), but we can do it later.
@@ -3491,6 +3529,10 @@ static void preload_link(void) | |||
if (!found) continue; | |||
} | |||
|
|||
if (!preload_all_types_known(ce)) { |
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.
This check is seriously more restricted than necessary, but we try to improve it later. Please add TODO comments.
zend_class_entry *fe_ce = lookup_class(fe, fe_class_name); | ||
if (!fe_ce) { | ||
*unresolved_class = fe_class_name; | ||
return INHERITANCE_UNRESOLVED; | ||
} |
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.
This check is not necessary. Any class should work, so we may avoid class loading.
<?php
interface A {
function m(): object;
}
interface B extends A {
function m(): unknown;
}
@dstogov My proposal for "minimal" variance support, with only enough to make the non-circular cases work.