← All results

stringable-object is a Psalm-only object refinement

Group: Advanced PHPDoc types · Category: ecosystem · File: phpdoc_advanced_psalm_stringable_object.php

stringable-object matches any object exposing __toString(). Psalm models it structurally; other analyzers do not recognize the keyword and fall back to accepting any object (or report an unknown type). References: - Psalm stringable-object maps to an object-with-__toString shape

Analyzer results

AnalyzerVersionResultDiagnostics
phan 6.0.7Phan 6.0.7 php-ast version 1.1.3 PHP version used to run Phan: 8.5.9 Unrecognized
phpdoc_advanced_psalm_stringable_object.php:31: Saw possibly unextractable annotation for a fragment of comment '* @param stringable-object $obj': after stringable, did not see an element name (will guess based on comment order) [PhanUnextractableAnnotationElementName]
phpdoc_advanced_psalm_stringable_object.php:31: Saw a token Phan may have failed to parse after '* @param stringable-object $obj': after stringable, saw '-' [PhanUnextractableAnnotationSuffix]
phpdoc_advanced_psalm_stringable_object.php:33: Parameter $obj has undeclared type \Conformance\Tests\PhpdocAdvancedPsalmStringableObject\stringable (Did you mean interface \Stringable) [PhanUndeclaredTypeParameter]
phpdoc_advanced_psalm_stringable_object.php:38: Argument 1 ($obj) is new WithToString() of type \Conformance\Tests\PhpdocAdvancedPsalmStringableObject\WithToString|\Stringable but \Conformance\Tests\PhpdocAdvancedPsalmStringableObject\acceptsStringable() takes \Conformance\Tests\PhpdocAdvancedPsalmStringableObject\stringable defined at /Users/megurine/repo/php/php-typing-conformance/conformance/tests/phpdoc_advanced_psalm_stringable_object.php:33 [PhanTypeMismatchArgument]
phpdoc_advanced_psalm_stringable_object.php:41: Argument 1 ($obj) is new WithoutToString() of type \Conformance\Tests\PhpdocAdvancedPsalmStringableObject\WithoutToString but \Conformance\Tests\PhpdocAdvancedPsalmStringableObject\acceptsStringable() takes \Conformance\Tests\PhpdocAdvancedPsalmStringableObject\stringable defined at /Users/megurine/repo/php/php-typing-conformance/conformance/tests/phpdoc_advanced_psalm_stringable_object.php:33 [PhanTypeMismatchArgument]
  • Recognition: spelling not resolved — reported on declaration line(s) 31, 33
  • Enforcement: 1/1 of the expected violations reported — incidental, since the spelling was not resolved
Expectation diff
Line 38: Expected valid value to be accepted, got ["Argument 1 ($obj) is new WithToString() of type \\Conformance\\Tests\\PhpdocAdvancedPsalmStringableObject\\WithToString|\\Stringable but \\Conformance\\Tests\\PhpdocAdvancedPsalmStringableObject\\acceptsStringable() takes \\Conformance\\Tests\\PhpdocAdvancedPsalmStringableObject\\stringable defined at /Users/megurine/repo/php/php-typing-conformance/conformance/tests/phpdoc_advanced_psalm_stringable_object.php:33 [PhanTypeMismatchArgument]"]
phpstan 2.2.8PHPStan - PHP Static Analysis Tool 2.2.8 Unrecognized
phpdoc_advanced_psalm_stringable_object.php:33: Function Conformance\Tests\PhpdocAdvancedPsalmStringableObject\acceptsStringable() has parameter $obj with no type specified. [identifier=missingType.parameter] [reported-from-level=6]
phpdoc_advanced_psalm_stringable_object.php:33: PHPDoc tag @param for parameter $obj contains unresolvable type. [identifier=parameter.unresolvableType] [reported-from-level=2]
With strict-rules
phpdoc_advanced_psalm_stringable_object.php:33: Function Conformance\Tests\PhpdocAdvancedPsalmStringableObject\acceptsStringable() has parameter $obj with no type specified. [identifier=missingType.parameter]
phpdoc_advanced_psalm_stringable_object.php:33: PHPDoc tag @param for parameter $obj contains unresolvable type. [identifier=parameter.unresolvableType]
  • Recognition: spelling not resolved — reported on declaration line(s) 33
  • Enforcement: 0/1 of the expected violations reported — incidental, since the spelling was not resolved
psalm 6.16.1Psalm 6.16.1@f1f5de594dc76faf8784e02d3dc4716c91c6f6ac
next: 7.0.0-beta19
Enforced
phpdoc_advanced_psalm_stringable_object.php:41: Argument 1 of Conformance\Tests\PhpdocAdvancedPsalmStringableObject\acceptsStringable expects object{__tostring()}, but Conformance\Tests\PhpdocAdvancedPsalmStringableObject\WithoutToString provided [InvalidArgument]
  • Recognition: spelling resolved
  • Enforcement: 1/1 of the expected violations reported
mago 1.46.0mago 1.46.0 Unrecognized
phpdoc_advanced_psalm_stringable_object.php:31: Could not resolve the type for the @param tag. [invalid-param-tag]
  • Recognition: spelling not resolved — reported on declaration line(s) 31
  • Enforcement: 0/1 of the expected violations reported — incidental, since the spelling was not resolved
mir 0.70.1mir 0.70.1 Not enforced

No diagnostics reported.

  • Recognition: spelling resolved
  • Enforcement: 0/1 of the expected violations reported
phpantom 0.9.0phpantom_lsp 0.9.0 Incidental (1/1)
phpdoc_advanced_psalm_stringable_object.php:38: Argument 1 ($obj) expects Conformance\Tests\PhpdocAdvancedPsalmStringableObject\stringable-object, got Conformance\Tests\PhpdocAdvancedPsalmStringableObject\WithToString [type_mismatch_argument]
phpdoc_advanced_psalm_stringable_object.php:41: Argument 1 ($obj) expects Conformance\Tests\PhpdocAdvancedPsalmStringableObject\stringable-object, got Conformance\Tests\PhpdocAdvancedPsalmStringableObject\WithoutToString [type_mismatch_argument]
  • Recognition: spelling resolved
  • Enforcement: 1/1 of the expected violations reported — incidental, since values the type admits were also rejected on line(s) 38
Expectation diff
Line 38: Expected valid value to be accepted, got ["Argument 1 ($obj) expects Conformance\\Tests\\PhpdocAdvancedPsalmStringableObject\\stringable-object, got Conformance\\Tests\\PhpdocAdvancedPsalmStringableObject\\WithToString [type_mismatch_argument]"]
intelephense 1.18.5intelephense 1.18.5 Not enforced

No diagnostics reported.

  • Recognition: spelling resolved
  • Enforcement: 0/1 of the expected violations reported
phpy 0.2.0phpy 0.2.0 Unrecognized
phpdoc_advanced_psalm_stringable_object.php:31: Use of unknown class: 'Conformance\Tests\PhpdocAdvancedPsalmStringableObject\stringable-object'
phpdoc_advanced_psalm_stringable_object.php:38: Argument '1' passed to Conformance\Tests\PhpdocAdvancedPsalmStringableObject\acceptsStringable() is expected to be of type Conformance\Tests\PhpdocAdvancedPsalmStringableObject\stringable-object, Conformance\Tests\PhpdocAdvancedPsalmStringableObject\WithToString given
phpdoc_advanced_psalm_stringable_object.php:41: Argument '1' passed to Conformance\Tests\PhpdocAdvancedPsalmStringableObject\acceptsStringable() is expected to be of type Conformance\Tests\PhpdocAdvancedPsalmStringableObject\stringable-object, Conformance\Tests\PhpdocAdvancedPsalmStringableObject\WithoutToString given
  • Recognition: spelling not resolved — reported on declaration line(s) 31
  • Enforcement: 1/1 of the expected violations reported — incidental, since the spelling was not resolved
Expectation diff
Line 38: Expected valid value to be accepted, got ["Argument '1' passed to Conformance\\Tests\\PhpdocAdvancedPsalmStringableObject\\acceptsStringable() is expected to be of type Conformance\\Tests\\PhpdocAdvancedPsalmStringableObject\\stringable-object, Conformance\\Tests\\PhpdocAdvancedPsalmStringableObject\\WithToString given"]
qodana 262.8665.325Qodana 262.8665.325 Unrecognized
phpdoc_advanced_psalm_stringable_object.php:31: Undefined class 'stringable-object' [PhpUndefinedClassInspection]
phpdoc_advanced_psalm_stringable_object.php:38: Parameter 'new WithToString()' type is not compatible with declaration [PhpParamsInspection]
phpdoc_advanced_psalm_stringable_object.php:41: Parameter 'new WithoutToString()' type is not compatible with declaration [PhpParamsInspection]
  • Recognition: spelling not resolved — reported on declaration line(s) 31
  • Enforcement: 1/1 of the expected violations reported — incidental, since the spelling was not resolved
Expectation diff
Line 38: Expected valid value to be accepted, got ["Parameter 'new WithToString()' type is not compatible with declaration [PhpParamsInspection]"]
noverify 0.5.5NoVerify, version 0.5.5: built on: 2025.04.22 14:36:46 OS: r-kuchinskas arm64 Commit: 4774b82f8adc53fbef38f95e97af4b953b4d1529 Unrecognized
phpdoc_advanced_psalm_stringable_object.php:31: Class or interface named \Conformance\Tests\PhpdocAdvancedPsalmStringableObject\stringable-object does not exist [undefinedClass]
  • Recognition: spelling not resolved — reported on declaration line(s) 31
  • Enforcement: 0/1 of the expected violations reported — incidental, since the spelling was not resolved
steins 0.1.5steins 0.1.5 (2026-08-12 revision 39b4cc1) Widened to a nonexistent-class reference

No diagnostics reported.

  • Recognition: spelling resolved
  • Enforcement: 0/1 of the expected violations reported

Notes: `stringable-object` has no `lower_identifier` entry, so it lowers through the catch-all to `ContractTy::Class("stringable-object")` — Steins has no `__toString`-presence fact to check against.

phpstan-strict 2.2.8PHPStan - PHP Static Analysis Tool 2.2.8 Unrecognized
phpdoc_advanced_psalm_stringable_object.php:33: Function Conformance\Tests\PhpdocAdvancedPsalmStringableObject\acceptsStringable() has parameter $obj with no type specified. [identifier=missingType.parameter]
phpdoc_advanced_psalm_stringable_object.php:33: PHPDoc tag @param for parameter $obj contains unresolvable type. [identifier=parameter.unresolvableType]
  • Recognition: spelling not resolved — reported on declaration line(s) 33
  • Enforcement: 0/1 of the expected violations reported — incidental, since the spelling was not resolved
psalm-next 7.0.0-beta19Psalm 7.0.0-beta19@7e751c06a756fa64dc4c759c09fe4a173afcb433 Enforced
phpdoc_advanced_psalm_stringable_object.php:41: Argument 1 of Conformance\Tests\PhpdocAdvancedPsalmStringableObject\acceptsStringable expects object{__tostring()}, but Conformance\Tests\PhpdocAdvancedPsalmStringableObject\WithoutToString provided [InvalidArgument]
  • Recognition: spelling resolved
  • Enforcement: 1/1 of the expected violations reported

Source

<?php

declare(strict_types=1);

namespace Conformance\Tests\PhpdocAdvancedPsalmStringableObject;

/**
 * `stringable-object` is a Psalm-only object refinement.
 *
 * `stringable-object` matches any object exposing `__toString()`. Psalm models
 * it structurally; other analyzers do not recognize the keyword and fall back
 * to accepting any object (or report an unknown type).
 *
 * References:
 * - Psalm `stringable-object` maps to an object-with-__toString shape
 */

final class WithToString
{
    public function __toString(): string
    {
        return 'x';
    }
}

final class WithoutToString
{
}

/**
 * @param stringable-object $obj
 */
function acceptsStringable($obj): void // T: stringable-object
{
}

// An object with __toString satisfies the parameter.
acceptsStringable(new WithToString()); // V

// An object without __toString is rejected by analyzers that model it.
acceptsStringable(new WithoutToString()); // E?: object without __toString is not a stringable-object