Skip to content

instanceof ベースの絞り込みで Result の型引数が失われる(PHPStan の制限) #83

Description

@valbeat

概要

Result<int, RuntimeException>instanceof Ok / instanceof Err で絞り込むと、PHPStan は型引数を失った Ok / Err(型引数なし)に絞り込み、unwrap() / unwrapErr()mixed になる。

isOk() / isErr()@phpstan-assert-if-true Ok<T> $this)経由なら Ok<int> / Err<RuntimeException> が保たれる。

再現

/** @param Result<int, RuntimeException> $result */
function f(Result $result): void
{
    if ($result instanceof Ok) {
        // actual: Valbeat\Result\Ok(型引数なし)、unwrap() は mixed
    }
    if ($result->isOk()) {
        // actual: Valbeat\Result\Ok<int>、unwrap() は int
    }
}

Ok<T> implements Result<T, never>@template-covariant@phpstan-sealed は宣言済みであり、Result<int, E> のサブタイプである Ok は論理的に Ok<int> しかあり得ないため、Ok<int> への絞り込みは健全。PHPStan が instanceof で逆方向のテンプレート解決をしないことが原因(PHPStan 2.2.2 で実測)。

対応状況

アップストリーム関連 issue

Metadata

Metadata

Assignees

Labels

No labels
No labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions