Skip to content

Commit

Permalink
Fixed bug #81582
Browse files Browse the repository at this point in the history
If __toString() comes from a trait, implement Stringable during
inheritance.
  • Loading branch information
nikic committed Nov 4, 2021
1 parent f22f4af commit d393268
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 0 deletions.
4 changes: 4 additions & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@ PHP NEWS
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
?? ??? 2021, PHP 8.0.14

- Core:
. Fixed bug #81582 (Stringable not implicitly declared if __toString() came
from a trait). (Nikita)

- GD:
. Fixed bug #71316 (libpng warning from imagecreatefromstring). (cmb)

Expand Down
20 changes: 20 additions & 0 deletions Zend/tests/stringable_trait.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
--TEST--
Bug #81582: Stringable not implicitly declared if __toString() came from a trait
--FILE--
<?php

trait T {
public function __toString(): string {
return "ok";
}
}

class C {
use T;
}

var_dump(new C instanceof Stringable);

?>
--EXPECT--
bool(true)
20 changes: 20 additions & 0 deletions Zend/tests/stringable_trait_invalid.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
--TEST--
__toString() from trait with invalid return type
--FILE--
<?php

trait T {
public function __toString(): int {
return "ok";
}
}

class C {
use T;
}

var_dump(new C instanceof Stringable);

?>
--EXPECTF--
Fatal error: Declaration of T::__toString(): int must be compatible with Stringable::__toString(): string in %s on line %d
12 changes: 12 additions & 0 deletions Zend/zend_inheritance.c
Original file line number Diff line number Diff line change
Expand Up @@ -2485,6 +2485,18 @@ ZEND_API zend_result zend_do_link_class(zend_class_entry *ce, zend_string *lc_pa
zend_verify_abstract_class(ce);
}

/* Normally Stringable is added during compilation. However, if it is important from a trait,

This comment has been minimized.

Copy link
@cmb69

cmb69 Nov 4, 2021

Contributor

typo: important → imported

* we need to explicilty add the interface here. */
if (ce->__tostring && !zend_class_implements_interface(ce, zend_ce_stringable)) {
ZEND_ASSERT(ce->__tostring->common.fn_flags & ZEND_ACC_TRAIT_CLONE);
ce->ce_flags |= ZEND_ACC_RESOLVED_INTERFACES;
ce->num_interfaces++;
ce->interfaces = perealloc(ce->interfaces,
sizeof(zend_class_entry *) * ce->num_interfaces, ce->type == ZEND_INTERNAL_CLASS);
ce->interfaces[ce->num_interfaces - 1] = zend_ce_stringable;
do_interface_implementation(ce, zend_ce_stringable);
}

zend_build_properties_info_table(ce);

if (!(ce->ce_flags & ZEND_ACC_UNRESOLVED_VARIANCE)) {
Expand Down

0 comments on commit d393268

Please sign in to comment.