Allow @throws annotation in base classes for exceptions not actually thrown
Bug report
A method in a base class may be annotated with @throws SomeException to express that derived classes are allowed to throw such exceptions:
abstract class Base { /** * @throws \LogicException */ public function f(): void { } } class Derived extends Base { public function f(): void { throw new \LogicException(); } }
This informs users of the base class that code calling the method has to expect the exception:
function g(Base $obj): void { try { $obj->f(); } catch (\LogicException $e) { // Not a dead catch: Base::f itself doesn't throw, // but it may be overridden to throw } }
However, PhpStan reports the @throws annotation as an error:
Method Base::f() has LogicException in PHPDoc @throws tag but it's not thrown.
Some thoughts around this:
- A class which is not
finalis a slight hint that this situation may happen. 'Slight hint' refers to the fact that most code bases do not usefinalconsistently. I think this is the most important curlpit here. - A class which is tagged as
abstractis a stronger hint that this may happen. - A class tagged as
finalwould disallow overriding the method, making the error message valid. - Same applies to
finalon the method. - And to
privatemethods.
Code snippet that reproduces the problem
https://phpstan.org/r/f7f8735c-2620-4cfa-88e1-f4442f36214f
Expected output
No error reported.
Did PHPStan help you today? Did it make you happy in any way?
No response