Skip to content

Generic star projection #3290

@hrach

Description

@hrach

Let's say my function accepts a generic class with upper bound type that I do not care about.

interface Bound {}

/**
 * @template T of Bound
 */
class Collection {}

/**
 * @param Collection<*> $list
 */
function size($list): int
{
    return $list->count();
}

https://phpstan.org/r/3c37ae59-d50b-4ea3-872f-235f5cf05fc2

(Not) possible workarounds:

If call-site variance would be allowed, this could be also written as:

interface Bound {}

/**
 * @template T of Bound
 */
class Collection {}

/**
 * @param Collection<out Bound> $list
 */
function size($list): int
{
    return $list->count();
}

Not working example: https://phpstan.org/r/fe3c4116-a825-45e1-8bab-0ab502497a92

If Collection would accept multiple subtypes of T at the same time, this could be also written as:

interface Bound {}

/**
 * @template-covariance T of Bound
 */
class Collection {}

/**
 * @param Collection<Bound> $list
 */
function size($list): int
{
    return $list->count();
}

Working example: https://phpstan.org/r/56bb4ce8-ce3c-4f82-9532-8048a0a9eebe


Great articles about generics (star projection): https://typealias.com/guides/star-projections-and-how-they-work/

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