summaryrefslogtreecommitdiff
path: root/Zend/zend_compile.h
diff options
context:
space:
mode:
authorNikita Popov <nikita.ppv@gmail.com>2019-05-27 11:39:56 +0200
committerNikita Popov <nikita.ppv@gmail.com>2019-06-11 13:09:33 +0200
commit8f8fcbbd397370b407dc2552c4bd6ee4ccb0e93b (patch)
tree88aa957f3c81df9e9eaefa5b9e2c3b58cde020ec /Zend/zend_compile.h
parent89b2d88659b8a561769f51dfab1fa325e7fc0603 (diff)
downloadphp-git-8f8fcbbd397370b407dc2552c4bd6ee4ccb0e93b.tar.gz
Support full variance if autoloading is used
Keep track of delayed variance obligations and check them after linking a class is otherwise finished. Obligations may either be unresolved method compatibility (because the necessecary classes aren't available yet) or open parent/interface dependencies. The latter occur because we allow the use of not fully linked classes as parents/interfaces now. An important aspect of the implementation is we do not require classes involved in variance checks to be fully linked in order for the class to be fully linked. Because the involved types do have to exist in the class table (as partially linked classes) and we do check these for correct variance, we have the guarantee that either those classes will successfully link lateron or generate an error, but there is no way to actually use them until that point and as such no possibility of violating the variance contract. This is important because it ensures that a class declaration always either errors or will produce an immediately usable class afterwards -- there are no cases where the finalization of the class declaration has to be delayed until a later time, as earlier variants of this patch did. Because variance checks deal with classes in various stages of linking, we need to use a special instanceof implementation that supports this, and also introduce finer-grained flags that tell us which parts have been linked already and which haven't. Class autoloading for variance checks is delayed into a separate stage after the class is otherwise linked and before delayed variance obligations are processed. This separation is needed to handle cases like A extends B extends C, where B is the autoload root, but C is required to check variance. This could end up loading C while the class structure of B is in an inconsistent state.
Diffstat (limited to 'Zend/zend_compile.h')
-rw-r--r--Zend/zend_compile.h11
1 files changed, 9 insertions, 2 deletions
diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h
index 3f2ec6ba07..b47d762a74 100644
--- a/Zend/zend_compile.h
+++ b/Zend/zend_compile.h
@@ -269,8 +269,14 @@ typedef struct _zend_oparray_context {
/* Children must reuse parent get_iterator() | | | */
#define ZEND_ACC_REUSE_GET_ITERATOR (1 << 18) /* X | | | */
/* | | | */
-/* Class is being linked. Don't free strings. | | | */
-#define ZEND_ACC_LINKING_IN_PROGRESS (1 << 19) /* X | | | */
+/* Parent class is resolved (CE). | | | */
+#define ZEND_ACC_RESOLVED_PARENT (1 << 19) /* X | | | */
+/* | | | */
+/* Interfaces are resolved (CEs). | | | */
+#define ZEND_ACC_RESOLVED_INTERFACES (1 << 20) /* X | | | */
+/* | | | */
+/* Class has unresolved variance obligations. | | | */
+#define ZEND_ACC_UNRESOLVED_VARIANCE (1 << 21) /* X | | | */
/* | | | */
/* Function Flags (unused: 28...30) | | | */
/* ============== | | | */
@@ -852,6 +858,7 @@ void zend_assert_valid_class_name(const zend_string *const_name);
#define ZEND_FETCH_CLASS_NO_AUTOLOAD 0x80
#define ZEND_FETCH_CLASS_SILENT 0x0100
#define ZEND_FETCH_CLASS_EXCEPTION 0x0200
+#define ZEND_FETCH_CLASS_ALLOW_UNLINKED 0x0400
#define ZEND_PARAM_REF (1<<0)
#define ZEND_PARAM_VARIADIC (1<<1)