mirror of
https://github.com/php/php-src.git
synced 2025-08-16 14:08:47 +02:00
Don't implement Stringable on traits
Traits do not support interfaces, so we should not implement Stringable on them. Also check the __toString() return type in the same way other magic methods do, otherwise we would now miss the check in the trait case.
This commit is contained in:
parent
7e67366a9b
commit
d478ae73b1
6 changed files with 25 additions and 10 deletions
|
@ -8,4 +8,4 @@ class Foo {
|
||||||
}
|
}
|
||||||
?>
|
?>
|
||||||
--EXPECTF--
|
--EXPECTF--
|
||||||
Fatal error: Declaration of Foo::__toString(): bool must be compatible with Stringable::__toString(): string in %s on line %d
|
Fatal error: Foo::__toString(): Return type must be string when declared in %s on line %d
|
||||||
|
|
|
@ -8,13 +8,31 @@ trait T {
|
||||||
return "ok";
|
return "ok";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
trait T2 {
|
||||||
|
use T;
|
||||||
|
}
|
||||||
|
|
||||||
class C {
|
class C {
|
||||||
use T;
|
use T;
|
||||||
}
|
}
|
||||||
|
class C2 {
|
||||||
|
use T2;
|
||||||
|
}
|
||||||
|
|
||||||
var_dump(new C instanceof Stringable);
|
var_dump(new C instanceof Stringable);
|
||||||
|
var_dump(new C2 instanceof Stringable);
|
||||||
|
|
||||||
|
// The traits themselves should not implement Stringable -- traits cannot implement interfaces.
|
||||||
|
$rc = new ReflectionClass(T::class);
|
||||||
|
var_dump($rc->getInterfaceNames());
|
||||||
|
$rc = new ReflectionClass(T2::class);
|
||||||
|
var_dump($rc->getInterfaceNames());
|
||||||
|
|
||||||
?>
|
?>
|
||||||
--EXPECT--
|
--EXPECT--
|
||||||
bool(true)
|
bool(true)
|
||||||
|
bool(true)
|
||||||
|
array(0) {
|
||||||
|
}
|
||||||
|
array(0) {
|
||||||
|
}
|
||||||
|
|
|
@ -9,12 +9,6 @@ trait T {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class C {
|
|
||||||
use T;
|
|
||||||
}
|
|
||||||
|
|
||||||
var_dump(new C instanceof Stringable);
|
|
||||||
|
|
||||||
?>
|
?>
|
||||||
--EXPECTF--
|
--EXPECTF--
|
||||||
Fatal error: Declaration of T::__toString(): int must be compatible with Stringable::__toString(): string in %s on line %d
|
Fatal error: T::__toString(): Return type must be string when declared in %s on line %d
|
||||||
|
|
|
@ -2233,6 +2233,7 @@ ZEND_API void zend_check_magic_method_implementation(const zend_class_entry *ce,
|
||||||
zend_check_magic_method_args(0, ce, fptr, error_type);
|
zend_check_magic_method_args(0, ce, fptr, error_type);
|
||||||
zend_check_magic_method_non_static(ce, fptr, error_type);
|
zend_check_magic_method_non_static(ce, fptr, error_type);
|
||||||
zend_check_magic_method_public(ce, fptr, error_type);
|
zend_check_magic_method_public(ce, fptr, error_type);
|
||||||
|
zend_check_magic_method_return_type(ce, fptr, error_type, MAY_BE_STRING);
|
||||||
} else if (zend_string_equals_literal(lcname, ZEND_DEBUGINFO_FUNC_NAME)) {
|
} else if (zend_string_equals_literal(lcname, ZEND_DEBUGINFO_FUNC_NAME)) {
|
||||||
zend_check_magic_method_args(0, ce, fptr, error_type);
|
zend_check_magic_method_args(0, ce, fptr, error_type);
|
||||||
zend_check_magic_method_non_static(ce, fptr, error_type);
|
zend_check_magic_method_non_static(ce, fptr, error_type);
|
||||||
|
|
|
@ -6817,7 +6817,8 @@ zend_string *zend_begin_method_decl(zend_op_array *op_array, zend_string *name,
|
||||||
}
|
}
|
||||||
|
|
||||||
zend_add_magic_method(ce, (zend_function *) op_array, lcname);
|
zend_add_magic_method(ce, (zend_function *) op_array, lcname);
|
||||||
if (zend_string_equals_literal(lcname, ZEND_TOSTRING_FUNC_NAME)) {
|
if (zend_string_equals_literal(lcname, ZEND_TOSTRING_FUNC_NAME)
|
||||||
|
&& !(ce->ce_flags & ZEND_ACC_TRAIT)) {
|
||||||
add_stringable_interface(ce);
|
add_stringable_interface(ce);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2487,7 +2487,8 @@ ZEND_API zend_result zend_do_link_class(zend_class_entry *ce, zend_string *lc_pa
|
||||||
|
|
||||||
/* Normally Stringable is added during compilation. However, if it is imported from a trait,
|
/* Normally Stringable is added during compilation. However, if it is imported from a trait,
|
||||||
* we need to explicilty add the interface here. */
|
* we need to explicilty add the interface here. */
|
||||||
if (ce->__tostring && !zend_class_implements_interface(ce, zend_ce_stringable)) {
|
if (ce->__tostring && !(ce->ce_flags & ZEND_ACC_TRAIT)
|
||||||
|
&& !zend_class_implements_interface(ce, zend_ce_stringable)) {
|
||||||
ZEND_ASSERT(ce->__tostring->common.fn_flags & ZEND_ACC_TRAIT_CLONE);
|
ZEND_ASSERT(ce->__tostring->common.fn_flags & ZEND_ACC_TRAIT_CLONE);
|
||||||
ce->ce_flags |= ZEND_ACC_RESOLVED_INTERFACES;
|
ce->ce_flags |= ZEND_ACC_RESOLVED_INTERFACES;
|
||||||
ce->num_interfaces++;
|
ce->num_interfaces++;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue