vimeo / psalm

A static analysis tool for finding errors in PHP applications
https://psalm.dev
MIT License
5.55k stars 661 forks source link

Array type with contiguous int keys is forced to a list type, considered incompatible with property type declaration #10392

Open Xerkus opened 10 months ago

Xerkus commented 10 months ago

Psalm forces array with contiguous int keys starting from 0 to be a list which leads to false positive errors.

https://psalm.dev/r/1c5e5eacb6

In the wild this false positive is encountered here https://github.com/laminas/laminas-component-installer/blob/946b6c36faad0694d386750385006c384f4e0410/src/ComponentInstaller.php#L422-L433 :

    /**
     * Map of known package types to composer config keys.
     */
    private const PACKAGE_TYPES = [
        InjectorInterface::TYPE_CONFIG_PROVIDER => 'config-provider',
        InjectorInterface::TYPE_COMPONENT       => 'component',
        InjectorInterface::TYPE_MODULE          => 'module',
    ];

    /**
     * Marshal a collection of defined package types.
     *
     * @param ComposerExtraComponentInstallerArrayType $extra extra.laminas value
     * @return Collection<InjectorInterface::TYPE_*,non-empty-string>
     */
    private function marshalPackageTypes(array $extra): Collection
    {
        // Create a collection of types registered in the package.
        return (new Collection(self::PACKAGE_TYPES))
            ->filter(fn(string $configKey) => isset($extra[$configKey]));
    }
ERROR: InvalidReturnType - src/ComponentInstaller.php:426:16 - The declared return type
  'Laminas\ComponentInstaller\Collection<0|1|2|3|4, non-empty-string>' for
  Laminas\ComponentInstaller\ComponentInstaller::marshalPackageTypes is incorrect,
  got 'Laminas\ComponentInstaller\Collection<int<0, 2>, 'component'|'config-provider'|'module'>' (see https://psalm.dev/011)
     * @return Collection<InjectorInterface::TYPE_*,non-empty-string>
psalm-github-bot[bot] commented 10 months ago

I found these snippets:

https://psalm.dev/r/1c5e5eacb6 ```php */ private const PACKAGE_TYPES = [ self::TYPE_CONFIG_PROVIDER => 'config-provider', self::TYPE_COMPONENT => 'component', self::TYPE_MODULE => 'module', ]; } ``` ``` Psalm output (using commit 5095f4e): ERROR: InvalidConstantAssignmentValue - 14:19 - ComponentInstaller::PACKAGE_TYPES with declared type array cannot be assigned type list{'config-provider', 'component', 'module'} ```
Xerkus commented 10 months ago

Changing order around to ensure it won't pass array_is_list check errors goes away

https://psalm.dev/r/568ea4fc1a

psalm-github-bot[bot] commented 10 months ago

I found these snippets:

https://psalm.dev/r/568ea4fc1a ```php */ private const PACKAGE_TYPES = [ self::TYPE_COMPONENT => 'component', self::TYPE_CONFIG_PROVIDER => 'config-provider', self::TYPE_MODULE => 'module', ]; } ``` ``` Psalm output (using commit 5095f4e): No issues! ```