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鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

throwing closure not cascaded to main function #9935

Closed
etienneroudeix opened this issue Sep 28, 2023 · 3 comments
Closed

throwing closure not cascaded to main function #9935

etienneroudeix opened this issue Sep 28, 2023 · 3 comments

Comments

@etienneroudeix
Copy link

Bug report

Hi there 馃憢

My PHPstan version is : 1.10.35

My phpstan config is :

includes:
	- phpstan-baseline.neon
	- vendor/phpstan/phpstan/conf/bleedingEdge.neon

parameters:
	level: 9
	paths:
		- src

	exceptions:
		check:
			missingCheckedExceptionInThrows: true
			tooWideThrowType: true

I'm facing the following problem, I have a closure explicitly throwing an exception.

This closure is passed to a wider function (call), which expects a closure as a param and the closure could throw anything.

However, when I call this wider function (from main), I wish I can document that main could throw the closure exceptions but I cannot.

<?php

declare(strict_types=1);

class Foo
{
    /**
     * @throws \ArgumentCountError
     */
    public function main(int $value): void
    {
        $this->call(fn () => $this->callback($value));
    }

    /**
     * @param \Closure(): void $closure
     */
    protected function call(\Closure $closure): void
    {
        $closure();
    }

    /**
     * @throws \ArgumentCountError
     */
    protected function callback(int $value): void
    {
        if ($value > 5) {
            throw new \ArgumentCountError();
        }
    }
}

And PHPStan tells me :

Method Foo::main() has ArgumentCountError in PHPDoc @throws tag but it's not thrown.

I guess it's a problem with tooWideThrowType rule and I am pretty sure it should not happen.

I feel like I am missing an instruction to either

  • say that my function call is throwing whatever $closure is throwing
  • say that my function call parameter $closure is throwing something

Note : I have a (very not elegant) workaround using :

    /**
     * @throws \ArgumentCountError
     */
    public function main(int $value): void
    {
        /**
         * @throws \ArgumentCountError
         */
        $this->call(fn () => $this->callback($value));
    }

Code snippet that reproduces the problem

https://phpstan.org/r/57ddea74-f72f-4063-9f79-d5caee6849f2

Expected output

鈿狅笍 snipper is fine since I cannot enable tooWideThrowType rule

Method Foo::main() has ArgumentCountError in PHPDoc @throws tag but it's not thrown.

I guess it's a problem with tooWideThrowType rule and I am pretty sure it should not happen.

Did PHPStan help you today? Did it make you happy in any way?

Yes ! Big yes ! Thank you for this awesome product !

@ondrejmirtes
Copy link
Member

See #5001 and phpstan/phpstan-src#2066.

The problem is that we don' know call will call the closure immediately. Your workaround with inline @throws is good enough.

@janedbal
Copy link
Contributor

See #5001 (comment), that might help you

Copy link

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Nov 11, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants