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

Wrong MixedArgumentTypeCoercion #10964

Open
loevgaard opened this issue May 7, 2024 · 1 comment
Open

Wrong MixedArgumentTypeCoercion #10964

loevgaard opened this issue May 7, 2024 · 1 comment

Comments

@loevgaard
Copy link

I have this class:

<?php

declare(strict_types=1);

namespace Setono\ClientBundle\MetadataProvider;

use Doctrine\Persistence\ManagerRegistry;
use Setono\Client\Metadata;
use Setono\ClientBundle\Client\LazyChangeAwareMetadata;
use Setono\ClientBundle\Entity\MetadataInterface;
use Setono\Doctrine\ORMTrait;

final class DoctrineOrmBasedMetadataProvider implements MetadataProviderInterface
{
    use ORMTrait;

    public function __construct(
        private readonly MetadataProviderInterface $decorated,
        ManagerRegistry $managerRegistry,
        /**
         * @var class-string<MetadataInterface> $metadataEntityClass
         */
        private readonly string $metadataEntityClass,
    ) {
        $this->managerRegistry = $managerRegistry;
    }

    public function getMetadata(string $clientId): Metadata
    {
        $manager = $this->getManager($this->metadataEntityClass);

        return LazyChangeAwareMetadata::createLazyGhost(function (Metadata $instance) use ($clientId, $manager): void {
            /** @var MetadataInterface|null $entity */
            $entity = $manager->find($this->metadataEntityClass, $clientId);

            if (null === $entity) {
                /** @psalm-trace $metadata */
                $metadata = $this->decorated->getMetadata($clientId)->toArray();
            } else {
                /** @psalm-trace $metadata */
                $metadata = $entity->getMetadata();
            }

            /** @psalm-suppress DirectConstructorCall */
            $instance->__construct($metadata);
        });
    }
}

It outputs this:

ERROR: Trace - src/MetadataProvider/DoctrineOrmBasedMetadataProvider.php:38:17 - $metadata: array{__expires?: array<string, int>, ...<string, mixed>} (see https://psalm.dev/224)
                /** @psalm-trace $metadata */
                $metadata = $this->decorated->getMetadata($clientId)->toArray();


ERROR: Trace - src/MetadataProvider/DoctrineOrmBasedMetadataProvider.php:41:17 - $metadata: array{__expires?: array<string, int>, ...<string, mixed>} (see https://psalm.dev/224)
                /** @psalm-trace $metadata */
                $metadata = $entity->getMetadata();


ERROR: MixedArgumentTypeCoercion - src/MetadataProvider/DoctrineOrmBasedMetadataProvider.php:45:36 - Argument 1 of Setono\Client\Metadata::__construct expects array{__expires?: array<string, int>, ...<string, mixed>}, but parent type array{__expires?: array<string, int>|mixed, ...<string, mixed>} provided (see https://psalm.dev/194)
            $instance->__construct($metadata);

I can't get this around my head. Both traces says that $metadata has the correct type, however, the error says it's not. How is this possible? :D

Copy link

Hey @loevgaard, can you reproduce the issue on https://psalm.dev? These will be used as phpunit tests when implementing the feature or fixing this bug.

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

No branches or pull requests

1 participant