1
0
mirror of https://github.com/danog/psalm.git synced 2025-01-21 21:31:13 +01:00

Add support for Stringable

This commit is contained in:
Matt Brown 2020-10-04 00:17:16 -04:00
parent ec3501b244
commit d532133325
2 changed files with 47 additions and 12 deletions

View File

@ -495,19 +495,33 @@ class AtomicTypeComparator
if ($container_type_part instanceof TString || $container_type_part instanceof TScalar) {
if ($input_type_part instanceof TNamedObject) {
// check whether the object has a __toString method
if ($codebase->classOrInterfaceExists($input_type_part->value)
&& $codebase->methods->methodExists(
new \Psalm\Internal\MethodIdentifier(
$input_type_part->value,
'__tostring'
)
)
) {
if ($atomic_comparison_result) {
$atomic_comparison_result->to_string_cast = true;
if ($codebase->classOrInterfaceExists($input_type_part->value)) {
if ($codebase->php_major_version >= 8
&& ($input_type_part->value === 'Stringable'
|| ($codebase->classlikes->classExists($input_type_part->value)
&& $codebase->classlikes->classImplements($input_type_part->value, 'Stringable'))
|| $codebase->classlikes->interfaceExtends($input_type_part->value, 'Stringable'))
) {
if ($atomic_comparison_result) {
$atomic_comparison_result->to_string_cast = true;
}
return true;
}
return true;
if ($codebase->methods->methodExists(
new \Psalm\Internal\MethodIdentifier(
$input_type_part->value,
'__tostring'
)
)
) {
if ($atomic_comparison_result) {
$atomic_comparison_result->to_string_cast = true;
}
return true;
}
}
// PHP 5.6 doesn't support this natively, so this introduces a bug *just* when checking PHP 5.6 code

View File

@ -145,8 +145,29 @@ class ToStringTest extends TestCase
if (is_callable([$object, \'__toString\'])) {
$a = (string) $object;
echo $a;
}'
],
'stringableInterface' => [
'<?php
interface Foo extends Stringable {}
function takesString(string $s) : void {}
function takesFoo(Foo $foo) : void {
/** @psalm-suppress ImplicitToStringCast */
takesString($foo);
}
'
class FooImplementer implements Foo {
public function __toString() : string {
return "hello";
}
}
takesFoo(new FooImplementer());',
[],
[],
'8.0'
],
];
}