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

@psalm-assert should assert type after passing all never-returning branches #9661

Closed
fluffycondor opened this issue Apr 17, 2023 · 4 comments

Comments

@fluffycondor
Copy link
Contributor

fluffycondor commented Apr 17, 2023

https://psalm.dev/r/4150a3c1a7

It's safe to assume the type from @psalm-assert for $bar after passing all never-returning branches.

Expected: no errors.
Got: LessSpecificReturnStatement and MoreSpecificReturnType.

@psalm-github-bot
Copy link

I found these snippets:

https://psalm.dev/r/1e53bfa534
<?php

/**
 * @psalm-assert non-empty-string $bar
 * @return non-empty-string
 */
function foo(string $bar): string
{
    if (strlen($bar) < 4) {
        throw new RuntimeException();
    }
    
    // here $bar should be assumed as non-empty-string because of the @psalm-assert
    
    // of course one can do $bar = '' here, so assuming the type in the moment of returning it is unsafe
    // because the type a function asserts and the type the function returns can differ
    // but it's safe to assume the type from @psalm-assert for $bar after every never-returning branches 

    return $bar;
}
Psalm output (using commit a9bc87e):

INFO: LessSpecificReturnStatement - 19:12 - The type 'string' is more general than the declared return type 'non-empty-string' for foo

INFO: MoreSpecificReturnType - 5:12 - The declared return type 'non-empty-string' for foo is more specific than the inferred return type 'string'

@orklah
Copy link
Collaborator

orklah commented Apr 17, 2023

the strlen check should let Psalm infer that $bar is non-empty.

Aside from that, it's Psalm's job to check, not to assume you didn't make mistakes. It would be weird to automatically consider that the type is the correct one (and it would lead to a whole new set of issues to be emitted in case you want to force a bool to be a string through an assertion for example).

Your snippet is pretty weird too, why would you return $bar without changing it after asserting its type?

@kkmuffme
Copy link
Contributor

There is an issue for strlen already, see #7387.

The error is correct here, as it shouldn't make any assumptions. When checking for !== '' https://psalm.dev/r/97270ba09f

This issue can be closed.

@psalm-github-bot
Copy link

I found these snippets:

https://psalm.dev/r/97270ba09f
<?php

/**
 * @psalm-assert non-empty-string $bar
 * @return non-empty-string
 */
function foo(string $bar): string
{
    if ($bar === '') {
        throw new RuntimeException();
    }
    
    // here $bar should be assumed as non-empty-string because of the @psalm-assert
    
    // of course one can do $bar = '' here, so assuming the type in the moment of returning it is unsafe
    // because the type a function asserts and the type the function returns can differ
    // but it's safe to assume the type from @psalm-assert for $bar after passing all never-returning branches 

    return $bar;
}
Psalm output (using commit bebce06):

No issues!

@orklah orklah closed this as completed May 31, 2023
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

3 participants