Skip to content

generator.valueType false positives: oversized-array generalization produces types that reject their own contributors #14560

@gnutix

Description

@gnutix

Filing this at @VincentLanglet's request on phpstan/phpstan-src#5568.

Summary

PHPStan 2.1.52+ produces generator.valueType false positives where a closure's inferred Generator value type rejects the very yields it was synthesised from. The oversized-array generalization in TypeCombinator::optimizeConstantArrays produces a type that is not a super-type of the variants it was derived from.

The error is self-inconsistent: PHPStan complains that each yielded value (with a perfectly valid concrete shape) does not match the Generator value type — but that inferred value type is synthesized from those very same yields. A function cannot legitimately yield a value its own inferred return type rejects; the oversized-array generalization step is producing a type that fails to be a super-type of its own contributors.

Symptom signature: the inferred type contains &oversized-array markers on shapes that are themselves empty (array{}&oversized-array) or fully-generalized array<intKey, V>&accessories mixed in the same union as preserved array{...}&oversized-array records.

Reproducer

https://phpstan.org/r/5b811780-35b4-4ebf-b2a6-cecb90f02b2b

(level: max, bleedingEdge: true, treatPhpDocTypesAsCertain: true.)

A standalone version with non-numeric-string yield keys is included in the PR's test data file: bug-yield-oversized-self-rejection.php.

Affected versions

Version Result
2.1.51 OK
2.1.52 9 errors (regression)
2.1.53 9 errors
2.1.54 9 errors (still broken)
with #5568 0 errors

Introduced by 2f66c45222 ("Preserve constant array when assigning a union of scalars") in 2.1.52. That commit is itself a correct precision improvement; it exposed two latent bugs in TypeCombinator downstream.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions