echo "ok\n";
?>
--EXPECTF--
-Fatal error: Interface RecurisiveFooFar cannot implement itself in %s on line %d
+Fatal error: Interface 'RecurisiveFooFar' not found in %s on line %d
--- /dev/null
+--TEST--
+Using an unlinked parent class
+--FILE--
+<?php
+
+spl_autoload_register(function($class) {
+ class X extends B {}
+});
+
+class B extends A {
+}
+
+?>
+--EXPECTF--
+Fatal error: Class 'B' not found in %s on line %d
--- /dev/null
+--TEST--
+Using an unlinked parent interface
+--FILE--
+<?php
+
+spl_autoload_register(function($class) {
+ class X implements B {}
+});
+
+interface B extends A {
+}
+
+?>
+--EXPECTF--
+Fatal error: Interface 'B' not found in %s on line %d
/* op_array or class is preloaded | | | */
#define ZEND_ACC_PRELOADED (1 << 10) /* X | X | | */
/* | | | */
-/* Class Flags (unused: 22...) | | | */
+/* Class Flags (unused: 23...) | | | */
/* =========== | | | */
/* | | | */
/* Special class types | | | */
/* Class has unresolved variance obligations. | | | */
#define ZEND_ACC_UNRESOLVED_VARIANCE (1 << 21) /* X | | | */
/* | | | */
+/* Class is linked apart from variance obligations. | | | */
+#define ZEND_ACC_NEARLY_LINKED (1 << 22) /* X | | | */
+/* | | | */
/* Function Flags (unused: 23, 26) | | | */
/* ============== | | | */
/* | | | */
#define ZEND_FETCH_CLASS_SILENT 0x0100
#define ZEND_FETCH_CLASS_EXCEPTION 0x0200
#define ZEND_FETCH_CLASS_ALLOW_UNLINKED 0x0400
+#define ZEND_FETCH_CLASS_ALLOW_NEARLY_LINKED 0x0800
#define ZEND_PARAM_REF (1<<0)
#define ZEND_PARAM_VARIADIC (1<<1)
zend_string_release_ex(lc_name, 0);
}
ce = (zend_class_entry*)Z_PTR_P(zv);
- if (UNEXPECTED(!(ce->ce_flags & ZEND_ACC_LINKED)) &&
- !(flags & ZEND_FETCH_CLASS_ALLOW_UNLINKED)) {
+ if (UNEXPECTED(!(ce->ce_flags & ZEND_ACC_LINKED))) {
+ if ((flags & ZEND_FETCH_CLASS_ALLOW_UNLINKED) ||
+ ((flags & ZEND_FETCH_CLASS_ALLOW_NEARLY_LINKED) &&
+ (ce->ce_flags & ZEND_ACC_NEARLY_LINKED))) {
+ return ce;
+ }
return NULL;
}
return ce;
if (!(ce->ce_flags & ZEND_ACC_INTERFACE) && iface->interface_gets_implemented && iface->interface_gets_implemented(iface, ce) == FAILURE) {
zend_error_noreturn(E_CORE_ERROR, "Class %s could not implement interface %s", ZSTR_VAL(ce->name), ZSTR_VAL(iface->name));
}
- if (UNEXPECTED(ce == iface)) {
- zend_error_noreturn(E_ERROR, "Interface %s cannot implement itself", ZSTR_VAL(ce->name));
- }
+ /* This should be prevented by the class lookup logic. */
+ ZEND_ASSERT(ce != iface);
}
/* }}} */
for (i = 0; i < ce->num_interfaces; i++) {
iface = zend_fetch_class_by_name(
ce->interface_names[i].name, ce->interface_names[i].lc_name,
- ZEND_FETCH_CLASS_INTERFACE|ZEND_FETCH_CLASS_ALLOW_UNLINKED);
+ ZEND_FETCH_CLASS_INTERFACE|ZEND_FETCH_CLASS_ALLOW_NEARLY_LINKED);
if (!(iface->ce_flags & ZEND_ACC_LINKED)) {
add_dependency_obligation(ce, iface);
}
{
if (ce->parent_name) {
zend_class_entry *parent = zend_fetch_class_by_name(
- ce->parent_name, lc_parent_name, ZEND_FETCH_CLASS_ALLOW_UNLINKED);
+ ce->parent_name, lc_parent_name, ZEND_FETCH_CLASS_ALLOW_NEARLY_LINKED);
if (!(parent->ce_flags & ZEND_ACC_LINKED)) {
add_dependency_obligation(ce, parent);
}
return;
}
+ ce->ce_flags |= ZEND_ACC_NEARLY_LINKED;
load_delayed_classes();
if (ce->ce_flags & ZEND_ACC_UNRESOLVED_VARIANCE) {
resolve_delayed_variance_obligations(ce);