Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Internal Psalm Error: Could not get class storage for <interface> #10350

Closed
ohader opened this issue Nov 6, 2023 · 1 comment · Fixed by #10720
Closed

Internal Psalm Error: Could not get class storage for <interface> #10350

ohader opened this issue Nov 6, 2023 · 1 comment · Fixed by #10720

Comments

@ohader
Copy link
Contributor

ohader commented Nov 6, 2023

Error Message using latest release vimeo/psalm:5.15.0

Uncaught InvalidArgumentException: Could not get class storage for sessionhandlerinterface in .../vendor/vimeo/psalm/src/Psalm/Internal/Provider/ClassLikeStorageProvider.php:45

This scenario occurred while analyzing \Symfony\Component\HttpFoundation\Session\Storage\Handler\MigratingSessionHandler.

I've created a simplified version at https://psalm.dev/r/4c29e2bae8

The problem seems to be related to using intersection types in class property declarations. Resolving that results in the mentioned Could not get class storage for <interface> error.

class Subject implements \JsonSerializable
{
    // @hint Demo: Remove the intersection type here to see how the error disappears
    // `Internal Psalm error on line 47 - /vendor/vimeo/psalm/src/Psalm/Internal/Provider/ClassLikeStorageProvider.php: Could not get class storage for jsonserializable`
    private \JsonSerializable&\Stringable $property;
...

Relevant stack trace

→ I'm guessing, that the TypeHintResolver is causing this when resolving intersection types

#0 .../vimeo/psalm/src/Psalm/Internal/Codebase/ClassLikes.php(723): Psalm\Internal\Provider\ClassLikeStorageProvider->get('sessionhandleri...')
#1 .../vimeo/psalm/src/Psalm/Internal/Codebase/ClassLikes.php(713): Psalm\Internal\Codebase\ClassLikes->getParentInterfaces('sessionhandleri...')
#2 .../vimeo/psalm/src/Psalm/Codebase.php(761): Psalm\Internal\Codebase\ClassLikes->interfaceExtends('sessionhandleri...', 'sessionupdateti...')
#3 .../vimeo/psalm/src/Psalm/Internal/Type/Comparator/ObjectComparator.php(358): Psalm\Codebase->interfaceExtends('sessionhandleri...', 'sessionupdateti...')
#4 .../vimeo/psalm/src/Psalm/Internal/Type/Comparator/ObjectComparator.php(118): Psalm\Internal\Type\Comparator\ObjectComparator::isIntersectionShallowlyContainedBy(Object(Psalm\Codebase), Object(Psalm\Type\Atomic\TNamedObject), Object(Psalm\Type\Atomic\TNamedObject), 'sessionupdateti...', false, false, NULL)
#5 .../vimeo/psalm/src/Psalm/Internal/Type/Comparator/AtomicTypeComparator.php(355): Psalm\Internal\Type\Comparator\ObjectComparator::isShallowlyContainedBy(Object(Psalm\Codebase), Object(Psalm\Type\Atomic\TNamedObject), Object(Psalm\Type\Atomic\TNamedObject), false, NULL)
#6 .../vimeo/psalm/src/Psalm/Type.php(870): Psalm\Internal\Type\Comparator\AtomicTypeComparator::isContainedBy(Object(Psalm\Codebase), Object(Psalm\Type\Atomic\TNamedObject), Object(Psalm\Type\Atomic\TNamedObject))
#7 .../vimeo/psalm/src/Psalm/Type.php(751): Psalm\Type::intersectAtomicTypes(Object(Psalm\Type\Atomic\TNamedObject), Object(Psalm\Type\Atomic\TNamedObject), Object(Psalm\Codebase), false)
#8 .../vimeo/psalm/src/Psalm/Internal/PhpVisitor/Reflector/TypeHintResolver.php(112): Psalm\Type::intersectUnionTypes(Object(Psalm\Type\Union), Object(Psalm\Type\Union), Object(Psalm\Codebase))
#9 .../vimeo/psalm/src/Psalm/Internal/PhpVisitor/Reflector/ClassLikeNodeScanner.php(1607): Psalm\Internal\PhpVisitor\Reflector\TypeHintResolver::resolve(Object(PhpParser\Node\IntersectionType), Object(Psalm\CodeLocation), Object(Psalm\Codebase), Object(Psalm\Storage\FileStorage), Object(Psalm\Storage\ClassLikeStorage), Object(Psalm\Aliases), 80125)
#10 .../vimeo/psalm/src/Psalm/Internal/PhpVisitor/Reflector/ClassLikeNodeScanner.php(766): Psalm\Internal\PhpVisitor\Reflector\ClassLikeNodeScanner->visitPropertyDeclaration(Object(PhpParser\Node\Stmt\Property), Object(Psalm\Config), Object(Psalm\Storage\ClassLikeStorage), 'Symfony\\Compone...')
Copy link

I found these snippets:

https://psalm.dev/r/4c29e2bae8
<?php
class Anything implements \JsonSerializable, \Stringable
{
    public function jsonSerialize(): array { return []; }
    public function __toString(): string { return ''; }
}

class Subject implements \JsonSerializable
{
	// @hint Resolve the union type here to resolve the error:
    // `Internal Psalm error on line 47 - /vendor/vimeo/psalm/src/Psalm/Internal/Provider/ClassLikeStorageProvider.php: Could not get class storage for jsonserializable`
    private \JsonSerializable&\Stringable $property;

    public function __construct()
    {
        $this->property = new Anything();
    }

    public function jsonSerialize(): array
    {
        return [];
    }
}
Psalm encountered an internal error:

/vendor/vimeo/psalm/src/Psalm/Internal/Provider/ClassLikeStorageProvider.php: Could not get class storage for jsonserializable

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
2 participants