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

Double coalescing confuses array analyser #9174

Open
someniatko opened this issue Jan 24, 2023 · 9 comments
Open

Double coalescing confuses array analyser #9174

someniatko opened this issue Jan 24, 2023 · 9 comments

Comments

@someniatko
Copy link
Contributor

someniatko commented Jan 24, 2023

https://psalm.dev/r/fa647867eb
Upd: reproducer without using explode: https://psalm.dev/r/97e3b85fac

Should report no issue in both functions.

The bug has been introduced sometime after 5.4.0.
Upd: the explode types refinement has been introduced in 5.5.0 by #9016 which exposed the bug, but the bug itself most probably existed way before the 5.4.0.

@psalm-github-bot
Copy link

psalm-github-bot bot commented Jan 24, 2023

I found these snippets:

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

function doubleCoalesce(?string $param): string {
    return explode(':', $param ?? '', 2)[1] ?? '';
}

function singleCoalesce(string $param): string {
    return explode(':', $param, 2)[1] ?? '';
}
Psalm output (using commit e784128):

ERROR: PossiblyUndefinedArrayOffset - 4:12 - Possibly undefined array key  on list{0: string, 1?: string}

@Boldewyn
Copy link

I’ve been biten by this bug, too. Upgrading from 5.4.0 to 5.6.0 left me with a PossiblyUndefinedArrayOffset for code that looks like this:

<?php

function test(string $input) : void {
    if (strpos($input, '=') === false) {
        return;
    }
    list($key, $value) = explode('=', $input, 2); # ! here I know that explode returns
                                                  # an array of length 2, but Psalm reports an error
}

test('a=b');

@weirdan
Copy link
Collaborator

weirdan commented Jan 25, 2023

@Boldewyn that's beyond Psalm's understanding, so you need to help it a bit: https://psalm.dev/r/3140be0736

It doesn't seem to have anything to do with the original report though.

@psalm-github-bot
Copy link

I found these snippets:

https://psalm.dev/r/3140be0736
<?php

function test(string $input) : void {
    if (strpos($input, '=') === false) {
        return;
    }
    $v = explode('=', $input, 2); 
    assert(count($v) === 2);
    list($_key, $_value) = $v;
}

test('a=b');
Psalm output (using commit aec0edc):

No issues!

@Boldewyn
Copy link

OK, understood! Thank you!

It just happens that psalm started to report these lines in versions > 5.4.0, and the snippet in the original post seemed to match somewhat the case I saw.

@someniatko
Copy link
Contributor Author

someniatko commented Jan 26, 2023

@Boldewyn It seems the thing which is introduced in 5.5.0 is not the bug itself, but rather the new feature - better types of explode function, done in #9016

And that feature probably just exposed the already existing bug I'm reporting here. And this is also the reason why you too get the error which you didn't earlier.

@someniatko someniatko changed the title Double coalescing confuses explode analyser Double coalescing confuses array analyser Jan 26, 2023
@someniatko
Copy link
Contributor Author

someniatko commented Jan 26, 2023

I have updated the issue title and the first message description. Provided there a reproducer which does not rely on explode types.

@orklah
Copy link
Collaborator

orklah commented Feb 1, 2023

Hum, weird, doc says that null coalescing should suppress the error: https://psalm.dev/docs/running_psalm/issues/PossiblyUndefinedArrayOffset/

https://psalm.dev/r/97e3b85fac (I posted your snippet again for better triage)

@psalm-github-bot
Copy link

I found these snippets:

https://psalm.dev/r/97e3b85fac
<?php

/** @return list{0: string, 1?: string} */
function returnOneOrTwoVals(string $param): array {
    return $param === 'two' ? [ $param, $param ] : [ $param ] ;
}

function doubleCoalesce(?string $param): string {
    return returnOneOrTwoVals($param ?? '')[1] ?? '';
}

function singleCoalesce(string $param): string {
    return returnOneOrTwoVals($param)[1] ?? '';
}
Psalm output (using commit d7e9cbc):

ERROR: PossiblyUndefinedArrayOffset - 9:12 - Possibly undefined array key  on list{0: string, 1?: string}

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

No branches or pull requests

4 participants