Fixed covariance of return-by-ref constraints

This commit is contained in:
Etienne Kneuss 2010-11-03 15:40:24 +00:00
parent 823d7cb55f
commit 105db96e78
2 changed files with 45 additions and 2 deletions

View file

@ -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==

View file

@ -2956,8 +2956,9 @@ static zend_bool zend_do_perform_implementation_check(const zend_function *fe, c
return 0; return 0;
} }
if ((fe->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) != /* by-ref constraints on return values are covariant */
(proto->common.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { if ((proto->common.fn_flags & ZEND_ACC_RETURN_REFERENCE)
&& !(fe->common.fn_flags & ZEND_ACC_RETURN_REFERENCE)) {
return 0; return 0;
} }
@ -2981,6 +2982,8 @@ static zend_bool zend_do_perform_implementation_check(const zend_function *fe, c
/* Incompatible type hint */ /* Incompatible type hint */
return 0; 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) { if (fe->common.arg_info[i].pass_by_reference != proto->common.arg_info[i].pass_by_reference) {
return 0; return 0;
} }