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

Incorrect PossiblyUndefinedVariable after consecutive if statement blocks #8157

Closed
colin-saunders-bluefruit opened this issue Jun 24, 2022 · 5 comments

Comments

@colin-saunders-bluefruit

Vimeo appears to not follow through all the potential code branches to work out that variable will be set it all cases.

Involves try/throw/catch so wondered if it was related to #7688 but in the snippet provided you will see that it is working with exceptions - the charlie case. It seems to get confused by two consecutive if statements in the delta case.

https://psalm.dev/r/19db0757ab

Note: I currently have psalm configured at level 3 so the snippet includes 2 issues which I hadn't seen before but may, I think, be related to the PossiblyUndefinedVariable issue.

@psalm-github-bot
Copy link

I found these snippets:

https://psalm.dev/r/19db0757ab
<?php

namespace App\Application;

use Doctrine\ORM\Query\Expr;
use Exception;

class Test
{
    public function alpha() : string
    {
        try
        {
            $response = 'OK';
        }
        catch (Exception $ex)
        {
            $response = 'Exception';
        }
        
        return $response;
    }

    public function bravo(bool $ok) : string
    {
        try
        {
            if ($ok)
            {
                $response = 'OK';
            }
            else
            {
                $response = 'Problem';
            }
        }
        catch (Exception $ex)
        {
            $response = 'Exception';
        }
        
        return $response;
    }

    public function charlie(bool $submitted, bool $valid) : string
    {
        try
        {
            if ($submitted)
            {
                if ($valid)
                {
                    $response = 'Close';
                }
                else
                {
                    throw new Exception("Invalid");
                }
            }
            else
            {
                $response = 'Form';
            }
        }
        catch (Exception $ex)
        {
            $response = 'Exception';
        }
        
        return $response;
    }

    public function delta(bool $submitted, bool $valid) : string
    {
        try
        {
            $showForm = true;
            $formInfo = array();
            
            if ($submitted)
            {
                if ($valid)
                {
                    $response = 'Close';
                    $showForm = false;
                }
                else
                {
                    throw new Exception("Invalid");
                }
            }
            else
            {
                $formInfo[] = '123';
            }
            
            if ($showForm)
            {
                $response = 'Form' . json_encode($formInfo);
            }
        }
        catch (Exception $ex)
        {
            $response = 'Exception';
        }
        
        return $response;
    }

}
Psalm output (using commit cbc597f):

INFO: PossiblyUndefinedVariable - 107:16 - Possibly undefined variable $response, first seen on line 84

INFO: MixedReturnStatement - 107:16 - Could not infer a return type

INFO: MixedInferredReturnType - 73:59 - Could not verify return type 'string' for App\Application\Test::delta

@AndrolGenhald
Copy link
Collaborator

Reproduced without the try/catch: https://psalm.dev/r/7c174098a1
Further simplified: https://psalm.dev/r/f5087b6b3c

I think this is similar to a few other open issues, the difficulty is that Psalm would have to understand the relation between $submitted, $response, and $showForm.

@psalm-github-bot
Copy link

I found these snippets:

https://psalm.dev/r/7c174098a1
<?php

function test(bool $submitted, bool $valid): string
{
	$showForm = true;
    $formInfo = array();

    if ($submitted)
    {
        if ($valid)
        {
            $response = 'Close';
            $showForm = false;
        }
        else
        {
            throw new Exception("Invalid");
        }
    }
    else
    {
        $formInfo[] = '123';
    }

    if ($showForm)
    {
        $response = 'Form' . json_encode($formInfo);
	}
    
    return $response;
}
Psalm output (using commit f2f211c):

INFO: PossiblyUndefinedVariable - 30:12 - Possibly undefined variable $response, first seen on line 12

INFO: MixedReturnStatement - 30:12 - Could not infer a return type

INFO: MixedInferredReturnType - 3:46 - Could not verify return type 'string' for test
https://psalm.dev/r/f5087b6b3c
<?php

function test(bool $submitted, bool $valid): ?string
{
	$showForm = true;

    if ($submitted) {
        if ($valid) {
            $response = "foo";
            $showForm = false;
        } else {
            return null;
        }
    }

    if ($showForm) {
        $response = "bar";
	}
    
    return $response;
}
Psalm output (using commit f2f211c):

INFO: PossiblyUndefinedVariable - 20:12 - Possibly undefined variable $response, first seen on line 9

INFO: MixedReturnStatement - 20:12 - Could not infer a return type

INFO: MixedInferredReturnType - 3:46 - Could not verify return type 'null|string' for test

@orklah
Copy link
Collaborator

orklah commented Jun 25, 2022

@AndrolGenhald note that in your repro, initializing the variable first resolves the issue. But yeah, basically, this is horrible for Psalm (and I'd also argue that I'd hate to be the dev debugging that particular code)

@colin-saunders-bluefruit
Copy link
Author

Thanks for the responses.

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

3 participants