Skip to content

Prevent exception widening in overridden methods (LSP-compliant @throws types) #13649

@SplotyCode

Description

@SplotyCode

Feature request

PHPStan (even with missingCheckedExceptionInThrows enabled) allows an implementation/override to declare a wider exception type than its interface or parent. This violates the Liskov Substitution Principle: if an interface promises only LogicException, an implementation must not declare or effectively throw Exception.

interface Foo {
    /**
     * @throws LogicException
     */
    public function run(): void;
}

final class Bar implements Foo {
    /**
     * @throws Exception // ← wider than LogicException
     */
    public function run(): void {
        throw new Exception('boom'); // also too wide
    }
}

PHPStan should report an error when an overriding method’s @throws includes any type that is not the same as or a subtype of a parent-declared thrown type. Narrowing (e.g., InvalidArgumentException for LogicException) is fine; widening (Exception|LogicException, Throwable, Exception) should fail.

Adding a check would allow fewer surprising runtime failures for callers relying on the interface’s narrower @throws.

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

PHPStan often helps me catch contract violations again today. This feature would make it even more consistent and delightful to use

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions