psalm icon indicating copy to clipboard operation
psalm copied to clipboard

Disjointed array shape blocks non-empty-array

Open robchett opened this issue 1 year ago • 4 comments

https://psalm.dev/r/d92d35a175

Is there a correct way of asserting to Psalm that array{A?: 'A', B?: 'B'} is in fact non-empty-array?

robchett avatar Jan 26 '24 17:01 robchett

I found these snippets:

https://psalm.dev/r/d92d35a175
<?php

    /**
     * @return non-empty-array<string, string>|true
     */
  function run_count(): array|bool
    {
      
        $out = [];
      	if (rand(0,1)) {
            $out['A'] = 'A';
        }
      	if (rand(0,1)) {
            $out['B'] = 'B';
        }

        return count($out) === 0 ? true : $out;
    }


    /**
     * @return non-empty-array<string, string>|true
     */
  function run_empty(): array|bool
    {
      
        $out = [];
      	if (rand(0,1)) {
            $out['A'] = 'A';
        }
      	if (rand(0,1)) {
            $out['B'] = 'B';
        }

        return empty($out) ? true : $out;
    }

    /**
     * @return non-empty-array<string, string>|true
     */
  function run_equality(): array|bool
    {
      
        $out = [];
      	if (rand(0,1)) {
            $out['A'] = 'A';
        }
      	if (rand(0,1)) {
            $out['B'] = 'B';
        }

        return $out == [] ? true : $out;
    }
Psalm output (using commit 3c90054):

INFO: LessSpecificReturnStatement - 17:16 - The type 'array{A?: 'A', B?: 'B'}|true' is more general than the declared return type 'non-empty-array<string, string>|true' for run_count

INFO: MoreSpecificReturnType - 4:16 - The declared return type 'non-empty-array<string, string>|true' for run_count is more specific than the inferred return type 'array{A?: 'A', B?: 'B'}|true'

INFO: LessSpecificReturnStatement - 35:16 - The type 'array{A?: 'A', B?: 'B'}|true' is more general than the declared return type 'non-empty-array<string, string>|true' for run_empty

INFO: MoreSpecificReturnType - 22:16 - The declared return type 'non-empty-array<string, string>|true' for run_empty is more specific than the inferred return type 'array{A?: 'A', B?: 'B'}|true'

INFO: LessSpecificReturnStatement - 52:16 - The type 'array{A?: 'A', B?: 'B'}|true' is more general than the declared return type 'non-empty-array<string, string>|true' for run_equality

INFO: MoreSpecificReturnType - 39:16 - The declared return type 'non-empty-array<string, string>|true' for run_equality is more specific than the inferred return type 'array{A?: 'A', B?: 'B'}|true'

psalm-github-bot[bot] avatar Jan 26 '24 17:01 psalm-github-bot[bot]

Also fails if the outputs are fully independent https://psalm.dev/r/c39f3c8c05

robchett avatar Jan 26 '24 17:01 robchett

I found these snippets:

https://psalm.dev/r/c39f3c8c05
<?php

    /**
     * @return non-empty-array<string, string>|true
     */
  function run_count(): array|bool
    {
        if (rand(0,1)) {
            return ['A' => 'A'];
        }
      	if (rand(0,1)) {
            return ['B' => 'B'];
        }
        return true;
    }
Psalm output (using commit 3c90054):

INFO: MoreSpecificReturnType - 4:16 - The declared return type 'non-empty-array<string, string>|true' for run_count is more specific than the inferred return type 'array{A?: 'A', B?: 'B'}|true'

psalm-github-bot[bot] avatar Jan 26 '24 17:01 psalm-github-bot[bot]

Not possible currently, see https://github.com/vimeo/psalm/issues/9413

kkmuffme avatar Feb 01 '24 19:02 kkmuffme