From: Etienne Kneuss <colder@php.net>
Date: Wed, 3 Nov 2010 15:40:24 +0000 (+0000)
Subject: Fixed covariance of return-by-ref constraints
X-Git-Tag: php-5.4.0alpha1~191^2~737
X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=105db96e781d5def2eeec102f9b5e56e187b78f1;p=php

Fixed covariance of return-by-ref constraints
---

diff --git a/Zend/tests/objects_032.phpt b/Zend/tests/objects_032.phpt
new file mode 100644
index 0000000000..e5e3ecadb2
--- /dev/null
+++ b/Zend/tests/objects_032.phpt
@@ -0,0 +1,40 @@
+--TEST--
+Covariant return-by-ref constraints
+--FILE--
+<?php
+
+class A implements ArrayAccess {
+    public $foo = array();
+
+    public function &offsetGet($n) {
+        return $this->foo[$n];
+    }
+
+    public function offsetSet($n, $v) {
+    }
+    public function offsetUnset($n) {
+    }
+    public function offsetExists($n) {
+    }
+}
+
+$a = new A;
+
+$a['foo']['bar'] = 2;
+
+var_dump($a);
+
+?>
+==DONE==
+--EXPECTF--
+object(A)#1 (1) {
+  ["foo"]=>
+  array(1) {
+    ["foo"]=>
+    array(1) {
+      ["bar"]=>
+      int(2)
+    }
+  }
+}
+==DONE==
diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c
index 08b70b2267..c49dce6fcb 100644
--- a/Zend/zend_compile.c
+++ b/Zend/zend_compile.c
@@ -2956,8 +2956,9 @@ static zend_bool zend_do_perform_implementation_check(const zend_function *fe, c
 		return 0;
 	}
 
-	if ((fe->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) !=
-	    (proto->common.fn_flags & ZEND_ACC_RETURN_REFERENCE)) {
+	/* by-ref constraints on return values are covariant */
+	if ((proto->common.fn_flags & ZEND_ACC_RETURN_REFERENCE)
+		&& !(fe->common.fn_flags & ZEND_ACC_RETURN_REFERENCE)) {
 		return 0;
 	}
 
@@ -2981,6 +2982,8 @@ static zend_bool zend_do_perform_implementation_check(const zend_function *fe, c
 			/* Incompatible type hint */
 			return 0;
 		}
+
+		/* by-ref constraints on arguments are invariant */
 		if (fe->common.arg_info[i].pass_by_reference != proto->common.arg_info[i].pass_by_reference) {
 			return 0;
 		}